aiqtech commited on
Commit
5d1c552
ยท
verified ยท
1 Parent(s): 6b8ef5e

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +375 -81
app.py CHANGED
@@ -125,23 +125,33 @@ class WuxingLLMSystem:
125
  "X-Subscription-Token": self.bapi_token
126
  }
127
 
128
- def create_wood_initial_prompt(self, user_query: str) -> str:
129
  """ๆœจ(๊ฐ๋…๊ด€) ์ดˆ๊ธฐ ํ”„๋กฌํ”„ํŠธ"""
 
 
 
 
130
  return f"""๋‹น์‹ ์€ ไป(์ธ์žํ•จ)์˜ ๋•๋ชฉ์„ ์ง€๋‹Œ ๆœจ์˜ ๊ธฐ์šด์„ ๊ฐ€์ง„ ๊ฐ๋…๊ด€์ž…๋‹ˆ๋‹ค.
131
  ํฌ์šฉ์ ์ด๊ณ  ์„ฑ์žฅ์ง€ํ–ฅ์ ์ธ ๋ฆฌ๋”์‹ญ์œผ๋กœ ํŒ€์„ ์ด๋•๋‹ˆ๋‹ค.
132
 
133
  ์‚ฌ์šฉ์ž ์งˆ๋ฌธ: {user_query}
 
134
 
135
  ํŒ€์žฅ์œผ๋กœ์„œ ์ด ์งˆ๋ฌธ์— ๋Œ€ํ•ด:
136
  1. ์ „์ฒด์ ์ธ ๋น„์ „๊ณผ ๋ฐฉํ–ฅ์„ฑ์„ ์ œ์‹œํ•˜์„ธ์š”
137
  2. ๊ฐ ํŒ€์›(็ซ, ๅœŸ, ้‡‘, ๆฐด)์˜ ์—ญํ• ๊ณผ ๊ธฐ์—ฌ ๋ฐฉํ–ฅ์„ ์„ค๊ณ„ํ•˜์„ธ์š”
138
  3. ์„ฑ์žฅ๊ณผ ๋ฐœ์ „์˜ ๊ด€์ ์—์„œ ํ•ต์‹ฌ ๋ชฉํ‘œ๋ฅผ ์„ค์ •ํ•˜์„ธ์š”
139
  4. ํŒ€ ์ „์ฒด๊ฐ€ ์กฐํ™”๋กญ๊ฒŒ ํ˜‘๋ ฅํ•  ์ˆ˜ ์žˆ๋Š” ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ์ œ์‹œํ•˜์„ธ์š”
 
140
 
141
  [ํ•ต์‹ฌ ํ‚ค์›Œ๋“œ]: 5-7๊ฐœ์˜ ์กฐ์‚ฌ๊ฐ€ ํ•„์š”ํ•œ ํ‚ค์›Œ๋“œ๋ฅผ ์ œ์‹œํ•˜์„ธ์š”"""
142
 
143
- def create_fire_strategy_prompt(self, user_query: str, wood_response: str, critic_feedback: str) -> str:
144
  """็ซ(์ „๋žต๊ธฐํš) ํ”„๋กฌํ”„ํŠธ"""
 
 
 
 
145
  return f"""๋‹น์‹ ์€ ็พฉ(์ •์˜๋กœ์›€)์˜ ๋•๋ชฉ์„ ์ง€๋‹Œ ็ซ์˜ ๊ธฐ์šด์„ ๊ฐ€์ง„ ์ „๋žตยท๊ธฐํš ๋ฆฌ๋”์ž…๋‹ˆ๋‹ค.
146
  ์—ด์ •๊ณผ ๊ฒฐ๋‹จ๋ ฅ์œผ๋กœ ํ˜์‹ ์ ์ธ ์ „๋žต์„ ์ˆ˜๋ฆฝํ•ฉ๋‹ˆ๋‹ค.
147
 
@@ -152,16 +162,22 @@ class WuxingLLMSystem:
152
 
153
  ๋น„ํ‰์ž์˜ ํ”ผ๋“œ๋ฐฑ:
154
  {critic_feedback}
 
155
 
156
  ์ „๋žต๊ธฐํš ๋ฆฌ๋”๋กœ์„œ:
157
  1. ์ค‘ยท์žฅ๊ธฐ ๋กœ๋“œ๋งต์„ ๊ตฌ์ฒด์ ์œผ๋กœ ์ˆ˜๋ฆฝํ•˜์„ธ์š”
158
  2. ํ˜์‹ ์ ์ธ ์‚ฌ์—… ๋ชจ๋ธ์„ ์„ค๊ณ„ํ•˜์„ธ์š”
159
  3. ๋ฆฌ์Šคํฌ์™€ ๊ธฐํšŒ ๋ถ„์„์„ ์ˆ˜ํ–‰ํ•˜์„ธ์š”
160
  4. ๊ฒฝ์Ÿ ์šฐ์œ„ ํ™•๋ณด ์ „๋žต์„ ์ œ์‹œํ•˜์„ธ์š”
161
- 5. ๋น„ํ‰์ž์˜ ํ”ผ๋“œ๋ฐฑ์„ ๋ฐ˜์˜ํ•˜์—ฌ ์ „๋žต์„ ๋ณด์™„ํ•˜์„ธ์š”"""
 
162
 
163
- def create_earth_execution_prompt(self, user_query: str, fire_response: str, critic_feedback: str, search_results: Dict) -> str:
164
  """ๅœŸ(์‹คํ–‰์šด์˜) ํ”„๋กฌํ”„ํŠธ"""
 
 
 
 
165
  return f"""๋‹น์‹ ์€ ไฟก(์‹ ๋ขฐ)์˜ ๋•๋ชฉ์„ ์ง€๋‹Œ ๅœŸ์˜ ๊ธฐ์šด์„ ๊ฐ€์ง„ ์‹คํ–‰ยท์šด์˜ยทํ’ˆ์งˆ ๋‹ด๋‹น์ž์ž…๋‹ˆ๋‹ค.
166
  ์„ฑ์‹คํ•จ๊ณผ ์‹คํ–‰๋ ฅ์œผ๋กœ ๊ณ„ํš์„ ํ˜„์‹ค๋กœ ๋งŒ๋“ญ๋‹ˆ๋‹ค.
167
 
@@ -172,19 +188,22 @@ class WuxingLLMSystem:
172
 
173
  ๋น„ํ‰์ž์˜ ํ”ผ๋“œ๋ฐฑ:
174
  {critic_feedback}
175
-
176
- ์›น ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ:
177
- {self._format_search_results(search_results)}
178
 
179
  ์‹คํ–‰์šด์˜ ๋‹ด๋‹น์ž๋กœ์„œ:
180
  1. ๊ตฌ์ฒด์ ์ธ ์‹คํ–‰ ๊ณ„ํš๊ณผ ์ผ์ •์„ ์ˆ˜๋ฆฝํ•˜์„ธ์š”
181
  2. ํ•„์š”ํ•œ ๋ฆฌ์†Œ์Šค์™€ ์˜ˆ์‚ฐ์„ ์‚ฐ์ •ํ•˜์„ธ์š”
182
  3. ํ’ˆ์งˆ ๊ด€๋ฆฌ ๊ธฐ์ค€๊ณผ ํ”„๋กœ์„ธ์Šค๋ฅผ ์ •์˜ํ•˜์„ธ์š”
183
  4. ๋ฆฌ์Šคํฌ ๋Œ€์‘ ๊ณ„ํš์„ ์ˆ˜๋ฆฝํ•˜์„ธ์š”
184
- 5. ์„ฑ๊ณผ ์ธก์ • ์ง€ํ‘œ๋ฅผ ์„ค์ •ํ•˜์„ธ์š”"""
 
185
 
186
- def create_metal_architecture_prompt(self, user_query: str, earth_response: str, critic_feedback: str) -> str:
187
  """้‡‘(์•„ํ‚คํ…์ฒ˜) ํ”„๋กฌํ”„ํŠธ"""
 
 
 
 
188
  return f"""๋‹น์‹ ์€ ็ฆฎ(์˜ˆ์˜ยท์งˆ์„œ)์˜ ๋•๋ชฉ์„ ์ง€๋‹Œ ้‡‘์˜ ๊ธฐ์šด์„ ๊ฐ€์ง„ ์•„ํ‚คํ…์ฒ˜ & ํ‘œ์ค€ ์ฑ…์ž„์ž์ž…๋‹ˆ๋‹ค.
189
  ์ •๋ฐ€ํ•จ๊ณผ ๊ตฌ์กฐํ™” ๋Šฅ๋ ฅ์œผ๋กœ ์™„๋ฒฝํ•œ ์‹œ์Šคํ…œ์„ ์„ค๊ณ„ํ•ฉ๋‹ˆ๋‹ค.
190
 
@@ -195,16 +214,22 @@ class WuxingLLMSystem:
195
 
196
  ๋น„ํ‰์ž์˜ ํ”ผ๋“œ๋ฐฑ:
197
  {critic_feedback}
 
198
 
199
  ์•„ํ‚คํ…์ฒ˜ ์ฑ…์ž„์ž๋กœ์„œ:
200
  1. ์ „์ฒด ์‹œ์Šคํ…œ์˜ ๊ธฐ์ˆ ยท๋ฐ์ดํ„ฐ ์•„ํ‚คํ…์ฒ˜๋ฅผ ์„ค๊ณ„ํ•˜์„ธ์š”
201
  2. ์ฝ”๋”ฉ/APIยท๋ฐ์ดํ„ฐยท๋ณด์•ˆ ํ‘œ์ค€์„ ์ˆ˜๋ฆฝํ•˜์„ธ์š”
202
  3. ํ™•์žฅ์„ฑ๊ณผ ํ˜ธํ™˜์„ฑ์„ ๊ณ ๋ คํ•œ ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ์ œ์‹œํ•˜์„ธ์š”
203
  4. ํ’ˆ์งˆ ๊ฒ€์ฆ ์ฒด๊ณ„์™€ ๊ธฐ์ค€์„ ์ •์˜ํ•˜์„ธ์š”
204
- 5. ๊ธฐ์ˆ ์  ์ œ์•ฝ์‚ฌํ•ญ๊ณผ ํ•ด๊ฒฐ๋ฐฉ์•ˆ์„ ์ œ์‹œํ•˜์„ธ์š”"""
 
