dev-yuje commited on
Commit
7813475
Β·
1 Parent(s): 7ca482a

Fix: Expand UI features to 14 to match prediction model and fix No API found error

Browse files
Files changed (1) hide show
  1. app.py +48 -41
app.py CHANGED
@@ -1,4 +1,3 @@
1
- # [λͺ½ν‚€ 패치] Gradio와 huggingface_hub 버전 κ°ˆλ“± ν•΄κ²°
2
  import huggingface_hub
3
  if not hasattr(huggingface_hub, "HfFolder"):
4
  class MockHfFolder:
@@ -21,68 +20,65 @@ from langchain_google_genai import ChatGoogleGenerativeAI
21
  from langchain_huggingface import HuggingFaceEmbeddings
22
  from langchain_community.vectorstores import FAISS
23
 
24
- # ν”„λ‘œμ νŠΈ μ„€μ • 및 ν”„λ‘¬ν”„νŠΈ 뢈러였기
25
  from llm.prompt import QA_PROMPT
26
  from predictors.score_prediction import predictor
27
- from config import EMBEDDING_MODEL, FAISS_PATH, RETRIEVER_K
28
 
29
  # API ν‚€ μ„€μ •
30
- os.environ["GOOGLE_API_KEY"] = os.getenv("GOOGLE_API_KEY", "AIzaSyDRlDaMDFTVM4I8uNZdmuYRLMG38U_Ks6g")
31
 
32
- FEATURES = {
 
33
  'C1Z001386': '1λ…„λ‚΄ μΉ΄λ“œ 총 μ΄μš©κΈˆμ•‘ (λ§Œμ›)',
34
  'C1M210000': 'μ‹ μš©μΉ΄λ“œ 건수',
35
  'C18210000': 'μ²΄ν¬μΉ΄λ“œ 건수',
36
  'C1L120001': 'μΉ΄λ“œ 총 ν•œλ„κΈˆμ•‘ (λ§Œμ›)',
37
  'C1L120004': 'μΉ΄λ“œ κ°œμ„€μΌμˆ˜',
 
 
 
 
 
 
38
  'D10110000': '연체 건수',
39
- 'D10113000': '연체 μž”μ•‘ (λ§Œμ›)',
40
- 'E1L210000': '은행업쒅 λŒ€μΆœ 건수',
41
- 'E1L21B000': '담보 λŒ€μΆœ 건수',
42
  'PERF1': '90일 연체 μ—¬λΆ€'
43
  }
44
 
45
- FEATURE_ORDER = [
 
46
  'C1Z001386', 'C1M210000', 'C18210000', 'C1L120001', 'C1L120004',
47
- 'D10110000', 'D10113000', 'E1L210000', 'E1L21B000', 'PERF1'
 
48
  ]
49
 
50
  class CreditRAGConsultant:
51
  def __init__(self):
52
  self.embedding_model = HuggingFaceEmbeddings(model_name=EMBEDDING_MODEL)
53
  if os.path.exists(FAISS_PATH):
54
- self.vectorstore = FAISS.load_local(
55
- FAISS_PATH, self.embedding_model, allow_dangerous_deserialization=True
56
- )
57
  self.retriever = self.vectorstore.as_retriever(search_kwargs={"k": RETRIEVER_K})
58
  else:
59
- self.vectorstore = None
60
- self.retriever = None
61
 
62
- self.llm = ChatGoogleGenerativeAI(
63
- model="gemini-1.5-flash",
64
- temperature=0.7,
65
- max_output_tokens=1024
66
- )
67
 
68
  def generate_response(self, history, user_message, analysis_report):
69
- if not user_message:
70
- yield history, ""
71
- return
72
-
73
- if history and history[-1].get("content") == "생각 쀑...":
74
- history = history[:-1]
75
-
76
  history = history + [{"role": "assistant", "content": ""}]
77
  t0 = time.time()
78
-
 
79
  docs = self.retriever.invoke(user_message) if self.retriever else []
80
  t_retrieve = time.time() - t0
81
- context = "\n\n".join([f"[λ¬Έμ„œ {i+1}]\n{doc.page_content}" for i, doc in enumerate(docs)])
82
-
 
83
  if analysis_report:
84
  score_val = int(analysis_report["score"])
85
- features_text = "\n".join([f"- {FEATURES.get(k, k)}: {v}" for k, v in analysis_report['features'].items()])
86
  query_text = f"β–  고객 뢄석 κ²°κ³Ό: {score_val}점\n{features_text}\n\nβ–  질문: {user_message}"
87
  else:
88
  query_text = f"β–  질문: {user_message}"
@@ -90,6 +86,7 @@ class CreditRAGConsultant:
90
  prompt_text = QA_PROMPT.format(context=context, query=query_text)
91
  t_augment = time.time() - t0
92
 
 
93
  answer_buffer = ""
94
  try:
95
  for chunk in self.llm.stream(prompt_text):
@@ -109,16 +106,17 @@ with gr.Blocks(title="KCB Credit AI", theme=gr.themes.Soft()) as demo:
109
  analysis_report = gr.State(None)
