Add thinking box UI and fix async event loop errors
- Show thinking progress in a separate animated box above chatbot (🤔 사고 중... while streaming, 💭 사고 완료 when answer starts) - Fix ValueError: add missing 5th yield value (thinking_box) to all respond() yield statements - Fix [Reset] and other sync handlers: replace asyncio.get_event_loop() .run_until_complete() with asyncio.run() for AnyIO thread compatibility Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -95,23 +95,20 @@ async def tts_speak(text: str) -> str | None:
|
|||||||
|
|
||||||
async def respond(message, history, show_thinking, user_id, use_tts, run_ids):
|
async def respond(message, history, show_thinking, user_id, use_tts, run_ids):
|
||||||
if not message.strip():
|
if not message.strip():
|
||||||
yield history, "", None, run_ids
|
yield history, "", None, run_ids, gr.update()
|
||||||
return
|
return
|
||||||
|
|
||||||
history = list(history)
|
history = list(history)
|
||||||
run_ids = list(run_ids)
|
run_ids = list(run_ids)
|
||||||
history.append({"role": "user", "content": message})
|
history.append({"role": "user", "content": message})
|
||||||
history.append({"role": "assistant", "content": ""})
|
history.append({"role": "assistant", "content": ""})
|
||||||
yield history, "", None, run_ids
|
yield history, "", None, run_ids, gr.update(value="", visible=False)
|
||||||
|
|
||||||
collected_run_id: str | None = None
|
collected_run_id: str | None = None
|
||||||
tts_text = "" # 순수 답변만 누적 (TTS용)
|
tts_text = "" # 순수 답변만 누적 (TTS용)
|
||||||
thinking_acc = "" # 사고 과정 누적
|
thinking_acc = "" # 사고 과정 누적
|
||||||
thinking_active = False
|
thinking_active = False
|
||||||
|
|
||||||
# 사고 과정 박스 초기화
|
|
||||||
yield history, "", None, run_ids, gr.update(value="", visible=False)
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
async for token, run_id in api_client.chat(message, user_id, show_thinking):
|
async for token, run_id in api_client.chat(message, user_id, show_thinking):
|
||||||
if run_id is not None:
|
if run_id is not None:
|
||||||
@@ -171,9 +168,7 @@ def handle_feedback(like_data: gr.LikeData, history, run_ids, user_id):
|
|||||||
rating = 1 if like_data.liked else -1
|
rating = 1 if like_data.liked else -1
|
||||||
|
|
||||||
try:
|
try:
|
||||||
asyncio.get_event_loop().run_until_complete(
|
asyncio.run(api_client.save_feedback(user_id, user_msg, asst_msg, rating, run_id))
|
||||||
api_client.save_feedback(user_id, user_msg, asst_msg, rating, run_id)
|
|
||||||
)
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"[Feedback] 저장 실패: {e}")
|
print(f"[Feedback] 저장 실패: {e}")
|
||||||
|
|
||||||
@@ -184,7 +179,7 @@ def switch_user(user_id):
|
|||||||
|
|
||||||
def reset_chat(user_id):
|
def reset_chat(user_id):
|
||||||
try:
|
try:
|
||||||
asyncio.get_event_loop().run_until_complete(api_client.reset(user_id))
|
asyncio.run(api_client.reset(user_id))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"[Reset] 실패: {e}")
|
print(f"[Reset] 실패: {e}")
|
||||||
return [], []
|
return [], []
|
||||||
@@ -199,7 +194,7 @@ def ingest_files(files):
|
|||||||
results = []
|
results = []
|
||||||
for path in paths:
|
for path in paths:
|
||||||
try:
|
try:
|
||||||
result = asyncio.get_event_loop().run_until_complete(api_client.ingest(path))
|
result = asyncio.run(api_client.ingest(path))
|
||||||
name = os.path.basename(path)
|
name = os.path.basename(path)
|
||||||
results.append(f"{name} → {result.get('chunks', '?')}개 청크")
|
results.append(f"{name} → {result.get('chunks', '?')}개 청크")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@@ -209,7 +204,7 @@ def ingest_files(files):
|
|||||||
|
|
||||||
def list_docs():
|
def list_docs():
|
||||||
try:
|
try:
|
||||||
sources = asyncio.get_event_loop().run_until_complete(api_client.list_documents())
|
sources = asyncio.run(api_client.list_documents())
|
||||||
return [[os.path.basename(s), s] for s in sources]
|
return [[os.path.basename(s), s] for s in sources]
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return [[f"오류: {e}", ""]]
|
return [[f"오류: {e}", ""]]
|
||||||
@@ -219,7 +214,7 @@ def delete_doc(source):
|
|||||||
if not source.strip():
|
if not source.strip():
|
||||||
return "삭제할 파일 경로를 입력하세요.", list_docs()
|
return "삭제할 파일 경로를 입력하세요.", list_docs()
|
||||||
try:
|
try:
|
||||||
asyncio.get_event_loop().run_until_complete(api_client.delete_document(source.strip()))
|
asyncio.run(api_client.delete_document(source.strip()))
|
||||||
return f"삭제 완료: {os.path.basename(source.strip())}", list_docs()
|
return f"삭제 완료: {os.path.basename(source.strip())}", list_docs()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return f"오류: {e}", list_docs()
|
return f"오류: {e}", list_docs()
|
||||||
|
|||||||
Reference in New Issue
Block a user