205
 
206
- def create_water_rd_prompt(self, user_query: str, metal_response: str, critic_feedback: str, search_results: Dict) -> str:
207
  """ๆฐด(R&D) ํ”„๋กฌํ”„ํŠธ"""
 
 
 
 
208
  return f"""๋‹น์‹ ์€ ๆ™บ(์ง€ํ˜œ)์˜ ๋•๋ชฉ์„ ์ง€๋‹Œ ๆฐด์˜ ๊ธฐ์šด์„ ๊ฐ€์ง„ ๋„๊ตฌ ํ™œ์šฉ R&D ์ŠคํŽ˜์…œ๋ฆฌ์ŠคํŠธ์ž…๋‹ˆ๋‹ค.
209
  ๋ถ„์„๋ ฅ๊ณผ ํ˜ธ๊ธฐ์‹ฌ์œผ๋กœ ์ตœ์‹  ๊ธฐ์ˆ ์„ ํƒ๊ตฌํ•˜๊ณ  ํ˜์‹ ํ•ฉ๋‹ˆ๋‹ค.
210
 
@@ -215,16 +240,15 @@ class WuxingLLMSystem:
215
 
216
  ๋น„ํ‰์ž์˜ ํ”ผ๋“œ๋ฐฑ:
217
  {critic_feedback}
218
-
219
- ์ตœ์‹  ๊ธฐ์ˆ  ์กฐ์‚ฌ ๊ฒฐ๊ณผ:
220
- {self._format_search_results(search_results)}
221
 
222
  R&D ์ŠคํŽ˜์…œ๋ฆฌ์ŠคํŠธ๋กœ์„œ:
223
  1. ์ตœ์‹  ๊ธฐ์ˆ  ํŠธ๋ Œ๋“œ์™€ ๋„๊ตฌ๋ฅผ ๋ถ„์„ํ•˜์„ธ์š”
224
  2. ํ˜์‹ ์ ์ธ ํ”„๋กœํ† ํƒ€์ž… ๊ฐœ๋ฐœ ๋ฐฉ์•ˆ์„ ์ œ์‹œํ•˜์„ธ์š”
225
  3. ์ž๋™ํ™”์™€ ์ƒ์‚ฐ์„ฑ ํ–ฅ์ƒ ๋„๊ตฌ๋ฅผ ์ถ”์ฒœํ•˜์„ธ์š”
226
  4. ๊ธฐ์ˆ  ๋„์ž…์˜ ROI์™€ ์‹คํ˜„ ๊ฐ€๋Šฅ์„ฑ์„ ํ‰๊ฐ€ํ•˜์„ธ์š”
227
- 5. ํŒ€ ๊ต์œก๊ณผ ๊ธฐ์ˆ  ์ „ํŒŒ ๊ณ„ํš์„ ์ˆ˜๋ฆฝํ•˜์„ธ์š”"""
 
228
 
229
  def create_wood_final_prompt(self, user_query: str, all_responses: Dict, all_critics: List) -> str:
230
  """ๆœจ(๊ฐ๋…๊ด€) ์ตœ์ข… ์ข…ํ•ฉ ํ”„๋กฌํ”„ํŠธ"""
@@ -251,8 +275,12 @@ R&D ์ŠคํŽ˜์…œ๋ฆฌ์ŠคํŠธ๋กœ์„œ:
251
 
252
  ๋งˆํฌ๋‹ค์šด ํ˜•์‹์„ ํ™œ์šฉํ•˜์—ฌ ์ „๋ฌธ์ ์ด๊ณ  ์ฒด๊ณ„์ ์œผ๋กœ ์ž‘์„ฑํ•˜์„ธ์š”."""
253
 
254
- def create_critic_prompt(self, stage: str, content: str, context: str = "") -> str:
255
  """์ค‘๋ฆฝ์  ๋น„ํ‰์ž ํ”„๋กฌํ”„ํŠธ"""
 
 
 
 
256
  return f"""๋‹น์‹ ์€ ์ค‘๋ฆฝ์ ์ด๊ณ  ๋…ผ๋ฆฌ์ ์ธ ๋น„ํ‰์ž์ž…๋‹ˆ๋‹ค.
257
  ํŽธ๊ฒฌ ์—†์ด ํ•ฉ๋ฆฌ์ ์ด๊ณ  ๊ฑด์„ค์ ์ธ ๋น„ํ‰์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.
258
 
@@ -262,6 +290,7 @@ R&D ์ŠคํŽ˜์…œ๋ฆฌ์ŠคํŠธ๋กœ์„œ:
262
  {content}
263
 
264
  {f"์ด์ „ ๋งฅ๋ฝ: {context}" if context else ""}
 
265
 
266
  ๋‹ค์Œ ๊ด€์ ์—์„œ ๋น„ํ‰ํ•˜์„ธ์š”:
267
  1. ๋…ผ๋ฆฌ์  ์ผ๊ด€์„ฑ๊ณผ ํƒ€๋‹น์„ฑ
@@ -269,9 +298,12 @@ R&D ์ŠคํŽ˜์…œ๋ฆฌ์ŠคํŠธ๋กœ์„œ:
269
  3. ๋ˆ„๋ฝ๋œ ์ค‘์š” ์š”์†Œ
270
  4. ๊ฐœ์„  ๊ฐ€๋Šฅํ•œ ๋ถ€๋ถ„
271
  5. ๊ฐ•์ ๊ณผ ์•ฝ์ ์˜ ๊ท ํ˜•์žกํžŒ ํ‰๊ฐ€
 
272
 
273
  ๊ฑด์„ค์ ์ด๊ณ  ๊ตฌ์ฒด์ ์ธ ํ”ผ๋“œ๋ฐฑ์„ ์ œ๊ณตํ•˜๋˜, ๋‹ค์Œ ๋‹จ๊ณ„ ๋‹ด๋‹น์ž๊ฐ€
