Files
iov_ana/layers/context.py

81 lines
2.8 KiB
Python
Raw Normal View History

"""
Layer 4: 上下文管理器
"""
import time
from dataclasses import dataclass, field
from typing import Optional
from layers.explorer import ExplorationStep
from layers.insights import Insight
@dataclass
class AnalysisSession:
"""一次分析的完整记录"""
question: str
plan: dict
steps: list[ExplorationStep]
insights: list[Insight]
report: str
timestamp: float = field(default_factory=time.time)
def summary(self) -> str:
parts = [f"**问题**: {self.question}"]
if self.plan:
parts.append(f"**分析类型**: {self.plan.get('analysis_type', 'unknown')}")
parts.append(f"**维度**: {', '.join(self.plan.get('dimensions', []))}")
key_findings = []
for step in self.steps:
if step.success and step.rows:
top_row = step.rows[0] if step.rows else {}
finding = f"{step.purpose}: " + ", ".join(f"{k}={v}" for k, v in top_row.items() if k.lower() != "id")
key_findings.append(finding)
if key_findings:
parts.append("**核心发现**:")
for f in key_findings[:5]:
parts.append(f" - {f}")
if self.insights:
parts.append("**洞察**:")
for i in self.insights[:3]:
parts.append(f" - {i}")
return "\n".join(parts)
def to_reference_text(self) -> str:
return (
f"## 之前的分析\n### 问题\n{self.question}\n### 摘要\n{self.summary()}\n### 发现\n"
+ "\n".join(f"- {s.purpose}: {s.row_count}" for s in self.steps if s.success)
)
class ContextManager:
"""上下文管理器"""
def __init__(self, max_history: int = 10):
self.sessions: list[AnalysisSession] = []
self.max_history = max_history
def add_session(self, question: str, plan: dict, steps: list[ExplorationStep],
insights: list[Insight], report: str) -> AnalysisSession:
session = AnalysisSession(question=question, plan=plan, steps=steps, insights=insights, report=report)
self.sessions.append(session)
if len(self.sessions) > self.max_history:
self.sessions = self.sessions[-self.max_history:]
return session
def get_context_for(self, new_question: str) -> Optional[str]:
if not self.sessions:
return None
return "\n\n---\n\n".join(s.to_reference_text() for s in self.sessions[-2:])
def get_history_summary(self) -> str:
if not self.sessions:
return "(无历史分析)"
lines = [f"{len(self.sessions)} 次分析:"]
for i, s in enumerate(self.sessions, 1):
ts = time.strftime("%H:%M", time.localtime(s.timestamp))
lines.append(f" {i}. [{ts}] {s.question}")
return "\n".join(lines)
def clear(self):
self.sessions.clear()