#!/usr/bin/env python3 """简洁演示问数脚本:只保留问题输入与结果输出。""" from __future__ import annotations import argparse import sys import time import traceback import uuid from pathlib import Path from typing import Any, Dict, Iterable, Optional # 允许直接使用 `python scripts/demo_chat.py` 运行 PROJECT_ROOT = Path(__file__).resolve().parent.parent if str(PROJECT_ROOT) not in sys.path: sys.path.insert(0, str(PROJECT_ROOT)) from agent.agents.conversation import ConversationAgent from config import Config from scripts.console_chat import extract_table_rows, parse_sr_api_result, render_text_table def build_parser() -> argparse.ArgumentParser: parser = argparse.ArgumentParser( description="演示版控制台问数:仅展示耗时、SQL、结果表和数据行数。" ) parser.add_argument("--model-section", default=None, help="可选:指定 config.ini 中的模型配置段") parser.add_argument("--conversation-id", default=None, help="可选:会话 ID") parser.add_argument("--user", default="demo-user", help="可选:用户标识") parser.add_argument("--query", "-q", default=None, help="单次执行模式:直接执行一条问题后退出") return parser def _last_answer_text(result: Dict[str, Any]) -> str: messages = (result or {}).get("messages") or [] if not messages: return "" last = messages[-1] return getattr(last, "content", "") or str(last) def format_demo_result(result: Dict[str, Any], elapsed_seconds: float) -> str: context = (result or {}).get("context") or {} final_sql = str(context.get("final_sql") or "") parsed_result = parse_sr_api_result(context.get("sr_api_result")) headers, rows = extract_table_rows(parsed_result) row_count = len(rows) has_structured_result = context.get("sr_api_result") is not None and isinstance(parsed_result, (dict, list)) is_empty_result = bool(context.get("is_empty_result")) response_source = str(context.get("response_source") or "") answer = _last_answer_text(result) blocks = [f"耗时: {elapsed_seconds:.2f}s"] if final_sql: blocks.append(f"SQL:\n{final_sql}") else: blocks.append("SQL:\n<未生成 SQL>") blocks.append(f"数据行数: {row_count}") if is_empty_result and response_source in {"model_empty_result_fallback", "empty_result_fixed_fallback"}: blocks.append(f"结果说明:\n{answer or '未查询到符合条件的数据,请尝试调整筛选条件后再查询。'}") elif has_structured_result: table_text = render_text_table(headers or ['result'], rows) blocks.append(f"SQL执行结果表:\n{table_text}") else: blocks.append(f"SQL执行结果:\n{answer or str(parsed_result or '<无结果>')}") return "\n\n".join(blocks) def run_turn( agent: ConversationAgent, query: str, *, user: str, conversation_id: str, ) -> Dict[str, Any]: started_at = time.perf_counter() result = agent.run( query, user=user, conversation_id=conversation_id, skip_sr_api=False, debug_node_trace=False, ) elapsed_seconds = time.perf_counter() - started_at print(format_demo_result(result, elapsed_seconds)) return result def interactive_loop(args: argparse.Namespace) -> int: conversation_id = args.conversation_id or f"demo_{uuid.uuid4().hex[:8]}" agent = ConversationAgent(model_section=args.model_section) while True: try: user_input = input("\n问题> ").strip() except (EOFError, KeyboardInterrupt): print("\nBye.") return 0 if not user_input: continue if user_input.lower() in {"/quit", "/exit", "quit", "exit"}: print("Bye.") return 0 try: run_turn( agent, user_input, user=args.user, conversation_id=conversation_id, ) except Exception as exc: print(f"\n[ERROR] {exc}") traceback.print_exc() return 0 def one_shot(args: argparse.Namespace) -> int: conversation_id = args.conversation_id or f"demo_{uuid.uuid4().hex[:8]}" agent = ConversationAgent(model_section=args.model_section) query = str(args.query or "") try: run_turn( agent, query, user=args.user, conversation_id=conversation_id, ) return 0 except Exception as exc: print(f"[ERROR] {exc}", file=sys.stderr) traceback.print_exc() return 1 def main(argv: Optional[Iterable[str]] = None) -> int: parser = build_parser() args = parser.parse_args(list(argv) if argv is not None else None) try: Config.validate_config() except Exception as exc: print(f"Configuration error: {exc}", file=sys.stderr) print("Please check `config/config.ini` and your model/API settings.", file=sys.stderr) return 1 if args.query: return one_shot(args) return interactive_loop(args) if __name__ == "__main__": raise SystemExit(main())