274
- ๊ฐœ์„ ํ•  ์ˆ˜ ์žˆ๋Š” ์‹ค์งˆ์ ์ธ ์ œ์•ˆ์„ ํฌํ•จํ•˜์„ธ์š”."""
 
 
275
 
276
  def _format_search_results(self, search_results: Dict) -> str:
277
  """๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ ํฌ๋งทํŒ…"""
@@ -298,17 +330,30 @@ R&D ์ŠคํŽ˜์…œ๋ฆฌ์ŠคํŠธ๋กœ์„œ:
298
  formatted += f"\n**{stages[i]} ๋‹จ๊ณ„ ๋น„ํ‰:**\n{critic}\n"
299
  return formatted
300
 
301
- def extract_keywords(self, wood_response: str) -> List[str]:
302
- """๊ฐ๋…๊ด€ ์‘๋‹ต์—์„œ ํ‚ค์›Œ๋“œ ์ถ”์ถœ"""
303
  keywords = []
304
 
305
- keyword_match = re.search(r'\[ํ•ต์‹ฌ ํ‚ค์›Œ๋“œ\]:\s*(.+)', wood_response, re.IGNORECASE)
306
- if keyword_match:
307
- keyword_str = keyword_match.group(1)
308
- keywords = [k.strip() for k in keyword_str.split(',') if k.strip()]
 
 
 
 
 
 
 
 
 
 
 
 
309
 
310
  if not keywords:
311
- keywords = ["best practices", "implementation", "strategy", "innovation", "optimization"]
 
312
 
313
  return keywords[:7]
314
 
@@ -488,17 +533,30 @@ wuxing_system = WuxingLLMSystem()
488
  def process_wuxing_query(user_query: str, llm_mode: str):
489
  """์˜คํ–‰ ๊ธฐ๋ฐ˜ ์ฟผ๋ฆฌ ์ฒ˜๋ฆฌ"""
490
  if not user_query:
491
- return "", "", "", "", "", "", "โŒ ์งˆ๋ฌธ์„ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”."
492
 
493
  wuxing_system.set_llm_mode(llm_mode)
494
 
495
  all_responses = {}
496
  all_critics = []
497
- search_results = {}
498
 
499
  try:
 
 
 
 
 
 
 
 
 
 
 
 
 
500
  # 1. ๆœจ(๊ฐ๋…๊ด€) ์ดˆ๊ธฐ ๋ถ„์„
501
- wood_prompt = wuxing_system.create_wood_initial_prompt(user_query)
502
  wood_response = ""
503
 
504
  wood_text = "๐ŸŒณ **ๆœจ - ๊ฐ๋…๊ด€** (ไป)\n๐Ÿ”„ ๋ถ„์„ ์ค‘...\n"
@@ -507,22 +565,22 @@ def process_wuxing_query(user_query: str, llm_mode: str):
507
  ):
508
  wood_response += chunk
509
  wood_text = f"๐ŸŒณ **ๆœจ - ๊ฐ๋…๊ด€** (ไป)\n{wood_response}"
510
- yield wood_text, "", "", "", "", "", "๐ŸŒณ ๊ฐ๋…๊ด€์ด ๋น„์ „์„ ์ˆ˜๋ฆฝ ์ค‘..."
511
 
512
  all_responses['wood_initial'] = wood_response
513
 
514
- # ํ‚ค์›Œ๋“œ ์ถ”์ถœ ๋ฐ ๊ฒ€์ƒ‰
515
  keywords = wuxing_system.extract_keywords(wood_response)
516
- status_text = "๐Ÿ” ์›น ๊ฒ€์ƒ‰ ์ˆ˜ํ–‰ ์ค‘..."
517
- yield wood_text, "", "", "", "", "", status_text
518
 
519
- for keyword in keywords:
520
- results = wuxing_system.brave_search(keyword)
 
 
521
  if results:
522
- search_results[keyword] = results
 
523
 
524
- # 2. ๆœจ ๋น„ํ‰
525
- critic_prompt = wuxing_system.create_critic_prompt("ๆœจ ์ดˆ๊ธฐ ๋ถ„์„", wood_response)
526
  critic_response = ""
527
 
528
  critic_text = "๐Ÿ” **์ค‘๋ฆฝ์  ๋น„ํ‰์ž**\n[ๆœจ ๋ถ„์„ ๋น„ํ‰] ๐Ÿ”„ ๋น„ํ‰ ์ค‘...\n"
@@ -531,12 +589,22 @@ def process_wuxing_query(user_query: str, llm_mode: str):
531
  ):
532
  critic_response += chunk
533
  critic_text = f"๐Ÿ” **์ค‘๋ฆฝ์  ๋น„ํ‰์ž**\n[ๆœจ ๋ถ„์„ ๋น„ํ‰]\n{critic_response}"
534
- yield wood_text, "", "", "", "", critic_text, "๐Ÿ” ๋น„ํ‰์ž๊ฐ€ ๋ถ„์„ ์ค‘..."
535
 
536
  all_critics.append(critic_response)
537
 
538
- # 3. ็ซ(์ „๋žต๊ธฐํš)
539
- fire_prompt = wuxing_system.create_fire_strategy_prompt(user_query, wood_response, critic_response)
 
 
 
 
 
 
 
 
 
 
540
  fire_response = ""
541
 
542
  fire_text = "๐Ÿ”ฅ **็ซ - ์ „๋žตยท๊ธฐํš ๋ฆฌ๋”** (็พฉ)\n๐Ÿ”„ ์ „๋žต ์ˆ˜๋ฆฝ ์ค‘...\n"
@@ -545,12 +613,21 @@ def process_wuxing_query(user_query: str, llm_mode: str):
545
  ):
546
  fire_response += chunk
547
  fire_text = f"๐Ÿ”ฅ **็ซ - ์ „๋žตยท๊ธฐํš ๋ฆฌ๋”** (็พฉ)\n{fire_response}"
548
- yield wood_text, fire_text, "", "", "", critic_text, "๐Ÿ”ฅ ์ „๋žต ์ˆ˜๋ฆฝ ์ค‘..."
549
 
550
  all_responses['fire'] = fire_response
551
 
552
  # 4. ็ซ ๋น„ํ‰
553
- critic_prompt = wuxing_system.create_critic_prompt("็ซ ์ „๋žต๊ธฐํš", fire_response, wood_response)
 
 
 
 
 
 
 
 
 
554
  critic_response = ""
555
 
556
  critic_text += "\n\n---\n\n[็ซ ์ „๋žต ๋น„ํ‰] ๐Ÿ”„ ๋น„ํ‰ ์ค‘...\n"
@@ -560,12 +637,19 @@ def process_wuxing_query(user_query: str, llm_mode: str):
560
  critic_response += chunk
561
  temp_text = all_critics[0] + f"\n\n---\n\n[็ซ ์ „๋žต ๋น„ํ‰]\n{critic_response}"
562
  critic_text = f"๐Ÿ” **์ค‘๋ฆฝ์  ๋น„ํ‰์ž**\n[ๆœจ ๋ถ„์„ ๋น„ํ‰]\n{temp_text}"
563
- yield wood_text, fire_text, "", "", "", critic_text, "๐Ÿ” ์ „๋žต ๋น„ํ‰ ์ค‘..."
564
 
565
  all_critics.append(critic_response)
566
 
567
  # 5. ๅœŸ(์‹คํ–‰์šด์˜)
568
- earth_prompt = wuxing_system.create_earth_execution_prompt(user_query, fire_response, critic_response, search_results)
 
 
 
 
 
 
 
569
  earth_response = ""
570
 
571
  earth_text = "๐Ÿ”๏ธ **ๅœŸ - ์‹คํ–‰ยท์šด์˜ยทํ’ˆ์งˆ** (ไฟก)\n๐Ÿ”„ ์‹คํ–‰ ๊ณ„ํš ์ˆ˜๋ฆฝ ์ค‘...\n"
@@ -574,35 +658,37 @@ def process_wuxing_query(user_query: str, llm_mode: str):
574
  ):
575
  earth_response += chunk
576
  earth_text = f"๐Ÿ”๏ธ **ๅœŸ - ์‹คํ–‰ยท์šด์˜ยทํ’ˆ์งˆ** (ไฟก)\n{earth_response}"
577
- yield wood_text, fire_text, earth_text, "", "", critic_text, "๐Ÿ”๏ธ ์‹คํ–‰ ๊ณ„ํš ์ˆ˜๋ฆฝ ์ค‘..."
578
 
579
  all_responses['earth'] = earth_response
580
 
581
  # 6. ๅœŸ ๋น„ํ‰
582
- critic_prompt = wuxing_system.create_critic_prompt("ๅœŸ ์‹คํ–‰๊ณ„ํš", earth_response, fire_response)
583
- critic_response = ""
 
 
 
584
 
585
- critic_text = "๐Ÿ” **์ค‘๋ฆฝ์  ๋น„ํ‰์ž**\n" + "\n\n".join([
586
- f"[ๆœจ ๋ถ„์„ ๋น„ํ‰]\n{all_critics[0]}",
587
- f"[็ซ ์ „๋žต ๋น„ํ‰]\n{all_critics[1]}",
588
- "[ๅœŸ ์‹คํ–‰ ๋น„ํ‰] ๐Ÿ”„ ๋น„ํ‰ ์ค‘...\n"
589
- ])
590
 
591
  for chunk in wuxing_system.call_llm_streaming(
592
  [{"role": "user", "content": critic_prompt}], "critic"
593
  ):
594
  critic_response += chunk
595
- critic_text = "๐Ÿ” **์ค‘๋ฆฝ์  ๋น„ํ‰์ž**\n" + "\n\n".join([
596
- f"[ๆœจ ๋ถ„์„ ๋น„ํ‰]\n{all_critics[0]}",
597
- f"[็ซ ์ „๋žต ๋น„ํ‰]\n{all_critics[1]}",
598
- f"[ๅœŸ ์‹คํ–‰ ๋น„ํ‰]\n{critic_response}"
599
- ])
600
- yield wood_text, fire_text, earth_text, "", "", critic_text, "๐Ÿ” ์‹คํ–‰ ๋น„ํ‰ ์ค‘..."
601
 
602
  all_critics.append(critic_response)
603
 
604
  # 7. ้‡‘(์•„ํ‚คํ…์ฒ˜)
605
- metal_prompt = wuxing_system.create_metal_architecture_prompt(user_query, earth_response, critic_response)
 
 
 
 
 
 
 
606
  metal_response = ""
607
 
608
  metal_text = "โš™๏ธ **้‡‘ - ์•„ํ‚คํ…์ฒ˜ & ํ‘œ์ค€** (็ฆฎ)\n๐Ÿ”„ ์•„ํ‚คํ…์ฒ˜ ์„ค๊ณ„ ์ค‘...\n"
@@ -611,32 +697,37 @@ def process_wuxing_query(user_query: str, llm_mode: str):
611
  ):
612
  metal_response += chunk
613
  metal_text = f"โš™๏ธ **้‡‘ - ์•„ํ‚คํ…์ฒ˜ & ํ‘œ์ค€** (็ฆฎ)\n{metal_response}"
614
- yield wood_text, fire_text, earth_text, metal_text, "", critic_text, "โš™๏ธ ์•„ํ‚คํ…์ฒ˜ ์„ค๊ณ„ ์ค‘..."
615
 
616
  all_responses['metal'] = metal_response
617
 
618
  # 8. ้‡‘ ๋น„ํ‰
619
- critic_prompt = wuxing_system.create_critic_prompt("้‡‘ ์•„ํ‚คํ…์ฒ˜", metal_response, earth_response)
620
- critic_response = ""
 
 
 
621
 
622
- # ์ถ”๊ฐ€ ๊ฒ€์ƒ‰ ์ˆ˜ํ–‰
623
- additional_keywords = ["architecture patterns", "system design", "technical standards"]
624
- for keyword in additional_keywords:
625
- results = wuxing_system.brave_search(f"{user_query} {keyword}")
626
- if results:
627
- search_results[keyword] = results
628
 
629
- # ๋น„ํ‰ ์ˆ˜ํ–‰
630
  for chunk in wuxing_system.call_llm_streaming(
631
  [{"role": "user", "content": critic_prompt}], "critic"
632
  ):
633
  critic_response += chunk
634
- yield wood_text, fire_text, earth_text, metal_text, "", critic_text, "๐Ÿ” ์•„ํ‚คํ…์ฒ˜ ๋น„ํ‰ ์ค‘..."
635
 
636
  all_critics.append(critic_response)
637
 
638
  # 9. ๆฐด(R&D)
639
- water_prompt = wuxing_system.create_water_rd_prompt(user_query, metal_response, critic_response, search_results)
 
 
 
 
 
 
 
640
  water_response = ""
641
 
642
  water_text = "๐Ÿ’ง **ๆฐด - R&D ์ŠคํŽ˜์…œ๋ฆฌ์ŠคํŠธ** (ๆ™บ)\n๐Ÿ”„ ํ˜์‹  ๋ฐฉ์•ˆ ์—ฐ๊ตฌ ์ค‘...\n"
@@ -645,19 +736,25 @@ def process_wuxing_query(user_query: str, llm_mode: str):
645
  ):
646
  water_response += chunk
647
  water_text = f"๐Ÿ’ง **ๆฐด - R&D ์ŠคํŽ˜์…œ๋ฆฌ์ŠคํŠธ** (ๆ™บ)\n{water_response}"
648
- yield wood_text, fire_text, earth_text, metal_text, water_text, critic_text, "๐Ÿ’ง ํ˜์‹  ์—ฐ๊ตฌ ์ค‘..."
649
 
650
  all_responses['water'] = water_response
651
 
652
  # 10. ๆฐด ๋น„ํ‰
653
- critic_prompt = wuxing_system.create_critic_prompt("ๆฐด R&D", water_response, metal_response)
 
 
 
 
 
 
654
  critic_response = ""
655
 
656
  for chunk in wuxing_system.call_llm_streaming(
657
  [{"role": "user", "content": critic_prompt}], "critic"
658
  ):
659
  critic_response += chunk
660
- yield wood_text, fire_text, earth_text, metal_text, water_text, critic_text, "๐Ÿ” R&D ๋น„ํ‰ ์ค‘..."
661
 
662
  all_critics.append(critic_response)
663
 
@@ -672,18 +769,78 @@ def process_wuxing_query(user_query: str, llm_mode: str):
672
  wood_final_response += chunk
673
  temp_text = all_responses['wood_initial'] + f"\n\n---\n\n๐ŸŒณ **์ตœ์ข… ์ข…ํ•ฉ ๋ณด๊ณ ์„œ**\n{wood_final_response}"
674
  wood_text = f"๐ŸŒณ **ๆœจ - ๊ฐ๋…๊ด€** (ไป)\n{temp_text}"
675
- yield wood_text, fire_text, earth_text, metal_text, water_text, critic_text, "๐ŸŒณ ์ตœ์ข… ๋ณด๊ณ ์„œ ์ž‘์„ฑ ์ค‘..."
676
 
677
- status_text = f"โœ… ์˜คํ–‰ ํ˜‘๋ ฅ ํ”„๋กœ์„ธ์Šค ์™„๋ฃŒ! ({len(search_results)} ํ‚ค์›Œ๋“œ, {sum(len(r) for r in search_results.values())} ๊ฒ€์ƒ‰๊ฒฐ๊ณผ)"
678
- yield wood_text, fire_text, earth_text, metal_text, water_text, critic_text, status_text
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
679
 
680
  except Exception as e:
681
  error_msg = f"โŒ ์ฒ˜๋ฆฌ ์ค‘ ์˜ค๋ฅ˜: {str(e)}"
682
- yield "", "", "", "", "", "", error_msg
683
 
684
  def clear_wuxing():
685
  """์ดˆ๊ธฐํ™”"""
686
- return "", "", "", "", "", "", "๐Ÿ”„ ์ดˆ๊ธฐํ™”๋˜์—ˆ์Šต๋‹ˆ๋‹ค."
687
 
688
  # CSS ์Šคํƒ€์ผ
689
  css = """
