Skip to content

Commit 7d8a108

Browse files
committed
챗봇 tool 로 search_database_tables 추가
1 parent 87feb63 commit 7d8a108

File tree

4 files changed

+166
-70
lines changed

4 files changed

+166
-70
lines changed

utils/llm/chatbot.py

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,16 @@
44
"""
55

66
from langchain_openai import ChatOpenAI
7+
from langchain_core.messages import SystemMessage
78
from langgraph.checkpoint.memory import MemorySaver
89
from langgraph.graph import START, MessagesState, StateGraph
910
from langgraph.prebuilt import ToolNode
1011

11-
from utils.llm.tools import get_weather, get_famous_opensource
12+
from utils.llm.tools import (
13+
get_weather,
14+
get_famous_opensource,
15+
search_database_tables,
16+
)
1217

1318

1419
class ChatBot:
@@ -36,7 +41,12 @@ def __init__(self, openai_api_key: str, model_name: str = "gpt-4o-mini"):
3641
"""
3742
self.openai_api_key = openai_api_key
3843
self.model_name = model_name
39-
self.tools = [get_weather, get_famous_opensource] # 사용 가능한 tool 목록
44+
# SQL 생성을 위한 데이터베이스 메타데이터 조회 도구
45+
self.tools = [
46+
search_database_tables, # 데이터베이스 테이블 정보 검색
47+
get_weather, # 테스트용 도구 (추후 제거 가능)
48+
get_famous_opensource, # 테스트용 도구 (추후 제거 가능)
49+
]
4050
self.llm = self._setup_llm() # LLM 인스턴스 설정
4151
self.app = self._setup_workflow() # LangGraph 워크플로우 설정
4252

@@ -49,7 +59,7 @@ def _setup_llm(self):
4959
ChatOpenAI: Tool이 바인딩된 LLM 인스턴스
5060
"""
5161
llm = ChatOpenAI(
52-
temperature=0.1, # 응답의 일관성을 위해 낮은 temperature 설정
62+
temperature=0.0, # SQL 생성은 정확성이 중요하므로 0으로 설정
5363
openai_api_key=self.openai_api_key,
5464
model_name=self.model_name,
5565
)
@@ -79,8 +89,33 @@ def call_model(state: MessagesState):
7989
Returns:
8090
dict: LLM 응답이 포함된 상태 업데이트
8191
"""
82-
# sys_msg = SystemMessage(content="You are a helpful assistant ")
83-
response = self.llm.invoke(state["messages"])
92+
# SQL 생성 전문 어시스턴트 시스템 메시지
93+
sys_msg = SystemMessage(
94+
content="""# 역할
95+
당신은 사용자가 SQL 쿼리를 생성하도록 돕는 전문 AI 어시스턴트입니다.
96+
97+
# 주요 임무
98+
- 사용자의 자연어 질문을 이해하고 SQL 쿼리 생성에 필요한 정보를 파악합니다
99+
- 필요한 경우 데이터베이스 스키마나 메타데이터를 확인하기 위해 도구를 활용합니다
100+
- 단계별로 사용자와 대화하며 명확한 SQL 쿼리를 만들어갑니다
101+
- 생성된 SQL에 대해 이해하기 쉽게 설명합니다
102+
103+
# 작업 프로세스
104+
1. 사용자의 의도를 명확히 파악
105+
2. 필요한 테이블/컬럼 정보 확인 (도구 사용)
106+
3. 사용자의 질문을 바탕으로 정보를 추출할 수 있는 명확한 질문으로 변환합니다
107+
108+
# 주의사항
109+
- 항상 친절하고 명확하게 대화합니다
110+
- 이전 대화 맥락을 고려하여 일관성 있게 응답합니다
111+
- 사용자가 SQL을 이해할 수 있도록 단계별로 설명합니다
112+
113+
---
114+
다음은 사용자와의 대화입니다:"""
115+
)
116+
# 시스템 메시지를 대화의 맨 앞에 추가
117+
messages = [sys_msg] + state["messages"]
118+
response = self.llm.invoke(messages)
84119
return {"messages": response}
85120

86121
def route_model_output(state: MessagesState):

utils/llm/tools/__init__.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,17 @@
44
set_gms_server,
55
)
66

7-
from utils.llm.tools.test import get_weather, get_famous_opensource
7+
from utils.llm.tools.chatbot_tool import (
8+
get_weather,
9+
get_famous_opensource,
10+
search_database_tables,
11+
)
812

913
__all__ = [
1014
"set_gms_server",
1115
"get_info_from_db",
1216
"get_metadata_from_db",
1317
"get_weather",
1418
"get_famous_opensource",
19+
"search_database_tables",
1520
]

