Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feat] 홍보용 피드 요약 기능 추가 #37

Merged
merged 13 commits into from
Feb 6, 2025
Merged

[Feat] 홍보용 피드 요약 기능 추가 #37

merged 13 commits into from
Feb 6, 2025

Conversation

kimhji
Copy link
Collaborator

@kimhji kimhji commented Feb 5, 2025

🔨 테스크

Issue

모델 선택

  • naver clova studio 사용
    • 기존에 이미 만들어져 있는 요약 explorer 시도
      • 해당 모델을 통해 테스트 앱 생성 후 api 전송
      • 프롬프트나 글자 수와 같은 속성 설정 등이 거의 불가함을 확인
    • HCX-003 모델을 사용하여 playground에서 테스트
      • playground에서 여러 데이터를 직접 넣어보며 속성 파악
      • maxToken 및 프롬프트 지정을 통해 응답에 대한 정확도 향상
      • 해당 모델을 통한 테스트 앱을 사용하여 응답 정확도 확인

응답 데이터 필터링

  • 최대 글자 수 지정
    • 120자. 200자 이상은 feed card로 간단히 보여주기에 많고, 50자 미만은 내용을 정확히 파악하기 어려움.
  • 최대 재요청 횟수 5회
    • 응답 내용이 120자가 넘거나, 데이터를 가져오지 못한 경우를 위해 재요청 횟수를 지정함.
    • seed를 따로 지정하지 않도록 하여 요청마다 랜덤으로 조금씩 바뀌는 응답을 가져올 수 있도록 함.
  • 글자 잘림 문제 해결
    • maxToken 지정으로 인해 응답이 잘리는 경우의 데이터를 다듬기 위해, 마지막 .을 찾고 그 뒤 문자는 삭제하도록 함.

📋 작업 내용

  • 테스트 앱을 통해 LLM api를 사용하여 피드 XML 데이터로 120자 이내의 홍보용 요약글 생성
  • 프롬프트 및 maxToken, TopP 등의 속성 조정
  • 응답 내용이 120자를 넘을 경우 최대 5번까지 요약 재요청
  • maxToken에 의해 응답이 잘리는 경우를 위해 subString 예외 처리
  • HCX-003 모델의 최대 입력값 크기인 7600토큰(임의로 7600자로 지정함.)을 넘어가는 입력 content의 경우 subString을 통해 불 필요한 뒤쪽의 데이터 삭제

📷 스크린 샷(선택 사항)

image

@kimhji kimhji self-assigned this Feb 5, 2025
Copy link
Collaborator

@Jeongwisdom Jeongwisdom left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

너무 고생 많으셨어요!! 꼼꼼한 에러 처리 아주 좋습니당

