Notice
Recent Posts
Recent Comments
Link
| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | |||
| 5 | 6 | 7 | 8 | 9 | 10 | 11 |
| 12 | 13 | 14 | 15 | 16 | 17 | 18 |
| 19 | 20 | 21 | 22 | 23 | 24 | 25 |
| 26 | 27 | 28 | 29 | 30 |
Tags
- springboot
- 게시판
- Spring
- docker
- mysql
- 코딩테스트
- llm
- OOM
- 우테코
- 프로그래머스
- spring boot
- Java
- 네팔
- 서버 꺼짐
- 부트스트랩
- 커밋 메시지
- 세션로그인
- cors
- 회고
- 알고리즘
- 프로젝트
- Dockerfile
- 로그인
- 해외봉사
- crud
- openAI
- LV2
- Lv.2
- fastapi
- 쿠키로그인
Archives
- Today
- Total
s00jin 님의 블로그
6. [FastAPI + OpenAI API] 사전 공부 | OpenAI API 입력에 따른 함수 호출(Function Calling) 본문
프로젝트/AI 분석 가계부
6. [FastAPI + OpenAI API] 사전 공부 | OpenAI API 입력에 따른 함수 호출(Function Calling)
s00jin 2025. 6. 26. 11:16api를 설계하면서 llm 쪽을 어떻게 설계할 지 고민했다.
우리의 챗봇 기능에는 크게
- 사용자 입력을 받아, 소비 내역으로 저장
- 사용자가 피드백을 원하면 피드백 반환
이렇게 있다.
처음에는 저 2개의 기능의 api 따로 설계했다. 하지만 생각해보니
챗봇 인터페이스에서 사용자와 대화하며 넘어오는 데이터들인데…이걸 따로 분리하는게 맞나..?라는 생각이 들었다.
그래서 사용자 입력
→ llm이 1차적으로 소비 내역인지 피드백 반환인지 구분
→ 소비 내역이라면 함수 호출로 구조화 된 출력 반환 / 피드백이면 피드백 반환
위 흐름으로 다시 구현해봤다.
구현 코드
from openai import OpenAI
import os
import json
from datetime import datetime
from typing import Union
from pydantic import BaseModel
from fastapi import FastAPI, HTTPException
client = OpenAI(
api_key=os.environ.get("OPENAI_API_KEY")
)
class ChatRequest(BaseModel):
userId: int
message: str
class ExpenseData(BaseModel):
category: str
amount: int
date: str
class ChatResponse(BaseModel):
type: str
reply: str
data: Union[ExpenseData, None] = None
tools = [{
"type": "function",
"function": {
"name": "save_expense",
"description": "사용자의 소비 내역을 파싱하여 금액과 카테고리, 날짜를 저장",
"parameters": {
"type": "object",
"properties": {
"category": {
"type": "string",
"enum": ["카페", "식비", "교통", "의류", "문화", "공과금", "기타"],
"description": "정해진 소비 카테고리 중 하나"
},
"amount": {
"type": "integer",
"description": "금액 (숫자만, 원단위)"
},
"date": {
"type": "string",
"description": "소비한 날짜"
}
},
"required": ["category", "amount", "date"],
"additionalProperties": False
}
},
"strict": True
}]
def handle_message(message: str):
today = datetime.today().strftime("%Y-%m-%d")
response = client.chat.completions.create(
model="gpt-4.1-nano",
messages=[
{"role": "system", "content": f"""너는 사용자 소비 내역을 정리해주는 가계부 어시스턴트야.
오늘 날짜는 {today}야.
만약 사용자가 '오늘', '어제', '그제' 같은 말을 하면 이를 기준으로 정확한 날짜(YYY-MM-DD)로 바꿔줘.
소비 내역을 말하면 카테고리와 금액, 날짜를 파싱해서 JSON 형태로 반환해주고,
일반적인 질문이나 조언 요청이면 텍스트로 피드백을 반환해줘."""},
{"role": "user", "content": message}
],
tools=tools,
tool_choice="auto"
)
msg = response.choices[0].message
# 함수 호출이 있는 경우
if msg.tool_calls:
args = json.loads(msg.tool_calls[0].function.arguments)
return {
"type":"expense",
"reply": f"{args['category']} 카테고리로 {args['amount']}원을 기록했어요.",
"data": {
"category": args["category"],
"amount": args["amount"],
"date": args["date"]
}
}
else:
return {
"type":"feedback",
"reply": msg.content
}
# # 함수 코드 실행 - 모델의 응답을 구문 분석하고 함수 호출을 처리
# tool_call = response.choices[0].message.tool_calls[0]
# args = json.loads(tool_call.function.arguments)
# print(args)
API 테스트

결과가 잘 나온다.
(피드백 결과가 나온 스크린샷을 실수로 삭제했다...ㅎ)
'프로젝트 > AI 분석 가계부' 카테고리의 다른 글
| 7. [회고] 프로젝트 마무리 (1) | 2025.07.07 |
|---|---|
| 5. [FastAPI + OpenAI API] 사전 공부 | 날짜 출력 오류 문제 해결 (0) | 2025.06.26 |
| 4. [FastAPI + OpenAI API] 사전 공부 | OpenAI API 구조화된 출력 (1) | 2025.06.26 |
| 3. [FastAPI + OpenAI API] 사전 공부 | OpenAI API 연결 (1) | 2025.06.23 |
| 2. [FastAPI + OpenAI API] 사전 공부 | 가상환경 구축 및 서버 테스트 (1) | 2025.06.23 |