diff --git a/apps/server/src/ai/ai.controller.ts b/apps/server/src/ai/ai.controller.ts index f735ddc..c82d67e 100644 --- a/apps/server/src/ai/ai.controller.ts +++ b/apps/server/src/ai/ai.controller.ts @@ -3,7 +3,9 @@ import { ApiBody } from '@nestjs/swagger'; import { AiService } from './ai.service'; import { ImproveQuestionDto } from './dto/improve-question.dto'; +import { ShortenQuestionDto } from './dto/shorten-question.dto'; 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') @@ -19,4 +21,14 @@ export class AiController { const result = { question: await this.aiService.requestImproveQuestion(userContent) }; return { result }; } + + @Post('question-shorten') + @ShortenQuestionSwagger() + @ApiBody({ type: ShortenQuestionDto }) + @UseGuards(SessionTokenValidationGuard) + public async shortenQuestion(@Body() shortenQuestionDto: ShortenQuestionDto) { + const { body: userContent } = shortenQuestionDto; + const result = { question: await this.aiService.requestShortenQuestion(userContent) }; + return { result }; + } } diff --git a/apps/server/src/ai/ai.service.ts b/apps/server/src/ai/ai.service.ts index 917a908..8cc2b42 100644 --- a/apps/server/src/ai/ai.service.ts +++ b/apps/server/src/ai/ai.service.ts @@ -37,6 +37,10 @@ export class AiService { return await this.requestAIResponse(userContent, prompt.improveQuestion); } + public async requestShortenQuestion(userContent: string) { + return await this.requestAIResponse(userContent, prompt.shortenQuestion); + } + private async requestAIResponse(userContent: string, prompt: string) { const headers = { Authorization: this.API_KEY, @@ -56,7 +60,7 @@ export class AiService { ], topP: 0.8, topK: 0, - maxTokens: 512, + maxTokens: 1024, temperature: 0.5, repeatPenalty: 5.0, stopBefore: [], diff --git a/apps/server/src/ai/dto/shorten-question.dto.ts b/apps/server/src/ai/dto/shorten-question.dto.ts new file mode 100644 index 0000000..21b1750 --- /dev/null +++ b/apps/server/src/ai/dto/shorten-question.dto.ts @@ -0,0 +1,15 @@ +import { ApiProperty } from '@nestjs/swagger'; +import { IsNotEmpty, IsString } from 'class-validator'; + +import { BaseDto } from '@common/base.dto'; + +export class ShortenQuestionDto extends BaseDto { + @ApiProperty({ + example: '리마큐가 뭐임?', + description: '질문 본문 내용', + required: true, + }) + @IsString() + @IsNotEmpty({ message: '질문 본문은 필수입니다.' }) + body: string; +} diff --git a/apps/server/src/ai/promt.constant.ts b/apps/server/src/ai/promt.constant.ts index 633c56a..7a6f7ac 100644 --- a/apps/server/src/ai/promt.constant.ts +++ b/apps/server/src/ai/promt.constant.ts @@ -33,4 +33,31 @@ export const prompt = { [응답 예시2] # 결혼 적령 시기 - 결혼 적령 시기에 대해 설명해주세요.`, + + shortenQuestion: `당신은 질문 요약 전문가입니다. 아래의 기준에 따라 사용자가 입력한 질문을 분석하고, 짧게 요약해 주세요 +0. **마크다운 유지**: 원본 질문에 포함된 모든 링크, 이미지, 코드 블록 등 모든 마크다운 요소를 그대로 보존하세요. 수정 과정 중 형식, URL, 이미지 주소 등이 변경되거나 누락되지 않도록 주의하세요. +1. **글자 수 제한**: 원본 질문이 링크를 제외하고 500자 이하가 될 수 있도록 하세요. '![](링크 주소)'와 같은 형태는 500자에 포함되지 않으니 링크는 반드시 포함하세요. +2. 요약의 핵심: 질문의 주요 요소와 의도를 파악하여, 불필요한 부분은 제거하되 핵심 내용은 그대로 반영해 주세요. +3. 정보 누락 방지: 중요한 정보나 세부 사항이 빠지지 않도록 주의해 주세요. +4. 명확성과 이해 용이성: 요약된 질문이 누구에게나 명확하고 쉽게 이해될 수 있도록 작성해 주세요. +5. **질문 속 URL, 이미지 주소 유지**: 원본 질문에 포함된 모든 링크, 이미지, 코드 블록 등 모든 마크다운 요소를 그대로 보존하세요. 수정 과정 중 형식, URL, 이미지 주소 등이 변경되거나 누락되지 않도록 주의하세요. 링크 형식은 '![]()'으로 되어 있습니다. 반드시 포함하세요. +최종적으로 개선된, 짧고 명료한 질문을 출력해 주세요. +--- +아래는 입출력 예시입니다. + +[질문 예시1] +# 누가 더 위대한 축구선수인가: 메시 vs 호날두 +메시와 호날두 중에서 누가 더 위대한 선수일까요? +![두 선수의 매서운 눈빛](https://private-user-images.githubusercontent.com/11) +- [메시](https://private-user-images.githubusercontent.com/112055561) +- [호날두](https://private-user-images.githubusercontent.com/112055562) + +[응답 예시1] +# 메시 vs 호날두 +![두 선수의 매서운 눈빛](https://private-user-images.githubusercontent.com/11) +- [메시](https://private-user-images.githubusercontent.com/112055561) +- [호날두](https://private-user-images.githubusercontent.com/112055562) + + +`, } as const; diff --git a/apps/server/src/ai/swagger/shorten-question.swagger.ts b/apps/server/src/ai/swagger/shorten-question.swagger.ts new file mode 100644 index 0000000..2d59dad --- /dev/null +++ b/apps/server/src/ai/swagger/shorten-question.swagger.ts @@ -0,0 +1,18 @@ +import { applyDecorators } from '@nestjs/common'; +import { ApiOperation, ApiResponse } from '@nestjs/swagger'; + +export const ShortenQuestionSwagger = () => + applyDecorators( + ApiOperation({ summary: '질문 요약' }), + ApiResponse({ + status: 201, + description: '질문 요약 성공', + schema: { + example: { + result: { + question: '리마큐(Remacu)란 무엇인가요?', + }, + }, + }, + }), + ); diff --git a/apps/server/src/auth/auth.service.ts b/apps/server/src/auth/auth.service.ts index a55c6b1..3656bc9 100644 --- a/apps/server/src/auth/auth.service.ts +++ b/apps/server/src/auth/auth.service.ts @@ -1,4 +1,4 @@ -import { Inject, Injectable, OnModuleInit } from '@nestjs/common'; +import { Inject, Injectable } from '@nestjs/common'; import { JwtService } from '@nestjs/jwt'; import * as bcrypt from 'bcryptjs'; import Redis from 'ioredis';