Skip to content

[FEATURE] CV 분석 결과를 바탕으로 OpenAI에 설명 요청#22

Merged
youyeon11 merged 6 commits intodevelopfrom
feat/add-openai-20
Sep 7, 2025
Merged

[FEATURE] CV 분석 결과를 바탕으로 OpenAI에 설명 요청#22
youyeon11 merged 6 commits intodevelopfrom
feat/add-openai-20

Conversation

@youyeon11
Copy link
Contributor

@youyeon11 youyeon11 commented Sep 7, 2025

📌 작업 목적

  • CV로 분류한 응답에 대하여 open AI에 설명을 요청하는 기능 구현하였습니다.

🗂 작업 유형

  • 기능 추가 (Feature)
  • 버그 수정 (Bug Fix)
  • 리팩터링 (Refactor)
  • 성능 개선 (Performance)
  • 테스트 추가/수정 (Test)
  • 빌드/배포/환경 설정 (Chore)
  • 문서 수정 (Docs)

🔨 주요 작업 내용

  • openai_service.py
    def ask_chatgpt_about_pregnancy_safety(self, pill_name: str) -> tuple[str, int]:
        prompt = f"""
        약 이름: {pill_name}
        질문: 이 약은 임산부가 복용해도 안전한가요? 복용 가능 여부와 주의사항을 알려주세요.
        description 안에는 문장마다 \\n 을 적용하세요.
        결과를 JSON 형식으로 정확히 반환하세요. 설명이나 다른 텍스트를 절대 덧붙이지 마세요.
        스키마:
        {{
            "description": "복용 가능 여부 및 주의사항에 대한 설명",
            "isSafe": 1 또는 0
        }}
        """
  • 딥러닝 팀에서 작성한대로 일단 작성했습니다. GPT-4o-mini를 사용하였습니다.
  • isSafe에 대하여 0 혹은 1로 반환을 부탁받아 변환 코드도 추가했습니다

🧪 테스트 결과

  • 응답 제대로 반환됨 확인
image

📎 관련 이슈


💬 논의 및 고민한 점

  • env 파일에 open AI 키 추가해야합니다.

✅ 체크리스트

  • 모든 단위/통합 테스트를 통과했습니다
  • 환경 변수 변경 사항이 문서화되었습니다 (해당 시)
  • API 명세서(Swagger/Redoc)가 최신화되었습니다 (해당 시)
  • 관련 이슈와 커밋이 명확히 연결되어 있습니다

@youyeon11 youyeon11 changed the base branch from main to develop September 7, 2025 08:30
Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Summary of Changes

Hello @youyeon11, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

이 Pull Request는 CV 분석 파이프라인에 OpenAI 기반의 약물 안전성 검사 기능을 통합하고, Redis Stream을 통한 비동기 작업 처리의 안정성을 대폭 향상시킵니다. 또한, 새로운 배포 스크립트와 Docker Compose 설정을 추가하여 시스템의 배포 및 운영 효율성을 높였습니다.

Highlights

  • OpenAI 통합: CV 분석 결과를 바탕으로 약물의 임산부 복용 안전성에 대해 OpenAI (GPT-4o-mini)에 설명을 요청하는 기능이 추가되었습니다. 응답은 JSON 형식으로 파싱되어 isSafe 여부와 설명을 제공합니다.
  • Redis Stream 처리 개선: Redis Stream 메시지 처리 로직이 전반적으로 리팩토링되었습니다. RedisStreamClient 클래스를 도입하여 xadd, xreadgroup, xack_and_del 등 Redis Stream 관련 작업을 보다 견고하게 처리하며, 메시지 타입 검증 및 Dead Letter Queue (DLQ) 처리 메커니즘이 추가되었습니다.
  • 데이터 모델 및 S3 서비스 변경: OpenAI 통합에 맞춰 JobResult 스키마가 업데이트되었고, ImageJobJobRequest의 필드명이 camelCase로 통일되었습니다. S3 서비스는 이제 임시 파일 대신 BytesIO 스트림을 사용하여 이미지를 다운로드하고 처리합니다.
  • 배포 환경 구성 추가: 블루-그린 배포 전략을 위한 deploy.sh 스크립트, docker-compose.yml 파일, Nginx 설정 파일 (nginx.conf)이 추가되어 배포 프로세스가 정의되었습니다.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point in your pull request via creating an issue comment (i.e. comment on the pull request page) using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in issue comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@youyeon11
