Skip to content

Conversation

@yeonju73
Copy link
Contributor

@yeonju73 yeonju73 commented Jul 26, 2025

πŸ’» Related Issue


πŸš€ Work Description

  • GPT API μ—°κ²°
스크란샷 2025-07-26 17 05 52 - μ„œλ²„μ˜ request body와 μΌμΉ˜μ‹œμΌ°μŠ΅λ‹ˆλ‹€.
  • 더미 μ˜ˆμ‹œ λ°μ΄ν„°λ‘œ ν”„λ‘¬ν”„νŠΈ μ—”μ§€λ‹ˆμ–΄λ§ μ§„ν–‰
  • app.prompts.data.fraud_examples μ—μ„œ μœ ν˜•λ³„ μ˜ˆμ‹œ 데이터λ₯Ό κ΄€λ¦¬ν•˜λ©°,
  • app.prompts.fraud_prompts μ—μ„œ ν”„λ‘¬ν”„νŠΈμ— μ§€μ‹œμ‚¬ν•­κ³Ό μ˜ˆμ‹œλ°μ΄ν„°λ₯Ό μ£Όμž…ν•˜μ˜€μŠ΅λ‹ˆλ‹€.

πŸ™‡πŸ»β€β™€οΈ To Reviewer

  • ν˜„μž¬λŠ” λͺ¨λ‘ 더미 μ˜ˆμ‹œ λ°μ΄ν„°λ‘œ ν”„λ‘¬ν”„νŠΈ κ°œλ°œμ„ μ§„ν–‰ν•˜μ˜€μŠ΅λ‹ˆλ‹€.
  • ν˜„μž¬ gpt api κ²°μ œμˆ˜λ‹¨μ„ 아직 λ“±λ‘ν•˜μ§€ μ•Šμ•˜λŠ”λ° api 호좜이 잘 λ©λ‹ˆλ‹€..! Usage의 Total Spend도 0λ‹¬λŸ¬λ‘œ 찍히고 μžˆμŠ΅λ‹ˆλ‹€.
  • λͺ¨λ“  μœ ν˜•μ˜ 3-4개의 μ˜ˆμ‹œλ₯Ό assistant 둜 맀번 ν”„λ‘¬ν”„νŠΈμ— μž…λ ₯ν•˜λŠ” 것은 input token 맀우 많이 μ†Œλͺ¨λ  것 κ°™μŠ΅λ‹ˆλ‹€.. κ·Έλž˜μ„œ λŒ€μ•ˆμœΌλ‘œ 미리 λ§Œλ“€μ–΄λ†“μ€ ν”„λ‘¬ν”„νŠΈλ₯Ό μ—°κ²°ν•΄μ„œ μ“°λŠ” Reusable Prompt 방식도 μ•Œμ•„λ³΄μ•˜λŠ”λ°, ν”„λ‘¬ν”„νŠΈ 생성을 ν•˜λ €λ©΄ 결제 μˆ˜λ‹¨μ„ λ“±λ‘ν•˜λΌκ³  λ– μ„œ μΆ”ν›„ λ„μž…ν•΄λ³΄λ©΄ 쒋을 것 κ°™μŠ΅λ‹ˆλ‹€! μ§€κΈˆ λ„μž…ν•˜μ§€ μ•Šμ€ μ΄μœ λŠ” λ¬΄λ£Œλ‘œλ„ 잘 μž‘λ™ν•˜κΈ° λ•Œλ¬Έμž…λ‹ˆλ‹€...
  • Reusable Prompt https://platform.openai.com/docs/guides/text#reusable-prompts
  • ν”„λ‘œμ νŠΈμ˜ μš”κ΅¬μ‚¬ν•­μ— 맞게 μ§€μ‹œμ‚¬ν•­ μˆ˜μ •λ„ μΆ”ν›„ μ§„ν–‰ν•΄μ•Όν•  것 κ°™μŠ΅λ‹ˆλ‹€.

βž• Next

  • μ˜ˆμ‹œ 데이터 μˆ˜μ§‘
  • ν”„λ‘¬ν”„νŠΈ μ§€μ‹œμ‚¬ν•­ μˆ˜μ •
  • spring μ„œλ²„μ™€ μ—°κ²°

Summary by CodeRabbit

  • μ‹ κ·œ κΈ°λŠ₯

    • λ‹€μ–‘ν•œ 사기 μœ ν˜•μ„ λΆ„λ₯˜ν•˜κ³  μœ„ν—˜λ„λ₯Ό ν‰κ°€ν•˜λŠ” 사기 뢄석 APIκ°€ μΆ”κ°€λ˜μ—ˆμŠ΅λ‹ˆλ‹€.
    • λ©”μ‹œμ§€, ν‚€μ›Œλ“œ, μΆ”κ°€ μ„€λͺ…, 이미지 정보λ₯Ό μž…λ ₯ν•˜μ—¬ 사기 μœ ν˜•μ„ 뢄석할 수 μžˆμŠ΅λ‹ˆλ‹€.
    • 사기 뢄석 결과둜 λΆ„λ₯˜λœ 사기 μœ ν˜•, μ£Όμš” ν‚€μ›Œλ“œ, μ„€λͺ…, μœ„ν—˜ μ μˆ˜κ°€ μ œκ³΅λ©λ‹ˆλ‹€.
    • 사기 뢄석을 μœ„ν•œ μ˜ˆμ‹œ 데이터와 ν”„λ‘¬ν”„νŠΈκ°€ μΆ”κ°€λ˜μ–΄ λΆ„λ₯˜ 정확도가 ν–₯μƒλ˜μ—ˆμŠ΅λ‹ˆλ‹€.
  • ν™˜κ²½ μ„€μ •

    • OpenAI GPT API 연동을 μœ„ν•œ ν™˜κ²½ λ³€μˆ˜μ™€ μ„€μ • 파일이 μΆ”κ°€λ˜μ—ˆμŠ΅λ‹ˆλ‹€.
    • GPT API ν‚€κ°€ 배포 μ›Œν¬ν”Œλ‘œμš°μ— μ•ˆμ „ν•˜κ²Œ ν†΅ν•©λ˜μ—ˆμŠ΅λ‹ˆλ‹€.
    • κ΄€λ ¨ 라이브러리 및 μ˜μ‘΄μ„±μ΄ μ—…λ°μ΄νŠΈλ˜μ—ˆμŠ΅λ‹ˆλ‹€.
  • 버그 μˆ˜μ • 및 기타

    • κΈ°μ‘΄ 사기 뢄석 GET μ—”λ“œν¬μΈνŠΈκ°€ μ œκ±°λ˜μ—ˆμŠ΅λ‹ˆλ‹€.
    • λΌμš°νŒ… 경둜 및 νƒœκ·Έ ν‘œκΈ°κ°€ ν•˜μ΄ν”ˆμœΌλ‘œ 일관성 있게 κ°œμ„ λ˜μ—ˆμŠ΅λ‹ˆλ‹€.

