Download dataflow_agent/trajectory/manager.py from pzp5700/Paper2Any: direct link, hf CLI and curl.
- Browser
- Download file 9.4 kB
-
https://huggingface.co/spaces/pzp5700/Paper2Any/resolve/main/dataflow_agent/trajectory/manager.py
- Command line
-
hf download hf://spaces/pzp5700/Paper2Any/dataflow_agent/trajectory/manager.py
-
curl -L -o manager.py https://huggingface.co/spaces/pzp5700/Paper2Any/resolve/main/dataflow_agent/trajectory/manager.py
9.4 kB
| """ | |
| 轨迹管理器 - 统一的轨迹管理入口 | |
| 提供简单易用的 API 来: | |
| 1. 开始/停止轨迹记录 | |
| 2. 自动构建和导出轨迹 | |
| 3. 批量管理轨迹 | |
| """ | |
| from typing import Any, Dict, List, Optional, Union | |
| from pathlib import Path | |
| from dataflow_agent.trajectory.models import Trajectory | |
| from dataflow_agent.trajectory.collector import TrajectoryCollector | |
| from dataflow_agent.trajectory.builder import TrajectoryBuilder | |
| from dataflow_agent.trajectory.exporter import TrajectoryExporter | |
| from dataflow_agent.state import MainState | |
| from dataflow_agent.logger import get_logger | |
| log = get_logger(__name__) | |
| class TrajectoryManager: | |
| """ | |
| 轨迹管理器 - 统一入口 | |
| 使用示例: | |
| ```python | |
| # 1. 创建管理器 | |
| trj_manager = TrajectoryManager() | |
| # 2. 开始记录 | |
| trj_manager.start_recording(inputs={"query": "..."}) | |
| # 3. 在 workflow 执行过程中,collector 会自动记录 | |
| # (需要在 workflow 中集成 collector 的 hook) | |
| # 4. 停止记录并生成轨迹 | |
| trajectory = trj_manager.stop_recording( | |
| state=final_state, | |
| workflow_name="my_workflow" | |
| ) | |
| # 5. 导出 | |
| filepath = trj_manager.export(trajectory, format="json") | |
| ``` | |
| """ | |
| def __init__(self, output_dir: str = None): | |
| """ | |
| Args: | |
| output_dir: 导出目录 | |
| """ | |
| self.collector = TrajectoryCollector() | |
| self.builder = TrajectoryBuilder() | |
| self.exporter = TrajectoryExporter(output_dir) | |
| self.is_recording = False | |
| self.current_trajectory: Optional[Trajectory] = None | |
| log.info("[TrajectoryManager] 初始化完成") | |
| def start_recording(self, | |
| inputs: Dict[str, Any] = None, | |
| metadata: Dict[str, Any] = None): | |
| """ | |
| 开始记录轨迹 | |
| Args: | |
| inputs: 初始输入数据 | |
| metadata: 额外元数据 | |
| """ | |
| self.collector.start(inputs=inputs, metadata=metadata) | |
| self.is_recording = True | |
| log.info("[TrajectoryManager] 开始记录轨迹") | |
| def stop_recording(self, | |
| state: MainState, | |
| workflow_name: str, | |
| user_id: str = None, | |
| session_id: str = None) -> Trajectory: | |
| """ | |
| 停止记录并生成轨迹 | |
| Args: | |
| state: Workflow 执行后的最终状态 | |
| workflow_name: Workflow 名称 | |
| user_id: 用户 ID | |
| session_id: 会话 ID | |
| Returns: | |
| 生成的 Trajectory 对象 | |
| """ | |
| if not self.is_recording: | |
| log.warning("[TrajectoryManager] 未在记录状态,无法停止") | |
| return None | |
| # 构建轨迹 | |
| trajectory = self.builder.build_from_state( | |
| state=state, | |
| collector=self.collector, | |
| workflow_name=workflow_name, | |
| user_id=user_id, | |
| session_id=session_id | |
| ) | |
| self.is_recording = False | |
| self.current_trajectory = trajectory | |
| log.info(f"[TrajectoryManager] 轨迹记录完成: {trajectory.trace_id}") | |
| return trajectory | |
| def export(self, | |
| trajectory: Trajectory = None, | |
| format: str = "json", | |
| filepath: str = None, | |
| **kwargs) -> str: | |
| """ | |
| 导出轨迹 | |
| Args: | |
| trajectory: 要导出的轨迹,如果为 None 则使用当前轨迹 | |
| format: 导出格式(json/jsonl/sft/dpo) | |
| filepath: 文件路径 | |
| **kwargs: 其他参数 | |
| Returns: | |
| 保存的文件路径 | |
| """ | |
| if trajectory is None: | |
| trajectory = self.current_trajectory | |
| if trajectory is None: | |
| log.error("[TrajectoryManager] 没有可导出的轨迹") | |
| return None | |
| if format == "json": | |
| return self.exporter.export_to_json(trajectory, filepath, **kwargs) | |
| elif format == "jsonl": | |
| return self.exporter.export_to_jsonl([trajectory], filepath, **kwargs) | |
| elif format == "sft": | |
| return self.exporter.export_to_jsonl([trajectory], filepath, mode="sft") | |
| elif format == "dpo": | |
| return self.exporter.export_to_jsonl([trajectory], filepath, mode="dpo") | |
| else: | |
| raise ValueError(f"Unknown format: {format}") | |
| def export_batch(self, | |
| trajectories: List[Trajectory], | |
| format: str = "jsonl", | |
| filepath: str = None, | |
| **kwargs) -> str: | |
| """ | |
| 批量导出轨迹 | |
| Args: | |
| trajectories: 轨迹列表 | |
| format: 导出格式 | |
| filepath: 文件路径 | |
| **kwargs: 其他参数 | |
| Returns: | |
| 保存的文件路径 | |
| """ | |
| if format == "jsonl": | |
| return self.exporter.export_to_jsonl(trajectories, filepath, **kwargs) | |
| elif format == "sft": | |
| return self.exporter.export_sft_dataset(trajectories, filepath, **kwargs) | |
| else: | |
| raise ValueError(f"Batch export not supported for format: {format}") | |
| def get_collector(self) -> TrajectoryCollector: | |
| """获取收集器实例(用于手动集成)""" | |
| return self.collector | |
| def get_current_trajectory(self) -> Optional[Trajectory]: | |
| """获取当前轨迹""" | |
| return self.current_trajectory | |
| def add_feedback(self, | |
| trajectory: Trajectory = None, | |
| score: int = None, | |
| comment: str = None, | |
| edited_response: str = None, | |
| labels: List[str] = None): | |
| """ | |
| 添加用户反馈 | |
| Args: | |
| trajectory: 轨迹对象,如果为 None 则使用当前轨迹 | |
| score: 评分 1-5 | |
| comment: 评论 | |
| edited_response: 用户修改后的回答 | |
| labels: 标签列表 | |
| """ | |
| if trajectory is None: | |
| trajectory = self.current_trajectory | |
| if trajectory is None: | |
| log.error("[TrajectoryManager] 没有可添加反馈的轨迹") | |
| return | |
| trajectory.set_feedback( | |
| score=score, | |
| comment=comment, | |
| edited_response=edited_response, | |
| labels=labels | |
| ) | |
| log.info(f"[TrajectoryManager] 已添加反馈到轨迹: {trajectory.trace_id}") | |
| # ==================== 全局单例 ==================== | |
| _global_manager: Optional[TrajectoryManager] = None | |
| def get_trajectory_manager(output_dir: str = None) -> TrajectoryManager: | |
| """ | |
| 获取全局轨迹管理器(单例模式) | |
| Args: | |
| output_dir: 输出目录 | |
| Returns: | |
| TrajectoryManager 实例 | |
| """ | |
| global _global_manager | |
| if _global_manager is None: | |
| _global_manager = TrajectoryManager(output_dir) | |
| return _global_manager | |
| def reset_trajectory_manager(): | |
| """重置全局轨迹管理器""" | |
| global _global_manager | |
| _global_manager = None | |
| # ==================== 便捷函数 ==================== | |
| def quick_record(workflow_func, | |
| workflow_name: str, | |
| inputs: Dict[str, Any] = None, | |
| export_format: str = "json", | |
| **workflow_kwargs): | |
| """ | |
| 快速记录 workflow 执行轨迹的装饰器/函数 | |
| 使用示例: | |
| ```python | |
| # 作为装饰器 | |
| @quick_record(workflow_name="my_workflow") | |
| async def my_workflow(state): | |
| # workflow 逻辑 | |
| return final_state | |
| # 或作为函数 | |
| final_state = await quick_record( | |
| my_workflow, | |
| workflow_name="my_workflow", | |
| inputs={"query": "..."}, | |
| state=initial_state | |
| ) | |
| ``` | |
| """ | |
| import asyncio | |
| from functools import wraps | |
| # 如果是装饰器用法 | |
| if callable(workflow_func): | |
| async def wrapper(*args, **kwargs): | |
| manager = get_trajectory_manager() | |
| # 开始记录 | |
| manager.start_recording(inputs=inputs) | |
| try: | |
| # 执行 workflow | |
| if asyncio.iscoroutinefunction(workflow_func): | |
| result = await workflow_func(*args, **kwargs) | |
| else: | |
| result = workflow_func(*args, **kwargs) | |
| # 停止记录 | |
| trajectory = manager.stop_recording( | |
| state=result, | |
| workflow_name=workflow_name | |
| ) | |
| # 导出 | |
| filepath = manager.export(trajectory, format=export_format) | |
| log.info(f"[quick_record] 轨迹已导出: {filepath}") | |
| return result | |
| except Exception as e: | |
| log.exception(f"[quick_record] Workflow 执行失败: {e}") | |
| raise | |
| return wrapper | |
| # 如果是函数调用用法 | |
| else: | |
| raise ValueError("quick_record 应该作为装饰器使用") | |