Copy link
Contributor Author

🤖 Gemini 코드 리뷰 결과

1. 주요 변경 사항 요약 및 의도 파악

이 PR은 #20 이슈를 해결하기 위해 CV 분석 결과(약 이름)를 바탕으로 OpenAI의 GPT 모델을 사용하여 임산부 복용 안전성 정보를 얻는 기능을 추가합니다. openai_service.py에 OpenAI API를 호출하는 로직이 추가되었고, tasks.py에서 해당 서비스를 사용하여 분석 결과를 가져오도록 수정되었습니다. 관련 설정은 config.py에 추가되었고, 필요한 라이브러리는 requirements.txt에 추가되었습니다. S3 관련 코드는 이 기능과 무관해 보이므로 삭제된 것 같습니다.

2. 코드 품질 및 가독성

  • 코드 스타일: 전반적으로 PEP 8을 잘 준수하고 있습니다. 다만, openai_service.py 파일 끝에 불필요한 공백 줄이 있습니다.
  • 변수/함수명: isSafe 보다는 is_safe 와 같이 snake_case를 사용하는 것이 Python 컨벤션에 더 부합합니다. 함수명 ask_chatgpt_about_pregnancy_safety는 조금 길어 보입니다. check_pregnancy_safety 혹은 query_pregnancy_safety 정도로 간결하게 할 수 있을 것 같습니다.
  • 주석/문서화: 함수의 역할과 파라미터, 반환 값에 대한 docstring이 잘 작성되어 있습니다. isSafe 변수에 대한 타입 변환 로직은 조금 복잡해 보이므로 추가적인 주석을 통해 의도를 명확히 설명하는 것이 좋겠습니다.
  • 중복 코드: 현재 PR에서는 중복 코드가 발견되지 않았습니다.

3. 잠재적 버그 및 엣지 케이스

  • 논리적 오류: OpenAI API 호출 결과가 예상과 다른 형식으로 반환될 경우를 대비한 에러 핸들링이 추가되어 있습니다. 하지만, description 필드가 없거나 다른 형태의 데이터가 올 경우에 대한 처리도 필요해 보입니다. isSafe 값이 0 또는 1 이외의 값으로 올 경우에 대한 명시적인 처리도 필요할 수 있습니다.
  • 경쟁 상태 (Race Condition): 현재 코드에서는 경쟁 상태 문제가 발생할 가능성이 낮아 보입니다.
  • 에러 핸들링: json.loads에서 발생하는 JSONDecodeError는 잘 처리하고 있지만, OpenAI API 호출 자체에서 발생할 수 있는 예외(네트워크 오류, API 키 오류 등)에 대한 처리가 필요합니다. try-except 블록을 추가하여 이러한 예외를 처리하고 적절한 로그를 남기는 것이 좋겠습니다.

4. 성능 및 효율성

  • 시간 복잡도: OpenAI API 호출이 주요 성능 병목 지점이 될 것으로 예상됩니다. 현재는 GPT-4o-mini 모델을 사용하고 있는데, 필요에 따라 다른 모델을 고려해볼 수 있습니다.
  • 자원 사용: 현재 코드에서 과도한 자원 사용은 예상되지 않습니다.
  • 최적화 제안: OpenAI API 응답 시간을 줄이기 위해 프롬프트를 최적화하거나, 응답 캐싱 전략을 고려해 볼 수 있습니다.

5. 보안 및 아키텍처

  • 보안 취약점: OpenAI API 키가 환경 변수에 저장되는데, 이 값이 유출되지 않도록 주의해야 합니다. secrets management 도구를 사용하는 것을 권장합니다.
  • 아키텍처 적합성: 비동기 작업 큐를 사용하여 OpenAI API 호출을 처리하는 것은 좋은 설계입니다.
  • 확장성: 향후 다른 유형의 안전성 정보를 얻기 위해 OpenAI API를 사용해야 할 경우, openai_service.py에 새로운 함수를 추가하고 tasks.py에서 호출하도록 쉽게 확장할 수 있습니다. 하지만, 너무 많은 기능이 추가될 경우, 서비스를 기능별로 분리하는 것을 고려해 볼 수 있습니다.