@coderabbitai
Copy link

coderabbitai bot commented Jul 26, 2025

"""

Walkthrough

GPT API 연동을 μœ„ν•œ μ£Όμš” λ°±μ—”λ“œ κΈ°λŠ₯이 μΆ”κ°€λ˜μ—ˆμŠ΅λ‹ˆλ‹€. FastAPI μ—”λ“œν¬μΈνŠΈ, μ„œλΉ„μŠ€ λ ˆμ΄μ–΄, ν”„λ‘¬ν”„νŠΈ 생성, μ˜ˆμ‹œ 데이터, μ„€μ • 관리, λͺ¨λΈ μ •μ˜ 등이 μ‹ κ·œλ‘œ λ„μž…λ˜μ—ˆκ³ , 배포 μ›Œν¬ν”Œλ‘œμ™€ μ˜μ‘΄μ„±λ„ λ³΄κ°•λ˜μ—ˆμŠ΅λ‹ˆλ‹€. κΈ°μ‘΄ λΌμš°ν„°λŠ” μ‚­μ œ 및 κ²½λ‘œκ°€ λ³€κ²½λ˜μ—ˆμŠ΅λ‹ˆλ‹€.

Changes

파일/경둜 λ³€κ²½ μš”μ•½
.coderabbit/config.yml features.docstrings 섀정을 false둜 λͺ…μ‹œν•œ μ‹ κ·œ ꡬ성 파일 μΆ”κ°€
.github/workflows/deploy.yml 배포 μ›Œν¬ν”Œλ‘œμ— GPT_API_KEY ν™˜κ²½ λ³€μˆ˜ μΆ”κ°€ 및 Docker에 전달
app/api/fraud_analysis.py GPT API 연동 POST μ—”λ“œν¬μΈνŠΈ 및 μ˜ˆμ™Έ 처리 μ‹ μ„€
app/config/setting.py ν™˜κ²½ λ³€μˆ˜ 기반 μ„€μ • 클래슀 및 μΈμŠ€ν„΄μŠ€ μΆ”κ°€
app/main.py fraud_analysis λΌμš°ν„° 경둜 및 νƒœκ·Έλ₯Ό ν•˜μ΄ν”ˆ ν‘œκΈ°λ‘œ λ³€κ²½, import 경둜 μˆ˜μ •
app/models/fraud_request.py FraudRequest Pydantic λͺ¨λΈ(4개 ν•„λ“œ) μ‹ κ·œ μΆ”κ°€
app/models/fraud_response.py FraudResponse Pydantic λͺ¨λΈ(4개 ν•„λ“œ) μ‹ κ·œ μΆ”κ°€
app/prompts/fraud_example.py FraudExample Pydantic λͺ¨λΈ(5개 ν•„λ“œ) μ‹ κ·œ μΆ”κ°€
app/prompts/data/fraud_examples.py 60~70개 μœ ν˜•μ˜ 사기 μ˜ˆμ‹œ 데이터 리슀트(FRAUD_EXAMPLES) μ‹ κ·œ μΆ”κ°€
app/prompts/fraud_prompts.py 사기 λΆ„λ₯˜ ν”„λ‘¬ν”„νŠΈ 생성 ν•¨μˆ˜ 및 μ˜ˆμ‹œ ν¬λ§·νŒ… ν•¨μˆ˜ μΆ”κ°€
app/routers/fraud_analysis.py κΈ°μ‘΄ GET 방식 λΌμš°ν„° 파일 μ‚­μ œ
app/services/gpt_service.py OpenAI GPT API 호좜 비동기 ν•¨μˆ˜ 및 μ˜ˆμ™Έ 처리 μ‹ μ„€
requirements.txt click 제거, openai, pydantic-settings λ“± μ‹ κ·œ νŒ¨ν‚€μ§€ λŒ€κ±° μΆ”κ°€

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant FastAPI (fraud_analysis)
    participant GPTService
    participant OpenAI API

    Client->>FastAPI (fraud_analysis): POST /api/fraud-analysis (FraudRequest)
    FastAPI (fraud_analysis)->>GPTService: call_gpt(request)
    GPTService->>OpenAI API: GPT-4o-mini λͺ¨λΈλ‘œ ν”„λ‘¬ν”„νŠΈ μš”μ²­
    OpenAI API-->>GPTService: JSON 응닡 λ°˜ν™˜
    GPTService-->>FastAPI (fraud_analysis): FraudResponse νŒŒμ‹±/λ°˜ν™˜
    FastAPI (fraud_analysis)-->>Client: FraudResponse λ°˜ν™˜
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~18 minutes

Poem

πŸ₯•
μƒˆμ‹Ήμ²˜λŸΌ μžλΌλ‚œ μ½”λ“œ ν•œ 쀄,
사기 μž‘λŠ” ν† λΌμ˜ μš©κ°ν•œ 좜근길!
ν”„λ‘¬ν”„νŠΈμ™€ λͺ¨λΈ, μ˜ˆμ‹œ 데이터도
GPT API와 νž˜μ„ 합쳐
μ˜€λŠ˜μ€ 사기꾼도 λ‹¬μ•„λ‚˜λ„€β€”
ν† λΌλŠ” 깑총, λ¦¬λ·°λŠ” μˆœν•­!
🌱
"""

Note

⚑️ Unit Test Generation is now available in beta!

Learn more here, or try it out under "Finishing Touches" below.


πŸ“œ Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between 38b06f6 and e190004.

