Files
iov_ana/cli.py

137 lines
4.5 KiB
Python
Raw Normal View History

"""
交互式 CLI 四层架构自适应分析
用法: python cli.py [数据库路径]
"""
import os
import sys
sys.path.insert(0, os.path.dirname(__file__))
from core.config import DB_PATH, LLM_CONFIG, MAX_EXPLORATION_ROUNDS, PLAYBOOK_DIR
from agent import DataAnalysisAgent
def print_help():
print("""
可用命令:
<问题> 分析一个问题
rounds=<N> <问题> 设置探索轮数
report [主题] 整合所有分析生成综合报告
schema 查看数据库 Schema
playbooks 查看已加载的预设剧本
regen 重新生成预设剧本
history 查看分析历史
audit 查看 SQL 审计日志
clear 清空分析历史
help 显示帮助
quit / q 退出
""")
def main():
db_path = sys.argv[1] if len(sys.argv) > 1 else DB_PATH
if not os.path.exists(db_path):
print(f"❌ 数据库不存在: {db_path}")
sys.exit(1)
if not LLM_CONFIG["api_key"]:
print("⚠️ 未配置 LLM_API_KEY")
sys.exit(1)
agent = DataAnalysisAgent(db_path)
print("=" * 60)
print(" 🤖 数据分析 Agent —— 四层架构")
print("=" * 60)
print(f"\n🔗 LLM: {LLM_CONFIG['model']} @ {LLM_CONFIG['base_url']}")
print(f"🔄 最大探索轮数: {MAX_EXPLORATION_ROUNDS}")
print(f"💾 数据库: {db_path}")
print(f"📋 预设剧本: {len(agent.playbook_mgr.playbooks)}")
print(f"\n💬 输入分析问题help 查看命令)\n")
while True:
try:
user_input = input("📊 > ").strip()
except (EOFError, KeyboardInterrupt):
print("\n👋 再见!")
break
if not user_input:
continue
cmd = user_input.lower()
if cmd in ("quit", "exit", "q"):
print("👋 再见!")
break
elif cmd == "help":
print_help()
elif cmd == "schema":
print(agent.get_schema())
elif cmd == "history":
print(agent.get_history())
elif cmd == "audit":
print(agent.get_audit())
elif cmd == "clear":
agent.clear_history()
print("✅ 历史已清空")
elif cmd.startswith("report"):
topic = user_input[6:].strip()
try:
report = agent.full_report(question=topic)
print("\n" + report)
print("\n" + "~" * 60)
except Exception as e:
print(f"\n❌ 报告整合出错: {e}")
import traceback
traceback.print_exc()
elif cmd == "playbooks":
if not agent.playbook_mgr.playbooks:
print("(无预设剧本,输入 regen 让 AI 自动生成)")
else:
for i, pb in enumerate(agent.playbook_mgr.playbooks, 1):
print(f" {i}. 📋 {pb.name}{pb.description} ({len(pb.preset_queries)} 条预设)")
elif cmd == "regen":
if os.path.isdir(PLAYBOOK_DIR):
for f in os.listdir(PLAYBOOK_DIR):
if f.startswith("auto_") and f.endswith(".json"):
os.remove(os.path.join(PLAYBOOK_DIR, f))
agent.playbook_mgr.playbooks.clear()
print("🤖 AI 正在重新生成预设剧本...")
generated = agent.playbook_mgr.auto_generate(agent.schema_text, save_dir=PLAYBOOK_DIR)
if generated:
print(f"✅ 生成 {len(generated)} 个剧本:")
for pb in generated:
print(f" 📋 {pb.name}{pb.description}")
else:
print("⚠️ 生成失败")
else:
# 解析 rounds=N
max_rounds = MAX_EXPLORATION_ROUNDS
question = user_input
if "rounds=" in question.lower():
parts = question.split("rounds=")
question = parts[0].strip()
try:
max_rounds = int(parts[1].strip().split()[0])
except (ValueError, IndexError):
pass
try:
report = agent.analyze(question, max_rounds=max_rounds)
print("\n" + report)
print("\n" + "~" * 60)
except Exception as e:
print(f"\n❌ 分析出错: {e}")
import traceback
traceback.print_exc()
print("\n📋 本次会话审计:")
print(agent.get_audit())
agent.close()
if __name__ == "__main__":
main()