Complete AI Data Analysis Agent implementation with 95.7% test coverage
This commit is contained in:
894
docs/API.md
Normal file
894
docs/API.md
Normal file
@@ -0,0 +1,894 @@
|
||||
# API 文档
|
||||
|
||||
本文档描述了 AI 数据分析 Agent 系统的核心 API 接口。
|
||||
|
||||
## 目录
|
||||
|
||||
- [主流程 API](#主流程-api)
|
||||
- [配置管理 API](#配置管理-api)
|
||||
- [数据访问 API](#数据访问-api)
|
||||
- [分析引擎 API](#分析引擎-api)
|
||||
- [工具系统 API](#工具系统-api)
|
||||
- [数据模型](#数据模型)
|
||||
|
||||
---
|
||||
|
||||
## 主流程 API
|
||||
|
||||
### `run_analysis()`
|
||||
|
||||
运行完整的数据分析流程。
|
||||
|
||||
**函数签名**:
|
||||
```python
|
||||
def run_analysis(
|
||||
data_file: str,
|
||||
user_requirement: Optional[str] = None,
|
||||
template_file: Optional[str] = None,
|
||||
output_dir: str = "output",
|
||||
progress_callback: Optional[callable] = None
|
||||
) -> Dict[str, Any]
|
||||
```
|
||||
|
||||
**参数**:
|
||||
- `data_file` (str): 数据文件路径(CSV 格式)
|
||||
- `user_requirement` (Optional[str]): 用户需求(自然语言),如果为 None 则自动推断
|
||||
- `template_file` (Optional[str]): 模板文件路径(可选)
|
||||
- `output_dir` (str): 输出目录,默认为 "output"
|
||||
- `progress_callback` (Optional[callable]): 进度回调函数,接收 (stage, current, total) 参数
|
||||
|
||||
**返回值**:
|
||||
```python
|
||||
{
|
||||
'success': bool, # 是否成功
|
||||
'data_type': str, # 数据类型
|
||||
'objectives_count': int, # 分析目标数量
|
||||
'tasks_count': int, # 任务数量
|
||||
'results_count': int, # 结果数量
|
||||
'report_path': str, # 报告路径
|
||||
'elapsed_time': float, # 执行时间(秒)
|
||||
'error': str # 错误信息(如果失败)
|
||||
}
|
||||
```
|
||||
|
||||
**示例**:
|
||||
```python
|
||||
from src.main import run_analysis
|
||||
|
||||
# 基本使用
|
||||
result = run_analysis(
|
||||
data_file="data.csv",
|
||||
user_requirement="分析工单健康度"
|
||||
)
|
||||
|
||||
if result['success']:
|
||||
print(f"报告路径: {result['report_path']}")
|
||||
print(f"执行时间: {result['elapsed_time']:.1f}秒")
|
||||
else:
|
||||
print(f"分析失败: {result['error']}")
|
||||
|
||||
# 使用进度回调
|
||||
def progress_handler(stage, current, total):
|
||||
print(f"[{current}/{total}] {stage}")
|
||||
|
||||
result = run_analysis(
|
||||
data_file="data.csv",
|
||||
progress_callback=progress_handler
|
||||
)
|
||||
```
|
||||
|
||||
### `AnalysisOrchestrator`
|
||||
|
||||
分析编排器类,协调五个阶段的执行。
|
||||
|
||||
**类签名**:
|
||||
```python
|
||||
class AnalysisOrchestrator:
|
||||
def __init__(
|
||||
self,
|
||||
data_file: str,
|
||||
user_requirement: Optional[str] = None,
|
||||
template_file: Optional[str] = None,
|
||||
output_dir: Optional[str] = None,
|
||||
progress_callback: Optional[callable] = None
|
||||
)
|
||||
```
|
||||
|
||||
**方法**:
|
||||
|
||||
#### `run_analysis()`
|
||||
运行完整的分析流程。
|
||||
|
||||
**返回值**:与 `run_analysis()` 函数相同
|
||||
|
||||
**示例**:
|
||||
```python
|
||||
from src.main import AnalysisOrchestrator
|
||||
|
||||
orchestrator = AnalysisOrchestrator(
|
||||
data_file="data.csv",
|
||||
user_requirement="分析工单健康度",
|
||||
output_dir="output"
|
||||
)
|
||||
|
||||
result = orchestrator.run_analysis()
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 配置管理 API
|
||||
|
||||
### `Config`
|
||||
|
||||
系统配置类。
|
||||
|
||||
**类签名**:
|
||||
```python
|
||||
@dataclass
|
||||
class Config:
|
||||
llm: LLMConfig
|
||||
performance: PerformanceConfig
|
||||
output: OutputConfig
|
||||
code_repo_enable_reuse: bool = True
|
||||
```
|
||||
|
||||
**类方法**:
|
||||
|
||||
#### `from_env()`
|
||||
从环境变量加载配置。
|
||||
|
||||
```python
|
||||
@classmethod
|
||||
def from_env(cls) -> "Config"
|
||||
```
|
||||
|
||||
**示例**:
|
||||
```python
|
||||
from src.config import Config
|
||||
|
||||
config = Config.from_env()
|
||||
print(f"模型: {config.llm.model}")
|
||||
print(f"输出目录: {config.output.output_dir}")
|
||||
```
|
||||
|
||||
#### `from_file()`
|
||||
从配置文件加载配置。
|
||||
|
||||
```python
|
||||
@classmethod
|
||||
def from_file(cls, config_file: str) -> "Config"
|
||||
```
|
||||
|
||||
**参数**:
|
||||
- `config_file` (str): 配置文件路径(JSON 格式)
|
||||
|
||||
**示例**:
|
||||
```python
|
||||
config = Config.from_file("config.json")
|
||||
```
|
||||
|
||||
#### `from_dict()`
|
||||
从字典加载配置。
|
||||
|
||||
```python
|
||||
@classmethod
|
||||
def from_dict(cls, config_dict: Dict[str, Any]) -> "Config"
|
||||
```
|
||||
|
||||
**参数**:
|
||||
- `config_dict` (Dict[str, Any]): 配置字典
|
||||
|
||||
#### `to_dict()`
|
||||
转换为字典。
|
||||
|
||||
```python
|
||||
def to_dict(self) -> Dict[str, Any]
|
||||
```
|
||||
|
||||
#### `save_to_file()`
|
||||
保存配置到文件。
|
||||
|
||||
```python
|
||||
def save_to_file(self, config_file: str)
|
||||
```
|
||||
|
||||
#### `validate()`
|
||||
验证配置的有效性。
|
||||
|
||||
```python
|
||||
def validate(self) -> bool
|
||||
```
|
||||
|
||||
### `LLMConfig`
|
||||
|
||||
LLM API 配置。
|
||||
|
||||
**类签名**:
|
||||
```python
|
||||
@dataclass
|
||||
class LLMConfig:
|
||||
provider: str = "openai"
|
||||
api_key: str = ""
|
||||
base_url: str = "https://api.openai.com/v1"
|
||||
model: str = "gpt-4"
|
||||
timeout: int = 120
|
||||
max_retries: int = 3
|
||||
temperature: float = 0.7
|
||||
max_tokens: Optional[int] = None
|
||||
```
|
||||
|
||||
### `PerformanceConfig`
|
||||
|
||||
性能参数配置。
|
||||
|
||||
**类签名**:
|
||||
```python
|
||||
@dataclass
|
||||
class PerformanceConfig:
|
||||
agent_max_rounds: int = 20
|
||||
agent_timeout: int = 300
|
||||
tool_max_query_rows: int = 10000
|
||||
tool_execution_timeout: int = 60
|
||||
data_max_rows: int = 1000000
|
||||
data_sample_threshold: int = 1000000
|
||||
max_concurrent_tasks: int = 1
|
||||
```
|
||||
|
||||
### `OutputConfig`
|
||||
|
||||
输出路径配置。
|
||||
|
||||
**类签名**:
|
||||
```python
|
||||
@dataclass
|
||||
class OutputConfig:
|
||||
output_dir: str = "output"
|
||||
log_dir: Optional[str] = None
|
||||
chart_dir: Optional[str] = None
|
||||
report_filename: str = "analysis_report.md"
|
||||
log_level: str = "INFO"
|
||||
log_to_file: bool = True
|
||||
log_to_console: bool = True
|
||||
```
|
||||
|
||||
**方法**:
|
||||
- `get_output_path() -> Path`: 获取输出目录路径
|
||||
- `get_log_path() -> Path`: 获取日志目录路径
|
||||
- `get_chart_path() -> Path`: 获取图表目录路径
|
||||
- `get_report_path() -> Path`: 获取报告文件路径
|
||||
|
||||
### 全局配置函数
|
||||
|
||||
#### `get_config()`
|
||||
获取全局配置实例。
|
||||
|
||||
```python
|
||||
def get_config() -> Config
|
||||
```
|
||||
|
||||
#### `set_config()`
|
||||
设置全局配置实例。
|
||||
|
||||
```python
|
||||
def set_config(config: Config)
|
||||
```
|
||||
|
||||
#### `load_config_from_env()`
|
||||
从环境变量加载配置并设置为全局配置。
|
||||
|
||||
```python
|
||||
def load_config_from_env() -> Config
|
||||
```
|
||||
|
||||
#### `load_config_from_file()`
|
||||
从文件加载配置并设置为全局配置。
|
||||
|
||||
```python
|
||||
def load_config_from_file(config_file: str) -> Config
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 数据访问 API
|
||||
|
||||
### `DataAccessLayer`
|
||||
|
||||
数据访问层,提供数据加载和隐私保护机制。
|
||||
|
||||
**类方法**:
|
||||
|
||||
#### `load_from_file()`
|
||||
从文件加载数据。
|
||||
|
||||
```python
|
||||
@classmethod
|
||||
def load_from_file(cls, file_path: str) -> "DataAccessLayer"
|
||||
```
|
||||
|
||||
**参数**:
|
||||
- `file_path` (str): 数据文件路径
|
||||
|
||||
**返回值**:DataAccessLayer 实例
|
||||
|
||||
**示例**:
|
||||
```python
|
||||
from src.data_access import DataAccessLayer
|
||||
|
||||
data_access = DataAccessLayer.load_from_file("data.csv")
|
||||
print(f"数据形状: {data_access.shape}")
|
||||
```
|
||||
|
||||
**实例方法**:
|
||||
|
||||
#### `get_profile()`
|
||||
获取数据画像(不包含原始数据)。
|
||||
|
||||
```python
|
||||
def get_profile(self) -> DataProfile
|
||||
```
|
||||
|
||||
#### `execute_tool()`
|
||||
执行工具并返回聚合结果。
|
||||
|
||||
```python
|
||||
def execute_tool(self, tool: AnalysisTool, **kwargs) -> Dict[str, Any]
|
||||
```
|
||||
|
||||
**参数**:
|
||||
- `tool` (AnalysisTool): 工具实例
|
||||
- `**kwargs`: 工具参数
|
||||
|
||||
**返回值**:聚合后的结果字典
|
||||
|
||||
---
|
||||
|
||||
## 分析引擎 API
|
||||
|
||||
### 数据理解引擎
|
||||
|
||||
#### `understand_data()`
|
||||
AI 驱动的数据理解。
|
||||
|
||||
```python
|
||||
def understand_data(data_access: DataAccessLayer) -> DataProfile
|
||||
```
|
||||
|
||||
**参数**:
|
||||
- `data_access` (DataAccessLayer): 数据访问层实例
|
||||
|
||||
**返回值**:DataProfile 对象
|
||||
|
||||
**示例**:
|
||||
```python
|
||||
from src.engines import understand_data
|
||||
from src.data_access import DataAccessLayer
|
||||
|
||||
data_access = DataAccessLayer.load_from_file("data.csv")
|
||||
profile = understand_data(data_access)
|
||||
|
||||
print(f"数据类型: {profile.inferred_type}")
|
||||
print(f"质量分数: {profile.quality_score}")
|
||||
```
|
||||
|
||||
### 需求理解引擎
|
||||
|
||||
#### `understand_requirement()`
|
||||
AI 驱动的需求理解。
|
||||
|
||||
```python
|
||||
def understand_requirement(
|
||||
user_input: str,
|
||||
data_profile: DataProfile,
|
||||
template_path: Optional[str] = None
|
||||
) -> RequirementSpec
|
||||
```
|
||||
|
||||
**参数**:
|
||||
- `user_input` (str): 用户需求(自然语言)
|
||||
- `data_profile` (DataProfile): 数据画像
|
||||
- `template_path` (Optional[str]): 模板文件路径
|
||||
|
||||
**返回值**:RequirementSpec 对象
|
||||
|
||||
### 分析规划引擎
|
||||
|
||||
#### `plan_analysis()`
|
||||
AI 驱动的分析规划。
|
||||
|
||||
```python
|
||||
def plan_analysis(
|
||||
data_profile: DataProfile,
|
||||
requirement: RequirementSpec
|
||||
) -> AnalysisPlan
|
||||
```
|
||||
|
||||
**参数**:
|
||||
- `data_profile` (DataProfile): 数据画像
|
||||
- `requirement` (RequirementSpec): 需求规格
|
||||
|
||||
**返回值**:AnalysisPlan 对象
|
||||
|
||||
### 任务执行引擎
|
||||
|
||||
#### `execute_task()`
|
||||
使用 ReAct 模式执行任务。
|
||||
|
||||
```python
|
||||
def execute_task(
|
||||
task: AnalysisTask,
|
||||
tools: List[AnalysisTool],
|
||||
data_access: DataAccessLayer
|
||||
) -> AnalysisResult
|
||||
```
|
||||
|
||||
**参数**:
|
||||
- `task` (AnalysisTask): 分析任务
|
||||
- `tools` (List[AnalysisTool]): 可用工具列表
|
||||
- `data_access` (DataAccessLayer): 数据访问层
|
||||
|
||||
**返回值**:AnalysisResult 对象
|
||||
|
||||
### 计划调整引擎
|
||||
|
||||
#### `adjust_plan()`
|
||||
根据中间结果动态调整计划。
|
||||
|
||||
```python
|
||||
def adjust_plan(
|
||||
plan: AnalysisPlan,
|
||||
completed_results: List[AnalysisResult]
|
||||
) -> AnalysisPlan
|
||||
```
|
||||
|
||||
**参数**:
|
||||
- `plan` (AnalysisPlan): 当前分析计划
|
||||
- `completed_results` (List[AnalysisResult]): 已完成的分析结果
|
||||
|
||||
**返回值**:调整后的 AnalysisPlan 对象
|
||||
|
||||
### 报告生成引擎
|
||||
|
||||
#### `generate_report()`
|
||||
AI 驱动的报告生成。
|
||||
|
||||
```python
|
||||
def generate_report(
|
||||
results: List[AnalysisResult],
|
||||
requirement: RequirementSpec,
|
||||
data_profile: DataProfile,
|
||||
output_path: str
|
||||
) -> str
|
||||
```
|
||||
|
||||
**参数**:
|
||||
- `results` (List[AnalysisResult]): 分析结果列表
|
||||
- `requirement` (RequirementSpec): 需求规格
|
||||
- `data_profile` (DataProfile): 数据画像
|
||||
- `output_path` (str): 输出路径
|
||||
|
||||
**返回值**:Markdown 格式的报告内容
|
||||
|
||||
---
|
||||
|
||||
## 工具系统 API
|
||||
|
||||
### `AnalysisTool`
|
||||
|
||||
分析工具的抽象基类。
|
||||
|
||||
**抽象属性**:
|
||||
|
||||
#### `name`
|
||||
工具名称。
|
||||
|
||||
```python
|
||||
@property
|
||||
@abstractmethod
|
||||
def name(self) -> str
|
||||
```
|
||||
|
||||
#### `description`
|
||||
工具描述(供 AI 理解)。
|
||||
|
||||
```python
|
||||
@property
|
||||
@abstractmethod
|
||||
def description(self) -> str
|
||||
```
|
||||
|
||||
#### `parameters`
|
||||
参数定义(JSON Schema 格式)。
|
||||
|
||||
```python
|
||||
@property
|
||||
@abstractmethod
|
||||
def parameters(self) -> Dict[str, Any]
|
||||
```
|
||||
|
||||
**抽象方法**:
|
||||
|
||||
#### `execute()`
|
||||
执行工具。
|
||||
|
||||
```python
|
||||
@abstractmethod
|
||||
def execute(self, data: pd.DataFrame, **kwargs) -> Dict[str, Any]
|
||||
```
|
||||
|
||||
**参数**:
|
||||
- `data` (pd.DataFrame): 原始数据
|
||||
- `**kwargs`: 工具参数
|
||||
|
||||
**返回值**:聚合后的结果字典
|
||||
|
||||
#### `is_applicable()`
|
||||
判断工具是否适用于当前数据。
|
||||
|
||||
```python
|
||||
@abstractmethod
|
||||
def is_applicable(self, data_profile: DataProfile) -> bool
|
||||
```
|
||||
|
||||
**参数**:
|
||||
- `data_profile` (DataProfile): 数据画像
|
||||
|
||||
**返回值**:True 如果工具适用,False 否则
|
||||
|
||||
**方法**:
|
||||
|
||||
#### `validate_parameters()`
|
||||
验证参数是否有效。
|
||||
|
||||
```python
|
||||
def validate_parameters(self, **kwargs) -> bool
|
||||
```
|
||||
|
||||
### `ToolRegistry`
|
||||
|
||||
工具注册表,管理所有可用的工具。
|
||||
|
||||
**方法**:
|
||||
|
||||
#### `register()`
|
||||
注册一个工具。
|
||||
|
||||
```python
|
||||
def register(self, tool: AnalysisTool) -> None
|
||||
```
|
||||
|
||||
#### `unregister()`
|
||||
注销一个工具。
|
||||
|
||||
```python
|
||||
def unregister(self, tool_name: str) -> None
|
||||
```
|
||||
|
||||
#### `get_tool()`
|
||||
获取指定名称的工具。
|
||||
|
||||
```python
|
||||
def get_tool(self, tool_name: str) -> AnalysisTool
|
||||
```
|
||||
|
||||
#### `list_tools()`
|
||||
列出所有已注册的工具名称。
|
||||
|
||||
```python
|
||||
def list_tools(self) -> list[str]
|
||||
```
|
||||
|
||||
#### `get_applicable_tools()`
|
||||
获取适用于指定数据的所有工具。
|
||||
|
||||
```python
|
||||
def get_applicable_tools(self, data_profile: DataProfile) -> list[AnalysisTool]
|
||||
```
|
||||
|
||||
### 全局工具函数
|
||||
|
||||
#### `register_tool()`
|
||||
注册工具到全局注册表。
|
||||
|
||||
```python
|
||||
def register_tool(tool: AnalysisTool) -> None
|
||||
```
|
||||
|
||||
#### `get_tool()`
|
||||
从全局注册表获取工具。
|
||||
|
||||
```python
|
||||
def get_tool(tool_name: str) -> AnalysisTool
|
||||
```
|
||||
|
||||
#### `list_tools()`
|
||||
列出全局注册表中的所有工具。
|
||||
|
||||
```python
|
||||
def list_tools() -> list[str]
|
||||
```
|
||||
|
||||
#### `get_applicable_tools()`
|
||||
获取适用于指定数据的所有工具。
|
||||
|
||||
```python
|
||||
def get_applicable_tools(data_profile: DataProfile) -> list[AnalysisTool]
|
||||
```
|
||||
|
||||
### `ToolManager`
|
||||
|
||||
工具管理器,根据数据特征动态选择工具。
|
||||
|
||||
**方法**:
|
||||
|
||||
#### `select_tools()`
|
||||
根据数据画像选择合适的工具。
|
||||
|
||||
```python
|
||||
def select_tools(self, data_profile: DataProfile) -> List[AnalysisTool]
|
||||
```
|
||||
|
||||
**参数**:
|
||||
- `data_profile` (DataProfile): 数据画像
|
||||
|
||||
**返回值**:适用的工具列表
|
||||
|
||||
#### `get_missing_tools()`
|
||||
获取缺失的工具列表。
|
||||
|
||||
```python
|
||||
def get_missing_tools(self) -> List[str]
|
||||
```
|
||||
|
||||
**返回值**:缺失的工具名称列表
|
||||
|
||||
---
|
||||
|
||||
## 数据模型
|
||||
|
||||
### `DataProfile`
|
||||
|
||||
数据画像,包含数据的元数据和统计摘要。
|
||||
|
||||
**字段**:
|
||||
```python
|
||||
@dataclass
|
||||
class DataProfile:
|
||||
file_path: str
|
||||
row_count: int
|
||||
column_count: int
|
||||
columns: List[ColumnInfo]
|
||||
inferred_type: str
|
||||
key_fields: Dict[str, str]
|
||||
quality_score: float
|
||||
summary: str
|
||||
```
|
||||
|
||||
### `ColumnInfo`
|
||||
|
||||
列信息。
|
||||
|
||||
**字段**:
|
||||
```python
|
||||
@dataclass
|
||||
class ColumnInfo:
|
||||
name: str
|
||||
dtype: str
|
||||
missing_rate: float
|
||||
unique_count: int
|
||||
sample_values: List[Any]
|
||||
statistics: Dict[str, Any]
|
||||
```
|
||||
|
||||
### `RequirementSpec`
|
||||
|
||||
需求规格。
|
||||
|
||||
**字段**:
|
||||
```python
|
||||
@dataclass
|
||||
class RequirementSpec:
|
||||
user_input: str
|
||||
objectives: List[AnalysisObjective]
|
||||
template_path: Optional[str]
|
||||
template_requirements: Optional[Dict[str, Any]]
|
||||
constraints: List[str]
|
||||
expected_outputs: List[str]
|
||||
```
|
||||
|
||||
### `AnalysisObjective`
|
||||
|
||||
分析目标。
|
||||
|
||||
**字段**:
|
||||
```python
|
||||
@dataclass
|
||||
class AnalysisObjective:
|
||||
name: str
|
||||
description: str
|
||||
metrics: List[str]
|
||||
priority: int
|
||||
```
|
||||
|
||||
### `AnalysisPlan`
|
||||
|
||||
分析计划。
|
||||
|
||||
**字段**:
|
||||
```python
|
||||
@dataclass
|
||||
class AnalysisPlan:
|
||||
objectives: List[AnalysisObjective]
|
||||
tasks: List[AnalysisTask]
|
||||
tool_config: Dict[str, Any]
|
||||
estimated_duration: int
|
||||
created_at: datetime
|
||||
updated_at: datetime
|
||||
```
|
||||
|
||||
### `AnalysisTask`
|
||||
|
||||
分析任务。
|
||||
|
||||
**字段**:
|
||||
```python
|
||||
@dataclass
|
||||
class AnalysisTask:
|
||||
id: str
|
||||
name: str
|
||||
description: str
|
||||
priority: int
|
||||
dependencies: List[str]
|
||||
required_tools: List[str]
|
||||
expected_output: str
|
||||
status: str
|
||||
```
|
||||
|
||||
### `AnalysisResult`
|
||||
|
||||
分析结果。
|
||||
|
||||
**字段**:
|
||||
```python
|
||||
@dataclass
|
||||
class AnalysisResult:
|
||||
task_id: str
|
||||
task_name: str
|
||||
success: bool
|
||||
data: Dict[str, Any]
|
||||
visualizations: List[str]
|
||||
insights: List[str]
|
||||
error: Optional[str]
|
||||
execution_time: float
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 错误处理 API
|
||||
|
||||
### `execute_task_with_recovery()`
|
||||
|
||||
带恢复机制的任务执行。
|
||||
|
||||
```python
|
||||
def execute_task_with_recovery(
|
||||
task: AnalysisTask,
|
||||
plan: AnalysisPlan,
|
||||
execute_func: callable,
|
||||
**kwargs
|
||||
) -> AnalysisResult
|
||||
```
|
||||
|
||||
**参数**:
|
||||
- `task` (AnalysisTask): 分析任务
|
||||
- `plan` (AnalysisPlan): 分析计划
|
||||
- `execute_func` (callable): 执行函数
|
||||
- `**kwargs`: 传递给执行函数的参数
|
||||
|
||||
**返回值**:AnalysisResult 对象
|
||||
|
||||
---
|
||||
|
||||
## 使用示例
|
||||
|
||||
### 完整示例:自定义分析流程
|
||||
|
||||
```python
|
||||
from src.main import AnalysisOrchestrator
|
||||
from src.config import Config, LLMConfig, OutputConfig
|
||||
|
||||
# 1. 配置系统
|
||||
llm_config = LLMConfig(
|
||||
provider="openai",
|
||||
api_key="your_api_key",
|
||||
model="gpt-4",
|
||||
temperature=0.7
|
||||
)
|
||||
|
||||
output_config = OutputConfig(
|
||||
output_dir="my_output",
|
||||
log_level="DEBUG"
|
||||
)
|
||||
|
||||
config = Config(llm=llm_config, output=output_config)
|
||||
|
||||
# 2. 创建编排器
|
||||
orchestrator = AnalysisOrchestrator(
|
||||
data_file="data.csv",
|
||||
user_requirement="分析工单健康度",
|
||||
output_dir="my_output"
|
||||
)
|
||||
|
||||
# 3. 运行分析
|
||||
result = orchestrator.run_analysis()
|
||||
|
||||
# 4. 处理结果
|
||||
if result['success']:
|
||||
print(f"✓ 分析完成")
|
||||
print(f" 数据类型: {result['data_type']}")
|
||||
print(f" 任务数量: {result['tasks_count']}")
|
||||
print(f" 报告路径: {result['report_path']}")
|
||||
print(f" 执行时间: {result['elapsed_time']:.1f}秒")
|
||||
else:
|
||||
print(f"✗ 分析失败: {result['error']}")
|
||||
```
|
||||
|
||||
### 示例:自定义工具
|
||||
|
||||
```python
|
||||
from src.tools.base import AnalysisTool, register_tool
|
||||
from src.models import DataProfile
|
||||
import pandas as pd
|
||||
|
||||
class CustomAnalysisTool(AnalysisTool):
|
||||
@property
|
||||
def name(self) -> str:
|
||||
return "custom_analysis"
|
||||
|
||||
@property
|
||||
def description(self) -> str:
|
||||
return "自定义分析工具"
|
||||
|
||||
@property
|
||||
def parameters(self) -> dict:
|
||||
return {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"column": {"type": "string"}
|
||||
},
|
||||
"required": ["column"]
|
||||
}
|
||||
|
||||
def execute(self, data: pd.DataFrame, **kwargs) -> dict:
|
||||
column = kwargs['column']
|
||||
# 执行自定义分析
|
||||
result = {
|
||||
"mean": data[column].mean(),
|
||||
"median": data[column].median()
|
||||
}
|
||||
return result
|
||||
|
||||
def is_applicable(self, data_profile: DataProfile) -> bool:
|
||||
# 检查是否有数值列
|
||||
return any(col.dtype == 'numeric' for col in data_profile.columns)
|
||||
|
||||
# 注册工具
|
||||
register_tool(CustomAnalysisTool())
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 注意事项
|
||||
|
||||
1. **隐私保护**:所有工具的 `execute()` 方法必须返回聚合数据,不能返回原始行级数据
|
||||
2. **错误处理**:所有 API 调用都应该包含适当的错误处理
|
||||
3. **配置验证**:在使用配置前,建议调用 `config.validate()` 验证配置的有效性
|
||||
4. **工具注册**:自定义工具必须在使用前注册到工具注册表
|
||||
5. **线程安全**:当前版本不支持并发执行,`max_concurrent_tasks` 必须设置为 1
|
||||
|
||||
---
|
||||
|
||||
## 版本信息
|
||||
|
||||
- **版本**: v1.0.0
|
||||
- **日期**: 2026-03-06
|
||||
- **状态**: 稳定版本
|
||||
851
docs/DEVELOPER_GUIDE.md
Normal file
851
docs/DEVELOPER_GUIDE.md
Normal file
@@ -0,0 +1,851 @@
|
||||
# 开发者指南
|
||||
|
||||
本指南帮助开发者理解系统架构、扩展功能和添加新工具。
|
||||
|
||||
## 目录
|
||||
|
||||
- [系统架构](#系统架构)
|
||||
- [开发环境设置](#开发环境设置)
|
||||
- [添加新工具](#添加新工具)
|
||||
- [扩展分析引擎](#扩展分析引擎)
|
||||
- [自定义数据模型](#自定义数据模型)
|
||||
- [测试指南](#测试指南)
|
||||
- [代码规范](#代码规范)
|
||||
- [调试技巧](#调试技巧)
|
||||
|
||||
---
|
||||
|
||||
## 系统架构
|
||||
|
||||
### 整体架构
|
||||
|
||||
系统采用五阶段流水线架构,每个阶段由 AI 驱动:
|
||||
|
||||
```
|
||||
数据输入 → 数据理解 → 需求理解 → 分析规划 → 任务执行 → 报告生成
|
||||
```
|
||||
|
||||
### 核心组件
|
||||
|
||||
```
|
||||
src/
|
||||
├── main.py # 主流程编排
|
||||
├── cli.py # 命令行接口
|
||||
├── config.py # 配置管理
|
||||
├── data_access.py # 数据访问层(隐私保护)
|
||||
├── error_handling.py # 错误处理
|
||||
├── logging_config.py # 日志配置
|
||||
├── env_loader.py # 环境变量加载
|
||||
├── engines/ # 分析引擎
|
||||
│ ├── data_understanding.py # 数据理解
|
||||
│ ├── requirement_understanding.py # 需求理解
|
||||
│ ├── analysis_planning.py # 分析规划
|
||||
│ ├── task_execution.py # 任务执行(ReAct)
|
||||
│ ├── plan_adjustment.py # 计划调整
|
||||
│ └── report_generation.py # 报告生成
|
||||
├── models/ # 数据模型
|
||||
│ ├── data_profile.py
|
||||
│ ├── requirement_spec.py
|
||||
│ ├── analysis_plan.py
|
||||
│ └── analysis_result.py
|
||||
└── tools/ # 分析工具
|
||||
├── base.py # 工具基类和注册表
|
||||
├── query_tools.py # 数据查询工具
|
||||
├── stats_tools.py # 统计分析工具
|
||||
├── viz_tools.py # 可视化工具
|
||||
└── tool_manager.py # 工具管理器
|
||||
```
|
||||
|
||||
### 数据流
|
||||
|
||||
```
|
||||
CSV 文件
|
||||
↓
|
||||
DataAccessLayer(数据访问层)
|
||||
↓
|
||||
DataProfile(数据画像:元数据 + 统计摘要)
|
||||
↓
|
||||
RequirementSpec(需求规格)
|
||||
↓
|
||||
AnalysisPlan(分析计划:任务列表)
|
||||
↓
|
||||
AnalysisResult[](分析结果列表)
|
||||
↓
|
||||
Markdown 报告
|
||||
```
|
||||
|
||||
### 设计原则
|
||||
|
||||
1. **AI 优先**:让 AI 做决策,而不是执行预定义的规则
|
||||
2. **动态适应**:根据数据特征和发现动态调整分析计划
|
||||
3. **隐私保护**:AI 不读取原始数据,只通过工具获取摘要信息
|
||||
4. **工具驱动**:通过动态工具集赋能 AI 的分析能力
|
||||
5. **可扩展性**:易于添加新工具和扩展功能
|
||||
|
||||
---
|
||||
|
||||
## 开发环境设置
|
||||
|
||||
### 1. 克隆仓库
|
||||
|
||||
```bash
|
||||
git clone <repository-url>
|
||||
cd <repository-name>
|
||||
```
|
||||
|
||||
### 2. 创建虚拟环境
|
||||
|
||||
```bash
|
||||
# 使用 venv
|
||||
python -m venv .venv
|
||||
|
||||
# 激活虚拟环境
|
||||
# Windows
|
||||
.venv\Scripts\activate
|
||||
# Linux/Mac
|
||||
source .venv/bin/activate
|
||||
```
|
||||
|
||||
### 3. 安装依赖
|
||||
|
||||
```bash
|
||||
# 安装生产依赖
|
||||
pip install -r requirements.txt
|
||||
|
||||
# 安装开发依赖(如果有)
|
||||
pip install pytest hypothesis pytest-cov black flake8
|
||||
```
|
||||
|
||||
### 4. 配置环境变量
|
||||
|
||||
```bash
|
||||
cp .env.example .env
|
||||
# 编辑 .env 文件,设置 API 密钥
|
||||
```
|
||||
|
||||
### 5. 运行测试
|
||||
|
||||
```bash
|
||||
# 运行所有测试
|
||||
pytest
|
||||
|
||||
# 运行特定测试
|
||||
pytest tests/test_integration.py -v
|
||||
|
||||
# 查看覆盖率
|
||||
pytest --cov=src --cov-report=html
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 添加新工具
|
||||
|
||||
### 步骤1:创建工具类
|
||||
|
||||
创建一个继承自 `AnalysisTool` 的新类:
|
||||
|
||||
```python
|
||||
# src/tools/my_custom_tools.py
|
||||
|
||||
from src.tools.base import AnalysisTool
|
||||
from src.models import DataProfile
|
||||
import pandas as pd
|
||||
from typing import Dict, Any
|
||||
|
||||
|
||||
class MyCustomTool(AnalysisTool):
|
||||
"""
|
||||
自定义分析工具。
|
||||
|
||||
功能:[描述工具的功能]
|
||||
"""
|
||||
|
||||
@property
|
||||
def name(self) -> str:
|
||||
"""工具名称(唯一标识)。"""
|
||||
return "my_custom_tool"
|
||||
|
||||
@property
|
||||
def description(self) -> str:
|
||||
"""工具描述(供 AI 理解)。"""
|
||||
return """
|
||||
这个工具用于 [具体功能描述]。
|
||||
|
||||
适用场景:
|
||||
- [场景1]
|
||||
- [场景2]
|
||||
|
||||
输入参数:
|
||||
- column: 要分析的列名
|
||||
- threshold: 阈值参数
|
||||
|
||||
输出:
|
||||
- result: 分析结果
|
||||
- insights: 洞察列表
|
||||
"""
|
||||
|
||||
@property
|
||||
def parameters(self) -> Dict[str, Any]:
|
||||
"""参数定义(JSON Schema 格式)。"""
|
||||
return {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"column": {
|
||||
"type": "string",
|
||||
"description": "要分析的列名"
|
||||
},
|
||||
"threshold": {
|
||||
"type": "number",
|
||||
"description": "阈值参数",
|
||||
"default": 0.5
|
||||
}
|
||||
},
|
||||
"required": ["column"]
|
||||
}
|
||||
|
||||
def execute(self, data: pd.DataFrame, **kwargs) -> Dict[str, Any]:
|
||||
"""
|
||||
执行工具。
|
||||
|
||||
参数:
|
||||
data: 原始数据(工具内部使用,不暴露给 AI)
|
||||
**kwargs: 工具参数
|
||||
|
||||
返回:
|
||||
聚合后的结果(不包含原始数据)
|
||||
"""
|
||||
# 1. 验证参数
|
||||
if not self.validate_parameters(**kwargs):
|
||||
raise ValueError("参数验证失败")
|
||||
|
||||
column = kwargs['column']
|
||||
threshold = kwargs.get('threshold', 0.5)
|
||||
|
||||
# 2. 检查列是否存在
|
||||
if column not in data.columns:
|
||||
raise ValueError(f"列 '{column}' 不存在")
|
||||
|
||||
# 3. 执行分析
|
||||
# 注意:只返回聚合数据,不返回原始行级数据
|
||||
result = {
|
||||
"column": column,
|
||||
"threshold": threshold,
|
||||
"count": len(data),
|
||||
"result_value": data[column].mean(), # 示例
|
||||
"insights": [
|
||||
f"列 {column} 的平均值为 {data[column].mean():.2f}"
|
||||
]
|
||||
}
|
||||
|
||||
return result
|
||||
|
||||
def is_applicable(self, data_profile: DataProfile) -> bool:
|
||||
"""
|
||||
判断工具是否适用于当前数据。
|
||||
|
||||
参数:
|
||||
data_profile: 数据画像
|
||||
|
||||
返回:
|
||||
True 如果工具适用,False 否则
|
||||
"""
|
||||
# 示例:检查是否有数值列
|
||||
has_numeric = any(
|
||||
col.dtype == 'numeric'
|
||||
for col in data_profile.columns
|
||||
)
|
||||
|
||||
return has_numeric
|
||||
```
|
||||
|
||||
### 步骤2:注册工具
|
||||
|
||||
在 `src/tools/__init__.py` 中注册工具:
|
||||
|
||||
```python
|
||||
from src.tools.base import register_tool
|
||||
from src.tools.my_custom_tools import MyCustomTool
|
||||
|
||||
# 注册工具
|
||||
register_tool(MyCustomTool())
|
||||
```
|
||||
|
||||
或者在工具管理器中动态注册:
|
||||
|
||||
```python
|
||||
from src.tools.tool_manager import ToolManager
|
||||
from src.tools.my_custom_tools import MyCustomTool
|
||||
|
||||
tool_manager = ToolManager()
|
||||
tool_manager.registry.register(MyCustomTool())
|
||||
```
|
||||
|
||||
### 步骤3:编写测试
|
||||
|
||||
创建测试文件 `tests/test_my_custom_tools.py`:
|
||||
|
||||
```python
|
||||
import pytest
|
||||
import pandas as pd
|
||||
from hypothesis import given, strategies as st
|
||||
|
||||
from src.tools.my_custom_tools import MyCustomTool
|
||||
from src.models import DataProfile, ColumnInfo
|
||||
|
||||
|
||||
def test_my_custom_tool_basic():
|
||||
"""测试工具的基本功能。"""
|
||||
# 准备测试数据
|
||||
data = pd.DataFrame({
|
||||
'value': [1, 2, 3, 4, 5]
|
||||
})
|
||||
|
||||
# 创建工具
|
||||
tool = MyCustomTool()
|
||||
|
||||
# 执行工具
|
||||
result = tool.execute(data, column='value', threshold=0.5)
|
||||
|
||||
# 验证结果
|
||||
assert result['column'] == 'value'
|
||||
assert result['threshold'] == 0.5
|
||||
assert result['count'] == 5
|
||||
assert 'insights' in result
|
||||
|
||||
|
||||
def test_my_custom_tool_invalid_column():
|
||||
"""测试无效列名的处理。"""
|
||||
data = pd.DataFrame({'value': [1, 2, 3]})
|
||||
tool = MyCustomTool()
|
||||
|
||||
with pytest.raises(ValueError, match="列 .* 不存在"):
|
||||
tool.execute(data, column='invalid_column')
|
||||
|
||||
|
||||
@given(data=st.data())
|
||||
def test_my_custom_tool_property(data):
|
||||
"""属性测试:工具应该总是返回聚合数据。"""
|
||||
# 生成随机数据
|
||||
df = pd.DataFrame({
|
||||
'value': data.draw(st.lists(st.floats(), min_size=10, max_size=100))
|
||||
})
|
||||
|
||||
tool = MyCustomTool()
|
||||
result = tool.execute(df, column='value')
|
||||
|
||||
# 验证:结果不应包含原始行级数据
|
||||
assert 'data' not in result or len(result.get('data', [])) <= 100
|
||||
assert 'insights' in result
|
||||
```
|
||||
|
||||
### 步骤4:更新文档
|
||||
|
||||
在 `docs/API.md` 中添加工具文档:
|
||||
|
||||
```markdown
|
||||
### MyCustomTool
|
||||
|
||||
自定义分析工具。
|
||||
|
||||
**功能**:[描述]
|
||||
|
||||
**参数**:
|
||||
- `column` (str): 要分析的列名
|
||||
- `threshold` (float): 阈值参数,默认 0.5
|
||||
|
||||
**返回值**:
|
||||
```python
|
||||
{
|
||||
"column": str,
|
||||
"threshold": float,
|
||||
"count": int,
|
||||
"result_value": float,
|
||||
"insights": List[str]
|
||||
}
|
||||
```
|
||||
|
||||
**示例**:
|
||||
```python
|
||||
tool = MyCustomTool()
|
||||
result = tool.execute(data, column='value', threshold=0.5)
|
||||
```
|
||||
```
|
||||
|
||||
### 工具开发最佳实践
|
||||
|
||||
1. **隐私保护**:
|
||||
- 永远不要返回原始行级数据
|
||||
- 只返回聚合数据(统计值、计数、分组结果等)
|
||||
- 限制返回的数据行数(最多 100 行)
|
||||
|
||||
2. **参数验证**:
|
||||
- 使用 JSON Schema 定义参数
|
||||
- 在 `execute()` 中验证参数
|
||||
- 提供清晰的错误信息
|
||||
|
||||
3. **错误处理**:
|
||||
- 捕获并处理异常
|
||||
- 返回有意义的错误信息
|
||||
- 不要让工具崩溃整个流程
|
||||
|
||||
4. **性能优化**:
|
||||
- 避免不必要的数据复制
|
||||
- 使用 pandas 的向量化操作
|
||||
- 考虑大数据集的性能
|
||||
|
||||
5. **文档完善**:
|
||||
- 提供清晰的工具描述
|
||||
- 说明适用场景
|
||||
- 提供使用示例
|
||||
|
||||
---
|
||||
|
||||
## 扩展分析引擎
|
||||
|
||||
### 添加新的分析阶段
|
||||
|
||||
如果需要添加新的分析阶段,按以下步骤操作:
|
||||
|
||||
#### 1. 创建引擎模块
|
||||
|
||||
```python
|
||||
# src/engines/my_new_engine.py
|
||||
|
||||
import logging
|
||||
from typing import Dict, Any
|
||||
|
||||
from src.models import DataProfile, AnalysisPlan
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def my_new_analysis_stage(
|
||||
data_profile: DataProfile,
|
||||
analysis_plan: AnalysisPlan
|
||||
) -> Dict[str, Any]:
|
||||
"""
|
||||
新的分析阶段。
|
||||
|
||||
参数:
|
||||
data_profile: 数据画像
|
||||
analysis_plan: 分析计划
|
||||
|
||||
返回:
|
||||
分析结果
|
||||
"""
|
||||
logger.info("执行新的分析阶段...")
|
||||
|
||||
# 实现分析逻辑
|
||||
result = {
|
||||
"status": "completed",
|
||||
"findings": []
|
||||
}
|
||||
|
||||
return result
|
||||
```
|
||||
|
||||
#### 2. 集成到主流程
|
||||
|
||||
在 `src/main.py` 中添加新阶段:
|
||||
|
||||
```python
|
||||
class AnalysisOrchestrator:
|
||||
def run_analysis(self):
|
||||
# ... 现有阶段 ...
|
||||
|
||||
# 新阶段
|
||||
self._report_progress("新分析阶段", 5, 6)
|
||||
self.tracker.track_stage("新分析阶段", "started")
|
||||
new_result = self._stage_new_analysis()
|
||||
self.tracker.track_stage("新分析阶段", "completed")
|
||||
|
||||
# ... 继续 ...
|
||||
|
||||
def _stage_new_analysis(self) -> Dict[str, Any]:
|
||||
"""新的分析阶段。"""
|
||||
from src.engines.my_new_engine import my_new_analysis_stage
|
||||
|
||||
log_stage_start(logger, "新分析阶段")
|
||||
result = my_new_analysis_stage(
|
||||
self.data_profile,
|
||||
self.analysis_plan
|
||||
)
|
||||
log_stage_end(logger, "新分析阶段")
|
||||
|
||||
return result
|
||||
```
|
||||
|
||||
### 自定义 ReAct 执行逻辑
|
||||
|
||||
如果需要自定义任务执行逻辑:
|
||||
|
||||
```python
|
||||
# src/engines/custom_execution.py
|
||||
|
||||
from typing import List, Dict, Any
|
||||
from src.models import AnalysisTask, AnalysisResult
|
||||
from src.tools.base import AnalysisTool
|
||||
from src.data_access import DataAccessLayer
|
||||
|
||||
|
||||
def custom_execute_task(
|
||||
task: AnalysisTask,
|
||||
tools: List[AnalysisTool],
|
||||
data_access: DataAccessLayer
|
||||
) -> AnalysisResult:
|
||||
"""
|
||||
自定义任务执行逻辑。
|
||||
|
||||
参数:
|
||||
task: 分析任务
|
||||
tools: 可用工具列表
|
||||
data_access: 数据访问层
|
||||
|
||||
返回:
|
||||
分析结果
|
||||
"""
|
||||
# 实现自定义执行逻辑
|
||||
# 例如:使用不同的 AI 模型、不同的提示策略等
|
||||
|
||||
pass
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 自定义数据模型
|
||||
|
||||
### 扩展数据画像
|
||||
|
||||
如果需要添加新的数据特征:
|
||||
|
||||
```python
|
||||
# src/models/data_profile.py
|
||||
|
||||
from dataclasses import dataclass, field
|
||||
from typing import List, Dict, Any
|
||||
|
||||
@dataclass
|
||||
class DataProfile:
|
||||
# 现有字段...
|
||||
|
||||
# 新增字段
|
||||
custom_features: Dict[str, Any] = field(default_factory=dict)
|
||||
|
||||
def add_custom_feature(self, name: str, value: Any):
|
||||
"""添加自定义特征。"""
|
||||
self.custom_features[name] = value
|
||||
```
|
||||
|
||||
### 添加新的分析任务类型
|
||||
|
||||
```python
|
||||
# src/models/analysis_plan.py
|
||||
|
||||
from dataclasses import dataclass
|
||||
from typing import Optional
|
||||
|
||||
@dataclass
|
||||
class CustomAnalysisTask(AnalysisTask):
|
||||
"""自定义分析任务。"""
|
||||
|
||||
custom_param: Optional[str] = None
|
||||
|
||||
def validate(self) -> bool:
|
||||
"""验证任务参数。"""
|
||||
# 实现验证逻辑
|
||||
return True
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 测试指南
|
||||
|
||||
### 测试策略
|
||||
|
||||
系统采用双重测试方法:
|
||||
|
||||
1. **单元测试**:验证特定示例、边缘情况和错误条件
|
||||
2. **属性测试**:验证跨所有输入的通用属性
|
||||
|
||||
### 编写单元测试
|
||||
|
||||
```python
|
||||
# tests/test_my_feature.py
|
||||
|
||||
import pytest
|
||||
from src.my_module import my_function
|
||||
|
||||
|
||||
def test_my_function_basic():
|
||||
"""测试基本功能。"""
|
||||
result = my_function(input_data)
|
||||
assert result == expected_output
|
||||
|
||||
|
||||
def test_my_function_edge_case():
|
||||
"""测试边缘情况。"""
|
||||
result = my_function(edge_case_input)
|
||||
assert result is not None
|
||||
|
||||
|
||||
def test_my_function_error_handling():
|
||||
"""测试错误处理。"""
|
||||
with pytest.raises(ValueError):
|
||||
my_function(invalid_input)
|
||||
```
|
||||
|
||||
### 编写属性测试
|
||||
|
||||
```python
|
||||
# tests/test_my_feature_properties.py
|
||||
|
||||
from hypothesis import given, strategies as st
|
||||
import hypothesis
|
||||
|
||||
|
||||
# Feature: my-feature, Property 1: 输出总是有效
|
||||
@given(input_data=st.data())
|
||||
@hypothesis.settings(max_examples=100)
|
||||
def test_output_always_valid(input_data):
|
||||
"""
|
||||
属性 1:对于任何有效输入,输出总是有效的。
|
||||
"""
|
||||
# 生成随机输入
|
||||
data = generate_random_input(input_data)
|
||||
|
||||
# 执行函数
|
||||
result = my_function(data)
|
||||
|
||||
# 验证属性
|
||||
assert result is not None
|
||||
assert validate_output(result)
|
||||
```
|
||||
|
||||
### 运行测试
|
||||
|
||||
```bash
|
||||
# 运行所有测试
|
||||
pytest
|
||||
|
||||
# 运行单元测试
|
||||
pytest tests/ -k "not properties"
|
||||
|
||||
# 运行属性测试
|
||||
pytest tests/ -k "properties"
|
||||
|
||||
# 运行特定测试文件
|
||||
pytest tests/test_my_feature.py -v
|
||||
|
||||
# 查看覆盖率
|
||||
pytest --cov=src --cov-report=html
|
||||
|
||||
# 生成覆盖率报告
|
||||
open htmlcov/index.html
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 代码规范
|
||||
|
||||
### Python 代码风格
|
||||
|
||||
遵循 PEP 8 规范:
|
||||
|
||||
```bash
|
||||
# 检查代码风格
|
||||
flake8 src/
|
||||
|
||||
# 自动格式化代码
|
||||
black src/
|
||||
```
|
||||
|
||||
### 文档字符串
|
||||
|
||||
使用 Google 风格的文档字符串:
|
||||
|
||||
```python
|
||||
def my_function(param1: str, param2: int) -> Dict[str, Any]:
|
||||
"""
|
||||
函数的简短描述。
|
||||
|
||||
更详细的描述(如果需要)。
|
||||
|
||||
参数:
|
||||
param1: 参数1的描述
|
||||
param2: 参数2的描述
|
||||
|
||||
返回:
|
||||
返回值的描述
|
||||
|
||||
异常:
|
||||
ValueError: 参数无效时抛出
|
||||
|
||||
示例:
|
||||
>>> result = my_function("test", 42)
|
||||
>>> print(result)
|
||||
{'status': 'success'}
|
||||
"""
|
||||
pass
|
||||
```
|
||||
|
||||
### 类型注解
|
||||
|
||||
使用类型注解提高代码可读性:
|
||||
|
||||
```python
|
||||
from typing import List, Dict, Optional, Any
|
||||
|
||||
def process_data(
|
||||
data: List[Dict[str, Any]],
|
||||
config: Optional[Dict[str, Any]] = None
|
||||
) -> Dict[str, Any]:
|
||||
"""处理数据。"""
|
||||
pass
|
||||
```
|
||||
|
||||
### 命名规范
|
||||
|
||||
- **模块名**:小写,下划线分隔(`my_module.py`)
|
||||
- **类名**:驼峰命名(`MyClass`)
|
||||
- **函数名**:小写,下划线分隔(`my_function`)
|
||||
- **常量**:大写,下划线分隔(`MY_CONSTANT`)
|
||||
- **私有成员**:前缀下划线(`_private_method`)
|
||||
|
||||
---
|
||||
|
||||
## 调试技巧
|
||||
|
||||
### 启用详细日志
|
||||
|
||||
```bash
|
||||
# 设置日志级别为 DEBUG
|
||||
export LOG_LEVEL=DEBUG
|
||||
|
||||
# 或在代码中设置
|
||||
import logging
|
||||
logging.basicConfig(level=logging.DEBUG)
|
||||
```
|
||||
|
||||
### 使用 Python 调试器
|
||||
|
||||
```python
|
||||
# 在代码中设置断点
|
||||
import pdb; pdb.set_trace()
|
||||
|
||||
# 或使用 ipdb(更友好)
|
||||
import ipdb; ipdb.set_trace()
|
||||
```
|
||||
|
||||
### 查看 AI 的思考过程
|
||||
|
||||
```bash
|
||||
# 使用 -v 参数显示详细日志
|
||||
python -m src.cli data.csv -v
|
||||
```
|
||||
|
||||
### 保存中间结果
|
||||
|
||||
```python
|
||||
# 在 AnalysisOrchestrator 中保存中间结果
|
||||
import json
|
||||
|
||||
# 保存数据画像
|
||||
with open('debug_data_profile.json', 'w') as f:
|
||||
json.dump(self.data_profile.__dict__, f, indent=2)
|
||||
|
||||
# 保存分析计划
|
||||
with open('debug_analysis_plan.json', 'w') as f:
|
||||
json.dump([task.__dict__ for task in self.analysis_plan.tasks], f, indent=2)
|
||||
```
|
||||
|
||||
### 模拟 AI 调用
|
||||
|
||||
在测试时模拟 AI 调用以避免 API 费用:
|
||||
|
||||
```python
|
||||
from unittest.mock import patch
|
||||
|
||||
with patch('src.engines.data_understanding.call_llm') as mock_llm:
|
||||
mock_llm.return_value = {
|
||||
'data_type': 'ticket',
|
||||
'key_fields': {'status': '工单状态'},
|
||||
'quality_score': 85.0
|
||||
}
|
||||
|
||||
# 执行测试
|
||||
result = understand_data(data_access)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 常见问题
|
||||
|
||||
### Q1: 如何添加对新数据格式的支持?
|
||||
|
||||
修改 `src/data_access.py` 中的 `load_from_file()` 方法:
|
||||
|
||||
```python
|
||||
@classmethod
|
||||
def load_from_file(cls, file_path: str) -> "DataAccessLayer":
|
||||
"""从文件加载数据。"""
|
||||
if file_path.endswith('.csv'):
|
||||
data = cls._load_csv(file_path)
|
||||
elif file_path.endswith('.xlsx'):
|
||||
data = cls._load_excel(file_path)
|
||||
elif file_path.endswith('.json'):
|
||||
data = cls._load_json(file_path)
|
||||
else:
|
||||
raise ValueError(f"不支持的文件格式: {file_path}")
|
||||
|
||||
return cls(data)
|
||||
```
|
||||
|
||||
### Q2: 如何更换 LLM 提供商?
|
||||
|
||||
修改 `.env` 文件:
|
||||
|
||||
```bash
|
||||
# 使用 Gemini
|
||||
LLM_PROVIDER=gemini
|
||||
GEMINI_API_KEY=your_gemini_key
|
||||
GEMINI_MODEL=gemini-2.0-flash-exp
|
||||
```
|
||||
|
||||
### Q3: 如何优化性能?
|
||||
|
||||
1. 增加并发任务数(未来版本支持)
|
||||
2. 使用更快的 LLM 模型
|
||||
3. 减少 ReAct 最大迭代次数
|
||||
4. 对大数据集进行采样
|
||||
|
||||
### Q4: 如何贡献代码?
|
||||
|
||||
1. Fork 项目
|
||||
2. 创建特性分支
|
||||
3. 编写代码和测试
|
||||
4. 确保所有测试通过
|
||||
5. 提交 Pull Request
|
||||
|
||||
---
|
||||
|
||||
## 资源链接
|
||||
|
||||
- **项目文档**: `docs/`
|
||||
- **API 文档**: `docs/API.md`
|
||||
- **配置指南**: `docs/configuration_guide.md`
|
||||
- **示例代码**: `examples/`
|
||||
- **测试数据**: `test_data/`
|
||||
|
||||
---
|
||||
|
||||
## 版本信息
|
||||
|
||||
- **版本**: v1.0.0
|
||||
- **日期**: 2026-03-06
|
||||
- **状态**: 稳定版本
|
||||
|
||||
---
|
||||
|
||||
## 联系方式
|
||||
|
||||
如有问题或建议,请创建 Issue 或联系维护者。
|
||||
198
docs/PERFORMANCE.md
Normal file
198
docs/PERFORMANCE.md
Normal file
@@ -0,0 +1,198 @@
|
||||
# 性能优化文档
|
||||
|
||||
## 概述
|
||||
|
||||
本文档描述了系统的性能优化措施和性能测试结果。
|
||||
|
||||
## 性能目标
|
||||
|
||||
根据需求 NFR-1.1 和 NFR-1.2,系统应满足以下性能指标:
|
||||
|
||||
- 数据理解阶段:< 30秒
|
||||
- 完整分析流程:< 30分钟
|
||||
- 支持最大 100万行数据
|
||||
- 支持最大 100MB 的 CSV 文件
|
||||
|
||||
## 性能优化措施
|
||||
|
||||
### 1. 数据加载优化
|
||||
|
||||
#### 内存优化
|
||||
- 自动优化数据类型以减少内存使用
|
||||
- 整数类型:int64 → int8/int16/int32(根据值范围)
|
||||
- 浮点类型:float64 → float32
|
||||
- 字符串类型:object → category(当唯一值比例 < 50%)
|
||||
|
||||
**优化效果**:
|
||||
- 测试数据(10万行 × 30列)
|
||||
- 优化前:123.88 MB
|
||||
- 优化后:2.97 MB
|
||||
- 节省:120.92 MB(97.6%)
|
||||
|
||||
#### 低内存模式
|
||||
- 使用 `pd.read_csv(..., low_memory=False)` 加载大文件
|
||||
- 避免内存碎片化
|
||||
|
||||
#### 大数据集采样
|
||||
- 自动检测数据大小
|
||||
- 超过100万行时自动采样到100万行
|
||||
- 使用固定随机种子确保可重复性
|
||||
|
||||
### 2. AI 调用优化
|
||||
|
||||
#### LLM 缓存
|
||||
- 实现基于 MD5 的缓存键生成
|
||||
- 支持内存缓存和文件缓存
|
||||
- 避免重复调用相同的提示
|
||||
|
||||
**使用方法**:
|
||||
```python
|
||||
from src.performance_optimization import get_global_cache, cached_llm_call
|
||||
|
||||
cache = get_global_cache(cache_dir=".cache")
|
||||
|
||||
@cached_llm_call(cache)
|
||||
def call_llm(prompt, model="gpt-4"):
|
||||
# LLM 调用逻辑
|
||||
pass
|
||||
```
|
||||
|
||||
#### 批处理
|
||||
- 实现批处理器用于批量处理工具调用
|
||||
- 减少 API 调用次数
|
||||
- 提高吞吐量
|
||||
|
||||
### 3. 性能监控
|
||||
|
||||
#### 性能监控器
|
||||
- 记录各阶段的执行时间
|
||||
- 计算统计信息(平均值、最小值、最大值)
|
||||
- 生成性能报告
|
||||
|
||||
**使用方法**:
|
||||
```python
|
||||
from src.performance_optimization import get_global_monitor, timed
|
||||
|
||||
monitor = get_global_monitor()
|
||||
|
||||
@timed(metric_name="my_function", monitor=monitor)
|
||||
def my_function():
|
||||
# 函数逻辑
|
||||
pass
|
||||
|
||||
# 获取统计信息
|
||||
stats = monitor.get_stats("my_function")
|
||||
print(f"平均耗时: {stats['mean']:.2f}秒")
|
||||
```
|
||||
|
||||
## 性能测试结果
|
||||
|
||||
### 数据理解阶段性能
|
||||
|
||||
| 数据规模 | 行数 | 列数 | 耗时(秒) | 行/秒 |
|
||||
|---------|------|------|-----------|-------|
|
||||
| 小数据集 | 1,000 | 10 | < 5 | - |
|
||||
| 中等数据集 | 100,000 | 20 | < 15 | 151,497 |
|
||||
| 大数据集 | 1,000,000 | 30 | < 30 | - |
|
||||
|
||||
**结论**:✅ 所有测试通过,满足 < 30秒的要求
|
||||
|
||||
### 数据加载性能基准
|
||||
|
||||
| 行数 | 耗时(秒) | 行/秒 |
|
||||
|------|-----------|-------|
|
||||
| 1,000 | 0.016 | 62,502 |
|
||||
| 10,000 | 0.068 | 147,301 |
|
||||
| 100,000 | 0.716 | 139,633 |
|
||||
|
||||
### 内存使用
|
||||
|
||||
| 测试场景 | 数据规模 | 内存增长 | 状态 |
|
||||
|---------|---------|---------|------|
|
||||
| 数据加载 | 10万行 × 50列 | < 500 MB | ✅ 通过 |
|
||||
| 大数据集 | 50万行 × 50列 | < 1 GB | ✅ 通过 |
|
||||
|
||||
## 性能优化建议
|
||||
|
||||
### 对于开发者
|
||||
|
||||
1. **使用性能监控器**
|
||||
- 在关键函数上使用 `@timed` 装饰器
|
||||
- 定期检查性能统计信息
|
||||
|
||||
2. **启用缓存**
|
||||
- 对于重复的 LLM 调用,使用缓存
|
||||
- 定期清理过期缓存
|
||||
|
||||
3. **优化数据加载**
|
||||
- 始终使用 `optimize_memory=True`
|
||||
- 对于大数据集,考虑预先采样
|
||||
|
||||
### 对于用户
|
||||
|
||||
1. **数据准备**
|
||||
- 尽量使用 UTF-8 编码
|
||||
- 避免过多的空值和重复数据
|
||||
- 控制数据规模在100万行以内
|
||||
|
||||
2. **性能调优**
|
||||
- 设置合理的超时时间
|
||||
- 使用模板可以加快分析速度
|
||||
- 避免过于复杂的需求描述
|
||||
|
||||
## 性能监控
|
||||
|
||||
### 查看性能统计
|
||||
|
||||
在分析完成后,系统会自动输出性能统计信息:
|
||||
|
||||
```
|
||||
==============================================================
|
||||
性能统计
|
||||
==============================================================
|
||||
data_understanding: 21.71秒 (min: 21.71s, max: 21.71s)
|
||||
requirement_understanding: 5.32秒 (min: 5.32s, max: 5.32s)
|
||||
analysis_planning: 8.45秒 (min: 8.45s, max: 8.45s)
|
||||
task_execution: 120.34秒 (min: 120.34s, max: 120.34s)
|
||||
report_generation: 15.67秒 (min: 15.67s, max: 15.67s)
|
||||
==============================================================
|
||||
```
|
||||
|
||||
### 性能瓶颈识别
|
||||
|
||||
如果某个阶段耗时过长,可以:
|
||||
|
||||
1. 检查数据质量和规模
|
||||
2. 查看日志中的详细信息
|
||||
3. 使用性能监控器定位具体函数
|
||||
4. 考虑优化或并行化
|
||||
|
||||
## 未来优化方向
|
||||
|
||||
1. **并行处理**
|
||||
- 并行执行独立的分析任务
|
||||
- 使用多进程处理大数据集
|
||||
|
||||
2. **增量分析**
|
||||
- 支持增量数据更新
|
||||
- 避免重复分析
|
||||
|
||||
3. **智能采样**
|
||||
- 根据数据特征智能采样
|
||||
- 保留关键数据点
|
||||
|
||||
4. **分布式处理**
|
||||
- 支持分布式数据处理
|
||||
- 横向扩展能力
|
||||
|
||||
## 参考资料
|
||||
|
||||
- [性能测试代码](../tests/test_performance.py)
|
||||
- [性能优化工具](../src/performance_optimization.py)
|
||||
- [配置文档](./configuration_guide.md)
|
||||
|
||||
---
|
||||
|
||||
**版本**: v1.0.0
|
||||
**日期**: 2026-03-06
|
||||
**状态**: 完成
|
||||
212
docs/configuration_guide.md
Normal file
212
docs/configuration_guide.md
Normal file
@@ -0,0 +1,212 @@
|
||||
# 配置管理指南
|
||||
|
||||
## 概述
|
||||
|
||||
本系统提供了灵活的配置管理机制,支持通过环境变量、配置文件和代码三种方式进行配置。
|
||||
|
||||
## 配置方式
|
||||
|
||||
### 1. 环境变量(推荐)
|
||||
|
||||
最简单的配置方式是使用 `.env` 文件:
|
||||
|
||||
```bash
|
||||
# .env 文件示例
|
||||
LLM_PROVIDER=openai
|
||||
OPENAI_API_KEY=your_api_key_here
|
||||
OPENAI_BASE_URL=https://api.openai.com/v1
|
||||
OPENAI_MODEL=gpt-4
|
||||
|
||||
AGENT_MAX_ROUNDS=20
|
||||
AGENT_OUTPUT_DIR=output
|
||||
TOOL_MAX_QUERY_ROWS=10000
|
||||
```
|
||||
|
||||
系统会自动加载 `.env` 文件中的配置。
|
||||
|
||||
### 2. 配置文件
|
||||
|
||||
使用 JSON 格式的配置文件:
|
||||
|
||||
```bash
|
||||
python -m src.cli data.csv -c config.json
|
||||
```
|
||||
|
||||
配置文件示例(`config.json`):
|
||||
|
||||
```json
|
||||
{
|
||||
"llm": {
|
||||
"provider": "openai",
|
||||
"api_key": "your_api_key_here",
|
||||
"base_url": "https://api.openai.com/v1",
|
||||
"model": "gpt-4",
|
||||
"timeout": 120,
|
||||
"max_retries": 3,
|
||||
"temperature": 0.7
|
||||
},
|
||||
"performance": {
|
||||
"agent_max_rounds": 20,
|
||||
"tool_max_query_rows": 10000
|
||||
},
|
||||
"output": {
|
||||
"output_dir": "output",
|
||||
"log_level": "INFO"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3. 代码配置
|
||||
|
||||
在代码中直接配置:
|
||||
|
||||
```python
|
||||
from src.config import Config, LLMConfig, set_config
|
||||
|
||||
config = Config(
|
||||
llm=LLMConfig(
|
||||
api_key="your_api_key",
|
||||
model="gpt-4"
|
||||
)
|
||||
)
|
||||
|
||||
set_config(config)
|
||||
```
|
||||
|
||||
## 配置优先级
|
||||
|
||||
配置的优先级从高到低:
|
||||
|
||||
1. 代码中直接设置的配置
|
||||
2. 命令行指定的配置文件(`-c config.json`)
|
||||
3. 环境变量
|
||||
4. `.env.local` 文件(本地开发,不提交到版本控制)
|
||||
5. `.env` 文件
|
||||
6. 默认值
|
||||
|
||||
## 配置项说明
|
||||
|
||||
### LLM 配置
|
||||
|
||||
| 配置项 | 环境变量 | 默认值 | 说明 |
|
||||
|--------|----------|--------|------|
|
||||
| provider | LLM_PROVIDER | openai | LLM 提供商(openai 或 gemini) |
|
||||
| api_key | OPENAI_API_KEY / GEMINI_API_KEY | - | API 密钥(必需) |
|
||||
| base_url | OPENAI_BASE_URL / GEMINI_BASE_URL | https://api.openai.com/v1 | API 基础 URL |
|
||||
| model | OPENAI_MODEL / GEMINI_MODEL | gpt-4 | 模型名称 |
|
||||
| timeout | LLM_TIMEOUT | 120 | 请求超时时间(秒) |
|
||||
| max_retries | LLM_MAX_RETRIES | 3 | 最大重试次数 |
|
||||
| temperature | LLM_TEMPERATURE | 0.7 | 温度参数 |
|
||||
| max_tokens | LLM_MAX_TOKENS | null | 最大 token 数 |
|
||||
|
||||
### 性能配置
|
||||
|
||||
| 配置项 | 环境变量 | 默认值 | 说明 |
|
||||
|--------|----------|--------|------|
|
||||
| agent_max_rounds | AGENT_MAX_ROUNDS | 20 | ReAct 最大迭代次数 |
|
||||
| agent_timeout | AGENT_TIMEOUT | 300 | Agent 执行超时(秒) |
|
||||
| tool_max_query_rows | TOOL_MAX_QUERY_ROWS | 10000 | 工具查询最大行数 |
|
||||
| tool_execution_timeout | TOOL_EXECUTION_TIMEOUT | 60 | 工具执行超时(秒) |
|
||||
| data_max_rows | DATA_MAX_ROWS | 1000000 | 最大数据行数 |
|
||||
| data_sample_threshold | DATA_SAMPLE_THRESHOLD | 1000000 | 数据采样阈值 |
|
||||
|
||||
### 输出配置
|
||||
|
||||
| 配置项 | 环境变量 | 默认值 | 说明 |
|
||||
|--------|----------|--------|------|
|
||||
| output_dir | AGENT_OUTPUT_DIR | output | 输出目录 |
|
||||
| log_dir | LOG_DIR | output | 日志目录 |
|
||||
| chart_dir | CHART_DIR | output/charts | 图表目录 |
|
||||
| report_filename | REPORT_FILENAME | analysis_report.md | 报告文件名 |
|
||||
| log_level | LOG_LEVEL | INFO | 日志级别 |
|
||||
| log_to_file | LOG_TO_FILE | true | 是否记录到文件 |
|
||||
| log_to_console | LOG_TO_CONSOLE | true | 是否输出到控制台 |
|
||||
|
||||
## 使用示例
|
||||
|
||||
### 示例 1:使用默认配置
|
||||
|
||||
```bash
|
||||
# 确保 .env 文件中设置了 OPENAI_API_KEY
|
||||
python -m src.cli data.csv
|
||||
```
|
||||
|
||||
### 示例 2:使用自定义配置文件
|
||||
|
||||
```bash
|
||||
python -m src.cli data.csv -c my_config.json
|
||||
```
|
||||
|
||||
### 示例 3:覆盖环境变量
|
||||
|
||||
```bash
|
||||
# 临时覆盖环境变量
|
||||
OPENAI_MODEL=gpt-3.5-turbo python -m src.cli data.csv
|
||||
```
|
||||
|
||||
### 示例 4:在代码中使用配置
|
||||
|
||||
```python
|
||||
from src.config import get_config
|
||||
|
||||
# 获取全局配置
|
||||
config = get_config()
|
||||
|
||||
# 访问配置项
|
||||
print(f"使用模型: {config.llm.model}")
|
||||
print(f"输出目录: {config.output.output_dir}")
|
||||
```
|
||||
|
||||
## 配置验证
|
||||
|
||||
系统会在启动时自动验证配置:
|
||||
|
||||
- 检查必需的配置项(如 API key)
|
||||
- 验证配置值的有效性
|
||||
- 检查输出目录是否可写
|
||||
|
||||
如果配置无效,系统会报错并退出。
|
||||
|
||||
## 安全建议
|
||||
|
||||
1. **不要提交 API 密钥到版本控制**
|
||||
- 将 `.env` 添加到 `.gitignore`
|
||||
- 使用 `.env.example` 作为模板
|
||||
|
||||
2. **使用环境变量存储敏感信息**
|
||||
- 在生产环境中使用环境变量而不是配置文件
|
||||
- 使用密钥管理服务(如 AWS Secrets Manager)
|
||||
|
||||
3. **限制配置文件权限**
|
||||
- 确保配置文件只有必要的用户可以读取
|
||||
- 在 Unix 系统上使用 `chmod 600 config.json`
|
||||
|
||||
## 故障排查
|
||||
|
||||
### 问题:配置未生效
|
||||
|
||||
**解决方案**:
|
||||
1. 检查配置优先级,确保没有被更高优先级的配置覆盖
|
||||
2. 使用 `-v` 参数查看详细日志
|
||||
3. 检查环境变量是否正确设置:`echo $OPENAI_API_KEY`
|
||||
|
||||
### 问题:API 密钥无效
|
||||
|
||||
**解决方案**:
|
||||
1. 确认 API 密钥正确无误
|
||||
2. 检查 API 密钥是否有足够的权限
|
||||
3. 验证 base_url 是否正确
|
||||
|
||||
### 问题:配置文件加载失败
|
||||
|
||||
**解决方案**:
|
||||
1. 检查 JSON 格式是否正确
|
||||
2. 确认文件路径是否正确
|
||||
3. 检查文件权限
|
||||
|
||||
## 参考
|
||||
|
||||
- 配置模块源码:`src/config.py`
|
||||
- 环境变量加载器:`src/env_loader.py`
|
||||
- 配置示例:`config.example.json`
|
||||
- 环境变量示例:`.env.example`
|
||||
Reference in New Issue
Block a user