110
  pending_msg = gr.State("")
111
 
112
- gr.Markdown("# πŸ›‘οΈ KCB AI μ‹ μš© 점수 상담 μ„œλΉ„μŠ€")
113
 
114
  with gr.Row():
115
  with gr.Column(scale=1):
 
116
  input_list = []
117
- for key in [k for k in FEATURE_ORDER if k in FEATURES]:
118
  if key == 'PERF1':
119
- input_list.append(gr.Checkbox(label=FEATURES[key], value=False))
120
  else:
121
- input_list.append(gr.Textbox(label=FEATURES[key], placeholder="0"))
122
  predict_btn = gr.Button("πŸ“ˆ 점수 λΆ„μ„ν•˜κΈ°", variant="primary")
123
 
124
  with gr.Column(scale=2):
@@ -130,11 +128,15 @@ with gr.Blocks(title="KCB Credit AI", theme=gr.themes.Soft()) as demo:
130
  submit_btn = gr.Button("μƒλ‹΄ν•˜κΈ°", variant="primary", scale=1)
131
 
132
  def handle_predict(*args):
133
- ui_input_keys = [k for k in FEATURE_ORDER if k in FEATURES]
134
  features_dict = {}
135
- for i, key in enumerate(ui_input_keys):
136
- if key == 'PERF1': features_dict[key] = int(args[i])
137
- else: features_dict[key] = float(args[i]) if args[i] else 0.0
 
 
 
 
 
138
  score = predictor.predict(features_dict)
139
  display_score = int(min(max(round(score), 0), 1000))
140
  return {"features": features_dict, "score": display_score}, display_score
@@ -144,8 +146,13 @@ with gr.Blocks(title="KCB Credit AI", theme=gr.themes.Soft()) as demo:
144
  return history + [{"role": "user", "content": user_message}, {"role": "assistant", "content": "생각 쀑..."}], "", user_message
145
 
146
  predict_btn.click(handle_predict, inputs=input_list, outputs=[analysis_report, result_display])
147
- msg.submit(user_msg, [msg, chatbot], [chatbot, msg, pending_msg]).then(consultant.generate_response, [chatbot, pending_msg, analysis_report], [chatbot, msg])
148
- submit_btn.click(user_msg, [msg, chatbot], [chatbot, msg, pending_msg]).then(consultant.generate_response, [chatbot, pending_msg, analysis_report], [chatbot, msg])
 
 
 
 
 
149
 
150
  if __name__ == "__main__":
151
  demo.launch()
 
 
1
  import huggingface_hub
2
  if not hasattr(huggingface_hub, "HfFolder"):
3
  class MockHfFolder:
 
20
  from langchain_huggingface import HuggingFaceEmbeddings
21
  from langchain_community.vectorstores import FAISS
22
 
23
+ from config import EMBEDDING_MODEL, FAISS_PATH, RETRIEVER_K, GEMINI_API_KEY
24
  from llm.prompt import QA_PROMPT
25
  from predictors.score_prediction import predictor
 
26
 
27
  # API ν‚€ μ„€μ •
28
+ os.environ["GOOGLE_API_KEY"] = os.getenv("GOOGLE_API_KEY", GEMINI_API_KEY)
29
 
30
+ # 14개 ν”Όμ²˜μ— λŒ€ν•œ 상세 μ„€λͺ… λ§€ν•‘
31
+ FEATURES_MAP = {
32
  'C1Z001386': '1λ…„λ‚΄ μΉ΄λ“œ 총 μ΄μš©κΈˆμ•‘ (λ§Œμ›)',
33
  'C1M210000': 'μ‹ μš©μΉ΄λ“œ 건수',
34
  'C18210000': 'μ²΄ν¬μΉ΄λ“œ 건수',
35
  'C1L120001': 'μΉ΄λ“œ 총 ν•œλ„κΈˆμ•‘ (λ§Œμ›)',
36
  'C1L120004': 'μΉ΄λ“œ κ°œμ„€μΌμˆ˜',
37
+ 'L10210000': '은행업쒅 λŒ€μΆœ 건수',
38
+ 'L90210100': 'λŒ€λΆ€μ—…μ’… λŒ€μΆœ 건수',
39
+ 'L90210200': '저좕은행 λŒ€μΆœ 건수',
40
+ 'L10210B00': '주택담보 λŒ€μΆœ 건수',
41
+ 'L10216000': 'μ‹ μš©λŒ€μΆœ 총 μž”μ•‘ (λ§Œμ›)',
42
+ 'L10217000': 'λ‹΄λ³΄λŒ€μΆœ 총 μž”μ•‘ (λ§Œμ›)',
43
  'D10110000': '연체 건수',
44
+ 'D10133000': '연체 μž”μ•‘ (λ§Œμ›)',
 
 
45
  'PERF1': '90일 연체 μ—¬λΆ€'
46
  }
47
 