πŸ“’ Files selected for processing (6)
  • app/api/fraud_analysis.py (1 hunks)
  • app/models/fraud_request.py (1 hunks)
  • app/models/fraud_response.py (1 hunks)
  • app/prompts/fraud_prompts.py (1 hunks)
  • app/services/gpt_service.py (1 hunks)
  • requirements.txt (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (6)
  • app/api/fraud_analysis.py
  • app/services/gpt_service.py
  • requirements.txt
  • app/models/fraud_response.py
  • app/prompts/fraud_prompts.py
  • app/models/fraud_request.py
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: deploy
✨ Finishing Touches
  • πŸ“ Generate Docstrings
πŸ§ͺ Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/#8/connect-gpt-api

πŸͺ§ Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 9

🧹 Nitpick comments (8)
app/models/fraud_request.py (1)

8-8: imageContent ν•„λ“œμ— λŒ€ν•œ 검증 μΆ”κ°€λ₯Ό κ³ λ €ν•˜μ„Έμš”.

imageContentκ°€ λ¬Έμžμ—΄λ‘œ μ •μ˜λ˜μ–΄ μžˆμ§€λ§Œ base64 μΈμ½”λ”©λœ 이미지 데이터인지 URL인지 λͺ…ν™•ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. μ μ ˆν•œ 검증을 μΆ”κ°€ν•˜λŠ” 것을 ꢌμž₯ν•©λ‹ˆλ‹€.

from pydantic import BaseModel, Field, validator
from typing import List, Optional
import base64

class FraudRequest(BaseModel):
    messageContent: str
    keywords: List[str]
    additionalDescription: Optional[str] = None
-    imageContent: Optional[str] = None
+    imageContent: Optional[str] = Field(None, description="Base64 encoded image or image URL")
+    
+    @validator('imageContent')
+    def validate_image_content(cls, v):
+        if v and not (v.startswith('data:image/') or v.startswith('http')):
+            # Check if it's valid base64
+            try:
+                base64.b64decode(v)
+            except Exception:
+                raise ValueError('imageContent must be base64 encoded image, data URL, or HTTP URL')
+        return v
.coderabbit/config.yml (1)

1-2: 파일 끝에 κ°œν–‰ 문자λ₯Ό μΆ”κ°€ν•˜μ„Έμš”.

YAML 파일의 λͺ¨λ²” 사둀에 따라 파일 끝에 κ°œν–‰ λ¬Έμžκ°€ ν•„μš”ν•©λ‹ˆλ‹€.

features:
-  docstrings: false
+  docstrings: false
+
.github/workflows/deploy.yml (1)

64-64: 파일 끝에 κ°œν–‰ 문자λ₯Ό μΆ”κ°€ν•˜μ„Έμš”.

YAML 파일의 λͺ¨λ²” 사둀에 따라 파일 끝에 κ°œν–‰ λ¬Έμžκ°€ ν•„μš”ν•©λ‹ˆλ‹€.

              -e GPT_API_KEY="${{ env.GPT_API_KEY }}" \
-              ${{ env.DOCKER_REPO }}:latest
+              ${{ env.DOCKER_REPO }}:latest
+
app/config/setting.py (1)

9-9: μ„€μ • μΈμŠ€ν„΄μŠ€ μ΄ˆκΈ°ν™” μ‹œ μ˜ˆμ™Έ 처리 κ³ λ €

ν™˜κ²½λ³€μˆ˜κ°€ λˆ„λ½λ˜κ±°λ‚˜ 잘λͺ»λœ 경우λ₯Ό λŒ€λΉ„ν•œ μ˜ˆμ™Έ 처리λ₯Ό μΆ”κ°€ν•˜λŠ” 것이 μ’‹μŠ΅λ‹ˆλ‹€.

λ‹€μŒκ³Ό 같이 κ°œμ„ ν•  수 μžˆμŠ΅λ‹ˆλ‹€:

-settings = Settings()
+try:
+    settings = Settings()
+except Exception as e:
+    raise RuntimeError(f"μ„€μ • μ΄ˆκΈ°ν™” μ‹€νŒ¨: {e}")
app/models/fraud_response.py (1)

1-1: μ‚¬μš©ν•˜μ§€ μ•ŠλŠ” import 제거

conintκ°€ importλ˜μ—ˆμ§€λ§Œ μ‚¬μš©λ˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

-from pydantic import BaseModel, conint
+from pydantic import BaseModel, Field, validator
app/prompts/fraud_example.py (1)

4-9: ν•„λ“œ 검증 및 λ¬Έμ„œν™” κ°œμ„ 

ν˜„μž¬ λͺ¨λ“  ν•„λ“œκ°€ κΈ°λ³Έ νƒ€μž…μœΌλ‘œλ§Œ μ •μ˜λ˜μ–΄ μžˆμ–΄ 검증이 λΆ€μ‘±ν•©λ‹ˆλ‹€. 특히 빈 κ°’μ΄λ‚˜ 잘λͺ»λœ 데이터에 λŒ€ν•œ μ²˜λ¦¬κ°€ ν•„μš”ν•©λ‹ˆλ‹€.

λ‹€μŒκ³Ό 같이 κ°œμ„ ν•  수 μžˆμŠ΅λ‹ˆλ‹€:

-from pydantic import BaseModel
+from pydantic import BaseModel, Field, validator
 from typing import List
 
 class FraudExample(BaseModel):
-    type_name: str
-    message_content: str
-    keywords: List[str]
-    additional_description: str
-    image_content: str
+    type_name: str = Field(..., min_length=1, description="사기 μœ ν˜•λͺ…")
+    message_content: str = Field(..., min_length=1, description="λ©”μ‹œμ§€ λ‚΄μš©")
+    keywords: List[str] = Field(..., min_items=1, description="ν‚€μ›Œλ“œ λͺ©λ‘")
+    additional_description: str = Field(default="", description="μΆ”κ°€ μ„€λͺ…")
+    image_content: str = Field(default="", description="이미지 λ‚΄μš©")
+    
+    @validator('type_name', 'message_content')
+    def validate_required_fields(cls, v):
+        if not v.strip():
+            raise ValueError('ν•„μˆ˜ ν•„λ“œλŠ” 빈 값일 수 μ—†μŠ΅λ‹ˆλ‹€')
+        return v.strip()
app/services/gpt_service.py (1)

6-8: OpenAI ν΄λΌμ΄μ–ΈνŠΈ 비동기 μ΄ˆκΈ°ν™” κ³ λ €

ν˜„μž¬ 동기 ν΄λΌμ΄μ–ΈνŠΈλ₯Ό μ‚¬μš©ν•˜κ³  μžˆμ§€λ§Œ, 비동기 ν•¨μˆ˜μ—μ„œ μ‚¬μš©ν•˜λ―€λ‘œ AsyncOpenAIλ₯Ό μ‚¬μš©ν•˜λŠ” 것이 더 μ μ ˆν•©λ‹ˆλ‹€.

-from openai import OpenAI, OpenAIError
+from openai import AsyncOpenAI, OpenAIError

-client = OpenAI(
+client = AsyncOpenAI(
     api_key = settings.gpt_api_key
     )
app/prompts/fraud_prompts.py (1)

10-10: λŒ€λŸ‰μ˜ μ˜ˆμ‹œ 데이터 처리 μ‹œ μ„±λŠ₯을 κ³ λ €ν•˜μ„Έμš”.

κΈ°λ³Έκ°’μœΌλ‘œ FRAUD_EXAMPLES 전체λ₯Ό μ‚¬μš©ν•˜κ³  μžˆλŠ”λ°, ν–₯ν›„ 60-70개 μ˜ˆμ‹œκ°€ λͺ¨λ‘ μΆ”κ°€λ˜λ©΄ 토큰 μ‚¬μš©λŸ‰μ΄ 크게 증가할 수 μžˆμŠ΅λ‹ˆλ‹€. PR λͺ©ν‘œμ—μ„œλ„ μ–ΈκΈ‰λœ μš°λ €μ‚¬ν•­μž…λ‹ˆλ‹€.

μ˜ˆμ‹œ 개수λ₯Ό μ œν•œν•˜λŠ” λ§€κ°œλ³€μˆ˜λ₯Ό μΆ”κ°€ν•˜λŠ” 것을 κ³ λ €ν•΄ λ³΄μ„Έμš”:

def get_fraud_detection_prompt(
    message_content: str,
    additional_description: str,
    keywords: List[str],
    image_content: str,
    examples: List[FraudExample] = FRAUD_EXAMPLES,
    max_examples: int = 10  # μ˜ˆμ‹œ 개수 μ œν•œ
) -> List[Dict[str, str]]:
    # μ˜ˆμ‹œ 개수 μ œν•œ 둜직 μΆ”κ°€
    limited_examples = examples[:max_examples] if max_examples else examples
πŸ“œ Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between db39166 and 218e02f.

πŸ“’ Files selected for processing (13)
  • .coderabbit/config.yml (1 hunks)
  • .github/workflows/deploy.yml (2 hunks)
  • app/api/fraud_analysis.py (1 hunks)
  • app/config/setting.py (1 hunks)
  • app/main.py (1 hunks)
  • app/models/fraud_request.py (1 hunks)
  • app/models/fraud_response.py (1 hunks)
  • app/prompts/data/fraud_examples.py (1 hunks)
  • app/prompts/fraud_example.py (1 hunks)
  • app/prompts/fraud_prompts.py (1 hunks)
  • app/routers/fraud_analysis.py (0 hunks)
  • app/services/gpt_service.py (1 hunks)
  • requirements.txt (1 hunks)
πŸ’€ Files with no reviewable changes (1)
  • app/routers/fraud_analysis.py
🧰 Additional context used
🧬 Code Graph Analysis (5)
app/main.py (1)
app/api/fraud_analysis.py (1)
  • fraud_analysis (13-20)
app/services/gpt_service.py (2)
app/models/fraud_request.py (1)
  • FraudRequest (4-8)
app/prompts/fraud_prompts.py (1)
  • get_fraud_detection_prompt (5-52)
app/prompts/data/fraud_examples.py (1)
app/prompts/fraud_example.py (1)
  • FraudExample (4-9)
app/api/fraud_analysis.py (3)
app/services/gpt_service.py (1)
  • call_gpt (10-32)
app/models/fraud_request.py (1)
  • FraudRequest (4-8)
app/models/fraud_response.py (1)
  • FraudResponse (4-8)
app/prompts/fraud_prompts.py (1)
app/prompts/fraud_example.py (1)
  • FraudExample (4-9)
πŸͺ› YAMLlint (1.37.1)
.coderabbit/config.yml

[error] 2-2: no new line character at the end of file

(new-line-at-end-of-file)

.github/workflows/deploy.yml

[error] 64-64: no new line character at the end of file

(new-line-at-end-of-file)

πŸͺ› Ruff (0.12.2)
app/services/gpt_service.py

28-28: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)

app/models/fraud_response.py

1-1: pydantic.conint imported but unused

Remove unused import: pydantic.conint

(F401)

app/api/fraud_analysis.py

20-20: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)

