Files
iov_ana/agent.py
OpenClaw Agent 96927a789d feat: 四层架构数据分析 Agent
- Layer 1 Planner: 意图规划,将问题转为结构化分析计划
- Layer 2 Explorer: 自适应探索循环,多轮迭代动态生成 SQL
- Layer 3 InsightEngine: 异常检测 + 主动洞察
- Layer 4 ContextManager: 多轮对话上下文记忆

安全设计:AI 只看 Schema + 聚合结果,不接触原始数据。
支持任意 OpenAI 兼容 API(OpenAI / Ollama / DeepSeek / vLLM)
2026-03-19 12:21:04 +08:00

140 lines
4.9 KiB
Python

"""
Agent 编排层 —— 调度四层架构完成分析
Layer 1: Planner 意图规划
Layer 2: Explorer 自适应探索
Layer 3: Insight 异常洞察
Layer 4: Context 上下文记忆
"""
from typing import Optional
from config import DB_PATH, MAX_EXPLORATION_ROUNDS
from schema_extractor import extract_schema, schema_to_text
from sandbox_executor import SandboxExecutor
from planner import Planner
from explorer import Explorer
from insights import InsightEngine, quick_detect
from reporter import ReportGenerator
from context import ContextManager
class DataAnalysisAgent:
"""
数据分析 Agent
四层架构:
1. Planner - 理解用户意图,生成分析计划
2. Explorer - 基于计划多轮迭代探索
3. Insights - 从结果中检测异常、输出主动洞察
4. Context - 管理多轮对话上下文
Agent 负责编排这四层,从问题到报告。
"""
def __init__(self, db_path: str):
# 数据层
self.db_path = db_path
self.schema = extract_schema(db_path)
self.schema_text = schema_to_text(self.schema)
self.executor = SandboxExecutor(db_path)
# 四层组件
self.planner = Planner()
self.explorer = Explorer(self.executor)
self.insight_engine = InsightEngine()
self.reporter = ReportGenerator()
self.context = ContextManager()
def analyze(self, question: str, max_rounds: Optional[int] = None) -> str:
"""
完整分析流程
Args:
question: 用户分析问题
max_rounds: 最大探索轮数(默认用配置值)
Returns:
格式化的分析报告
"""
max_rounds = max_rounds or MAX_EXPLORATION_ROUNDS
print(f"\n{'='*60}")
print(f"📊 {question}")
print(f"{'='*60}")
# ── Layer 0: 检查上下文 ──────────────────────────
prev_context = self.context.get_context_for(question)
if prev_context:
print("📎 发现历史分析上下文,将结合之前的发现")
# ── Layer 1: 意图规划 ────────────────────────────
print("\n🎯 [Layer 1] 意图规划...")
plan = self.planner.plan(question, self.schema_text)
analysis_type = plan.get("analysis_type", "unknown")
dimensions = plan.get("dimensions", [])
rationale = plan.get("rationale", "")
print(f" 类型: {analysis_type}")
print(f" 维度: {', '.join(dimensions) if dimensions else '自动发现'}")
print(f" 理由: {rationale[:80]}{'...' if len(rationale) > 80 else ''}")
# ── Layer 2: 自适应探索 ──────────────────────────
print(f"\n🔍 [Layer 2] 自适应探索 (最多 {max_rounds} 轮)...")
steps = self.explorer.explore(plan, self.schema_text, max_rounds=max_rounds)
successful = sum(1 for s in steps if s.success)
print(f"\n 完成: {len(steps)} 轮, {successful} 条成功查询")
# ── Layer 3: 异常洞察 ────────────────────────────
print("\n🔎 [Layer 3] 异常洞察...")
# 先做规则检测
rule_alerts = quick_detect(steps)
for alert in rule_alerts:
print(f" {alert}")
# 再做 LLM 深度分析
insights = self.insight_engine.analyze(steps, question)
if insights:
print(f" 发现 {len(insights)} 条洞察")
for insight in insights:
print(f" {insight}")
else:
print(" 未发现异常")
# ── 生成报告 ────────────────────────────────────
print("\n📝 正在生成报告...")
report = self.reporter.generate(question, plan, steps, insights)
# 追加主动洞察
if insights:
insight_text = self.insight_engine.format_insights(insights)
report += f"\n\n---\n\n{insight_text}"
# ── Layer 4: 记录上下文 ──────────────────────────
self.context.add_session(
question=question,
plan=plan,
steps=steps,
insights=insights,
report=report,
)
return report
def get_schema(self) -> str:
"""获取 Schema 文本"""
return self.schema_text
def get_history(self) -> str:
"""获取分析历史摘要"""
return self.context.get_history_summary()
def get_audit(self) -> str:
"""获取执行审计日志"""
return self.executor.get_execution_summary()
def clear_history(self):
"""清空分析历史"""
self.context.clear()