@@ -714,6 +871,134 @@ css = """
714
  border-left: 4px solid #6b7280 !important;
715
  background-color: #f9fafb !important;
716
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
717
  h1 {
718
  text-align: center;
719
  color: #1f2937;
@@ -766,6 +1051,15 @@ with gr.Blocks(title="์˜คํ–‰ยท์˜ค์ƒ ํ˜‘๋ ฅ ์‹œ์Šคํ…œ", theme=gr.themes.Soft(),
766
  lines=3
767
  )
768
 
 
 
 
 
 
 
 
 
 
769
  # ์˜คํ–‰ ์ถœ๋ ฅ - 2x3 ๊ทธ๋ฆฌ๋“œ
770
  with gr.Row():
771
  with gr.Column():
@@ -847,7 +1141,7 @@ with gr.Blocks(title="์˜คํ–‰ยท์˜ค์ƒ ํ˜‘๋ ฅ ์‹œ์Šคํ…œ", theme=gr.themes.Soft(),
847
  submit_btn.click(
848
  fn=process_wuxing_query,
849
  inputs=[user_input, llm_mode],
850
- outputs=[wood_output, fire_output, earth_output, metal_output, water_output, critic_output, status_text]
851
  ).then(
852
  fn=lambda: "",
853
  outputs=[user_input]
@@ -856,7 +1150,7 @@ with gr.Blocks(title="์˜คํ–‰ยท์˜ค์ƒ ํ˜‘๋ ฅ ์‹œ์Šคํ…œ", theme=gr.themes.Soft(),
856
  user_input.submit(
857
  fn=process_wuxing_query,
858
  inputs=[user_input, llm_mode],
859
- outputs=[wood_output, fire_output, earth_output, metal_output, water_output, critic_output, status_text]
860
  ).then(
861
  fn=lambda: "",
862
  outputs=[user_input]
@@ -864,7 +1158,7 @@ with gr.Blocks(title="์˜คํ–‰ยท์˜ค์ƒ ํ˜‘๋ ฅ ์‹œ์Šคํ…œ", theme=gr.themes.Soft(),
864
 
865
  clear_btn.click(
866
  fn=clear_wuxing,
867
- outputs=[wood_output, fire_output, earth_output, metal_output, water_output, critic_output, status_text]
868
  )
869
 
870
  if __name__ == "__main__":
 
125
  "X-Subscription-Token": self.bapi_token
126
  }
127
 
128
+ def create_wood_initial_prompt(self, user_query: str, search_results: Dict = None) -> str:
129
  """ๆœจ(๊ฐ๋…๊ด€) ์ดˆ๊ธฐ ํ”„๋กฌํ”„ํŠธ"""
130
+ search_info = ""
131
+ if search_results:
132
+ search_info = f"\n\n์›น ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ:\n{self._format_search_results(search_results)}"
133
+
134
  return f"""๋‹น์‹ ์€ ไป(์ธ์žํ•จ)์˜ ๋•๋ชฉ์„ ์ง€๋‹Œ ๆœจ์˜ ๊ธฐ์šด์„ ๊ฐ€์ง„ ๊ฐ๋…๊ด€์ž…๋‹ˆ๋‹ค.
135
  ํฌ์šฉ์ ์ด๊ณ  ์„ฑ์žฅ์ง€ํ–ฅ์ ์ธ ๋ฆฌ๋”์‹ญ์œผ๋กœ ํŒ€์„ ์ด๋•๋‹ˆ๋‹ค.
136
 
137
  ์‚ฌ์šฉ์ž ์งˆ๋ฌธ: {user_query}
138
+ {search_info}
139
 
140
  ํŒ€์žฅ์œผ๋กœ์„œ ์ด ์งˆ๋ฌธ์— ๋Œ€ํ•ด:
141
  1. ์ „์ฒด์ ์ธ ๋น„์ „๊ณผ ๋ฐฉํ–ฅ์„ฑ์„ ์ œ์‹œํ•˜์„ธ์š”
142
  2. ๊ฐ ํŒ€์›(็ซ, ๅœŸ, ้‡‘, ๆฐด)์˜ ์—ญํ• ๊ณผ ๊ธฐ์—ฌ ๋ฐฉํ–ฅ์„ ์„ค๊ณ„ํ•˜์„ธ์š”
143
  3. ์„ฑ์žฅ๊ณผ ๋ฐœ์ „์˜ ๊ด€์ ์—์„œ ํ•ต์‹ฌ ๋ชฉํ‘œ๋ฅผ ์„ค์ •ํ•˜์„ธ์š”
144
  4. ํŒ€ ์ „์ฒด๊ฐ€ ์กฐํ™”๋กญ๊ฒŒ ํ˜‘๋ ฅํ•  ์ˆ˜ ์žˆ๋Š” ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ์ œ์‹œํ•˜์„ธ์š”
145
+ 5. ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ๋ฅผ ์ฐธ๊ณ ํ•˜์—ฌ ์ตœ์‹  ํŠธ๋ Œ๋“œ์™€ ๋ชจ๋ฒ” ์‚ฌ๋ก€๋ฅผ ๋ฐ˜์˜ํ•˜์„ธ์š”
146
 
147
  [ํ•ต์‹ฌ ํ‚ค์›Œ๋“œ]: 5-7๊ฐœ์˜ ์กฐ์‚ฌ๊ฐ€ ํ•„์š”ํ•œ ํ‚ค์›Œ๋“œ๋ฅผ ์ œ์‹œํ•˜์„ธ์š”"""
148
 
149
+ def create_fire_strategy_prompt(self, user_query: str, wood_response: str, critic_feedback: str, search_results: Dict = None) -> str:
150
  """็ซ(์ „๋žต๊ธฐํš) ํ”„๋กฌํ”„ํŠธ"""
151
+ search_info = ""
152
+ if search_results:
153
+ search_info = f"\n\n์›น ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ:\n{self._format_search_results(search_results)}"
154
+
155
  return f"""๋‹น์‹ ์€ ็พฉ(์ •์˜๋กœ์›€)์˜ ๋•๋ชฉ์„ ์ง€๋‹Œ ็ซ์˜ ๊ธฐ์šด์„ ๊ฐ€์ง„ ์ „๋žตยท๊ธฐํš ๋ฆฌ๋”์ž…๋‹ˆ๋‹ค.
156
  ์—ด์ •๊ณผ ๊ฒฐ๋‹จ๋ ฅ์œผ๋กœ ํ˜์‹ ์ ์ธ ์ „๋žต์„ ์ˆ˜๋ฆฝํ•ฉ๋‹ˆ๋‹ค.
157
 
 
162
 
163
  ๋น„ํ‰์ž์˜ ํ”ผ๋“œ๋ฐฑ:
164
  {critic_feedback}
165
+ {search_info}
166
 
167
  ์ „๋žต๊ธฐํš ๋ฆฌ๋”๋กœ์„œ:
168
  1. ์ค‘ยท์žฅ๊ธฐ ๋กœ๋“œ๋งต์„ ๊ตฌ์ฒด์ ์œผ๋กœ ์ˆ˜๋ฆฝํ•˜์„ธ์š”
169
  2. ํ˜์‹ ์ ์ธ ์‚ฌ์—… ๋ชจ๋ธ์„ ์„ค๊ณ„ํ•˜์„ธ์š”
170
  3. ๋ฆฌ์Šคํฌ์™€ ๊ธฐํšŒ ๋ถ„์„์„ ์ˆ˜ํ–‰ํ•˜์„ธ์š”
171
  4. ๊ฒฝ์Ÿ ์šฐ์œ„ ํ™•๋ณด ์ „๋žต์„ ์ œ์‹œํ•˜์„ธ์š”
172
+ 5. ๋น„ํ‰์ž์˜ ํ”ผ๋“œ๋ฐฑ์„ ๋ฐ˜์˜ํ•˜์—ฌ ์ „๋žต์„ ๋ณด์™„ํ•˜์„ธ์š”
173
+ 6. ํ•„์š”ํ•œ ์ถ”๊ฐ€ ๊ฒ€์ƒ‰ ํ‚ค์›Œ๋“œ๋ฅผ ์ œ์‹œํ•˜์„ธ์š”: [์ถ”๊ฐ€ ๊ฒ€์ƒ‰]"""
174
 
175
+ def create_earth_execution_prompt(self, user_query: str, fire_response: str, critic_feedback: str, search_results: Dict = None) -> str:
176
  """ๅœŸ(์‹คํ–‰์šด์˜) ํ”„๋กฌํ”„ํŠธ"""
177
+ search_info = ""
178
+ if search_results:
179
+ search_info = f"\n\n์›น ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ:\n{self._format_search_results(search_results)}"
180
+
181
  return f"""๋‹น์‹ ์€ ไฟก(์‹ ๋ขฐ)์˜ ๋•๋ชฉ์„ ์ง€๋‹Œ ๅœŸ์˜ ๊ธฐ์šด์„ ๊ฐ€์ง„ ์‹คํ–‰ยท์šด์˜ยทํ’ˆ์งˆ ๋‹ด๋‹น์ž์ž…๋‹ˆ๋‹ค.