πŸͺ› GitHub Actions: CI/CD pipeline test
requirements.txt

[error] 4-4: pip install failed: No matching distribution found for click==8.2.1. The required version requires Python >=3.10 but the environment uses Python 3.9.

πŸ”‡ Additional comments (10)
app/main.py (2)

2-2: LGTM! λͺ¨λ“ˆ ꡬ쑰 κ°œμ„ μ΄ 잘 λ°˜μ˜λ˜μ—ˆμŠ΅λ‹ˆλ‹€.

app.routersμ—μ„œ app.api둜의 import 경둜 변경이 μƒˆλ‘œμš΄ ν”„λ‘œμ νŠΈ ꡬ쑰λ₯Ό 잘 λ°˜μ˜ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€.


7-7: LGTM! REST API λͺ…λͺ… κ·œμΉ™μ„ μ€€μˆ˜ν•©λ‹ˆλ‹€.

λΌμš°ν„° prefix와 tagμ—μ„œ μ–Έλ”μŠ€μ½”μ–΄λ₯Ό ν•˜μ΄ν”ˆμœΌλ‘œ λ³€κ²½ν•œ 것이 REST API λͺ¨λ²” 사둀λ₯Ό 잘 λ”°λ₯΄κ³  μžˆμŠ΅λ‹ˆλ‹€.

requirements.txt (1)

3-22: 검증 κ²°κ³Ό: λͺ¨λ“  μƒˆ νŒ¨ν‚€μ§€λŠ” Python 3.9와 ν˜Έν™˜λ©λ‹ˆλ‹€.

  • certifi
  • distro
  • dotenv
  • httpcore
  • httpx
  • jiter
  • openai
  • pydantic-settings
  • tqdm

