feat: enhance AIPlanner with loading spinner during Ollama requests and update print statements for clarity
This commit is contained in:
@@ -15,7 +15,9 @@ LLM 백엔드: 로컬 Ollama (structured output으로 JSON 스키마 강제)
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import time
|
||||
import threading
|
||||
import traceback
|
||||
import ollama
|
||||
|
||||
@@ -141,7 +143,7 @@ class AIPlanner:
|
||||
"⚠️ 제작은 재료가 있어야 합니다. 인벤토리를 확인하세요."
|
||||
)
|
||||
|
||||
print(f"\n[AI] 생각 중... (model={OLLAMA_MODEL}, host={OLLAMA_HOST})")
|
||||
print(f"\n[AI] 요청 시작 (model={OLLAMA_MODEL})")
|
||||
|
||||
try:
|
||||
plan = self._call_ollama(user_message)
|
||||
@@ -177,36 +179,53 @@ class AIPlanner:
|
||||
|
||||
def _call_ollama(self, user_message: str) -> dict:
|
||||
t0 = time.perf_counter()
|
||||
client = ollama.Client(host=OLLAMA_HOST)
|
||||
response = client.chat(
|
||||
model=OLLAMA_MODEL,
|
||||
messages=[
|
||||
{"role": "system", "content": SYSTEM_PROMPT},
|
||||
{"role": "user", "content": user_message},
|
||||
],
|
||||
format={
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"thinking": {"type": "string"},
|
||||
"current_goal": {"type": "string"},
|
||||
"actions": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"action": {"type": "string"},
|
||||
"params": {"type": "object"},
|
||||
"reason": {"type": "string"},
|
||||
stop_event = threading.Event()
|
||||
|
||||
def _spinner():
|
||||
while not stop_event.is_set():
|
||||
elapsed = time.perf_counter() - t0
|
||||
print(f"\r[AI] 생각 중... {elapsed:.0f}s", end="", flush=True)
|
||||
stop_event.wait(1.0)
|
||||
print("\r", end="")
|
||||
|
||||
spinner = threading.Thread(target=_spinner, daemon=True)
|
||||
spinner.start()
|
||||
|
||||
try:
|
||||
client = ollama.Client(host=OLLAMA_HOST)
|
||||
response = client.chat(
|
||||
model=OLLAMA_MODEL,
|
||||
messages=[
|
||||
{"role": "system", "content": SYSTEM_PROMPT},
|
||||
{"role": "user", "content": user_message},
|
||||
],
|
||||
format={
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"thinking": {"type": "string"},
|
||||
"current_goal": {"type": "string"},
|
||||
"actions": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"action": {"type": "string"},
|
||||
"params": {"type": "object"},
|
||||
"reason": {"type": "string"},
|
||||
},
|
||||
"required": ["action", "params"],
|
||||
},
|
||||
"required": ["action", "params"],
|
||||
},
|
||||
"after_this": {"type": "string"},
|
||||
},
|
||||
"after_this": {"type": "string"},
|
||||
"required": ["actions"],
|
||||
},
|
||||
"required": ["actions"],
|
||||
},
|
||||
options={"temperature": 0.3},
|
||||
)
|
||||
options={"temperature": 0.3},
|
||||
)
|
||||
finally:
|
||||
stop_event.set()
|
||||
spinner.join()
|
||||
|
||||
dt = time.perf_counter() - t0
|
||||
content = response.message.content
|
||||
print(f"[AI] 응답 수신 ({dt:.2f}s, {len(content)}자)")
|
||||
|
||||
Reference in New Issue
Block a user