182
  ์„ฑ์‹คํ•จ๊ณผ ์‹คํ–‰๋ ฅ์œผ๋กœ ๊ณ„ํš์„ ํ˜„์‹ค๋กœ ๋งŒ๋“ญ๋‹ˆ๋‹ค.
183
 
 
188
 
189
  ๋น„ํ‰์ž์˜ ํ”ผ๋“œ๋ฐฑ:
190
  {critic_feedback}
191
+ {search_info}
 
 
192
 
193
  ์‹คํ–‰์šด์˜ ๋‹ด๋‹น์ž๋กœ์„œ:
194
  1. ๊ตฌ์ฒด์ ์ธ ์‹คํ–‰ ๊ณ„ํš๊ณผ ์ผ์ •์„ ์ˆ˜๋ฆฝํ•˜์„ธ์š”
195
  2. ํ•„์š”ํ•œ ๋ฆฌ์†Œ์Šค์™€ ์˜ˆ์‚ฐ์„ ์‚ฐ์ •ํ•˜์„ธ์š”
196
  3. ํ’ˆ์งˆ ๊ด€๋ฆฌ ๊ธฐ์ค€๊ณผ ํ”„๋กœ์„ธ์Šค๋ฅผ ์ •์˜ํ•˜์„ธ์š”
197
  4. ๋ฆฌ์Šคํฌ ๋Œ€์‘ ๊ณ„ํš์„ ์ˆ˜๋ฆฝํ•˜์„ธ์š”
198
+ 5. ์„ฑ๊ณผ ์ธก์ • ์ง€ํ‘œ๋ฅผ ์„ค์ •ํ•˜์„ธ์š”
199
+ 6. ์ถ”๊ฐ€ ์กฐ์‚ฌ๊ฐ€ ํ•„์š”ํ•œ ์‹คํ–‰ ๊ด€๋ จ ํ‚ค์›Œ๋“œ: [์ถ”๊ฐ€ ๊ฒ€์ƒ‰]"""
200
 
201
+ def create_metal_architecture_prompt(self, user_query: str, earth_response: str, critic_feedback: str, search_results: Dict = None) -> str:
202
  """้‡‘(์•„ํ‚คํ…์ฒ˜) ํ”„๋กฌํ”„ํŠธ"""
203
+ search_info = ""
204
+ if search_results:
205
+ search_info = f"\n\n์›น ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ:\n{self._format_search_results(search_results)}"
206
+
207
  return f"""๋‹น์‹ ์€ ็ฆฎ(์˜ˆ์˜ยท์งˆ์„œ)์˜ ๋•๋ชฉ์„ ์ง€๋‹Œ ้‡‘์˜ ๊ธฐ์šด์„ ๊ฐ€์ง„ ์•„ํ‚คํ…์ฒ˜ & ํ‘œ์ค€ ์ฑ…์ž„์ž์ž…๋‹ˆ๋‹ค.
208
  ์ •๋ฐ€ํ•จ๊ณผ ๊ตฌ์กฐํ™” ๋Šฅ๋ ฅ์œผ๋กœ ์™„๋ฒฝํ•œ ์‹œ์Šคํ…œ์„ ์„ค๊ณ„ํ•ฉ๋‹ˆ๋‹ค.
209
 
 
214
 
215
  ๋น„ํ‰์ž์˜ ํ”ผ๋“œ๋ฐฑ:
216
  {critic_feedback}
217
+ {search_info}
218
 
219
  ์•„ํ‚คํ…์ฒ˜ ์ฑ…์ž„์ž๋กœ์„œ:
220
  1. ์ „์ฒด ์‹œ์Šคํ…œ์˜ ๊ธฐ์ˆ ยท๋ฐ์ดํ„ฐ ์•„ํ‚คํ…์ฒ˜๋ฅผ ์„ค๊ณ„ํ•˜์„ธ์š”
221
  2. ์ฝ”๋”ฉ/APIยท๋ฐ์ดํ„ฐยท๋ณด์•ˆ ํ‘œ์ค€์„ ์ˆ˜๋ฆฝํ•˜์„ธ์š”
222
  3. ํ™•์žฅ์„ฑ๊ณผ ํ˜ธํ™˜์„ฑ์„ ๊ณ ๋ คํ•œ ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ์ œ์‹œํ•˜์„ธ์š”
223
  4. ํ’ˆ์งˆ ๊ฒ€์ฆ ์ฒด๊ณ„์™€ ๊ธฐ์ค€์„ ์ •์˜ํ•˜์„ธ์š”
224
+ 5. ๊ธฐ์ˆ ์  ์ œ์•ฝ์‚ฌํ•ญ๊ณผ ํ•ด๊ฒฐ๋ฐฉ์•ˆ์„ ์ œ์‹œํ•˜์„ธ์š”
225
+ 6. ๊ธฐ์ˆ  ์•„ํ‚คํ…์ฒ˜ ๊ด€๋ จ ์ถ”๊ฐ€ ๊ฒ€์ƒ‰: [์ถ”๊ฐ€ ๊ฒ€์ƒ‰]"""
226
 
227
+ def create_water_rd_prompt(self, user_query: str, metal_response: str, critic_feedback: str, search_results: Dict = None) -> str:
228
  """ๆฐด(R&D) ํ”„๋กฌํ”„ํŠธ"""
229
+ search_info = ""
230
+ if search_results:
231
+ search_info = f"\n\n์ตœ์‹  ๊ธฐ์ˆ  ์กฐ์‚ฌ ๊ฒฐ๊ณผ:\n{self._format_search_results(search_results)}"
232
+
233
  return f"""๋‹น์‹ ์€ ๆ™บ(์ง€ํ˜œ)์˜ ๋•๋ชฉ์„ ์ง€๋‹Œ ๆฐด์˜ ๊ธฐ์šด์„ ๊ฐ€์ง„ ๋„๊ตฌ ํ™œ์šฉ R&D ์ŠคํŽ˜์…œ๋ฆฌ์ŠคํŠธ์ž…๋‹ˆ๋‹ค.
234
  ๋ถ„์„๋ ฅ๊ณผ ํ˜ธ๊ธฐ์‹ฌ์œผ๋กœ ์ตœ์‹  ๊ธฐ์ˆ ์„ ํƒ๊ตฌํ•˜๊ณ  ํ˜์‹ ํ•ฉ๋‹ˆ๋‹ค.
235
 
 
240
 
241
  ๋น„ํ‰์ž์˜ ํ”ผ๋“œ๋ฐฑ:
242
  {critic_feedback}
243
+ {search_info}
 
 
244
 
245
  R&D ์ŠคํŽ˜์…œ๋ฆฌ์ŠคํŠธ๋กœ์„œ:
246
  1. ์ตœ์‹  ๊ธฐ์ˆ  ํŠธ๋ Œ๋“œ์™€ ๋„๊ตฌ๋ฅผ ๋ถ„์„ํ•˜์„ธ์š”
247
  2. ํ˜์‹ ์ ์ธ ํ”„๋กœํ† ํƒ€์ž… ๊ฐœ๋ฐœ ๋ฐฉ์•ˆ์„ ์ œ์‹œํ•˜์„ธ์š”
248
  3. ์ž๋™ํ™”์™€ ์ƒ์‚ฐ์„ฑ ํ–ฅ์ƒ ๋„๊ตฌ๋ฅผ ์ถ”์ฒœํ•˜์„ธ์š”
249
  4. ๊ธฐ์ˆ  ๋„์ž…์˜ ROI์™€ ์‹คํ˜„ ๊ฐ€๋Šฅ์„ฑ์„ ํ‰๊ฐ€ํ•˜์„ธ์š”
250
+ 5. ํŒ€ ๊ต์œก๊ณผ ๊ธฐ์ˆ  ์ „ํŒŒ ๊ณ„ํš์„ ์ˆ˜๋ฆฝํ•˜์„ธ์š”
251
+ 6. ๋ฏธ๋ž˜ ๊ธฐ์ˆ  ๊ด€๋ จ ์ถ”๊ฐ€ ๊ฒ€์ƒ‰: [์ถ”๊ฐ€ ๊ฒ€์ƒ‰]"""
252
 
253
  def create_wood_final_prompt(self, user_query: str, all_responses: Dict, all_critics: List) -> str:
254
  """ๆœจ(๊ฐ๋…๊ด€) ์ตœ์ข… ์ข…ํ•ฉ ํ”„๋กฌํ”„ํŠธ"""
 
275
 
276
  ๋งˆํฌ๋‹ค์šด ํ˜•์‹์„ ํ™œ์šฉํ•˜์—ฌ ์ „๋ฌธ์ ์ด๊ณ  ์ฒด๊ณ„์ ์œผ๋กœ ์ž‘์„ฑํ•˜์„ธ์š”."""
277
 
278
+ def create_critic_prompt(self, stage: str, content: str, context: str = "", search_results: Dict = None) -> str:
279
  """์ค‘๋ฆฝ์  ๋น„ํ‰์ž ํ”„๋กฌํ”„ํŠธ"""