μœ„ νŒ¨ν‚€μ§€λ“€ λͺ¨λ‘ Python 3.9μ—μ„œ μš”κ΅¬μ‚¬ν•­ 였λ₯˜ 없이 μ„€μΉ˜ κ°€λŠ₯함을 ν™•μΈν–ˆμŠ΅λ‹ˆλ‹€.
λ”°λΌμ„œ μΆ”κ°€ μ‘°μΉ˜λŠ” ν•„μš”ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

.github/workflows/deploy.yml (2)

17-17: LGTM! API ν‚€ λ³΄μ•ˆ μ²˜λ¦¬κ°€ μ μ ˆν•©λ‹ˆλ‹€.

GitHub Secretsλ₯Ό ν†΅ν•œ GPT API ν‚€ 관리가 λ³΄μ•ˆ λͺ¨λ²” 사둀λ₯Ό 잘 λ”°λ₯΄κ³  μžˆμŠ΅λ‹ˆλ‹€.


60-64: LGTM! Docker μ»¨ν…Œμ΄λ„ˆμ— ν™˜κ²½ λ³€μˆ˜ 전달이 μ˜¬λ°”λ¦…λ‹ˆλ‹€.

Docker run λͺ…λ Ήμ–΄μ—μ„œ ν™˜κ²½ λ³€μˆ˜λ₯Ό μ•ˆμ „ν•˜κ²Œ μ „λ‹¬ν•˜λŠ” 방식이 μ μ ˆν•©λ‹ˆλ‹€.

app/prompts/data/fraud_examples.py (2)

5-28: 사기 μ˜ˆμ‹œ 데이터 ꡬ쑰가 잘 μ„€κ³„λ˜μ—ˆμŠ΅λ‹ˆλ‹€.

각 사기 μœ ν˜•λ³„λ‘œ μ μ ˆν•œ μ˜ˆμ‹œ 데이터가 제곡되고 있으며, ν•œκ΅­μ–΄ μ»¨ν…μŠ€νŠΈμ— λ§žλŠ” ν˜„μ‹€μ μΈ 사기 μ‹œλ‚˜λ¦¬μ˜€λ₯Ό λ°˜μ˜ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€. ν‚€μ›Œλ“œμ™€ μΆ”κ°€ μ„€λͺ…이 ν”„λ‘¬ν”„νŠΈ μ—”μ§€λ‹ˆμ–΄λ§μ— μœ μš©ν•œ μ»¨ν…μŠ€νŠΈλ₯Ό μ œκ³΅ν•  κ²ƒμœΌλ‘œ λ³΄μž…λ‹ˆλ‹€.


27-27: 데이터 완성도 확인이 ν•„μš”ν•©λ‹ˆλ‹€.

μ£Όμ„μ—μ„œ μ–ΈκΈ‰λœ 18개 μœ ν˜• Γ— 34개 μ˜ˆμ‹œ (총 6070개 ν•­λͺ©)κ°€ 아직 μ™„μ„±λ˜μ§€ μ•Šμ€ μƒνƒœμž…λ‹ˆλ‹€.

전체 데이터셋 μ™„μ„± κ³„νšκ³Ό νƒ€μž„λΌμΈμ„ 확인해 μ£Όμ„Έμš”. ν˜„μž¬ 3개 μ˜ˆμ‹œλ§ŒμœΌλ‘œλŠ” GPT λͺ¨λΈμ˜ μ„±λŠ₯이 μ œν•œλ  수 μžˆμŠ΅λ‹ˆλ‹€.

app/prompts/fraud_prompts.py (3)

5-11: ν•¨μˆ˜ μ‹œκ·Έλ‹ˆμ²˜κ°€ 잘 μ„€κ³„λ˜μ—ˆμŠ΅λ‹ˆλ‹€.

λ§€κ°œλ³€μˆ˜ νƒ€μž… νžŒνŠΈμ™€ κΈ°λ³Έκ°’ 섀정이 μ μ ˆν•˜λ©°, λ°˜ν™˜ νƒ€μž…λ„ λͺ…ν™•ν•˜κ²Œ μ •μ˜λ˜μ–΄ μžˆμŠ΅λ‹ˆλ‹€.


13-28: μ‹œμŠ€ν…œ ν”„λ‘¬ν”„νŠΈκ°€ λͺ…ν™•ν•˜κ³  κ΅¬μ²΄μ μž…λ‹ˆλ‹€.

JSON 좜λ ₯ ν˜•μ‹μ„ λͺ…μ‹œν•˜κ³  ν•œκ΅­μ–΄λ‘œ λͺ…ν™•ν•œ μ§€μ‹œμ‚¬ν•­μ„ μ œκ³΅ν•˜κ³  μžˆμ–΄ GPT λͺ¨λΈμ΄ μΌκ΄€λœ 응닡을 생성할 수 μžˆμ„ κ²ƒμœΌλ‘œ λ³΄μž…λ‹ˆλ‹€.


54-68: μ˜ˆμ‹œ 데이터 ν¬λ§·νŒ… 둜직이 νš¨μœ¨μ μž…λ‹ˆλ‹€.

build_example_lines ν•¨μˆ˜κ°€ μ˜ˆμ‹œ 데이터λ₯Ό μΌκ΄€λœ ν˜•μ‹μœΌλ‘œ λ³€ν™˜ν•˜κ³  있으며, JSON μ˜ˆμ‹œλ„ ν¬ν•¨ν•˜μ—¬ λͺ¨λΈμ˜ 이해λ₯Ό 돕고 μžˆμŠ΅λ‹ˆλ‹€.

Comment on lines 14 to 20
try:
answer = await call_gpt(request)
response = FraudResponse.model_validate_json(answer)
return response

except Exception as e:
raise HTTPException(status_code=500, detail=f"사기뢄석 μ‹€νŒ¨: {e}")
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

μ˜ˆμ™Έ 처리 및 였λ₯˜ λ‘œκΉ… κ°œμ„  ν•„μš”

ν˜„μž¬ μ˜ˆμ™Έ μ²˜λ¦¬μ—μ„œ 원본 μ˜ˆμ™Έ 정보가 μ†μ‹€λ˜κ³ , λ‘œκΉ…μ΄ μ—†μ–΄ 디버깅이 μ–΄λ ΅μŠ΅λ‹ˆλ‹€. λ˜ν•œ JSON νŒŒμ‹± μ‹€νŒ¨μ™€ GPT API 호좜 μ‹€νŒ¨λ₯Ό κ΅¬λΆ„ν•˜μ—¬ μ²˜λ¦¬ν•˜λŠ” 것이 μ’‹μŠ΅λ‹ˆλ‹€.