utils/llm/tools/chatbot_tool.py

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
"""
2+
LangGraph ChatBot에서 사용하는 도구(Tool) 함수들
3+
"""
4+
5+
from langchain_core.tools import tool
6+
from utils.llm.retrieval import search_tables
7+
8+
9+
@tool
10+
def get_weather(city: str) -> str:
11+
"""
12+
특정 도시의 현재 날씨 정보를 조회합니다.
13+
14+
이 함수는 도시 이름을 입력받아 해당 도시의 날씨 정보를 반환합니다.
15+
사용자가 날씨, 기상, weather 등의 키워드와 함께 도시 이름을 언급하면 이 도구를 사용하세요.
16+
17+
Args:
18+
city (str): 날씨를 확인하고 싶은 도시의 이름입니다.
19+
예: "Seoul", "New York", "Tokyo", "서울", "부산" 등
20+
영문과 한글 도시명을 모두 지원합니다.
21+
22+
Returns:
23+
str: 해당 도시의 날씨 정보를 담은 문자열입니다.
24+
현재는 항상 맑은 날씨를 반환합니다.
25+
26+
Examples:
27+
>>> get_weather("Seoul")
28+
'Seoul is sunny'
29+
30+
>>> get_weather("서울")
31+
'서울 is sunny'
32+
33+
Note:
34+
이 도구는 다음과 같은 경우에 사용하세요:
35+
- "서울 날씨 어때?"
36+
- "What's the weather in New York?"
37+
- "도쿄의 날씨를 알려줘"
38+
- "부산 날씨 확인해줘"
39+
"""
40+
return f"{city} is sunny"
41+
42+
43+
@tool
44+
def get_famous_opensource() -> str:
45+
"""
46+
가장 유명한 오픈소스 프로젝트를 조회합니다.
47+
48+
이 함수는 현재 가장 유명한 오픈소스 프로젝트의 이름을 반환합니다.
49+
사용자가 유명한 오픈소스, 인기있는 오픈소스, 최고의 오픈소스 등을 물어보면 이 도구를 사용하세요.
50+
51+
Returns:
52+
str: 가장 유명한 오픈소스 프로젝트 이름
53+
54+
Examples:
55+
>>> get_famous_opensource()
56+
'Lang2SQL'
57+
58+
Note:
59+
이 도구는 다음과 같은 경우에 사용하세요:
60+
- "제일 유명한 오픈소스가 뭐야?"
61+
- "가장 인기있는 오픈소스는?"
62+
- "최고의 오픈소스 프로젝트 알려줘"
63+
- "유명한 오픈소스 추천해줘"
64+
"""
65+
return "Lang2SQL"
66+
67+
68+
@tool
69+
def search_database_tables(
70+
query: str, retriever_name: str = "기본", top_n: int = 5, device: str = "cpu"
71+
) -> dict:
72+
"""
73+
사용자의 자연어 쿼리를 기반으로 관련된 데이터베이스 테이블 정보를 검색합니다.
74+
75+
이 함수는 SQL 쿼리 생성을 위해 필요한 테이블과 컬럼 정보를 찾아줍니다.
76+
사용자가 어떤 테이블을 사용해야 할지, 어떤 컬럼이 있는지 물어보거나,
77+
SQL 쿼리를 만들기 위한 스키마 정보가 필요할 때 이 도구를 사용하세요.
78+
79+
Args:
80+
query (str): 검색하려는 자연어 질문입니다.
81+
예: "고객 정보를 조회하려면?", "주문 관련 테이블"
82+
retriever_name (str, optional): 검색기 유형입니다.
83+
"기본" 또는 "Reranker" 중 선택. 기본값은 "기본"
84+
top_n (int, optional): 검색할 테이블 개수입니다. 기본값은 5개
85+
device (str, optional): 모델 실행 장치입니다. "cpu" 또는 "cuda". 기본값은 "cpu"
86+
87+
Returns:
88+
dict: 테이블 정보가 담긴 딕셔너리입니다.
89+
각 테이블은 키로 저장되며, 값으로 테이블 설명과 컬럼 정보를 포함합니다.
90+
91+
예시 형태:
92+
{
93+
"customers": {
94+
"table_description": "고객 정보 테이블",
95+
"customer_id": "고객 고유 ID",
96+
"name": "고객 이름",
97+
"email": "고객 이메일"
98+
},
99+
"orders": {
100+
"table_description": "주문 정보 테이블",
101+
"order_id": "주문 ID",
102+
"customer_id": "고객 ID (외래키)"
103+
}
104+
}
105+
106+
Examples:
107+
>>> search_database_tables("고객 정보가 필요해")
108+
{'customers': {'table_description': '고객 정보 테이블', ...}}
109+
110+
Note:
111+
이 도구는 다음과 같은 경우에 사용하세요:
112+
- "어떤 테이블을 사용해야 해?"
113+
- "고객 관련 테이블 정보를 알려줘"
114+
- "주문 데이터는 어디에 있어?"
115+
- "사용 가능한 컬럼을 보여줘"
116+
- SQL 쿼리를 생성하기 전에 스키마 정보가 필요할 때
117+
"""
118+
return search_tables(
119+
query=query, retriever_name=retriever_name, top_n=top_n, device=device
120+
)

utils/llm/tools/test.py

Lines changed: 0 additions & 64 deletions
This file was deleted.

0 commit comments

Comments
 (0)