추가적인 제안:

  • isSafe 변수의 타입 변환 로직을 함수로 분리하고, 각 조건에 대한 주석을 추가하여 가독성을 높이는 것을 추천합니다.
  • 테스트 코드를 추가하여 OpenAI API 호출 및 응답 처리 로직을 검증하는 것이 좋습니다. 다양한 입력값과 예외 상황에 대한 테스트 케이스를 포함해야 합니다.
  • oepnai_key 오타 수정 필요합니다. (oepnai -> openai)

전반적으로 잘 작성된 PR입니다. 위에 제시된 사항들을 수정하면 더욱 견고하고 유지보수하기 쉬운 코드가 될 것입니다. 👍

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

CV 분석 결과를 바탕으로 OpenAI에 약품 안전성 설명을 요청하는 기능 추가 PR을 리뷰했습니다. 전반적으로 기능 구현의 목표는 잘 달성되었으나, 몇 가지 중요한 수정 사항과 개선점을 제안합니다.
주요 피드백은 다음과 같습니다:

  • Critical: async 함수 내에서 동기 I/O 호출로 인한 이벤트 루프 블로킹 문제가 있습니다.
  • High: 설정 파일에 변수명 오타가 있어 수정이 필요합니다.
  • Medium: print 대신 표준 로깅 라이브러리 사용, asyncio 환경에 더 적합한 AsyncOpenAI 클라이언트 사용, 프롬프트 관리 방식 개선, 코드 가독성 향상을 위한 리팩토링을 제안했습니다.

자세한 내용은 각 파일의 개별 코멘트를 참고해 주세요.

isSafe = 0
description = "일단은 테스트입니다. 추후에 GPT 부분 추가할 예정"
print(f"[task] Start Asking GPT for job_id={correlationId}")
description, isSafe = checker.ask_chatgpt_about_pregnancy_safety(pillName)

Choose a reason for hiding this comment

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

critical

async 함수 내에서 동기 함수인 ask_chatgpt_about_pregnancy_safety를 직접 호출하고 있습니다. 이 방식은 이벤트 루프를 블로킹하여 전체 애플리케이션의 성능을 심각하게 저하시킬 수 있습니다. 다른 I/O 바운드 작업과 마찬가지로 asyncio.to_thread를 사용하여 비동기적으로 실행해야 합니다.

Suggested change
description, isSafe = checker.ask_chatgpt_about_pregnancy_safety(pillName)
description, isSafe = await asyncio.to_thread(checker.ask_chatgpt_about_pregnancy_safety, pillName)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

이미 실행 중인 이벤트 루프가 비동기적으로 동작하므로, 별도의 스레드를 두는 대신 동기 방식 처리를 선택

Comment on lines 8 to 12
oepnai_key = os.getenv("OPENAI_API_KEY")

class Settings(BaseSettings):
REDIS_URL: str = redis_url
S3_REGION: str = bucket_name
BUCKET_NAME: str = s3_region
OPENAI_KEY: str = oepnai_key

Choose a reason for hiding this comment

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

high

oepnai_key에 오타가 있습니다. openai_key로 수정해야 합니다. 이 변수는 8라인과 12라인 두 곳에서 사용되고 있으며, 이 오타는 애플리케이션 설정 로딩 시 오류를 발생시킬 수 있습니다.

Suggested change
oepnai_key = os.getenv("OPENAI_API_KEY")
class Settings(BaseSettings):
REDIS_URL: str = redis_url
S3_REGION: str = bucket_name
BUCKET_NAME: str = s3_region
OPENAI_KEY: str = oepnai_key
openai_key = os.getenv("OPENAI_API_KEY")
class Settings(BaseSettings):
REDIS_URL: str = redis_url
OPENAI_KEY: str = openai_key

