加入日志管理

This commit is contained in:
陈辅元
2026-04-16 10:53:10 +08:00
parent 284e02f41c
commit 695356a496
19 changed files with 582 additions and 181 deletions
+63 -9
View File
@@ -28,6 +28,10 @@ _BACKEND_DIR = _REPO_DIR / "backend"
if str(_BACKEND_DIR) not in sys.path:
sys.path.insert(0, str(_BACKEND_DIR))
from utils.repo_logging import configure_text2sql_api_logging
configure_text2sql_api_logging(_REPO_DIR)
from main import setup_environment, load_schema, create_orchestrator, resolve_sql_dialect
from agents.orchestrator import GenerationResult
from nl_lite_store import lite_nl_store
@@ -38,11 +42,6 @@ from utils.dialog_context import (
is_likely_follow_up,
)
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s [%(levelname)s] %(name)s: %(message)s',
datefmt='%Y-%m-%d %H:%M:%S'
)
logger = logging.getLogger(__name__)
# per-request 覆盖 LLM client 时,使用锁避免并发串改 orchestrator.deepseek
@@ -617,6 +616,15 @@ async def _run_generate(
orch = get_orchestrator()
dialect = resolve_sql_dialect(os.getenv("TEXT2SQL_DIALECT", "sqlserver"))
dc = (dialog_context or "").strip() or None
q = question.strip()
logger.info(
"[GEN/API] dialect=%s top_k=%s dialog_context_chars=%s question_len=%s preview=%r",
dialect,
top_k,
len(dc) if dc else 0,
len(q),
q[:300] + ("…" if len(q) > 300 else ""),
)
async def _call_with_orch(o) -> GenerationResult:
def _call() -> GenerationResult:
@@ -643,6 +651,20 @@ async def _chat_stream_events(request: NLChatRequest) -> AsyncIterator[bytes]:
text = request.message.strip()
orch = get_orchestrator()
dialog_block, last_data = await _load_session_text2sql_context(request, text)
logger.info(
"[API/stream] 开始: user_id=%r visitor_biz_id=%r session_id=%r service_code=%r model=%r "
"lang_code=%r msg_chars=%s preview=%r dialog_context_chars=%s last_turn_was_data_query=%s",
request.user_id,
request.visitor_biz_id,
request.session_id,
request.service_code,
request.model,
request.lang_code,
len(text),
text[:400] + ("…" if len(text) > 400 else ""),
len(dialog_block) if dialog_block else 0,
last_data,
)
lang = _normalize_lang_code(request.lang_code)
async with _maybe_override_orch_llm(orch, request) as o:
classified = await asyncio.to_thread(
@@ -656,7 +678,11 @@ async def _chat_stream_events(request: NLChatRequest) -> AsyncIterator[bytes]:
reply = (classified.reply_suggestion or "").strip()
if not reply:
reply = _localized_conversation_reply(lang)
logger.info("[API/stream] 对话意图: conversation(跳过 Text2SQL,与 CLI single_query 一致)")
logger.info(
"[API/stream] 对话意图 conversation(跳过 Text2SQL): reply_chars=%s reply_preview=%r",
len(reply),
reply[:500] + ("…" if len(reply) > 500 else ""),
)
yield _sse_data({"stage": "orchestrator", "stream_kind": "content", "content": "CHAT"})
async for pkt in _sse_stream_text_chunks("chat", reply):
yield pkt
@@ -669,10 +695,24 @@ async def _chat_stream_events(request: NLChatRequest) -> AsyncIterator[bytes]:
try:
result = await _run_generate(text, dialog_context=dialog_block or None, request=request)
except Exception as e:
logger.error(f"[API/stream] 生成异常: {e}")
logger.error(f"[API/stream] 生成异常: {e}", exc_info=True)
yield _sse_data({"code": 500, "msg": str(e), "data": None})
return
sql_out = (result.sql or "").strip()
logger.info(
"[API/stream] Text2SQL 完成: valid=%s attempts=%s tables_used=%s sql_chars=%s sql_head=%r",
result.valid,
result.attempts,
result.tables_used,
len(sql_out),
sql_out[:500] + ("…" if len(sql_out) > 500 else ""),
)
if result.errors:
logger.warning("[API/stream] 错误列表: %s", result.errors)
if result.warnings:
logger.info("[API/stream] 警告列表: %s", result.warnings)
# What this SQL does / SQL 说明:按 lang_code 本地化
try:
if isinstance(result.metadata, dict):
@@ -747,9 +787,21 @@ async def nl_chat(request: NLChatRequest):
lang = _normalize_lang_code(request.lang_code)
raise HTTPException(status_code=400, detail=_localized_empty_input_reply(lang))
text = request.message.strip()
logger.info(f"[API] 问题: {text[:100]}...")
orch = get_orchestrator()
dialog_block, last_data = await _load_session_text2sql_context(request, text)
logger.info(
"[API/chat] 请求: user_id=%r session_id=%r service_code=%r model=%r lang=%r "
"msg_chars=%s preview=%r dialog_context_chars=%s last_turn_was_data_query=%s",
request.user_id,
request.session_id,
request.service_code,
request.model,
request.lang_code,
len(text),
text[:400] + ("…" if len(text) > 400 else ""),
len(dialog_block) if dialog_block else 0,
last_data,
)
lang = _normalize_lang_code(request.lang_code)
async with _maybe_override_orch_llm(orch, request) as o:
classified = await asyncio.to_thread(
@@ -1004,5 +1056,7 @@ if __name__ == "__main__":
host=host,
port=port,
reload=False,
log_level="info"
log_level="info",
# 必须为 None:False 仍会进入 uvicorn 的 fileConfig 分支并崩溃;None 才跳过覆盖 root 日志
log_config=None,
)