Skip to content

Commit

Permalink
feat(be): create prompt result insertion API (#72)
Browse files Browse the repository at this point in the history
* 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]>
  • Loading branch information
4 people authored Feb 10, 2025
1 parent 0f759c8 commit 24b203c
Show file tree
Hide file tree
Showing 10 changed files with 133 additions and 87 deletions.
21 changes: 21 additions & 0 deletions apps/server/prisma/migrations/20250210082219_prompt/migration.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
-- CreateTable
CREATE TABLE "Prompt" (
"name" TEXT NOT NULL,
"content" TEXT NOT NULL,

CONSTRAINT "Prompt_pkey" PRIMARY KEY ("name")
);

-- CreateTable
CREATE TABLE "PromptHistory" (
"history_id" SERIAL NOT NULL,
"before" TEXT NOT NULL,
"after" TEXT NOT NULL,
"prompt_name" TEXT NOT NULL,
"result" TEXT NOT NULL,

CONSTRAINT "PromptHistory_pkey" PRIMARY KEY ("history_id")
);

-- AddForeignKey
ALTER TABLE "PromptHistory" ADD CONSTRAINT "PromptHistory_prompt_name_fkey" FOREIGN KEY ("prompt_name") REFERENCES "Prompt"("name") ON DELETE RESTRICT ON UPDATE CASCADE;
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/*
Warnings:
- You are about to drop the column `after` on the `PromptHistory` table. All the data in the column will be lost.
- You are about to drop the column `before` on the `PromptHistory` table. All the data in the column will be lost.
- Added the required column `request` to the `PromptHistory` table without a default value. This is not possible if the table is not empty.
- Added the required column `response` to the `PromptHistory` table without a default value. This is not possible if the table is not empty.
*/
-- AlterTable
ALTER TABLE "PromptHistory" DROP COLUMN "after",
DROP COLUMN "before",
ADD COLUMN "request" TEXT NOT NULL,
ADD COLUMN "response" TEXT NOT NULL;
17 changes: 17 additions & 0 deletions apps/server/prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -136,3 +136,20 @@ model Chatting {
@@index([sessionId])
@@index([sessionId, chattingId(Sort.desc)])
}

model Prompt {
name String @id
content String
PromptHistory PromptHistory[] @relation("promptHistories")
}

model PromptHistory {
historyId Int @id @default(autoincrement()) @map("history_id")
request String
response String
promptName String @map("prompt_name")
result String
prompt Prompt @relation("promptHistories", fields: [promptName], references: [name])
}
10 changes: 10 additions & 0 deletions apps/server/src/ai/ai.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,15 @@ import { Body, Controller, Post, UseGuards } from '@nestjs/common';
import { ApiBody } from '@nestjs/swagger';

import { AiService } from './ai.service';
import { CreateHistoryDto } from './dto/create-history.dto';
import { ImproveQuestionDto } from './dto/improve-question.dto';
import { ShortenQuestionDto } from './dto/shorten-question.dto';
import { CreateHistorySwagger } from './swagger/create-history.swagger';
import { ImproveQuestionSwagger } from './swagger/improve-question.swagger';
import { ShortenQuestionSwagger } from './swagger/shorten-question.swagger';

import { SessionTokenValidationGuard } from '@common/guards/session-token-validation.guard';

@Controller('ai')
export class AiController {
constructor(private readonly aiService: AiService) {}
Expand All @@ -31,4 +34,11 @@ export class AiController {
const result = { question: await this.aiService.requestShortenQuestion(userContent) };
return { result };
}

@Post('history')
@CreateHistorySwagger()
@ApiBody({ type: CreateHistoryDto })
public createHistory(@Body() createHistoryDto: CreateHistoryDto) {
this.aiService.createHistory(createHistoryDto);
}
}
3 changes: 2 additions & 1 deletion apps/server/src/ai/ai.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ import { AiController } from './ai.controller';
import { AiService } from './ai.service';

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

