Skip to content

Commit dc96a25

Browse files
committed
Qdrant vector search 지원 (Datahub glossary and query examples)
1 parent 3f9ac68 commit dc96a25

File tree

5 files changed

+226
-93
lines changed

5 files changed

+226
-93
lines changed

utils/llm/chatbot/guidelines.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,13 @@ def search_database_tables_tool(ctx: Dict[str, Any]) -> str:
1818

1919

2020
def get_glossary_terms_tool(ctx: Dict[str, Any]) -> str:
21-
gms_server = ctx.get("gms_server", "http://localhost:8080")
22-
return str(get_glossary_terms.invoke({"gms_server": gms_server}))
21+
query = ctx.get("query") or ctx.get("last_user_message", "")
22+
return str(get_glossary_terms.invoke({"query": query}))
2323

2424

2525
def get_query_examples_tool(ctx: Dict[str, Any]) -> str:
26-
gms_server = ctx.get("gms_server", "http://localhost:8080")
27-
return str(get_query_examples.invoke({"gms_server": gms_server}))
26+
query = ctx.get("query") or ctx.get("last_user_message", "")
27+
return str(get_query_examples.invoke({"query": query}))
2828

2929

3030
GUIDELINES: List[Guideline] = [

utils/llm/retrieval.py

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
from transformers import AutoModelForSequenceClassification, AutoTokenizer
77

88
from utils.llm.vectordb import get_vector_db
9+
from utils.llm.tools.datahub import get_glossary_vector_data, get_query_vector_data
10+
from utils.llm.core import get_embeddings
911

1012

1113
def load_reranker_model(device: str = "cpu"):
@@ -102,3 +104,86 @@ def search_tables(
102104
}
103105

104106
return documents_dict
107+
108+
109+
def _prepare_vector_data(data_fetcher, text_fields):
110+
"""
111+
데이터를 가져와서 임베딩을 생성하는 헬퍼 함수
112+
"""
113+
points = data_fetcher()
114+
embeddings = get_embeddings()
115+
116+
for point in points:
117+
payload = point["payload"]
118+
# 텍스트 필드들을 결합하여 임베딩 생성
119+
text_to_embed = " ".join([str(payload.get(field, "")) for field in text_fields])
120+
vector = embeddings.embed_query(text_to_embed)
121+
point["vector"] = {"dense": vector}
122+
123+
return points
124+
125+
126+
def search_glossary(query: str, force_update: bool = False, top_n: int = 5) -> list:
127+
"""
128+
용어집 검색 함수
129+
"""
130+
collection_name = "lang2sql_glossary"
131+
db = get_vector_db()
132+
133+
# 데이터 로더 정의 (임베딩 생성 포함)
134+
def data_loader():
135+
return _prepare_vector_data(get_glossary_vector_data, ["name", "description"])
136+
137+
# 컬렉션 초기화 (필요시)
138+
db.initialize_collection_if_empty(
139+
collection_name=collection_name,
140+
force_update=force_update,
141+
data_loader=data_loader,
142+
)
143+
144+
# 검색 수행
145+
embeddings = get_embeddings()
146+
query_vector = embeddings.embed_query(query)
147+
148+
results = db.search(
149+
collection_name=collection_name,
150+
query_vector=("dense", query_vector),
151+
limit=top_n,
152+
)
153+
154+
# 결과 포맷팅
155+
return [res.payload for res in results]
156+
157+
158+
def search_query_examples(
159+
query: str, force_update: bool = False, top_n: int = 5
160+
) -> list:
161+
"""
162+
쿼리 예제 검색 함수
163+
"""
164+
collection_name = "lang2sql_query_example"
165+
db = get_vector_db()
166+
167+
# 데이터 로더 정의 (임베딩 생성 포함)
168+
def data_loader():
169+
return _prepare_vector_data(get_query_vector_data, ["name", "description"])
170+
171+
# 컬렉션 초기화 (필요시)
172+
db.initialize_collection_if_empty(
173+
collection_name=collection_name,
174+
force_update=force_update,
175+
data_loader=data_loader,
176+
)
177+
178+
# 검색 수행
179+
embeddings = get_embeddings()
180+
query_vector = embeddings.embed_query(query)
181+
182+
results = db.search(
183+
collection_name=collection_name,
184+
query_vector=("dense", query_vector),
185+
limit=top_n,
186+
)
187+
188+
# 결과 포맷팅
189+
return [res.payload for res in results]

utils/llm/tools/chatbot_tool.py

Lines changed: 27 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from utils.data.datahub_services.base_client import DataHubBaseClient
77
from utils.data.datahub_services.glossary_service import GlossaryService
88
from utils.data.datahub_services.query_service import QueryService
9+
from utils.llm.retrieval import search_glossary, search_query_examples
910

1011

1112
@tool
@@ -105,11 +106,11 @@ def _simplify_glossary_data(glossary_data):
105106

106107

107108
@tool
108-
def get_glossary_terms(gms_server: str = "http://35.222.65.99:8080") -> list:
109+
def get_glossary_terms(query: str, force_update: bool = False) -> list:
109110
"""
110-
DataHub에서 용어집(Glossary) 정보를 조회합니다.
111+
DataHub에서 용어집(Glossary) 정보를 검색합니다.
111112
112-
이 함수는 DataHub 서버에 연결하여 전체 용어집 데이터를 가져옵니다.
113+
이 함수는 사용자의 질문과 관련된 용어 정의를 찾기 위해 Vector Search를 수행합니다.
113114
용어집은 비즈니스 용어, 도메인 지식, 데이터 정의 등을 표준화하여 관리하는 곳입니다.
114115
115116
**중요**: 사용자의 질문이나 대화에서 다음과 같은 상황이 발생하면 반드시 이 도구를 사용하세요:
@@ -120,40 +121,26 @@ def get_glossary_terms(gms_server: str = "http://35.222.65.99:8080") -> list:
120121
5. 표준 정의가 필요한 비즈니스 용어가 나왔을 때
121122
122123
Args:
123-
gms_server (str, optional): DataHub GMS 서버 URL입니다.
124-
기본값은 "http://35.222.65.99:8080"
124+
query (str): 검색할 용어 또는 관련 질문입니다.
125+
force_update (bool, optional): True일 경우 데이터를 새로고침하여 검색 인덱스를 재생성합니다. 기본값은 False.
125126
126127
Returns:
127-
list: 간소화된 용어집 데이터 리스트입니다.
128-
각 항목은 name, description, children(선택적) 필드를 포함합니다.
128+
list: 검색된 용어집 데이터 리스트입니다.
129+
각 항목은 name, description 등을 포함합니다.
129130
130131
예시 형태:
131132
[
132133
{
133134
"name": "가짜연구소",
134135
"description": "스터디 단체 가짜연구소를 의미하며...",
135-
"children": [
136-
{
137-
"name": "빌더",
138-
"description": "가짜연구소 스터디 리더를 지칭..."
139-
}
140-
]
136+
"type": "term"
141137
},
142-
{
143-
"name": "PII",
144-
"description": "개인 식별 정보...",
145-
"children": [
146-
{
147-
"name": "identifier",
148-
"description": "개인식별정보중 github 아이디..."
149-
}
150-
]
151-
}
138+
...
152139
]
153140
154141
Examples:
155-
>>> get_glossary_terms()
156-
[{'name': '가짜연구소', 'description': '...', 'children': [...]}]
142+
>>> get_glossary_terms("PII가 뭐야?")
143+
[{'name': 'PII', 'description': '개인 식별 정보...', ...}]
157144
158145
Note:
159146
이 도구는 다음과 같은 경우에 **반드시** 사용하세요:
@@ -178,37 +165,22 @@ def get_glossary_terms(gms_server: str = "http://35.222.65.99:8080") -> list:
178165
있는지 확인하고, 있다면 먼저 이 도구를 호출하여 정확한 정의를 파악하세요.
179166
"""
180167
try:
181-
# DataHub 클라이언트 초기화
182-
client = DataHubBaseClient(gms_server=gms_server)
183-
184-
# GlossaryService 초기화
185-
glossary_service = GlossaryService(client)
186-
187-
# 전체 용어집 데이터 가져오기
188-
glossary_data = glossary_service.get_glossary_data()
168+
return search_glossary(query=query, force_update=force_update)
189169

190-
# 간소화된 데이터 반환
191-
simplified_data = _simplify_glossary_data(glossary_data)
192-
193-
return simplified_data
194-
195-
except ValueError as e:
196-
return {"error": True, "message": f"DataHub 서버 연결 실패: {str(e)}"}
197170
except Exception as e:
198171
return {"error": True, "message": f"용어집 조회 중 오류 발생: {str(e)}"}
199172

200173

201174
@tool
202175
def get_query_examples(
203-
gms_server: str = "http://35.222.65.99:8080",
204-
start: int = 0,
205-
count: int = 10,
206-
query: str = "*",
176+
query: str,
177+
force_update: bool = False,
178+
count: int = 5,
207179
) -> list:
208180
"""
209-
DataHub에서 저장된 쿼리 예제들을 조회합니다.
181+
DataHub에서 저장된 쿼리 예제들을 검색합니다.
210182
211-
이 함수는 DataHub 서버에 연결하여 저장된 SQL 쿼리 목록을 가져옵니다.
183+
이 함수는 사용자의 질문과 관련된 SQL 쿼리 예제를 찾기 위해 Vector Search를 수행합니다.
212184
조직에서 실제로 사용되고 검증된 쿼리 패턴을 참고하여 더 정확한 SQL을 생성할 수 있습니다.
213185
214186
**중요**: 사용자의 질문이나 대화에서 다음과 같은 상황이 발생하면 반드시 이 도구를 사용하세요:
@@ -220,11 +192,9 @@ def get_query_examples(
220192
6. 조직 내에서 검증된 쿼리 작성 방식을 확인해야 할 때
221193
222194
Args:
223-
gms_server (str, optional): DataHub GMS 서버 URL입니다.
224-
기본값은 "http://35.222.65.99:8080"
225-
start (int, optional): 조회 시작 위치입니다. 기본값은 0
226-
count (int, optional): 조회할 쿼리 개수입니다. 기본값은 10
227-
query (str, optional): 검색 쿼리입니다. 기본값은 "*" (모든 쿼리)
195+
query (str): 검색할 쿼리 관련 질문이나 키워드입니다.
196+
force_update (bool, optional): True일 경우 데이터를 새로고침하여 검색 인덱스를 재생성합니다. 기본값은 False.
197+
count (int, optional): 반환할 검색 결과 개수입니다. 기본값은 5.
228198
229199
Returns:
230200
list: 쿼리 정보 리스트입니다.
@@ -237,19 +207,12 @@ def get_query_examples(
237207
"description": "각 고객별 주문 건수를 집계하는 쿼리",
238208
"statement": "SELECT customer_id, COUNT(*) as order_count FROM orders GROUP BY customer_id"
239209
},
240-
{
241-
"name": "월별 매출 현황",
242-
"description": "월별 총 매출을 계산하는 쿼리",
243-
"statement": "SELECT DATE_TRUNC('month', order_date) as month, SUM(amount) FROM orders GROUP BY month"
244-
}
210+
...
245211
]
246212
247213
Examples:
248-
>>> get_query_examples()
249-
[{'name': '고객별 주문 수 조회', 'description': '...', 'statement': 'SELECT ...'}]
250-
251-
>>> get_query_examples(count=5)
252-
# 5개의 쿼리 예제만 조회
214+
>>> get_query_examples("매출 집계 쿼리 보여줘")
215+
[{'name': '월별 매출 현황', 'description': '...', 'statement': 'SELECT ...'}]
253216
254217
Note:
255218
이 도구는 다음과 같은 경우에 **반드시** 사용하세요:
@@ -280,33 +243,10 @@ def get_query_examples(
280243
SQL을 생성하는 데 큰 도움이 됩니다.
281244
"""
282245
try:
283-
# DataHub 클라이언트 초기화
284-
client = DataHubBaseClient(gms_server=gms_server)
285-
286-
# QueryService 초기화
287-
query_service = QueryService(client)
288-
289-
# 쿼리 데이터 가져오기
290-
result = query_service.get_query_data(start=start, count=count, query=query)
291-
292-
# 오류 체크
293-
if "error" in result and result["error"]:
294-
return {"error": True, "message": result.get("message")}
295-
296-
# name, description, statement만 추출하여 리스트 생성
297-
simplified_queries = []
298-
for query_item in result.get("queries", []):
299-
simplified_query = {
300-
"name": query_item.get("name"),
301-
"description": query_item.get("description", ""),
302-
"statement": query_item.get("statement", ""),
303-
}
304-
simplified_queries.append(simplified_query)
305-
306-
return simplified_queries
246+
return search_query_examples(
247+
query=query, force_update=force_update, top_n=count
248+
)
307249

308-
except ValueError as e:
309-
return {"error": True, "message": f"DataHub 서버 연결 실패: {str(e)}"}
310250
except Exception as e:
311251
return {
312252
"error": True,

0 commit comments

Comments
 (0)