280
+ search_info = ""
281
+ if search_results:
282
+ search_info = f"\n\n์ฐธ๊ณ  ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ:\n{self._format_search_results(search_results)}"
283
+
284
  return f"""๋‹น์‹ ์€ ์ค‘๋ฆฝ์ ์ด๊ณ  ๋…ผ๋ฆฌ์ ์ธ ๋น„ํ‰์ž์ž…๋‹ˆ๋‹ค.
285
  ํŽธ๊ฒฌ ์—†์ด ํ•ฉ๋ฆฌ์ ์ด๊ณ  ๊ฑด์„ค์ ์ธ ๋น„ํ‰์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.
286
 
 
290
  {content}
291
 
292
  {f"์ด์ „ ๋งฅ๋ฝ: {context}" if context else ""}
293
+ {search_info}
294
 
295
  ๋‹ค์Œ ๊ด€์ ์—์„œ ๋น„ํ‰ํ•˜์„ธ์š”:
296
  1. ๋…ผ๋ฆฌ์  ์ผ๊ด€์„ฑ๊ณผ ํƒ€๋‹น์„ฑ
 
298
  3. ๋ˆ„๋ฝ๋œ ์ค‘์š” ์š”์†Œ
299
  4. ๊ฐœ์„  ๊ฐ€๋Šฅํ•œ ๋ถ€๋ถ„
300
  5. ๊ฐ•์ ๊ณผ ์•ฝ์ ์˜ ๊ท ํ˜•์žกํžŒ ํ‰๊ฐ€
301
+ 6. ์ตœ์‹  ํŠธ๋ Œ๋“œ์™€ ๋ชจ๋ฒ” ์‚ฌ๋ก€ ๋Œ€๋น„ ํ‰๊ฐ€
302
 
303
  ๊ฑด์„ค์ ์ด๊ณ  ๊ตฌ์ฒด์ ์ธ ํ”ผ๋“œ๋ฐฑ์„ ์ œ๊ณตํ•˜๋˜, ๋‹ค์Œ ๋‹จ๊ณ„ ๋‹ด๋‹น์ž๊ฐ€
304
+ ๊ฐœ์„ ํ•  ์ˆ˜ ์žˆ๋Š” ์‹ค์งˆ์ ์ธ ์ œ์•ˆ์„ ํฌํ•จํ•˜์„ธ์š”.
305
+
306
+ ํ•„์š”์‹œ ์ถ”๊ฐ€ ๊ฒ€์ƒ‰์ด ํ•„์š”ํ•œ ํ‚ค์›Œ๋“œ๋ฅผ ์ œ์•ˆํ•˜์„ธ์š”: [๋น„ํ‰ ๊ฒ€์ƒ‰]"""
307
 
308
  def _format_search_results(self, search_results: Dict) -> str:
309
  """๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ ํฌ๋งทํŒ…"""
 
330
  formatted += f"\n**{stages[i]} ๋‹จ๊ณ„ ๋น„ํ‰:**\n{critic}\n"
331
  return formatted
332
 
333
+ def extract_keywords(self, response: str, keyword_marker: str = "[ํ•ต์‹ฌ ํ‚ค์›Œ๋“œ]") -> List[str]:
334
+ """์‘๋‹ต์—์„œ ํ‚ค์›Œ๋“œ ์ถ”์ถœ (๋ฒ”์šฉ)"""
335
  keywords = []
336
 
337
+ # ๋‹ค์–‘ํ•œ ํ‚ค์›Œ๋“œ ๋งˆ์ปค ํŒจํ„ด
338
+ patterns = [
339
+ rf'\{keyword_marker}:\s*(.+)',
340
+ r'\[์ถ”๊ฐ€ ๊ฒ€์ƒ‰\]:\s*(.+)',
341
+ r'\[๋น„ํ‰ ๊ฒ€์ƒ‰\]:\s*(.+)'
342
+ ]
343
+
344
+ for pattern in patterns:
345
+ match = re.search(pattern, response, re.IGNORECASE)
346
+ if match:
347
+ keyword_str = match.group(1)
348
+ new_keywords = [k.strip() for k in keyword_str.split(',') if k.strip()]
349
+ keywords.extend(new_keywords)
350
+
351
+ # ์ค‘๋ณต ์ œ๊ฑฐ
352
+ keywords = list(dict.fromkeys(keywords))
353
 
354
  if not keywords:
355
+ # ๊ธฐ๋ณธ ํ‚ค์›Œ๋“œ ์ƒ์„ฑ
356
+ keywords = ["best practices", "implementation", "case studies", "latest trends"]
357
 
358
  return keywords[:7]
359
 
 
533
  def process_wuxing_query(user_query: str, llm_mode: str):
534
  """์˜คํ–‰ ๊ธฐ๋ฐ˜ ์ฟผ๋ฆฌ ์ฒ˜๋ฆฌ"""
535
  if not user_query:
536
+ return "", "", "", "", "", "", "", "โŒ ์งˆ๋ฌธ์„ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”."
537
 
538
  wuxing_system.set_llm_mode(llm_mode)
539
 
540
  all_responses = {}
541
  all_critics = []
542
+ all_search_results = {}
543
 
544
  try:
545
+ # 0. ์ดˆ๊ธฐ ๊ฒ€์ƒ‰ ์ˆ˜ํ–‰
546
+ initial_keywords = [user_query] + ["best practices", "latest trends", "case studies"]
547
+ wood_search_results = {}
548
+
549
+ status_text = "๐Ÿ” ์ดˆ๊ธฐ ์›น ๊ฒ€์ƒ‰ ์ˆ˜ํ–‰ ์ค‘..."
550
+ yield "", "", "", "", "", "", "", status_text
551
+
552
+ for keyword in initial_keywords[:3]:
553
+ results = wuxing_system.brave_search(keyword)
554
+ if results:
555
+ wood_search_results[keyword] = results
556
+ all_search_results[f"์ดˆ๊ธฐ-{keyword}"] = results
557
+
558
  # 1. ๆœจ(๊ฐ๋…๊ด€) ์ดˆ๊ธฐ ๋ถ„์„
559
+ wood_prompt = wuxing_system.create_wood_initial_prompt(user_query, wood_search_results)
560
  wood_response = ""
561
 
562
  wood_text = "๐ŸŒณ **ๆœจ - ๊ฐ๋…๊ด€** (ไป)\n๐Ÿ”„ ๋ถ„์„ ์ค‘...\n"
 
565
  ):
566
  wood_response += chunk
567
  wood_text = f"๐ŸŒณ **ๆœจ - ๊ฐ๋…๊ด€** (ไป)\n{wood_response}"
568
+ yield wood_text, "", "", "", "", "", "", "๐ŸŒณ ๊ฐ๋…๊ด€์ด ๋น„์ „์„ ์ˆ˜๋ฆฝ ์ค‘..."
569
 
570
  all_responses['wood_initial'] = wood_response
571
 
572
+ # ํ‚ค์›Œ๋“œ ์ถ”์ถœ
573
  keywords = wuxing_system.extract_keywords(wood_response)
 
 
574
 
575
+ # 2. ๆœจ ๋น„ํ‰ + ๋น„ํ‰์ž ๊ฒ€์ƒ‰
576
+ critic_search = {}
577
+ for keyword in keywords[:2]:
578
+ results = wuxing_system.brave_search(f"{keyword} analysis")
579
  if results:
580
+ critic_search[keyword] = results
581
+ all_search_results[f"๋น„ํ‰1-{keyword}"] = results
582
 
583
+ critic_prompt = wuxing_system.create_critic_prompt("ๆœจ ์ดˆ๊ธฐ ๋ถ„์„", wood_response, search_results=critic_search)
 
584
  critic_response = ""
585
 
586
  critic_text = "๐Ÿ” **์ค‘๋ฆฝ์  ๋น„ํ‰์ž**\n[ๆœจ ๋ถ„์„ ๋น„ํ‰] ๐Ÿ”„ ๋น„ํ‰ ์ค‘...\n"
 
589
  ):
590
  critic_response += chunk
591
  critic_text = f"๐Ÿ” **์ค‘๋ฆฝ์  ๋น„ํ‰์ž**\n[ๆœจ ๋ถ„์„ ๋น„ํ‰]\n{critic_response}"
592
+ yield wood_text, "", "", "", "", critic_text, "", "๐Ÿ” ๋น„ํ‰์ž๊ฐ€ ๋ถ„์„ ์ค‘..."
593
 
594
  all_critics.append(critic_response)
595
 
596
+ # 3. ็ซ(์ „๋žต๊ธฐํš) + ๊ฒ€์ƒ‰
597
+ # ๋น„ํ‰์ž๊ฐ€ ์ œ์•ˆํ•œ ์ถ”๊ฐ€ ํ‚ค์›Œ๋“œ ์ถ”์ถœ
598
+ critic_keywords = wuxing_system.extract_keywords(critic_response, "[๋น„ํ‰ ๊ฒ€์ƒ‰]")
599
+ fire_search = {}
600
+
601
+ for keyword in (keywords[:2] + critic_keywords[:2]):
602
+ results = wuxing_system.brave_search(f"{user_query} {keyword} strategy")
603
+ if results:
604
+ fire_search[keyword] = results
605
+ all_search_results[f"็ซ-{keyword}"] = results
606
+
607
+ fire_prompt = wuxing_system.create_fire_strategy_prompt(user_query, wood_response, critic_response, fire_search)
608
  fire_response = ""
609
 
610
  fire_text = "๐Ÿ”ฅ **็ซ - ์ „๋žตยท๊ธฐํš ๋ฆฌ๋”** (็พฉ)\n๐Ÿ”„ ์ „๋žต ์ˆ˜๋ฆฝ ์ค‘...\n"
 
613
  ):
614
  fire_response += chunk
615
  fire_text = f"๐Ÿ”ฅ **็ซ - ์ „๋žตยท๊ธฐํš ๋ฆฌ๋”** (็พฉ)\n{fire_response}"
616
+ yield wood_text, fire_text, "", "", "", critic_text, "", "๐Ÿ”ฅ ์ „๋žต ์ˆ˜๋ฆฝ ์ค‘..."
617
 
618
  all_responses['fire'] = fire_response
619
 
620
  # 4. ็ซ ๋น„ํ‰
621
+ fire_keywords = wuxing_system.extract_keywords(fire_response, "[์ถ”๊ฐ€ ๊ฒ€์ƒ‰]")
622
+ critic_search = {}
623
+
624
+ for keyword in fire_keywords[:2]:
625
+ results = wuxing_system.brave_search(keyword)
626
+ if results:
627
+ critic_search[keyword] = results
628
+ all_search_results[f"๋น„ํ‰2-{keyword}"] = results
629
+
630
+ critic_prompt = wuxing_system.create_critic_prompt("็ซ ์ „๋žต๊ธฐํš", fire_response, wood_response, critic_search)
631
  critic_response = ""
632
 
633
  critic_text += "\n\n---\n\n[็ซ ์ „๋žต ๋น„ํ‰] ๐Ÿ”„ ๋น„ํ‰ ์ค‘...\n"
 
637
  critic_response += chunk
638
  temp_text = all_critics[0] + f"\n\n---\n\n[็ซ ์ „๋žต ๋น„ํ‰]\n{critic_response}"
639
  critic_text = f"๐Ÿ” **์ค‘๋ฆฝ์  ๋น„ํ‰์ž**\n[ๆœจ ๋ถ„์„ ๋น„ํ‰]\n{temp_text}"
