Skip to content

Commit c906aaa

Browse files
authored
Merge pull request #56 Resolve #11
Feature/11 prompt config
2 parents 5d94c41 + 03c0292 commit c906aaa

File tree

8 files changed

+117
-71
lines changed

8 files changed

+117
-71
lines changed

data_utils/datahub_source.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import datahub.emitter.mce_builder as builder
2-
from datahub.emitter.mcp import MetadataChangeProposalWrapper
31
from datahub.metadata.schema_classes import DatasetPropertiesClass, SchemaMetadataClass
42
from datahub.emitter.rest_emitter import DatahubRestEmitter
53
from datahub.ingestion.graph.client import DatahubClientConfig, DataHubGraph

llm_utils/chains.py

Lines changed: 15 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
import os
2-
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
2+
from langchain_core.prompts import (
3+
ChatPromptTemplate,
4+
MessagesPlaceholder,
5+
SystemMessagePromptTemplate,
6+
)
37

48
from .llm_factory import get_llm
59

610
from dotenv import load_dotenv
11+
from prompt.template_loader import get_prompt_template
712

813
env_path = os.path.join(os.getcwd(), ".env")
914

@@ -16,45 +21,12 @@
1621

1722

1823
def create_query_refiner_chain(llm):
24+
prompt = get_prompt_template("query_refiner_prompt")
1925
tool_choice_prompt = ChatPromptTemplate.from_messages(
2026
[
21-
(
22-
"system",
23-
"""
24-
당신은 데이터 분석 전문가(데이터 분석가 페르소나)입니다.
25-
현재 subscription_activities, contract_activities, marketing_activities,
26-
sales_activities, success_activities, support_activities, trial_activities 데이터를
27-
보유하고 있으며, 사용자의 질문이 모호할 경우에도 우리가 가진 데이터를 기반으로
28-
충분히 답변 가능한 형태로 질문을 구체화해 주세요.
29-
30-
주의:
31-
- 사용자에게 추가 정보를 요구하는 ‘재질문(추가 질문)’을 하지 마세요.
32-
- 질문에 포함해야 할 요소(예: 특정 기간, 대상 유저 그룹, 분석 대상 로그 종류 등)가
33-
불충분하더라도, 합리적으로 추론해 가정한 뒤
34-
답변에 충분한 질문 형태로 완성해 주세요.
35-
36-
예시:
37-
사용자가 "유저 이탈 원인이 궁금해요"라고 했다면,
38-
재질문 형식이 아니라
39-
"최근 1개월 간의 접속·결제 로그를 기준으로,
40-
주로 어떤 사용자가 어떤 과정을 거쳐 이탈하는지를 분석해야 한다"처럼
41-
분석 방향이 명확해진 질문 한 문장(또는 한 문단)으로 정리해 주세요.
42-
43-
최종 출력 형식 예시:
44-
------------------------------
45-
구체화된 질문:
46-
"최근 1개월 동안 고액 결제 경험이 있는 유저가
47-
행동 로그에서 이탈 전 어떤 패턴을 보였는지 분석"
48-
49-
가정한 조건:
50-
- 최근 1개월치 행동 로그와 결제 로그 중심
51-
- 고액 결제자(월 결제액 10만 원 이상) 그룹 대상으로 한정
52-
------------------------------
53-
""",
54-
),
27+
SystemMessagePromptTemplate.from_template(prompt),
5528
MessagesPlaceholder(variable_name="user_input"),
56-
(
57-
"system",
29+
SystemMessagePromptTemplate.from_template(
5830
"""
5931
위 사용자의 입력을 바탕으로
6032
분석 관점에서 **충분히 답변 가능한 형태**로
@@ -70,36 +42,11 @@ def create_query_refiner_chain(llm):
7042

7143
# QueryMakerChain
7244
def create_query_maker_chain(llm):
45+
# SystemPrompt만 yaml 파일로 불러와서 사용
46+
prompt = get_prompt_template("query_maker_prompt")
7347
query_maker_prompt = ChatPromptTemplate.from_messages(
7448
[
75-
(
76-
"system",
77-
"""
78-
당신은 데이터 분석 전문가(데이터 분석가 페르소나)입니다.
79-
사용자의 질문을 기반으로, 주어진 테이블과 컬럼 정보를 활용하여 적절한 SQL 쿼리를 생성하세요.
80-
81-
주의사항:
82-
- 사용자의 질문이 다소 모호하더라도, 주어진 데이터를 참고하여 합리적인 가정을 통해 SQL 쿼리를 완성하세요.
83-
- 불필요한 재질문 없이, 가능한 가장 명확한 분석 쿼리를 만들어 주세요.
84-
- 최종 출력 형식은 반드시 아래와 같아야 합니다.
85-
86-
최종 형태 예시:
87-
88-
<SQL>
89-
```sql
90-
SELECT COUNT(DISTINCT user_id)
91-
FROM stg_users
92-
```
93-
94-
<해석>
95-
```plaintext (max_length_per_line=100)
96-
이 쿼리는 stg_users 테이블에서 고유한 사용자의 수를 계산합니다.
97-
사용자는 유니크한 user_id를 가지고 있으며
98-
중복을 제거하기 위해 COUNT(DISTINCT user_id)를 사용했습니다.
99-
```
100-
101-
""",
102-
),
49+
SystemMessagePromptTemplate.from_template(prompt),
10350
(
10451
"system",
10552
"아래는 사용자의 질문 및 구체화된 질문입니다:",
@@ -123,3 +70,6 @@ def create_query_maker_chain(llm):
12370

12471
query_refiner_chain = create_query_refiner_chain(llm)
12572
query_maker_chain = create_query_maker_chain(llm)
73+
74+
if __name__ == "__main__":
75+
query_refiner_chain.invoke()

llm_utils/graph.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -134,10 +134,10 @@ def query_maker_node_with_db_guide(state: QueryMakerState):
134134
# 노드 추가
135135
builder.add_node(QUERY_REFINER, query_refiner_node)
136136
builder.add_node(GET_TABLE_INFO, get_table_info_node)
137-
# builder.add_node(QUERY_MAKER, query_maker_node) # query_maker_node_with_db_guide
138-
builder.add_node(
139-
QUERY_MAKER, query_maker_node_with_db_guide
140-
) # query_maker_node_with_db_guide
137+
builder.add_node(QUERY_MAKER, query_maker_node) # query_maker_node_with_db_guide
138+
# builder.add_node(
139+
# QUERY_MAKER, query_maker_node_with_db_guide
140+
# ) # query_maker_node_with_db_guide
141141

142142
# 기본 엣지 설정
143143
builder.add_edge(QUERY_REFINER, GET_TABLE_INFO)

llm_utils/prompts_class.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
from langchain.chains.sql_database.prompt import SQL_PROMPTS
2+
import os
3+
4+
from langchain_core.prompts import load_prompt
5+
6+
7+
class SQLPrompt:
8+
def __init__(self):
9+
# os library를 확인해서 SQL_PROMPTS key에 해당하는 prompt가 있으면, 이를 교체
10+
self.sql_prompts = SQL_PROMPTS
11+
self.target_db_list = list(SQL_PROMPTS.keys())
12+
self.prompt_path = "../prompt"
13+
14+
def update_prompt_from_path(self):
15+
if os.path.exists(self.prompt_path):
16+
path_list = os.listdir(self.prompt_path)
17+
# yaml 파일만 가져옴
18+
file_list = [file for file in path_list if file.endswith(".yaml")]
19+
key_path_dict = {
20+
key.split(".")[0]: os.path.join(self.prompt_path, key)
21+
for key in file_list
22+
if key.split(".")[0] in self.target_db_list
23+
}
24+
# file_list에서 sql_prompts의 key에 해당하는 파일이 있는 것만 가져옴
25+
for key, path in key_path_dict.items():
26+
self.sql_prompts[key] = load_prompt(path, encoding="utf-8")
27+
else:
28+
raise FileNotFoundError(f"Prompt file not found in {self.prompt_path}")
29+
return False

prompt/__init__.py

Whitespace-only changes.

prompt/query_maker_prompt.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Role
2+
3+
당신은 데이터 분석 전문가(데이터 분석가 페르소나)입니다.
4+
사용자의 질문을 기반으로, 주어진 테이블과 컬럼 정보를 활용하여 적절한 SQL 쿼리를 생성하세요.
5+
6+
# 주의사항
7+
- 사용자의 질문이 다소 모호하더라도, 주어진 데이터를 참고하여 합리적인 가정을 통해 SQL 쿼리를 완성하세요.
8+
- 불필요한 재질문 없이, 가능한 가장 명확한 분석 쿼리를 만들어 주세요.
9+
- 최종 출력 형식은 반드시 아래와 같아야 합니다.
10+
11+
# Output Example
12+
최종 형태 예시:
13+
<SQL>
14+
```sql
15+
SELECT COUNT(DISTINCT user_id)
16+
FROM stg_users
17+
```
18+
19+
<해석>
20+
```plaintext (max_length_per_line=100)
21+
이 쿼리는 stg_users 테이블에서 고유한 사용자의 수를 계산합니다.
22+
사용자는 유니크한 user_id를 가지고 있으며
23+
중복을 제거하기 위해 COUNT(DISTINCT user_id)를 사용했습니다.

prompt/query_refiner_prompt.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# Role
2+
3+
당신은 데이터 분석 전문가(데이터 분석가 페르소나)입니다.
4+
현재 subscription_activities, contract_activities, marketing_activities,
5+
sales_activities, success_activities, support_activities, trial_activities 데이터를
6+
보유하고 있으며, 사용자의 질문이 모호할 경우에도 우리가 가진 데이터를 기반으로
7+
충분히 답변 가능한 형태로 질문을 구체화해 주세요.
8+
9+
# 주의사항:
10+
- 사용자에게 추가 정보를 요구하는 ‘재질문(추가 질문)’을 하지 마세요.
11+
- 질문에 포함해야 할 요소(예: 특정 기간, 대상 유저 그룹, 분석 대상 로그 종류 등)가
12+
불충분하더라도, 합리적으로 추론해 가정한 뒤
13+
답변에 충분한 질문 형태로 완성해 주세요.
14+
예시:
15+
사용자가 "유저 이탈 원인이 궁금해요"라고 했다면,
16+
재질문 형식이 아니라
17+
"최근 1개월 간의 접속·결제 로그를 기준으로,
18+
주로 어떤 사용자가 어떤 과정을 거쳐 이탈하는지를 분석해야 한다"처럼
19+
분석 방향이 명확해진 질문 한 문장(또는 한 문단)으로 정리해 주세요.
20+
21+
# Output Example
22+
23+
최종 출력 형식 예시:
24+
------------------------------
25+
구체화된 질문:
26+
"최근 1개월 동안 고액 결제 경험이 있는 유저가
27+
행동 로그에서 이탈 전 어떤 패턴을 보였는지 분석"
28+
29+
가정한 조건:
30+
- 최근 1개월치 행동 로그와 결제 로그 중심
31+
- 고액 결제자(월 결제액 10만 원 이상) 그룹 대상으로 한정
32+
------------------------------

prompt/template_loader.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import os
2+
3+
4+
def get_prompt_template(prompt_name: str) -> str:
5+
try:
6+
with open(
7+
os.path.join(os.path.dirname(__file__), f"{prompt_name}.md"),
8+
"r",
9+
encoding="utf-8",
10+
) as f:
11+
template = f.read()
12+
except FileNotFoundError:
13+
raise FileNotFoundError(f"경고: '{prompt_name}.md' 파일을 찾을 수 없습니다.")
14+
return template

0 commit comments

Comments
 (0)