Skip to content

Commit ce6e423

Browse files
committed
feat: 쿼리 및 용어집 정보 추가 및 관련 메시지 수정
- 사용 가능한 테이블 및 컬럼 정보에 예시 쿼리와 용어집 정보를 포함하도록 메시지 수정 - 테이블 정보 검색 기능에서 쿼리 및 용어집 정보를 섹션별로 추출하여 저장하는 로직 추가 - 데이터베이스 정보와 함께 쿼리 및 용어집 정보를 반환하도록 개선
1 parent 97a4f77 commit ce6e423

File tree

3 files changed

+150
-10
lines changed

3 files changed

+150
-10
lines changed

llm_utils/chains.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ def create_query_refiner_chain(llm):
3131
SystemMessagePromptTemplate.from_template(prompt),
3232
MessagesPlaceholder(variable_name="user_input"),
3333
SystemMessagePromptTemplate.from_template(
34-
"다음은 사용자의 실제 사용 가능한 테이블 및 컬럼 정보입니다:"
34+
"다음은 사용자의 실제 사용 가능한 테이블 및 컬럼 정보 와 예시쿼리 및 용어집 정보입니다:"
3535
),
3636
MessagesPlaceholder(variable_name="searched_tables"),
3737
SystemMessagePromptTemplate.from_template(
@@ -63,7 +63,7 @@ def create_query_maker_chain(llm):
6363
MessagesPlaceholder(variable_name="refined_input"),
6464
(
6565
"system",
66-
"다음은 사용자의 db 환경정보와 사용 가능한 테이블 및 컬럼 정보입니다:",
66+
"다음은 사용자의 db 환경정보와 사용 가능한 테이블 및 컬럼 정보 와 예시쿼리 및 용어집 정보입니다:",
6767
),
6868
MessagesPlaceholder(variable_name="user_database_env"),
6969
MessagesPlaceholder(variable_name="searched_tables"),
@@ -84,7 +84,7 @@ def create_query_refiner_with_profile_chain(llm):
8484
SystemMessagePromptTemplate.from_template(prompt),
8585
MessagesPlaceholder(variable_name="user_input"),
8686
SystemMessagePromptTemplate.from_template(
87-
"다음은 사용자의 실제 사용 가능한 테이블 및 컬럼 정보입니다:"
87+
"다음은 사용자의 실제 사용 가능한 테이블 및 컬럼 정보 와 예시쿼리 및 용어집 정보입니다:"
8888
),
8989
MessagesPlaceholder(variable_name="searched_tables"),
9090
# 프로파일 정보 입력

llm_utils/retrieval.py

Lines changed: 67 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -97,18 +97,79 @@ def search_tables(
9797
# 테이블명 및 설명 추출
9898
table_name, table_desc = lines[0].split(": ", 1)
9999

100-
# 컬럼 정보 추출
100+
# 섹션별로 정보 추출
101101
columns = {}
102-
if len(lines) > 2 and lines[1].strip() == "Columns:":
103-
for line in lines[2:]:
104-
if ": " in line:
105-
col_name, col_desc = line.split(": ", 1)
106-
columns[col_name.strip()] = col_desc.strip()
102+
queries = []
103+
terms = []
104+
105+
current_section = None
106+
current_query = {}
107+
current_term = {}
108+
109+
for i, line in enumerate(lines[1:], 1):
110+
line = line.strip()
111+
112+
# 섹션 헤더 확인
113+
if line == "Columns:":
114+
current_section = "columns"
115+
continue
116+
elif line == "Queries:":
117+
current_section = "queries"
118+
continue
119+
elif line == "Terms:":
120+
current_section = "terms"
121+
continue
122+
123+
# 각 섹션의 내용 파싱
124+
if current_section == "columns" and ": " in line:
125+
col_name, col_desc = line.split(": ", 1)
126+
columns[col_name.strip()] = col_desc.strip()
127+
128+
elif current_section == "queries" and line and line != "No queries":
129+
# 쿼리 구분자 확인
130+
if line == "---":
131+
# 이전 쿼리 저장
132+
if current_query:
133+
queries.append(current_query)
134+
current_query = {}
135+
elif line.startswith("Name: "):
136+
# 이전 쿼리가 있다면 저장
137+
if current_query:
138+
queries.append(current_query)
139+
current_query = {"name": line[6:]} # "Name: " 제거
140+
elif line.startswith("Description: "):
141+
if current_query:
142+
current_query["description"] = line[13:] # "Description: " 제거
143+
elif line.startswith("Query: "):
144+
if current_query:
145+
current_query["statement"] = line[7:] # "Query: " 제거
146+
147+
elif current_section == "terms" and line and line != "No terms":
148+
if line.startswith("Term: "):
149+
# 이전 용어가 있다면 저장
150+
if current_term:
151+
terms.append(current_term)
152+
# 새로운 용어 시작
153+
current_term = {"name": line[6:]} # "Term: " 제거
154+
elif line.startswith("Description: ") and current_term:
155+
current_term["description"] = line[13:] # "Description: " 제거
156+
elif line.startswith("Definition: ") and current_term:
157+
current_term["definition"] = line[12:] # "Definition: " 제거
158+
159+
# 마지막 쿼리 저장
160+
if current_query and current_section == "queries":
161+
queries.append(current_query)
162+
163+
# 마지막 용어 저장
164+
if current_term and current_section == "terms":
165+
terms.append(current_term)
107166

108167
# 딕셔너리 저장
109168
documents_dict[table_name] = {
110169
"table_description": table_desc.strip(),
111170
**columns, # 컬럼 정보 추가
171+
"queries": queries, # 쿼리 정보 추가 (딕셔너리 형태로)
172+
"glossary_terms": terms, # 용어집 정보 추가
112173
}
113174

114175
return documents_dict

llm_utils/tools.py

Lines changed: 80 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,12 @@ def get_info_from_db(max_workers: int = 8) -> List[Document]:
140140

141141
def process_table_info(item: tuple[str, str]) -> str:
142142
table_name, table_description = item
143+
urn = urn_table_mapping.get(table_name, "")
144+
145+
# fetcher 인스턴스 생성
146+
local_fetcher = _get_fetcher()
147+
148+
# 컬럼 정보 가져오기
143149
column_info = _get_column_info(
144150
table_name, urn_table_mapping, max_workers=max_workers
145151
)
@@ -149,7 +155,80 @@ def process_table_info(item: tuple[str, str]) -> str:
149155
for col in column_info
150156
]
151157
)
152-
return f"{table_name}: {table_description}\nColumns:\n {column_info_str}"
158+
159+
# 쿼리 및 용어집 정보 가져오기
160+
queries_result = local_fetcher.get_queries_by_urn(urn) if urn else {}
161+
glossary_terms_result = (
162+
local_fetcher.get_glossary_terms_by_urn(urn) if urn else {}
163+
)
164+
165+
# GraphQL 응답에서 실제 쿼리 리스트 추출
166+
queries = []
167+
if (
168+
queries_result
169+
and "data" in queries_result
170+
and "listQueries" in queries_result["data"]
171+
and "queries" in queries_result["data"]["listQueries"]
172+
):
173+
queries = queries_result["data"]["listQueries"]["queries"]
174+
175+
# GraphQL 응답에서 실제 glossary terms 추출
176+
glossary_terms = []
177+
if (
178+
glossary_terms_result
179+
and "data" in glossary_terms_result
180+
and "dataset" in glossary_terms_result["data"]
181+
and "glossaryTerms" in glossary_terms_result["data"]["dataset"]
182+
and glossary_terms_result["data"]["dataset"]["glossaryTerms"] is not None
183+
and "terms" in glossary_terms_result["data"]["dataset"]["glossaryTerms"]
184+
):
185+
terms_data = glossary_terms_result["data"]["dataset"]["glossaryTerms"][
186+
"terms"
187+
]
188+
for term_item in terms_data:
189+
if "term" in term_item and "properties" in term_item["term"]:
190+
props = term_item["term"]["properties"]
191+
name = props.get("name", "")
192+
description = props.get("description", "")
193+
definition = props.get("definition", "")
194+
glossary_terms.append(
195+
{
196+
"name": name,
197+
"description": description,
198+
"definition": definition,
199+
}
200+
)
201+
202+
# 쿼리 정보를 name, description, statement.value만 추출하여 포맷
203+
if queries:
204+
formatted_queries = []
205+
for q in queries[:3]: # 최대 3개 쿼리만
206+
if isinstance(q, dict) and "properties" in q:
207+
props = q["properties"]
208+
name = props.get("name", "No name")
209+
description = props.get("description", "No description")
210+
statement_value = props.get("statement", {}).get(
211+
"value", "No query statement"
212+
)
213+
formatted_query = f"Name: {name}\nDescription: {description}\nQuery: {statement_value}"
214+
formatted_queries.append(formatted_query)
215+
queries_str = (
216+
"\n---\n".join(formatted_queries) if formatted_queries else "No queries"
217+
)
218+
else:
219+
queries_str = "No queries"
220+
terms_str = (
221+
"\n".join(
222+
[
223+
f"Term: {term['name']}\nDescription: {term['description']}\nDefinition: {term['definition']}"
224+
for term in glossary_terms
225+
]
226+
)
227+
if glossary_terms
228+
else "No terms"
229+
)
230+
231+
return f"{table_name}: {table_description}\nColumns:\n {column_info_str}\nQueries:\n {queries_str}\nTerms:\n {terms_str}"
153232

154233
table_info_str_list = parallel_process(
155234
table_info.items(),

0 commit comments

Comments
 (0)