640
+ yield wood_text, fire_text, "", "", "", critic_text, "", "๐Ÿ” ์ „๋žต ๋น„ํ‰ ์ค‘..."
641
 
642
  all_critics.append(critic_response)
643
 
644
  # 5. ๅœŸ(์‹คํ–‰์šด์˜)
645
+ earth_search = {}
646
+ for keyword in ["implementation", "resource management", "quality assurance"]:
647
+ results = wuxing_system.brave_search(f"{user_query} {keyword}")
648
+ if results:
649
+ earth_search[keyword] = results
650
+ all_search_results[f"ๅœŸ-{keyword}"] = results
651
+
652
+ earth_prompt = wuxing_system.create_earth_execution_prompt(user_query, fire_response, critic_response, earth_search)
653
  earth_response = ""
654
 
655
  earth_text = "๐Ÿ”๏ธ **ๅœŸ - ์‹คํ–‰ยท์šด์˜ยทํ’ˆ์งˆ** (ไฟก)\n๐Ÿ”„ ์‹คํ–‰ ๊ณ„ํš ์ˆ˜๋ฆฝ ์ค‘...\n"
 
658
  ):
659
  earth_response += chunk
660
  earth_text = f"๐Ÿ”๏ธ **ๅœŸ - ์‹คํ–‰ยท์šด์˜ยทํ’ˆ์งˆ** (ไฟก)\n{earth_response}"
661
+ yield wood_text, fire_text, earth_text, "", "", critic_text, "", "๐Ÿ”๏ธ ์‹คํ–‰ ๊ณ„ํš ์ˆ˜๋ฆฝ ์ค‘..."
662
 
663
  all_responses['earth'] = earth_response
664
 
665
  # 6. ๅœŸ ๋น„ํ‰
666
+ critic_search = {}
667
+ results = wuxing_system.brave_search(f"{user_query} execution challenges")
668
+ if results:
669
+ critic_search["execution"] = results
670
+ all_search_results["๋น„ํ‰3-execution"] = results
671
 
672
+ critic_prompt = wuxing_system.create_critic_prompt("ๅœŸ ์‹คํ–‰๊ณ„ํš", earth_response, fire_response, critic_search)
673
+ critic_response = ""
 
 
 
674
 
675
  for chunk in wuxing_system.call_llm_streaming(
676
  [{"role": "user", "content": critic_prompt}], "critic"
677
  ):
678
  critic_response += chunk
679
+ yield wood_text, fire_text, earth_text, "", "", critic_text, "", "๐Ÿ” ์‹คํ–‰ ๋น„ํ‰ ์ค‘..."
 
 
 
 
 
680
 
681
  all_critics.append(critic_response)
682
 
683
  # 7. ้‡‘(์•„ํ‚คํ…์ฒ˜)
684
+ metal_search = {}
685
+ for keyword in ["architecture", "standards", "system design", "scalability"]:
686
+ results = wuxing_system.brave_search(f"{user_query} {keyword}")
687
+ if results:
688
+ metal_search[keyword] = results
689
+ all_search_results[f"้‡‘-{keyword}"] = results
690
+
691
+ metal_prompt = wuxing_system.create_metal_architecture_prompt(user_query, earth_response, critic_response, metal_search)
692
  metal_response = ""
693
 
694
  metal_text = "โš™๏ธ **้‡‘ - ์•„ํ‚คํ…์ฒ˜ & ํ‘œ์ค€** (็ฆฎ)\n๐Ÿ”„ ์•„ํ‚คํ…์ฒ˜ ์„ค๊ณ„ ์ค‘...\n"
 
697
  ):
698
  metal_response += chunk
699
  metal_text = f"โš™๏ธ **้‡‘ - ์•„ํ‚คํ…์ฒ˜ & ํ‘œ์ค€** (็ฆฎ)\n{metal_response}"
700
+ yield wood_text, fire_text, earth_text, metal_text, "", critic_text, "", "โš™๏ธ ์•„ํ‚คํ…์ฒ˜ ์„ค๊ณ„ ์ค‘..."
701
 
702
  all_responses['metal'] = metal_response
703
 
704
  # 8. ้‡‘ ๋น„ํ‰
705
+ critic_search = {}
706
+ results = wuxing_system.brave_search(f"{user_query} technical constraints")
707
+ if results:
708
+ critic_search["constraints"] = results
709
+ all_search_results["๋น„ํ‰4-constraints"] = results
710
 
711
+ critic_prompt = wuxing_system.create_critic_prompt("้‡‘ ์•„ํ‚คํ…์ฒ˜", metal_response, earth_response, critic_search)
712
+ critic_response = ""
 
 
 
 
713
 
 
714
  for chunk in wuxing_system.call_llm_streaming(
715
  [{"role": "user", "content": critic_prompt}], "critic"
716
  ):
717
  critic_response += chunk
718
+ yield wood_text, fire_text, earth_text, metal_text, "", critic_text, "", "๐Ÿ” ์•„ํ‚คํ…์ฒ˜ ๋น„ํ‰ ์ค‘..."
719
 
720
  all_critics.append(critic_response)
721
 
722
  # 9. ๆฐด(R&D)
723
+ water_search = {}
724
+ for keyword in ["innovation", "emerging technology", "R&D", "automation tools"]:
725
+ results = wuxing_system.brave_search(f"{user_query} {keyword}")
726
+ if results:
727
+ water_search[keyword] = results
728
+ all_search_results[f"ๆฐด-{keyword}"] = results
729
+
730
+ water_prompt = wuxing_system.create_water_rd_prompt(user_query, metal_response, critic_response, water_search)
731
  water_response = ""
732
 
733
  water_text = "๐Ÿ’ง **ๆฐด - R&D ์ŠคํŽ˜์…œ๋ฆฌ์ŠคํŠธ** (ๆ™บ)\n๐Ÿ”„ ํ˜์‹  ๋ฐฉ์•ˆ ์—ฐ๊ตฌ ์ค‘...\n"
 
736
  ):
737
  water_response += chunk
738
  water_text = f"๐Ÿ’ง **ๆฐด - R&D ์ŠคํŽ˜์…œ๋ฆฌ์ŠคํŠธ** (ๆ™บ)\n{water_response}"
739
+ yield wood_text, fire_text, earth_text, metal_text, water_text, critic_text, "", "๐Ÿ’ง ํ˜์‹  ์—ฐ๊ตฌ ์ค‘..."
740
 
741
  all_responses['water'] = water_response
742
 
743
  # 10. ๆฐด ๋น„ํ‰
744
+ critic_search = {}
745
+ results = wuxing_system.brave_search(f"{user_query} future trends")
746
+ if results:
747
+ critic_search["trends"] = results
748
+ all_search_results["๋น„ํ‰5-trends"] = results
749
+
750
+ critic_prompt = wuxing_system.create_critic_prompt("ๆฐด R&D", water_response, metal_response, critic_search)
751
  critic_response = ""
752
 
753
  for chunk in wuxing_system.call_llm_streaming(
754
  [{"role": "user", "content": critic_prompt}], "critic"
755
  ):
756
  critic_response += chunk
757
+ yield wood_text, fire_text, earth_text, metal_text, water_text, critic_text, "", "๐Ÿ” R&D ๋น„ํ‰ ์ค‘..."
758
 
759
  all_critics.append(critic_response)
760
 
 
769
  wood_final_response += chunk
770
  temp_text = all_responses['wood_initial'] + f"\n\n---\n\n๐ŸŒณ **์ตœ์ข… ์ข…ํ•ฉ ๋ณด๊ณ ์„œ**\n{wood_final_response}"
771
  wood_text = f"๐ŸŒณ **ๆœจ - ๊ฐ๋…๊ด€** (ไป)\n{temp_text}"
772
+ yield wood_text, fire_text, earth_text, metal_text, water_text, critic_text, "", "๐ŸŒณ ์ตœ์ข… ๋ณด๊ณ ์„œ ์ž‘์„ฑ ์ค‘..."
773
 