λ‹€μŒκ³Ό 같이 κ°œμ„ ν•  수 μžˆμŠ΅λ‹ˆλ‹€:

+import logging
+
+logger = logging.getLogger(__name__)
+
 async def fraud_analysis(request: FraudRequest):
     try:
         answer = await call_gpt(request)
+        logger.info(f"GPT 응닡 μˆ˜μ‹ : {len(answer)} κΈ€μž")
+    except Exception as e:
+        logger.error(f"GPT API 호좜 μ‹€νŒ¨: {e}", exc_info=True)
+        raise HTTPException(status_code=500, detail=f"GPT API 호좜 μ‹€νŒ¨: {e}") from e
+    
+    try:
         response = FraudResponse.model_validate_json(answer)
         return response
-        
     except Exception as e:
-        raise HTTPException(status_code=500, detail=f"사기뢄석 μ‹€νŒ¨: {e}")
+        logger.error(f"응닡 νŒŒμ‹± μ‹€νŒ¨: {e}, 원본 응닡: {answer}", exc_info=True)
+        raise HTTPException(status_code=500, detail=f"응닡 νŒŒμ‹± μ‹€νŒ¨: {e}") from e
πŸ“ Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
try:
answer = await call_gpt(request)
response = FraudResponse.model_validate_json(answer)
return response
except Exception as e:
raise HTTPException(status_code=500, detail=f"사기뢄석 μ‹€νŒ¨: {e}")
import logging
logger = logging.getLogger(__name__)
async def fraud_analysis(request: FraudRequest):
try:
answer = await call_gpt(request)
logger.info(f"GPT 응닡 μˆ˜μ‹ : {len(answer)} κΈ€μž")
except Exception as e:
logger.error(f"GPT API 호좜 μ‹€νŒ¨: {e}", exc_info=True)
raise HTTPException(status_code=500, detail=f"GPT API 호좜 μ‹€νŒ¨: {e}") from e
try:
response = FraudResponse.model_validate_json(answer)
return response
except Exception as e:
logger.error(f"응닡 νŒŒμ‹± μ‹€νŒ¨: {e}, 원본 응닡: {answer}", exc_info=True)
raise HTTPException(status_code=500, detail=f"응닡 νŒŒμ‹± μ‹€νŒ¨: {e}") from e
🧰 Tools
πŸͺ› Ruff (0.12.2)

20-20: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)

πŸ€– Prompt for AI Agents
In app/api/fraud_analysis.py around lines 14 to 20, the current exception
handling loses the original error details and lacks logging, making debugging
difficult. Improve this by adding proper logging of the caught exceptions and
differentiate between JSON parsing errors and GPT API call failures using
separate except blocks. This will help provide clearer error context and
maintain the original exception information in the HTTPException detail.

from pydantic_settings import BaseSettings

class Settings(BaseSettings):
gpt_api_key: str
Copy link

Choose a reason for hiding this comment

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

πŸ› οΈ Refactor suggestion

API ν‚€ ν•„λ“œμ— λŒ€ν•œ 검증 κ°•ν™” ν•„μš”

API ν‚€λŠ” ν•„μˆ˜ ν•„λ“œμ΄λ―€λ‘œ λͺ…μ‹œμ μœΌλ‘œ μ„€μ •ν•˜κ³  기본값을 μ œκ±°ν•˜λŠ” 것이 μ’‹μŠ΅λ‹ˆλ‹€. λ˜ν•œ 빈 λ¬Έμžμ—΄ 검증도 μΆ”κ°€ν•΄μ•Ό ν•©λ‹ˆλ‹€.

λ‹€μŒκ³Ό 같이 κ°œμ„ ν•  수 μžˆμŠ΅λ‹ˆλ‹€:

+from pydantic import Field, validator
+
 class Settings(BaseSettings):
-    gpt_api_key: str
+    gpt_api_key: str = Field(..., min_length=1, description="OpenAI GPT API ν‚€")
+    
+    @validator('gpt_api_key')
+    def validate_api_key(cls, v):
+        if not v or not v.strip():
+            raise ValueError('API ν‚€λŠ” ν•„μˆ˜μž…λ‹ˆλ‹€')
+        return v.strip()
πŸ“ Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
gpt_api_key: str
from pydantic import Field, validator
class Settings(BaseSettings):
gpt_api_key: str = Field(..., min_length=1, description="OpenAI GPT API ν‚€")
@validator('gpt_api_key')
def validate_api_key(cls, v):
if not v or not v.strip():
raise ValueError('API ν‚€λŠ” ν•„μˆ˜μž…λ‹ˆλ‹€')
return v.strip()
πŸ€– Prompt for AI Agents
In app/config/setting.py at line 4, the gpt_api_key field currently lacks
validation and a default value. To fix this, explicitly mark gpt_api_key as a
required field without a default and add validation to ensure it is not an empty
string. This will enforce that the API key must be provided and cannot be empty.

Comment on lines 4 to 8
class FraudRequest(BaseModel):
messageContent: str
keywords: List[str]
additionalDescription: str
imageContent: str No newline at end of file
Copy link

Choose a reason for hiding this comment

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

πŸ› οΈ Refactor suggestion

ν•„λ“œ 검증 및 선택적 ν•„λ“œ κ³ λ €κ°€ ν•„μš”ν•©λ‹ˆλ‹€.

ν˜„μž¬ λͺ¨λ“  ν•„λ“œκ°€ ν•„μˆ˜λ‘œ μ„€μ •λ˜μ–΄ μžˆμ–΄ API μ‚¬μš©μ„±μ΄ μ œν•œλ  수 μžˆμŠ΅λ‹ˆλ‹€. 특히 additionalDescriptionκ³Ό imageContentλŠ” μ„ νƒμ μœΌλ‘œ λ§Œλ“œλŠ” 것을 κ³ λ €ν•΄λ³΄μ„Έμš”.

from pydantic import BaseModel
from typing import List
+from typing import Optional

class FraudRequest(BaseModel):
    messageContent: str
    keywords: List[str]