48
+ # λͺ¨λΈμ΄ μš”κ΅¬ν•˜λŠ” μ •ν™•ν•œ μˆœμ„œ
49
+ ALL_FEATURES_KEYS = [
50
  'C1Z001386', 'C1M210000', 'C18210000', 'C1L120001', 'C1L120004',
51
+ 'L10210000', 'L90210100', 'L90210200', 'L10210B00', 'L10216000',
52
+ 'L10217000', 'D10110000', 'D10133000', 'PERF1'
53
  ]
54
 
55
  class CreditRAGConsultant:
56
  def __init__(self):
57
  self.embedding_model = HuggingFaceEmbeddings(model_name=EMBEDDING_MODEL)
58
  if os.path.exists(FAISS_PATH):
59
+ self.vectorstore = FAISS.load_local(FAISS_PATH, self.embedding_model, allow_dangerous_deserialization=True)
 
 
60
  self.retriever = self.vectorstore.as_retriever(search_kwargs={"k": RETRIEVER_K})
61
  else:
62
+ self.vectorstore = self.retriever = None
 
63
 
64
+ self.llm = ChatGoogleGenerativeAI(model="gemini-1.5-flash", temperature=0.7)
 
 
 
 
65
 
66
  def generate_response(self, history, user_message, analysis_report):
67
+ if not user_message: yield history, ""; return
68
+ if history and history[-1].get("content") == "생각 쀑...": history = history[:-1]
69
+
 
 
 
 
70
  history = history + [{"role": "assistant", "content": ""}]
71
  t0 = time.time()
72
+
73
+ # R
74
  docs = self.retriever.invoke(user_message) if self.retriever else []
75
  t_retrieve = time.time() - t0
76
+ context = "\n\n".join([doc.page_content for doc in docs])
77
+
78
+ # A
79
  if analysis_report:
80
  score_val = int(analysis_report["score"])
81
+ features_text = "\n".join([f"- {FEATURES_MAP.get(k, k)}: {v}" for k, v in analysis_report['features'].items()])
82
  query_text = f"β–  고객 뢄석 κ²°κ³Ό: {score_val}점\n{features_text}\n\nβ–  질문: {user_message}"
83
  else:
84
  query_text = f"β–  질문: {user_message}"
 
86
  prompt_text = QA_PROMPT.format(context=context, query=query_text)
87
  t_augment = time.time() - t0
88
 
89
+ # G
90
  answer_buffer = ""
91
  try:
92
  for chunk in self.llm.stream(prompt_text):
 
106
  analysis_report = gr.State(None)
107
  pending_msg = gr.State("")
108
 
109
+ gr.Markdown("# πŸ›‘οΈ KCB AI μ‹ μš© 점수 뢄석 μ‹œμŠ€ν…œ")
110
 
111
  with gr.Row():
112
  with gr.Column(scale=1):
113
+ gr.Markdown("### πŸ“Š 금육 μ§€ν‘œ μž…λ ₯")
114
  input_list = []
115
+ for key in ALL_FEATURES_KEYS:
116
  if key == 'PERF1':
117
+ input_list.append(gr.Checkbox(label=FEATURES_MAP[key], value=False))
118
  else:
119
+ input_list.append(gr.Textbox(label=FEATURES_MAP[key], placeholder="0"))
120
  predict_btn = gr.Button("πŸ“ˆ 점수 λΆ„μ„ν•˜κΈ°", variant="primary")
121
 
122
  with gr.Column(scale=2):
 
128
  submit_btn = gr.Button("μƒλ‹΄ν•˜κΈ°", variant="primary", scale=1)
129
 
130
  def handle_predict(*args):
 
131
  features_dict = {}
132
+ # μž…λ ₯ λ¦¬μŠ€νŠΈμ™€ ν‚€ μˆœμ„œκ°€ 동일함
133
+ for i, key in enumerate(ALL_FEATURES_KEYS):
134
+ if key == 'PERF1':
135
+ features_dict[key] = int(args[i])
136
+ else:
137
+ val = args[i] if args[i] else "0"
138
+ features_dict[key] = float(val)
139
+
140
  score = predictor.predict(features_dict)
141
  display_score = int(min(max(round(score), 0), 1000))
142
  return {"features": features_dict, "score": display_score}, display_score
 
146
  return history + [{"role": "user", "content": user_message}, {"role": "assistant", "content": "생각 쀑..."}], "", user_message
147
 
148
  predict_btn.click(handle_predict, inputs=input_list, outputs=[analysis_report, result_display])
149
+
150
+ msg.submit(user_msg, [msg, chatbot], [chatbot, msg, pending_msg]).then(
151
+ consultant.generate_response, [chatbot, pending_msg, analysis_report], [chatbot, msg]
152
+ )
153
+ submit_btn.click(user_msg, [msg, chatbot], [chatbot, msg, pending_msg]).then(
154
+ consultant.generate_response, [chatbot, pending_msg, analysis_report], [chatbot, msg]
155
+ )
156
 
157
  if __name__ == "__main__":
158
  demo.launch()