- isSafe: 안전하면 1, 안전하지 않으면 0
- description: 복용 가능 여부 설명
"""
def ask_chatgpt_about_pregnancy_safety(self, pill_name: str) -> tuple[str, int]:

Choose a reason for hiding this comment

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

medium

현재 ask_chatgpt_about_pregnancy_safety 메서드는 동기적으로 작동합니다. 이 애플리케이션은 asyncio를 기반으로 하므로, openai 라이브러리의 AsyncOpenAI 클라이언트를 사용하여 이 메서드를 async로 구현하는 것이 더 자연스럽고 효율적입니다. 이렇게 하면 호출부에서 asyncio.to_thread를 사용할 필요가 없어지고, 코드 전체의 비동기 일관성을 유지할 수 있습니다.

Comment on lines +16 to +26
prompt = f"""
약 이름: {pill_name}
질문: 이 약은 임산부가 복용해도 안전한가요? 복용 가능 여부와 주의사항을 알려주세요.
description 안에는 문장마다 \\n 을 적용하세요.
결과를 JSON 형식으로 정확히 반환하세요. 설명이나 다른 텍스트를 절대 덧붙이지 마세요.
스키마:
{{
"description": "복용 가능 여부 및 주의사항에 대한 설명",
"isSafe": 1 또는 0
}}
"""

Choose a reason for hiding this comment

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

medium

프롬프트 문자열이 메서드 내에 하드코딩되어 있습니다. 프롬프트가 길고 복잡해질 경우, 가독성과 유지보수성이 떨어질 수 있습니다. 프롬프트를 파일 상단의 상수로 분리하거나, 별도의 템플릿 파일로 관리하는 것을 고려해 보세요. 이렇게 하면 프롬프트의 재사용 및 수정이 용이해집니다.

max_tokens=600,
response_format={"type": "json_object"}
)
print("GPT Asking 성공...")

Choose a reason for hiding this comment

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

medium

print 문은 디버깅에는 유용하지만, 프로덕션 환경에서는 로그 레벨 관리, 포맷팅, 출력 위치 제어 등이 가능한 표준 logging 라이브러리를 사용하는 것이 좋습니다. 파일 상단에 import logging을 추가하고 logging.info()와 같은 함수를 사용하도록 변경하는 것을 권장합니다.

Suggested change
print("GPT Asking 성공...")
logging.info("GPT Asking 성공...")

Comment on lines +53 to +58
if isinstance(isSafe, bool):
isSafe = 1 if isSafe else 0
elif isinstance(isSafe, str):
isSafe = 1 if isSafe.strip() in {"1", "true", "True"} else 0
elif not isinstance(isSafe, int):
isSafe = 0

Choose a reason for hiding this comment

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

medium

isSafe 값을 정수로 변환하는 로직을 더 간결하게 개선할 수 있습니다. 다양한 타입(bool, str, int)을 처리하는 현재 로직은 방어적이지만, 아래와 같이 한 줄로 표현하여 가독성을 높일 수 있습니다. 이 코드는 isSafe 값이 1, True, "1", "true" 등일 경우 1을, 그 외의 모든 경우(None, 0, False, 다른 숫자나 문자열 등)에는 0을 반환합니다.

        isSafe = 1 if str(isSafe).strip().lower() in ("1", "true") else 0


isSafe = 0
description = "일단은 테스트입니다. 추후에 GPT 부분 추가할 예정"
print(f"[task] Start Asking GPT for job_id={correlationId}")

Choose a reason for hiding this comment

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

medium

디버깅 및 로깅을 위해 print를 사용하는 것보다 표준 logging 모듈을 사용하는 것이 좋습니다. 이를 통해 로그 레벨, 포맷, 출력 대상을 유연하게 관리할 수 있습니다. 파일 상단에 import logging을 추가하고 logging.info()와 같은 함수를 사용해 주세요.

Suggested change
print(f"[task] Start Asking GPT for job_id={correlationId}")
logging.info(f"[task] Start Asking GPT for job_id={correlationId}")

@youyeon11 youyeon11 merged commit 2d1b01e into develop Sep 7, 2025
@youyeon11 youyeon11 mentioned this pull request Sep 7, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEATURE] CV 분석 결과를 바탕으로 OpenAI에 설명 요청

1 participant