-    additionalDescription: str
-    imageContent: str
+    additionalDescription: Optional[str] = None
+    imageContent: Optional[str] = None
πŸ“ Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
class FraudRequest(BaseModel):
messageContent: str
keywords: List[str]
additionalDescription: str
imageContent: str
from pydantic import BaseModel
from typing import List
from typing import Optional
class FraudRequest(BaseModel):
messageContent: str
keywords: List[str]
additionalDescription: Optional[str] = None
imageContent: Optional[str] = None
πŸ€– Prompt for AI Agents
In app/models/fraud_request.py around lines 4 to 8, all fields in the
FraudRequest model are currently required, which limits API usability. Modify
the model to make additionalDescription and imageContent optional by using
typing.Optional and providing default values such as None. Also, consider adding
validation to ensure required fields are properly checked while allowing these
two fields to be omitted.

Comment on lines 4 to 8
class FraudResponse(BaseModel):
estimatedFraudType: str # λΆ„λ₯˜λœ 사기 μœ ν˜•
keywords: List[str] # μ£Όμš” μœ„ν—˜ ν‚€μ›Œλ“œ (μ΅œλŒ€ 3개)
explanation: str # ν•΄λ‹Ή μœ ν˜•μœΌλ‘œ νŒλ‹¨ν•œ 이유
score: float # μœ„ν—˜λ„(0~100) No newline at end of file
Copy link

Choose a reason for hiding this comment

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

πŸ› οΈ Refactor suggestion

ν•„λ“œ 검증 둜직 κ°•ν™” ν•„μš”

μ£Όμš” ν•„λ“œλ“€μ— λŒ€ν•œ 검증이 λΆ€μ‘±ν•©λ‹ˆλ‹€. 특히 scoreλŠ” 0-100 λ²”μœ„μ—¬μ•Ό ν•˜κ³ , keywordsλŠ” μ΅œλŒ€ 3개둜 μ œν•œλ˜μ–΄μ•Ό ν•©λ‹ˆλ‹€.

λ‹€μŒκ³Ό 같이 검증을 μΆ”κ°€ν•  수 μžˆμŠ΅λ‹ˆλ‹€:

 class FraudResponse(BaseModel):
     estimatedFraudType: str                  # λΆ„λ₯˜λœ 사기 μœ ν˜•
-    keywords: List[str]              # μ£Όμš” μœ„ν—˜ ν‚€μ›Œλ“œ (μ΅œλŒ€ 3개)
+    keywords: List[str] = Field(..., min_items=1, max_items=3, description="μ£Όμš” μœ„ν—˜ ν‚€μ›Œλ“œ (μ΅œλŒ€ 3개)")
     explanation: str                      # ν•΄λ‹Ή μœ ν˜•μœΌλ‘œ νŒλ‹¨ν•œ 이유
-    score: float                  # μœ„ν—˜λ„(0~100)
+    score: float = Field(..., ge=0, le=100, description="μœ„ν—˜λ„(0~100)")
+    
+    @validator('estimatedFraudType')
+    def validate_fraud_type(cls, v):
+        if not v.strip():
+            raise ValueError('사기 μœ ν˜•μ€ ν•„μˆ˜μž…λ‹ˆλ‹€')
+        return v.strip()
+    
+    @validator('explanation')
+    def validate_explanation(cls, v):
+        if not v.strip():
+            raise ValueError('μ„€λͺ…은 ν•„μˆ˜μž…λ‹ˆλ‹€')
+        return v.strip()
πŸ“ Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
class FraudResponse(BaseModel):
estimatedFraudType: str # λΆ„λ₯˜λœ 사기 μœ ν˜•
keywords: List[str] # μ£Όμš” μœ„ν—˜ ν‚€μ›Œλ“œ (μ΅œλŒ€ 3개)
explanation: str # ν•΄λ‹Ή μœ ν˜•μœΌλ‘œ νŒλ‹¨ν•œ 이유
score: float # μœ„ν—˜λ„(0~100)
class FraudResponse(BaseModel):
estimatedFraudType: str # λΆ„λ₯˜λœ 사기 μœ ν˜•
keywords: List[str] = Field(
...,
min_items=1,
max_items=3,
description="μ£Όμš” μœ„ν—˜ ν‚€μ›Œλ“œ (μ΅œλŒ€ 3개)"
)
explanation: str # ν•΄λ‹Ή μœ ν˜•μœΌλ‘œ νŒλ‹¨ν•œ 이유
score: float = Field(
...,
ge=0,
le=100,
description="μœ„ν—˜λ„(0~100)"
)
@validator('estimatedFraudType')
def validate_fraud_type(cls, v):
if not v.strip():
raise ValueError('사기 μœ ν˜•μ€ ν•„μˆ˜μž…λ‹ˆλ‹€')
return v.strip()
@validator('explanation')
def validate_explanation(cls, v):
if not v.strip():
raise ValueError('μ„€λͺ…은 ν•„μˆ˜μž…λ‹ˆλ‹€')
return v.strip()
πŸ€– Prompt for AI Agents
In app/models/fraud_response.py around lines 4 to 8, the FraudResponse model
lacks validation for key fields. Add validation to ensure the score field is
constrained between 0 and 100, and limit the keywords list to a maximum of 3
items. Use Pydantic validators or field constraints to enforce these rules,
raising appropriate errors if the conditions are not met.

Comment on lines 18 to 32
try:
response = client.responses.create(
model="gpt-4o-mini",
input = messages,
temperature = 0.5, # μƒμ„±λœ ν…μŠ€νŠΈμ˜ λ¬΄μž‘μœ„μ„±μ„ κ²°μ •
max_output_tokens = 200
)
print(response)

except OpenAIError as e:
raise RuntimeError(f"GPT API 호좜 μ‹€νŒ¨: {e}")
except Exception as e:
return f"μ„œλ²„ 였λ₯˜ λ°œμƒ: {e}"

return response.output_text.strip()
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

OpenAI API 호좜 방식 및 μ˜ˆμ™Έ 처리 μˆ˜μ • ν•„μš”

