Skip to content

Commit 24b203c

Browse files
wlgh1553shl0501yu-yj215cjeongmin
authored
feat(be): create prompt result insertion API (#72)
* feat: create prompt table Co-authored-by: shl0501 <[email protected]> Co-authored-by: 유영재 <[email protected]> Co-authored-by: Choi Jeongmin <[email protected]> * feat: create history insert API Co-authored-by: shl0501 <[email protected]> Co-authored-by: 유영재 <[email protected]> Co-authored-by: Choi Jeongmin <[email protected]> * fix: remove ai test file --------- Co-authored-by: shl0501 <[email protected]> Co-authored-by: 유영재 <[email protected]> Co-authored-by: Choi Jeongmin <[email protected]>
1 parent 0f759c8 commit 24b203c

File tree

10 files changed

+133
-87
lines changed

10 files changed

+133
-87
lines changed
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
-- CreateTable
2+
CREATE TABLE "Prompt" (
3+
"name" TEXT NOT NULL,
4+
"content" TEXT NOT NULL,
5+
6+
CONSTRAINT "Prompt_pkey" PRIMARY KEY ("name")
7+
);
8+
9+
-- CreateTable
10+
CREATE TABLE "PromptHistory" (
11+
"history_id" SERIAL NOT NULL,
12+
"before" TEXT NOT NULL,
13+
"after" TEXT NOT NULL,
14+
"prompt_name" TEXT NOT NULL,
15+
"result" TEXT NOT NULL,
16+
17+
CONSTRAINT "PromptHistory_pkey" PRIMARY KEY ("history_id")
18+
);
19+
20+
-- AddForeignKey
21+
ALTER TABLE "PromptHistory" ADD CONSTRAINT "PromptHistory_prompt_name_fkey" FOREIGN KEY ("prompt_name") REFERENCES "Prompt"("name") ON DELETE RESTRICT ON UPDATE CASCADE;
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/*
2+
Warnings:
3+
4+
- You are about to drop the column `after` on the `PromptHistory` table. All the data in the column will be lost.
5+
- You are about to drop the column `before` on the `PromptHistory` table. All the data in the column will be lost.
6+
- Added the required column `request` to the `PromptHistory` table without a default value. This is not possible if the table is not empty.
7+
- Added the required column `response` to the `PromptHistory` table without a default value. This is not possible if the table is not empty.
8+
9+
*/
10+
-- AlterTable
11+
ALTER TABLE "PromptHistory" DROP COLUMN "after",
12+
DROP COLUMN "before",
13+
ADD COLUMN "request" TEXT NOT NULL,
14+
ADD COLUMN "response" TEXT NOT NULL;

apps/server/prisma/schema.prisma

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,3 +136,20 @@ model Chatting {
136136
@@index([sessionId])
137137
@@index([sessionId, chattingId(Sort.desc)])
138138
}
139+
140+
model Prompt {
141+
name String @id
142+
content String
143+
144+
PromptHistory PromptHistory[] @relation("promptHistories")
145+
}
146+
147+
model PromptHistory {
148+
historyId Int @id @default(autoincrement()) @map("history_id")
149+
request String
150+
response String
151+
promptName String @map("prompt_name")
152+
result String
153+
154+
prompt Prompt @relation("promptHistories", fields: [promptName], references: [name])
155+
}

apps/server/src/ai/ai.controller.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,15 @@ import { Body, Controller, Post, UseGuards } from '@nestjs/common';
22
import { ApiBody } from '@nestjs/swagger';
33

44
import { AiService } from './ai.service';
5+
import { CreateHistoryDto } from './dto/create-history.dto';
56
import { ImproveQuestionDto } from './dto/improve-question.dto';
67
import { ShortenQuestionDto } from './dto/shorten-question.dto';
8+
import { CreateHistorySwagger } from './swagger/create-history.swagger';
79
import { ImproveQuestionSwagger } from './swagger/improve-question.swagger';
810
import { ShortenQuestionSwagger } from './swagger/shorten-question.swagger';
911

1012
import { SessionTokenValidationGuard } from '@common/guards/session-token-validation.guard';
13+
1114
@Controller('ai')
1215
export class AiController {
1316
constructor(private readonly aiService: AiService) {}
@@ -31,4 +34,11 @@ export class AiController {
3134
const result = { question: await this.aiService.requestShortenQuestion(userContent) };
3235
return { result };
3336
}
37+
38+
@Post('history')
39+
@CreateHistorySwagger()
40+
@ApiBody({ type: CreateHistoryDto })
41+
public createHistory(@Body() createHistoryDto: CreateHistoryDto) {
42+
this.aiService.createHistory(createHistoryDto);
43+
}
3444
}

apps/server/src/ai/ai.module.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@ import { AiController } from './ai.controller';
44
import { AiService } from './ai.service';
55

66
import { SessionTokenModule } from '@common/guards/session-token.module';
7+
import { PrismaModule } from '@prisma-alias/prisma.module';
78

89
@Module({
9-
imports: [SessionTokenModule],
10+
imports: [PrismaModule, SessionTokenModule],
1011
providers: [AiService],
1112
controllers: [AiController],
1213
})

apps/server/src/ai/ai.service.spec.ts

Lines changed: 0 additions & 19 deletions
This file was deleted.

apps/server/src/ai/ai.service.ts

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import { Injectable } from '@nestjs/common';
22

3-
import { prompt } from '@ai/promt.constant';
3+
import { CreateHistoryDto } from './dto/create-history.dto';
4+
5+
import { PrismaService } from '@prisma-alias/prisma.service';
46

57
interface ClovaApiResponse {
68
status: {
@@ -28,17 +30,25 @@ export class AiService {
2830
private readonly CLOVA_API_URL: string;
2931
private readonly API_KEY: string;
3032

31-
constructor() {
33+
constructor(private readonly prisma: PrismaService) {
3234
this.CLOVA_API_URL = process.env.CLOVA_API_URL;
3335
this.API_KEY = 'Bearer ' + process.env.CLOVA_API_KEY;
3436
}
3537

3638
public async requestImproveQuestion(userContent: string) {
37-
return await this.requestAIResponse(userContent, prompt.improveQuestion);
39+
const prompt = await this.prisma.prompt.findUnique({ where: { name: 'IMPROVE_QUESTION' } });
40+
return await this.requestAIResponse(userContent, prompt.content);
3841
}
3942

4043
public async requestShortenQuestion(userContent: string) {
41-
return await this.requestAIResponse(userContent, prompt.shortenQuestion);
44+
const prompt = await this.prisma.prompt.findUnique({ where: { name: 'SHORTEN_QUESTION' } });
45+
return await this.requestAIResponse(userContent, prompt.content);
46+
}
47+
48+
public async createHistory({ request, response, promptName, result }: CreateHistoryDto) {
49+
await this.prisma.promptHistory.create({
50+
data: { request, response, promptName, result },
51+
});
4252
}
4353

4454
private async requestAIResponse(userContent: string, prompt: string) {
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import { ApiProperty } from '@nestjs/swagger';
2+
import { IsIn, IsNotEmpty, IsString } from 'class-validator';
3+
4+
export class CreateHistoryDto {
5+
@ApiProperty({
6+
example: 'IMPROVE_QUESTION',
7+
description: '프롬프트 종류',
8+
required: true,
9+
})
10+
@IsIn(['IMPROVE_QUESTION', 'SHORTEN_QUESTION'], {
11+
message: 'promptName은 IMPROVE_QUESTION 또는 SHORTEN_QUESTION이어야 합니다.',
12+
})
13+
@IsNotEmpty()
14+
promptName: string;
15+
16+
@ApiProperty({
17+
example: '호날두 VS 메시',
18+
description: 'AI 수정 전의 원본',
19+
required: true,
20+
})
21+
@IsString()
22+
@IsNotEmpty()
23+
request: string;
24+
25+
@ApiProperty({
26+
example: '호날두와 메시 중 누가 더 뛰어난 축구선수인가요?',
27+
description: 'AI 수정 후의 결과',
28+
required: true,
29+
})
30+
@IsString()
31+
@IsNotEmpty()
32+
response: string;
33+
34+
@ApiProperty({
35+
example: 'ACCEPT',
36+
description: '사용자 반응',
37+
required: true,
38+
})
39+
@IsIn(['ACCEPT', 'REJECT'], {
40+
message: 'result는 ACCEPT 또는 REJECT이어야 합니다.',
41+
})
42+
@IsNotEmpty()
43+
result: string;
44+
}

apps/server/src/ai/promt.constant.ts

Lines changed: 0 additions & 63 deletions
This file was deleted.
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { applyDecorators } from '@nestjs/common';
2+
import { ApiOperation, ApiResponse } from '@nestjs/swagger';
3+
4+
export const CreateHistorySwagger = () =>
5+
applyDecorators(
6+
ApiOperation({ summary: 'AI 제안을 사용자가 accept/rejet했는지를 저장합니다.' }),
7+
ApiResponse({
8+
status: 201,
9+
description: 'history 저장 성공',
10+
}),
11+
);

0 commit comments

Comments
 (0)