- 답변 형태 : ~~~한 주제에 대해 다루고 있는 포스트입니다.`,
},
};
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이곳에 tag init도 들어가면 config 부분이 너무 길어질 것 같아서 혹시 ai.config.ts 파일을 만들어서 아래와 같은 형식으로 구현하는 것은 어떻게 생각하세용??
ai.config.ts

import { ConfigService } from '@nestjs/config';

export interface AIConfig {
  API_KEY: string;
  CLOVASTUDIO_REQUEST_ID: string;
  URL: URL;
  LIMITLENGTH: number;
  PROMPT: {
    role: string;
    content: string;
  };
}

export const AISummaryConfig = (configService: ConfigService, summaryMaxLength: number): AIConfig => ({
    API_KEY: configService.get<string>('API_KEY'),
    CLOVASTUDIO_REQUEST_ID: configService.get<string>(
      'CLOVASTUDIO_REQUEST_ID_SUMMARY',
    ),
    URL: configService.get<URL>('CLOVASTUDIO_URL_SUMMARY'),
    LIMITLENGTH: summaryMaxLength,
    PROMPT: {
      role: 'system',
      content: `- 당신은 반드시 ${summaryMaxLength} 글자 미만의 요약을 제공하는 텍스트 요약 어시스턴트입니다.
  - 주어진 XML 형태의 텍스트를 분석하고 핵심 주제를 추출합니다.
  - 이 글에 대한 요약은 해당 글을 홍보하고자 하는 목적으로 사용되며, 내부 내용에 대한 상세 사항은 응답에 포함되면 안됩니다.
  - 답변 형태 : ~~~한 주제에 대해 다루고 있는 포스트입니다.`,
    },
  }),
};

ai.service.ts

constructor(private readonly configService: ConfigService) {
    this.summaryConfig = AISummaryConfig(this.configService, summaryMaxLength);
  }

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

아예 init 부분을 config 파일로 빼니까 훨씬 가독성도 좋고 의존성에도 맞는 것 같네요! 해당 방식으로 수정 완료했습니다~

],
topP: 0.6,
topK: 0,
maxTokens: 35,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maxTokens값이 AIConfig.LIMITLENGTH 값으로 되어야 요약과 태그 요청마다 맥스 토큰 값을 변경할 수 있을 것 같습니당.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

token 값과 실제 응답 글자 수에 차이가 커서 LimitLength 값이 아닌 다른 값을 주는 것이 더 맞을 것 같아 동일한 값은 넣어두지 않았습니다! 수정에 용이하도록 config 속성 값으로 분리 완료했습니다, 감사합니다~

repeatPenalty: 2.0,
stopBefore: [],
includeAiFilters: true,
};
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

앗 그런데 이 파라미터 값들 저랑 조금 달라서 이 값들도 config로 빼도 괜찮을 것 같아요!!

Copy link
Collaborator Author

@kimhji kimhji Feb 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

넵 이 파라미터들 또한 config 속성 값으로 분리 완료했습니다!

if (resLength > AIConfig.LIMITLENGTH || resLength <= 0) {
result = '요약 데이터가 유효하지 않습니다.';
}
//console.log('응답 데이터:', result);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pr에 올리는 코드에서 console.log는 없어도 좋을 것 같습니당

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

디버깅을 위해 남겨뒀던 코드였는데 생각보다 빠르게 병합하게 되어서 삭제를 깜빡했네요! 삭제 완료했습니다 감사합니다~

if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

꼼꼼한 에러 처리 좋아요~~ 그런데 여기만 띄어쓰기가 있어서 에러 처리 부분들이 모두 끝나고 띄어쓰기를 해준다거나 의미별로 띄어쓰기를 하면 더 좋을 것 같습니다.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

띄어쓰기라는게 줄바꿈 말씀하시는거 맞을까요? 가독성을 위해 해당 부분도 에러 처리를 한데 모아 볼 수 있도록 수정했습니다!

if (!response.body) {
throw new Error('응답 스트림이 없습니다.');
}
result = await this.filterResponse(response);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

태그의 경우 응답이 수달, 족제비과, 서식지보호의 형식으로 들어와서 이 filterResponse는 사용하지 못할 것 같아요ㅠㅠ 이 함수는 응답이 끝난 후 요약 부분 후처리로 사용하고 여기에서는 모두가 사용할 수 있도록 response.json()으로 받아서 result.message.content로 반환해주는 것은 어떨까요???

Copy link
Collaborator Author

@kimhji kimhji Feb 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

response.json 사용 시, JSON으로 parsing 할 수 없다는 에러로 인해 해당 방식 사용에 어려움이 있습니다! 또한 응답에서 잘린 문장이 있으면 마저 정리한 후에 length를 파악하여 재요청을 보내야하기 때문에 filter 처리를 아예 함수 밖으로 빼버리는 것은 로직 상 맞지 않다는 생각이 듭니다!

image

filter 로직은 아무래도 응답 데이터 자체가 다르기 때문에 로직에도 차이가 있는게 맞을 것 같아요. AIType에 맞는 filter 함수를 지정하여 해당하는 데이터 처리를 할 수 있도록 하면 좋을 것 같아 그렇게 수정해두었습니다!

@kimhji kimhji merged commit 826cda2 into develop Feb 6, 2025
@kimhji kimhji deleted the feature/#36 branch February 6, 2025 13:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[BE] ai를 활용한 피드 3줄 홍보 기능
2 participants