@Module({
imports: [SessionTokenModule],
imports: [PrismaModule, SessionTokenModule],
providers: [AiService],
controllers: [AiController],
})
Expand Down
19 changes: 0 additions & 19 deletions apps/server/src/ai/ai.service.spec.ts

This file was deleted.

18 changes: 14 additions & 4 deletions apps/server/src/ai/ai.service.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { Injectable } from '@nestjs/common';

import { prompt } from '@ai/promt.constant';
import { CreateHistoryDto } from './dto/create-history.dto';

import { PrismaService } from '@prisma-alias/prisma.service';

interface ClovaApiResponse {
status: {
Expand Down Expand Up @@ -28,17 +30,25 @@ export class AiService {
private readonly CLOVA_API_URL: string;
private readonly API_KEY: string;

constructor() {
constructor(private readonly prisma: PrismaService) {
this.CLOVA_API_URL = process.env.CLOVA_API_URL;
this.API_KEY = 'Bearer ' + process.env.CLOVA_API_KEY;
}

public async requestImproveQuestion(userContent: string) {
return await this.requestAIResponse(userContent, prompt.improveQuestion);
const prompt = await this.prisma.prompt.findUnique({ where: { name: 'IMPROVE_QUESTION' } });
return await this.requestAIResponse(userContent, prompt.content);
}

public async requestShortenQuestion(userContent: string) {
return await this.requestAIResponse(userContent, prompt.shortenQuestion);
const prompt = await this.prisma.prompt.findUnique({ where: { name: 'SHORTEN_QUESTION' } });
return await this.requestAIResponse(userContent, prompt.content);
}

public async createHistory({ request, response, promptName, result }: CreateHistoryDto) {
await this.prisma.promptHistory.create({
data: { request, response, promptName, result },
});
}

private async requestAIResponse(userContent: string, prompt: string) {
Expand Down
44 changes: 44 additions & 0 deletions apps/server/src/ai/dto/create-history.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { ApiProperty } from '@nestjs/swagger';
import { IsIn, IsNotEmpty, IsString } from 'class-validator';

export class CreateHistoryDto {
@ApiProperty({
example: 'IMPROVE_QUESTION',
description: '프롬프트 종류',
required: true,
})
@IsIn(['IMPROVE_QUESTION', 'SHORTEN_QUESTION'], {
message: 'promptName은 IMPROVE_QUESTION 또는 SHORTEN_QUESTION이어야 합니다.',
})
@IsNotEmpty()
promptName: string;

@ApiProperty({
example: '호날두 VS 메시',
description: 'AI 수정 전의 원본',
required: true,
})
@IsString()
@IsNotEmpty()
request: string;

@ApiProperty({
example: '호날두와 메시 중 누가 더 뛰어난 축구선수인가요?',
description: 'AI 수정 후의 결과',
required: true,
})
@IsString()
@IsNotEmpty()
response: string;

@ApiProperty({
example: 'ACCEPT',
description: '사용자 반응',
required: true,
})
@IsIn(['ACCEPT', 'REJECT'], {
message: 'result는 ACCEPT 또는 REJECT이어야 합니다.',
})
@IsNotEmpty()
result: string;
}
63 changes: 0 additions & 63 deletions apps/server/src/ai/promt.constant.ts

This file was deleted.

11 changes: 11 additions & 0 deletions apps/server/src/ai/swagger/create-history.swagger.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { applyDecorators } from '@nestjs/common';
import { ApiOperation, ApiResponse } from '@nestjs/swagger';

export const CreateHistorySwagger = () =>
applyDecorators(
ApiOperation({ summary: 'AI 제안을 사용자가 accept/rejet했는지를 저장합니다.' }),
ApiResponse({
status: 201,
description: 'history 저장 성공',
}),
);

0 comments on commit 24b203c

Please sign in to comment.