774
+ # ์ตœ์ข… ๋ณด๊ณ ์„œ ์ƒ์„ฑ
775
+ final_report = f"""# ๐ŸŒŸ ์˜คํ–‰ ํ˜‘๋ ฅ ์‹œ์Šคํ…œ ์ตœ์ข… ์ข…ํ•ฉ ๋ณด๊ณ ์„œ
776
+
777
+ ## ๐Ÿ“Œ ์‚ฌ์šฉ์ž ์งˆ๋ฌธ
778
+ > **{user_query}**
779
+
780
+ ---
781
+
782
+ ## ๐ŸŒณ ํŒ€์žฅ ์ตœ์ข… ์ข…ํ•ฉ (ๆœจ - ไป)
783
+
784
+ {wood_final_response}
785
+
786
+ ---
787
+
788
+ ## ๐Ÿ“Š ์˜คํ–‰ ํŒ€์› ๊ธฐ์—ฌ ์š”์•ฝ
789
+
790
+ ### ๐Ÿ”ฅ ์ „๋žตยท๊ธฐํš (็ซ - ็พฉ)
791
+ {fire_response[:500]}...
792
+
793
+ ### ๐Ÿ”๏ธ ์‹คํ–‰ยท์šด์˜ (ๅœŸ - ไฟก)
794
+ {earth_response[:500]}...
795
+
796
+ ### โš™๏ธ ์•„ํ‚คํ…์ฒ˜ (้‡‘ - ็ฆฎ)
797
+ {metal_response[:500]}...
798
+
799
+ ### ๐Ÿ’ง R&D ํ˜์‹  (ๆฐด - ๆ™บ)
800
+ {water_response[:500]}...
801
+
802
+ ---
803
+
804
+ ## ๐Ÿ” ์ค‘๋ฆฝ์  ๋น„ํ‰ ํ•ต์‹ฌ ํ†ต์ฐฐ
805
+
806
+ ### ์ฃผ์š” ๊ฐœ์„ ์‚ฌํ•ญ
807
+ {all_critics[-1][:400]}...
808
+
809
+ ---
810
+
811
+ ## ๐Ÿ“ˆ ์„ฑ๊ณผ ์ง€ํ‘œ
812
+
813
+ | ํ•ญ๋ชฉ | ๋‚ด์šฉ |
814
+ |------|------|
815
+ | **์›น ๊ฒ€์ƒ‰ ์ˆ˜ํ–‰** | {len(all_search_results)}๊ฐœ ํ‚ค์›Œ๋“œ |
816
+ | **์ˆ˜์ง‘ ์ •๋ณด๋Ÿ‰** | {sum(len(r) for r in all_search_results.values())}๊ฐœ ๊ฒฐ๊ณผ |
817
+ | **ํ˜‘๋ ฅ ๋‹จ๊ณ„** | 11๋‹จ๊ณ„ (5์ธ + 5๋น„ํ‰ + ์ข…ํ•ฉ) |
818
+ | **์‚ฌ์šฉ ๋ชจ๋ธ** | {'Gemini 2.5 Pro' if wuxing_system.use_gemini else '๊ธฐ๋ณธ LLM'} |
819
+
820
+ ---
821
+
822
+ ## ๐ŸŽฏ ํ•ต์‹ฌ ์„ฑ๊ณต ์š”์ธ
823
+
824
+ 1. **์กฐํ™”๋กœ์šด ํ˜‘๋ ฅ**: ์˜คํ–‰์˜ ์ƒ์ƒ ๊ด€๊ณ„๋ฅผ ํ†ตํ•œ ์‹œ๋„ˆ์ง€ ์ฐฝ์ถœ
825
+ 2. **๋‹ค๊ฐ์  ๊ฒ€ํ† **: 5๊ฐ€์ง€ ์ „๋ฌธ์„ฑ๊ณผ ์ค‘๋ฆฝ์  ๋น„ํ‰์˜ ๊ท ํ˜•
826
+ 3. **๋ฐ์ดํ„ฐ ๊ธฐ๋ฐ˜**: {len(all_search_results)}ํšŒ์˜ ์›น ๊ฒ€์ƒ‰์„ ํ†ตํ•œ ์ตœ์‹  ์ •๋ณด ๋ฐ˜์˜
827
+ 4. **์‹คํ–‰ ๊ฐ€๋Šฅ์„ฑ**: ๊ตฌ์ฒด์ ์ด๊ณ  ๋‹จ๊ณ„๋ณ„ ์ ‘๊ทผ ๋ฐฉ์•ˆ ์ œ์‹œ
828
+
829
+ ---
830
+
831
+ *์ƒ์„ฑ ์‹œ๊ฐ: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}*
832
+ *์˜คํ–‰ ํ˜‘๋ ฅ ์‹œ์Šคํ…œ - ไป็พฉ็ฆฎๆ™บไฟก์˜ ์กฐํ™”*"""
833
+
834
+ status_text = f"โœ… ์˜คํ–‰ ํ˜‘๋ ฅ ํ”„๋กœ์„ธ์Šค ์™„๋ฃŒ! ({len(all_search_results)} ํ‚ค์›Œ๋“œ, {sum(len(r) for r in all_search_results.values())} ๊ฒ€์ƒ‰๊ฒฐ๊ณผ)"
835
+ yield wood_text, fire_text, earth_text, metal_text, water_text, critic_text, final_report, status_text
836
 
837
  except Exception as e:
838
  error_msg = f"โŒ ์ฒ˜๋ฆฌ ์ค‘ ์˜ค๋ฅ˜: {str(e)}"
839
+ yield "", "", "", "", "", "", "", error_msg
840
 
841
  def clear_wuxing():
842
  """์ดˆ๊ธฐํ™”"""
843
+ return "", "", "", "", "", "", "", "๐Ÿ”„ ์ดˆ๊ธฐํ™”๋˜์—ˆ์Šต๋‹ˆ๋‹ค."
844
 
845
  # CSS ์Šคํƒ€์ผ
846
  css = """
 
871
  border-left: 4px solid #6b7280 !important;
872
  background-color: #f9fafb !important;
873
  }
874
+ .final-report-box {
875
+ border: 2px solid #10b981 !important;
876
+ border-radius: 8px !important;
877
+ padding: 20px !important;
878
+ background: linear-gradient(to bottom, #f0fdf4, #ffffff) !important;
879
+ margin-top: 10px !important;
880
+ font-size: 14px !important;
881
+ max-height: 800px !important;
882
+ overflow-y: auto !important;
883
+ line-height: 1.8 !important;
884
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1) !important;
885
+ }
886
+ .final-report-box h1 {
887
+ color: #065f46 !important;
888
+ font-size: 28px !important;
889
+ margin-bottom: 16px !important;
890
+ text-align: center !important;
891
+ font-weight: bold !important;
892
+ }
893
+ .final-report-box h2 {
894
+ color: #047857 !important;
895
+ font-size: 22px !important;
896
+ margin-top: 20px !important;
897
+ margin-bottom: 12px !important;
898
+ border-bottom: 2px solid #10b981 !important;
899
+ padding-bottom: 8px !important;
900
+ }
901
+ .final-report-box h3 {
902
+ color: #059669 !important;
903
+ font-size: 18px !important;
904
+ margin-top: 16px !important;
905
+ margin-bottom: 10px !important;
906
+ font-weight: 600 !important;
907
+ }
908
+ .final-report-box h4 {
909
+ color: #10b981 !important;
910
+ font-size: 16px !important;
911
+ margin-top: 12px !important;
912
+ margin-bottom: 8px !important;
913
+ }
914
+ .final-report-box table {
915
+ border-collapse: collapse !important;
916
+ width: 100% !important;
917
+ margin: 20px 0 !important;
918
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1) !important;
919
+ }
920
+ .final-report-box th, .final-report-box td {
921
+ border: 1px solid #d1d5db !important;
922
+ padding: 12px 14px !important;
923
+ text-align: left !important;
924
+ }
925
+ .final-report-box th {
926
+ background-color: #065f46 !important;
927
+ font-weight: bold !important;
928
+ color: #ffffff !important;
929
+ text-transform: uppercase !important;
930
+ font-size: 13px !important;
931
+ letter-spacing: 0.5px !important;
932
+ }
933
+ .final-report-box tr:nth-child(even) {
934
+ background-color: #f9fafb !important;
935
+ }
936
+ .final-report-box tr:hover {
937
+ background-color: #f0fdf4 !important;
938
+ transition: background-color 0.2s !important;
939
+ }
940
+ .final-report-box code {
941
+ background-color: #ecfdf5 !important;
942
+ padding: 3px 8px !important;
943
+ border-radius: 4px !important;
944
+ font-family: 'Consolas', 'Monaco', monospace !important;
945
+ color: #047857 !important;
946
+ font-size: 13px !important;
947
+ border: 1px solid #10b981 !important;
948
+ }
949
+ .final-report-box pre {
950
+ background-color: #1e293b !important;
951
+ color: #e2e8f0 !important;
952
+ padding: 16px !important;
953
+ border-radius: 8px !important;
954
+ overflow-x: auto !important;
955
+ margin: 16px 0 !important;
956
+ font-size: 13px !important;
957
+ line-height: 1.5 !important;
958
+ }
959
+ .final-report-box pre code {
960
+ background-color: transparent !important;
961
+ color: #e2e8f0 !important;
962
+ padding: 0 !important;
963
+ border: none !important;
964
+ }
965
+ .final-report-box blockquote {
966
+ border-left: 4px solid #10b981 !important;
967
+ padding-left: 16px !important;
968
+ margin: 16px 0 !important;
969
+ color: #064e3b !important;
970
+ font-style: italic !important;
971
+ background-color: #f0fdf4 !important;
972
+ padding: 14px 16px !important;
973
+ border-radius: 0 8px 8px 0 !important;
974
+ }
975
+ .final-report-box ul, .final-report-box ol {
976
+ margin-left: 24px !important;
977
+ margin-bottom: 16px !important;
978
+ }
979
+ .final-report-box li {
980
+ margin-bottom: 8px !important;
981
+ line-height: 1.8 !important;
982
+ }
983
+ .final-report-box strong {
984
+ color: #065f46 !important;
985
+ font-weight: 600 !important;
986
+ }
987
+ .final-report-box em {
988
+ color: #047857 !important;
989
+ }
990
+ .final-report-box hr {
991
+ border: none !important;
992
+ border-top: 2px solid #10b981 !important;
993
+ margin: 28px 0 !important;
994
+ }
995
+ .final-report-box a {
996
+ color: #059669 !important;
997
+ text-decoration: underline !important;
998
+ }
999
+ .final-report-box a:hover {
1000
+ color: #047857 !important;
1001
+ }
1002
  h1 {
1003
  text-align: center;
1004
  color: #1f2937;
 
1051
  lines=3
1052
  )
1053
 
1054
+ # ์ตœ์ข… ๋ณด๊ณ ์„œ ์„น์…˜
1055
+ with gr.Row():
1056
+ with gr.Column():
1057
+ gr.Markdown("### ๐Ÿ“Š ์ตœ์ข… ์ข…ํ•ฉ ๋ณด๊ณ ์„œ")
1058
+ final_report = gr.Markdown(
1059
+ value="*์ตœ์ข… ๋ณด๊ณ ์„œ๊ฐ€ ์—ฌ๊ธฐ์— ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.*",
1060
+ elem_classes=["final-report-box"]
1061
+ )
1062
+
1063
  # ์˜คํ–‰ ์ถœ๋ ฅ - 2x3 ๊ทธ๋ฆฌ๋“œ
1064
  with gr.Row():
1065
  with gr.Column():
 
1141
  submit_btn.click(
1142
  fn=process_wuxing_query,
1143
  inputs=[user_input, llm_mode],
1144
+ outputs=[wood_output, fire_output, earth_output, metal_output, water_output, critic_output, final_report, status_text]
1145
  ).then(
1146
  fn=lambda: "",
1147
  outputs=[user_input]
 
1150
  user_input.submit(
1151
  fn=process_wuxing_query,
1152
  inputs=[user_input, llm_mode],
1153
+ outputs=[wood_output, fire_output, earth_output, metal_output, water_output, critic_output, final_report, status_text]
1154
  ).then(
1155
  fn=lambda: "",
1156
  outputs=[user_input]
 
1158
 
1159
  clear_btn.click(
1160
  fn=clear_wuxing,
1161
+ outputs=[wood_output, fire_output, earth_output, metal_output, water_output, critic_output, final_report, status_text]
1162
  )
1163
 
1164
  if __name__ == "__main__":