ν˜„μž¬ μ½”λ“œμ—μ„œ μ—¬λŸ¬ κ°€μ§€ μ€‘μš”ν•œ λ¬Έμ œκ°€ μžˆμŠ΅λ‹ˆλ‹€:

  1. client.responses.createλŠ” μ˜¬λ°”λ₯Έ OpenAI API λ©”μ„œλ“œκ°€ μ•„λ‹™λ‹ˆλ‹€
  2. 응닡 객체의 output_text 속성도 μ‘΄μž¬ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€
  3. μ˜ˆμ™Έ μ²˜λ¦¬μ—μ„œ 원본 μ˜ˆμ™Έ 정보가 μ†μ‹€λ©λ‹ˆλ‹€
  4. ν”„λ‘œλ•μ…˜ μ½”λ“œμ— λ””λ²„κΉ…μš© print문이 λ‚¨μ•„μžˆμŠ΅λ‹ˆλ‹€

λ‹€μŒκ³Ό 같이 μˆ˜μ •ν•΄μ•Ό ν•©λ‹ˆλ‹€:

+import logging
+
+logger = logging.getLogger(__name__)
+
 async def call_gpt(request: FraudRequest):
     messages = get_fraud_detection_prompt(
         message_content = request.messageContent, 
         additional_description = request.additionalDescription,
         keywords = request.keywords,
         image_content = request.imageContent
     )
     
     try:
-        response = client.responses.create(
+        response = await client.chat.completions.create(
             model="gpt-4o-mini",
-            input = messages,
+            messages=messages,
             temperature = 0.5, # μƒμ„±λœ ν…μŠ€νŠΈμ˜ λ¬΄μž‘μœ„μ„±μ„ κ²°μ •
-            max_output_tokens = 200
+            max_tokens=200
         )
-        print(response)
+        logger.info(f"GPT API 호좜 성곡, μ‚¬μš© 토큰: {response.usage}")
         
     except OpenAIError as e:
-        raise RuntimeError(f"GPT API 호좜 μ‹€νŒ¨: {e}")
+        logger.error(f"GPT API 호좜 μ‹€νŒ¨: {e}", exc_info=True)
+        raise RuntimeError(f"GPT API 호좜 μ‹€νŒ¨: {e}") from e
     except Exception as e:
-        return f"μ„œλ²„ 였λ₯˜ λ°œμƒ: {e}"
+        logger.error(f"μ˜ˆμƒμΉ˜ λͺ»ν•œ μ„œλ²„ 였λ₯˜: {e}", exc_info=True)
+        raise RuntimeError(f"μ„œλ²„ 였λ₯˜ λ°œμƒ: {e}") from e

-    return response.output_text.strip()
+    return response.choices[0].message.content.strip()
πŸ“ Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
try:
response = client.responses.create(
model="gpt-4o-mini",
input = messages,
temperature = 0.5, # μƒμ„±λœ ν…μŠ€νŠΈμ˜ λ¬΄μž‘μœ„μ„±μ„ κ²°μ •
max_output_tokens = 200
)
print(response)
except OpenAIError as e:
raise RuntimeError(f"GPT API 호좜 μ‹€νŒ¨: {e}")
except Exception as e:
return f"μ„œλ²„ 였λ₯˜ λ°œμƒ: {e}"
return response.output_text.strip()
import logging
logger = logging.getLogger(__name__)
async def call_gpt(request: FraudRequest):
messages = get_fraud_detection_prompt(
message_content=request.messageContent,
additional_description=request.additionalDescription,
keywords=request.keywords,
image_content=request.imageContent
)
try:
response = await client.chat.completions.create(
model="gpt-4o-mini",
messages=messages,
temperature=0.5, # μƒμ„±λœ ν…μŠ€νŠΈμ˜ λ¬΄μž‘μœ„μ„±μ„ κ²°μ •
max_tokens=200
)
logger.info(f"GPT API 호좜 성곡, μ‚¬μš© 토큰: {response.usage}")
except OpenAIError as e:
logger.error(f"GPT API 호좜 μ‹€νŒ¨: {e}", exc_info=True)
raise RuntimeError(f"GPT API 호좜 μ‹€νŒ¨: {e}") from e
except Exception as e:
logger.error(f"μ˜ˆμƒμΉ˜ λͺ»ν•œ μ„œλ²„ 였λ₯˜: {e}", exc_info=True)
raise RuntimeError(f"μ„œλ²„ 였λ₯˜ λ°œμƒ: {e}") from e
return response.choices[0].message.content.strip()
🧰 Tools
πŸͺ› Ruff (0.12.2)

28-28: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)

πŸ€– Prompt for AI Agents
In app/services/gpt_service.py around lines 18 to 32, the code incorrectly uses
client.responses.create which is not a valid OpenAI API method, and attempts to
access a non-existent output_text attribute on the response. Additionally, the
exception handling loses original error details and there is a leftover print
statement. To fix this, replace client.responses.create with the correct method
for chat completions (e.g., client.chat.completions.create), access the
generated text from the proper response field (like
response.choices[0].message.content), remove the print statement, and update
exception handling to preserve and propagate original error information
properly.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

πŸ“œ Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between 218e02f and 38b06f6.

πŸ“’ Files selected for processing (1)
  • requirements.txt (1 hunks)
πŸ”‡ Additional comments (1)
requirements.txt (1)

13-13: 이슈 μ—†μŒ: ꡬ버전 OpenAI API 호좜 νŒ¨ν„΄ 미발견
μ „μ—­ 검색 κ²°κ³Ό openai.ChatCompletion.create λ˜λŠ” openai.Completion.create 호좜이 λͺ¨λ‘ λ°œκ²¬λ˜μ§€ μ•Šμ•˜μŠ΅λ‹ˆλ‹€. λ”°λΌμ„œ 1.x API λ§ˆμ΄κ·Έλ ˆμ΄μ…˜μ΄ μ™„λ£Œλœ κ²ƒμœΌλ‘œ ν™•μΈλ©λ‹ˆλ‹€.

@chaeyuuu
Copy link
Contributor

μˆ˜κ³ ν•˜μ…¨μŠ΅λ‹ˆλ‹€.!! μ΅œλŒ€ν•œ 토큰 적게 μ“°λŠ” λ°©μ‹μœΌλ‘œ 잘 ν•™μŠ΅μ‹œν‚€λŠ” 방법을 μ°Ύμ•„λ΄μ•Όν• κ±°κ°™λ„€μœ΅..

@yeonju73 yeonju73 merged commit 4040389 into main Jul 26, 2025
3 checks passed
@yeonju73 yeonju73 deleted the feat/#8/connect-gpt-api branch July 26, 2025 11:17
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.

[Feat] GPT API μ—°κ²°

3 participants