Implement Report Agent for automated report generation and interaction
- Introduced the Report Agent module to facilitate the automatic generation of simulation analysis reports using LangChain and Zep, following the ReACT model. - Added functionality for report outline planning, segmented content generation, and user interaction through a dialogue interface. - Implemented new API endpoints for report generation, status checking, and retrieval, enhancing the overall reporting capabilities. - Updated README.md to include detailed instructions on the new report generation features and API usage. - Enhanced the project structure to accommodate the new report management functionalities, including report storage and retrieval mechanisms.
This commit is contained in:
@@ -6,7 +6,9 @@ from flask import Blueprint
|
||||
|
||||
graph_bp = Blueprint('graph', __name__)
|
||||
simulation_bp = Blueprint('simulation', __name__)
|
||||
report_bp = Blueprint('report', __name__)
|
||||
|
||||
from . import graph # noqa: E402, F401
|
||||
from . import simulation # noqa: E402, F401
|
||||
from . import report # noqa: E402, F401
|
||||
|
||||
|
||||
829
backend/app/api/report.py
Normal file
829
backend/app/api/report.py
Normal file
@@ -0,0 +1,829 @@
|
||||
"""
|
||||
Report API路由
|
||||
提供模拟报告生成、获取、对话等接口
|
||||
"""
|
||||
|
||||
import os
|
||||
import traceback
|
||||
import threading
|
||||
from flask import request, jsonify, send_file
|
||||
|
||||
from . import report_bp
|
||||
from ..config import Config
|
||||
from ..services.report_agent import ReportAgent, ReportManager, ReportStatus
|
||||
from ..services.simulation_manager import SimulationManager
|
||||
from ..models.project import ProjectManager
|
||||
from ..models.task import TaskManager, TaskStatus
|
||||
from ..utils.logger import get_logger
|
||||
|
||||
logger = get_logger('mirofish.api.report')
|
||||
|
||||
|
||||
# ============== 报告生成接口 ==============
|
||||
|
||||
@report_bp.route('/generate', methods=['POST'])
|
||||
def generate_report():
|
||||
"""
|
||||
生成模拟分析报告(异步任务)
|
||||
|
||||
这是一个耗时操作,接口会立即返回task_id,
|
||||
使用 GET /api/report/generate/status 查询进度
|
||||
|
||||
请求(JSON):
|
||||
{
|
||||
"simulation_id": "sim_xxxx", // 必填,模拟ID
|
||||
"force_regenerate": false // 可选,强制重新生成
|
||||
}
|
||||
|
||||
返回:
|
||||
{
|
||||
"success": true,
|
||||
"data": {
|
||||
"simulation_id": "sim_xxxx",
|
||||
"task_id": "task_xxxx",
|
||||
"status": "generating",
|
||||
"message": "报告生成任务已启动"
|
||||
}
|
||||
}
|
||||
"""
|
||||
try:
|
||||
data = request.get_json() or {}
|
||||
|
||||
simulation_id = data.get('simulation_id')
|
||||
if not simulation_id:
|
||||
return jsonify({
|
||||
"success": False,
|
||||
"error": "请提供 simulation_id"
|
||||
}), 400
|
||||
|
||||
force_regenerate = data.get('force_regenerate', False)
|
||||
|
||||
# 获取模拟信息
|
||||
manager = SimulationManager()
|
||||
state = manager.get_simulation(simulation_id)
|
||||
|
||||
if not state:
|
||||
return jsonify({
|
||||
"success": False,
|
||||
"error": f"模拟不存在: {simulation_id}"
|
||||
}), 404
|
||||
|
||||
# 检查是否已有报告
|
||||
if not force_regenerate:
|
||||
existing_report = ReportManager.get_report_by_simulation(simulation_id)
|
||||
if existing_report and existing_report.status == ReportStatus.COMPLETED:
|
||||
return jsonify({
|
||||
"success": True,
|
||||
"data": {
|
||||
"simulation_id": simulation_id,
|
||||
"report_id": existing_report.report_id,
|
||||
"status": "completed",
|
||||
"message": "报告已存在",
|
||||
"already_generated": True
|
||||
}
|
||||
})
|
||||
|
||||
# 获取项目信息
|
||||
project = ProjectManager.get_project(state.project_id)
|
||||
if not project:
|
||||
return jsonify({
|
||||
"success": False,
|
||||
"error": f"项目不存在: {state.project_id}"
|
||||
}), 404
|
||||
|
||||
graph_id = state.graph_id or project.graph_id
|
||||
if not graph_id:
|
||||
return jsonify({
|
||||
"success": False,
|
||||
"error": "缺少图谱ID,请确保已构建图谱"
|
||||
}), 400
|
||||
|
||||
simulation_requirement = project.simulation_requirement
|
||||
if not simulation_requirement:
|
||||
return jsonify({
|
||||
"success": False,
|
||||
"error": "缺少模拟需求描述"
|
||||
}), 400
|
||||
|
||||
# 创建异步任务
|
||||
task_manager = TaskManager()
|
||||
task_id = task_manager.create_task(
|
||||
task_type="report_generate",
|
||||
metadata={
|
||||
"simulation_id": simulation_id,
|
||||
"graph_id": graph_id
|
||||
}
|
||||
)
|
||||
|
||||
# 定义后台任务
|
||||
def run_generate():
|
||||
try:
|
||||
task_manager.update_task(
|
||||
task_id,
|
||||
status=TaskStatus.PROCESSING,
|
||||
progress=0,
|
||||
message="初始化Report Agent..."
|
||||
)
|
||||
|
||||
# 创建Report Agent
|
||||
agent = ReportAgent(
|
||||
graph_id=graph_id,
|
||||
simulation_id=simulation_id,
|
||||
simulation_requirement=simulation_requirement
|
||||
)
|
||||
|
||||
# 进度回调
|
||||
def progress_callback(stage, progress, message):
|
||||
task_manager.update_task(
|
||||
task_id,
|
||||
progress=progress,
|
||||
message=f"[{stage}] {message}"
|
||||
)
|
||||
|
||||
# 生成报告
|
||||
report = agent.generate_report(progress_callback=progress_callback)
|
||||
|
||||
# 保存报告
|
||||
ReportManager.save_report(report)
|
||||
|
||||
if report.status == ReportStatus.COMPLETED:
|
||||
task_manager.complete_task(
|
||||
task_id,
|
||||
result={
|
||||
"report_id": report.report_id,
|
||||
"simulation_id": simulation_id,
|
||||
"status": "completed"
|
||||
}
|
||||
)
|
||||
else:
|
||||
task_manager.fail_task(task_id, report.error or "报告生成失败")
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"报告生成失败: {str(e)}")
|
||||
task_manager.fail_task(task_id, str(e))
|
||||
|
||||
# 启动后台线程
|
||||
thread = threading.Thread(target=run_generate, daemon=True)
|
||||
thread.start()
|
||||
|
||||
return jsonify({
|
||||
"success": True,
|
||||
"data": {
|
||||
"simulation_id": simulation_id,
|
||||
"task_id": task_id,
|
||||
"status": "generating",
|
||||
"message": "报告生成任务已启动,请通过 /api/report/generate/status 查询进度",
|
||||
"already_generated": False
|
||||
}
|
||||
})
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"启动报告生成任务失败: {str(e)}")
|
||||
return jsonify({
|
||||
"success": False,
|
||||
"error": str(e),
|
||||
"traceback": traceback.format_exc()
|
||||
}), 500
|
||||
|
||||
|
||||
@report_bp.route('/generate/status', methods=['POST'])
|
||||
def get_generate_status():
|
||||
"""
|
||||
查询报告生成任务进度
|
||||
|
||||
请求(JSON):
|
||||
{
|
||||
"task_id": "task_xxxx", // 可选,generate返回的task_id
|
||||
"simulation_id": "sim_xxxx" // 可选,模拟ID
|
||||
}
|
||||
|
||||
返回:
|
||||
{
|
||||
"success": true,
|
||||
"data": {
|
||||
"task_id": "task_xxxx",
|
||||
"status": "processing|completed|failed",
|
||||
"progress": 45,
|
||||
"message": "..."
|
||||
}
|
||||
}
|
||||
"""
|
||||
try:
|
||||
data = request.get_json() or {}
|
||||
|
||||
task_id = data.get('task_id')
|
||||
simulation_id = data.get('simulation_id')
|
||||
|
||||
# 如果提供了simulation_id,先检查是否已有完成的报告
|
||||
if simulation_id:
|
||||
existing_report = ReportManager.get_report_by_simulation(simulation_id)
|
||||
if existing_report and existing_report.status == ReportStatus.COMPLETED:
|
||||
return jsonify({
|
||||
"success": True,
|
||||
"data": {
|
||||
"simulation_id": simulation_id,
|
||||
"report_id": existing_report.report_id,
|
||||
"status": "completed",
|
||||
"progress": 100,
|
||||
"message": "报告已生成",
|
||||
"already_completed": True
|
||||
}
|
||||
})
|
||||
|
||||
if not task_id:
|
||||
return jsonify({
|
||||
"success": False,
|
||||
"error": "请提供 task_id 或 simulation_id"
|
||||
}), 400
|
||||
|
||||
task_manager = TaskManager()
|
||||
task = task_manager.get_task(task_id)
|
||||
|
||||
if not task:
|
||||
return jsonify({
|
||||
"success": False,
|
||||
"error": f"任务不存在: {task_id}"
|
||||
}), 404
|
||||
|
||||
return jsonify({
|
||||
"success": True,
|
||||
"data": task.to_dict()
|
||||
})
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"查询任务状态失败: {str(e)}")
|
||||
return jsonify({
|
||||
"success": False,
|
||||
"error": str(e)
|
||||
}), 500
|
||||
|
||||
|
||||
# ============== 报告获取接口 ==============
|
||||
|
||||
@report_bp.route('/<report_id>', methods=['GET'])
|
||||
def get_report(report_id: str):
|
||||
"""
|
||||
获取报告详情
|
||||
|
||||
返回:
|
||||
{
|
||||
"success": true,
|
||||
"data": {
|
||||
"report_id": "report_xxxx",
|
||||
"simulation_id": "sim_xxxx",
|
||||
"status": "completed",
|
||||
"outline": {...},
|
||||
"markdown_content": "...",
|
||||
"created_at": "...",
|
||||
"completed_at": "..."
|
||||
}
|
||||
}
|
||||
"""
|
||||
try:
|
||||
report = ReportManager.get_report(report_id)
|
||||
|
||||
if not report:
|
||||
return jsonify({
|
||||
"success": False,
|
||||
"error": f"报告不存在: {report_id}"
|
||||
}), 404
|
||||
|
||||
return jsonify({
|
||||
"success": True,
|
||||
"data": report.to_dict()
|
||||
})
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"获取报告失败: {str(e)}")
|
||||
return jsonify({
|
||||
"success": False,
|
||||
"error": str(e),
|
||||
"traceback": traceback.format_exc()
|
||||
}), 500
|
||||
|
||||
|
||||
@report_bp.route('/by-simulation/<simulation_id>', methods=['GET'])
|
||||
def get_report_by_simulation(simulation_id: str):
|
||||
"""
|
||||
根据模拟ID获取报告
|
||||
|
||||
返回:
|
||||
{
|
||||
"success": true,
|
||||
"data": {
|
||||
"report_id": "report_xxxx",
|
||||
...
|
||||
}
|
||||
}
|
||||
"""
|
||||
try:
|
||||
report = ReportManager.get_report_by_simulation(simulation_id)
|
||||
|
||||
if not report:
|
||||
return jsonify({
|
||||
"success": False,
|
||||
"error": f"该模拟暂无报告: {simulation_id}",
|
||||
"has_report": False
|
||||
}), 404
|
||||
|
||||
return jsonify({
|
||||
"success": True,
|
||||
"data": report.to_dict(),
|
||||
"has_report": True
|
||||
})
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"获取报告失败: {str(e)}")
|
||||
return jsonify({
|
||||
"success": False,
|
||||
"error": str(e),
|
||||
"traceback": traceback.format_exc()
|
||||
}), 500
|
||||
|
||||
|
||||
@report_bp.route('/list', methods=['GET'])
|
||||
def list_reports():
|
||||
"""
|
||||
列出所有报告
|
||||
|
||||
Query参数:
|
||||
simulation_id: 按模拟ID过滤(可选)
|
||||
limit: 返回数量限制(默认50)
|
||||
|
||||
返回:
|
||||
{
|
||||
"success": true,
|
||||
"data": [...],
|
||||
"count": 10
|
||||
}
|
||||
"""
|
||||
try:
|
||||
simulation_id = request.args.get('simulation_id')
|
||||
limit = request.args.get('limit', 50, type=int)
|
||||
|
||||
reports = ReportManager.list_reports(
|
||||
simulation_id=simulation_id,
|
||||
limit=limit
|
||||
)
|
||||
|
||||
return jsonify({
|
||||
"success": True,
|
||||
"data": [r.to_dict() for r in reports],
|
||||
"count": len(reports)
|
||||
})
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"列出报告失败: {str(e)}")
|
||||
return jsonify({
|
||||
"success": False,
|
||||
"error": str(e),
|
||||
"traceback": traceback.format_exc()
|
||||
}), 500
|
||||
|
||||
|
||||
@report_bp.route('/<report_id>/download', methods=['GET'])
|
||||
def download_report(report_id: str):
|
||||
"""
|
||||
下载报告(Markdown格式)
|
||||
|
||||
返回Markdown文件
|
||||
"""
|
||||
try:
|
||||
report = ReportManager.get_report(report_id)
|
||||
|
||||
if not report:
|
||||
return jsonify({
|
||||
"success": False,
|
||||
"error": f"报告不存在: {report_id}"
|
||||
}), 404
|
||||
|
||||
md_path = ReportManager._get_report_markdown_path(report_id)
|
||||
|
||||
if not os.path.exists(md_path):
|
||||
# 如果MD文件不存在,生成一个临时文件
|
||||
import tempfile
|
||||
with tempfile.NamedTemporaryFile(mode='w', suffix='.md', delete=False) as f:
|
||||
f.write(report.markdown_content)
|
||||
temp_path = f.name
|
||||
|
||||
return send_file(
|
||||
temp_path,
|
||||
as_attachment=True,
|
||||
download_name=f"{report_id}.md"
|
||||
)
|
||||
|
||||
return send_file(
|
||||
md_path,
|
||||
as_attachment=True,
|
||||
download_name=f"{report_id}.md"
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"下载报告失败: {str(e)}")
|
||||
return jsonify({
|
||||
"success": False,
|
||||
"error": str(e),
|
||||
"traceback": traceback.format_exc()
|
||||
}), 500
|
||||
|
||||
|
||||
@report_bp.route('/<report_id>', methods=['DELETE'])
|
||||
def delete_report(report_id: str):
|
||||
"""删除报告"""
|
||||
try:
|
||||
success = ReportManager.delete_report(report_id)
|
||||
|
||||
if not success:
|
||||
return jsonify({
|
||||
"success": False,
|
||||
"error": f"报告不存在: {report_id}"
|
||||
}), 404
|
||||
|
||||
return jsonify({
|
||||
"success": True,
|
||||
"message": f"报告已删除: {report_id}"
|
||||
})
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"删除报告失败: {str(e)}")
|
||||
return jsonify({
|
||||
"success": False,
|
||||
"error": str(e),
|
||||
"traceback": traceback.format_exc()
|
||||
}), 500
|
||||
|
||||
|
||||
# ============== Report Agent对话接口 ==============
|
||||
|
||||
@report_bp.route('/chat', methods=['POST'])
|
||||
def chat_with_report_agent():
|
||||
"""
|
||||
与Report Agent对话
|
||||
|
||||
Report Agent可以在对话中自主调用检索工具来回答问题
|
||||
|
||||
请求(JSON):
|
||||
{
|
||||
"simulation_id": "sim_xxxx", // 必填,模拟ID
|
||||
"message": "请解释一下舆情走向", // 必填,用户消息
|
||||
"chat_history": [ // 可选,对话历史
|
||||
{"role": "user", "content": "..."},
|
||||
{"role": "assistant", "content": "..."}
|
||||
]
|
||||
}
|
||||
|
||||
返回:
|
||||
{
|
||||
"success": true,
|
||||
"data": {
|
||||
"response": "Agent回复...",
|
||||
"tool_calls": [调用的工具列表],
|
||||
"sources": [信息来源]
|
||||
}
|
||||
}
|
||||
"""
|
||||
try:
|
||||
data = request.get_json() or {}
|
||||
|
||||
simulation_id = data.get('simulation_id')
|
||||
message = data.get('message')
|
||||
chat_history = data.get('chat_history', [])
|
||||
|
||||
if not simulation_id:
|
||||
return jsonify({
|
||||
"success": False,
|
||||
"error": "请提供 simulation_id"
|
||||
}), 400
|
||||
|
||||
if not message:
|
||||
return jsonify({
|
||||
"success": False,
|
||||
"error": "请提供 message"
|
||||
}), 400
|
||||
|
||||
# 获取模拟和项目信息
|
||||
manager = SimulationManager()
|
||||
state = manager.get_simulation(simulation_id)
|
||||
|
||||
if not state:
|
||||
return jsonify({
|
||||
"success": False,
|
||||
"error": f"模拟不存在: {simulation_id}"
|
||||
}), 404
|
||||
|
||||
project = ProjectManager.get_project(state.project_id)
|
||||
if not project:
|
||||
return jsonify({
|
||||
"success": False,
|
||||
"error": f"项目不存在: {state.project_id}"
|
||||
}), 404
|
||||
|
||||
graph_id = state.graph_id or project.graph_id
|
||||
if not graph_id:
|
||||
return jsonify({
|
||||
"success": False,
|
||||
"error": "缺少图谱ID"
|
||||
}), 400
|
||||
|
||||
simulation_requirement = project.simulation_requirement or ""
|
||||
|
||||
# 创建Agent并进行对话
|
||||
agent = ReportAgent(
|
||||
graph_id=graph_id,
|
||||
simulation_id=simulation_id,
|
||||
simulation_requirement=simulation_requirement
|
||||
)
|
||||
|
||||
result = agent.chat(message=message, chat_history=chat_history)
|
||||
|
||||
return jsonify({
|
||||
"success": True,
|
||||
"data": result
|
||||
})
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"对话失败: {str(e)}")
|
||||
return jsonify({
|
||||
"success": False,
|
||||
"error": str(e),
|
||||
"traceback": traceback.format_exc()
|
||||
}), 500
|
||||
|
||||
|
||||
# ============== 报告进度与分章节接口 ==============
|
||||
|
||||
@report_bp.route('/<report_id>/progress', methods=['GET'])
|
||||
def get_report_progress(report_id: str):
|
||||
"""
|
||||
获取报告生成进度(实时)
|
||||
|
||||
返回:
|
||||
{
|
||||
"success": true,
|
||||
"data": {
|
||||
"status": "generating",
|
||||
"progress": 45,
|
||||
"message": "正在生成章节: 关键发现",
|
||||
"current_section": "关键发现",
|
||||
"completed_sections": ["执行摘要", "模拟背景"],
|
||||
"updated_at": "2025-12-09T..."
|
||||
}
|
||||
}
|
||||
"""
|
||||
try:
|
||||
progress = ReportManager.get_progress(report_id)
|
||||
|
||||
if not progress:
|
||||
return jsonify({
|
||||
"success": False,
|
||||
"error": f"报告不存在或进度信息不可用: {report_id}"
|
||||
}), 404
|
||||
|
||||
return jsonify({
|
||||
"success": True,
|
||||
"data": progress
|
||||
})
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"获取报告进度失败: {str(e)}")
|
||||
return jsonify({
|
||||
"success": False,
|
||||
"error": str(e),
|
||||
"traceback": traceback.format_exc()
|
||||
}), 500
|
||||
|
||||
|
||||
@report_bp.route('/<report_id>/sections', methods=['GET'])
|
||||
def get_report_sections(report_id: str):
|
||||
"""
|
||||
获取已生成的章节列表(分章节输出)
|
||||
|
||||
前端可以轮询此接口获取已生成的章节内容,无需等待整个报告完成
|
||||
|
||||
返回:
|
||||
{
|
||||
"success": true,
|
||||
"data": {
|
||||
"report_id": "report_xxxx",
|
||||
"sections": [
|
||||
{
|
||||
"filename": "section_01.md",
|
||||
"section_index": 1,
|
||||
"content": "## 执行摘要\\n\\n..."
|
||||
},
|
||||
...
|
||||
],
|
||||
"total_sections": 3,
|
||||
"is_complete": false
|
||||
}
|
||||
}
|
||||
"""
|
||||
try:
|
||||
sections = ReportManager.get_generated_sections(report_id)
|
||||
|
||||
# 获取报告状态
|
||||
report = ReportManager.get_report(report_id)
|
||||
is_complete = report is not None and report.status == ReportStatus.COMPLETED
|
||||
|
||||
return jsonify({
|
||||
"success": True,
|
||||
"data": {
|
||||
"report_id": report_id,
|
||||
"sections": sections,
|
||||
"total_sections": len(sections),
|
||||
"is_complete": is_complete
|
||||
}
|
||||
})
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"获取章节列表失败: {str(e)}")
|
||||
return jsonify({
|
||||
"success": False,
|
||||
"error": str(e),
|
||||
"traceback": traceback.format_exc()
|
||||
}), 500
|
||||
|
||||
|
||||
@report_bp.route('/<report_id>/section/<int:section_index>', methods=['GET'])
|
||||
def get_single_section(report_id: str, section_index: int):
|
||||
"""
|
||||
获取单个章节内容
|
||||
|
||||
返回:
|
||||
{
|
||||
"success": true,
|
||||
"data": {
|
||||
"filename": "section_01.md",
|
||||
"content": "## 执行摘要\\n\\n..."
|
||||
}
|
||||
}
|
||||
"""
|
||||
try:
|
||||
section_path = ReportManager._get_section_path(report_id, section_index)
|
||||
|
||||
if not os.path.exists(section_path):
|
||||
return jsonify({
|
||||
"success": False,
|
||||
"error": f"章节不存在: section_{section_index:02d}.md"
|
||||
}), 404
|
||||
|
||||
with open(section_path, 'r', encoding='utf-8') as f:
|
||||
content = f.read()
|
||||
|
||||
return jsonify({
|
||||
"success": True,
|
||||
"data": {
|
||||
"filename": f"section_{section_index:02d}.md",
|
||||
"section_index": section_index,
|
||||
"content": content
|
||||
}
|
||||
})
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"获取章节内容失败: {str(e)}")
|
||||
return jsonify({
|
||||
"success": False,
|
||||
"error": str(e),
|
||||
"traceback": traceback.format_exc()
|
||||
}), 500
|
||||
|
||||
|
||||
# ============== 报告状态检查接口 ==============
|
||||
|
||||
@report_bp.route('/check/<simulation_id>', methods=['GET'])
|
||||
def check_report_status(simulation_id: str):
|
||||
"""
|
||||
检查模拟是否有报告,以及报告状态
|
||||
|
||||
用于前端判断是否解锁Interview功能
|
||||
|
||||
返回:
|
||||
{
|
||||
"success": true,
|
||||
"data": {
|
||||
"simulation_id": "sim_xxxx",
|
||||
"has_report": true,
|
||||
"report_status": "completed",
|
||||
"report_id": "report_xxxx",
|
||||
"interview_unlocked": true
|
||||
}
|
||||
}
|
||||
"""
|
||||
try:
|
||||
report = ReportManager.get_report_by_simulation(simulation_id)
|
||||
|
||||
has_report = report is not None
|
||||
report_status = report.status.value if report else None
|
||||
report_id = report.report_id if report else None
|
||||
|
||||
# 只有报告完成后才解锁interview
|
||||
interview_unlocked = has_report and report.status == ReportStatus.COMPLETED
|
||||
|
||||
return jsonify({
|
||||
"success": True,
|
||||
"data": {
|
||||
"simulation_id": simulation_id,
|
||||
"has_report": has_report,
|
||||
"report_status": report_status,
|
||||
"report_id": report_id,
|
||||
"interview_unlocked": interview_unlocked
|
||||
}
|
||||
})
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"检查报告状态失败: {str(e)}")
|
||||
return jsonify({
|
||||
"success": False,
|
||||
"error": str(e),
|
||||
"traceback": traceback.format_exc()
|
||||
}), 500
|
||||
|
||||
|
||||
# ============== 工具调用接口(供调试使用)==============
|
||||
|
||||
@report_bp.route('/tools/search', methods=['POST'])
|
||||
def search_graph_tool():
|
||||
"""
|
||||
图谱搜索工具接口(供调试使用)
|
||||
|
||||
请求(JSON):
|
||||
{
|
||||
"graph_id": "mirofish_xxxx",
|
||||
"query": "搜索查询",
|
||||
"limit": 10
|
||||
}
|
||||
"""
|
||||
try:
|
||||
data = request.get_json() or {}
|
||||
|
||||
graph_id = data.get('graph_id')
|
||||
query = data.get('query')
|
||||
limit = data.get('limit', 10)
|
||||
|
||||
if not graph_id or not query:
|
||||
return jsonify({
|
||||
"success": False,
|
||||
"error": "请提供 graph_id 和 query"
|
||||
}), 400
|
||||
|
||||
from ..services.zep_tools import ZepToolsService
|
||||
|
||||
tools = ZepToolsService()
|
||||
result = tools.search_graph(
|
||||
graph_id=graph_id,
|
||||
query=query,
|
||||
limit=limit
|
||||
)
|
||||
|
||||
return jsonify({
|
||||
"success": True,
|
||||
"data": result.to_dict()
|
||||
})
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"图谱搜索失败: {str(e)}")
|
||||
return jsonify({
|
||||
"success": False,
|
||||
"error": str(e),
|
||||
"traceback": traceback.format_exc()
|
||||
}), 500
|
||||
|
||||
|
||||
@report_bp.route('/tools/statistics', methods=['POST'])
|
||||
def get_graph_statistics_tool():
|
||||
"""
|
||||
图谱统计工具接口(供调试使用)
|
||||
|
||||
请求(JSON):
|
||||
{
|
||||
"graph_id": "mirofish_xxxx"
|
||||
}
|
||||
"""
|
||||
try:
|
||||
data = request.get_json() or {}
|
||||
|
||||
graph_id = data.get('graph_id')
|
||||
|
||||
if not graph_id:
|
||||
return jsonify({
|
||||
"success": False,
|
||||
"error": "请提供 graph_id"
|
||||
}), 400
|
||||
|
||||
from ..services.zep_tools import ZepToolsService
|
||||
|
||||
tools = ZepToolsService()
|
||||
result = tools.get_graph_statistics(graph_id)
|
||||
|
||||
return jsonify({
|
||||
"success": True,
|
||||
"data": result
|
||||
})
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"获取图谱统计失败: {str(e)}")
|
||||
return jsonify({
|
||||
"success": False,
|
||||
"error": str(e),
|
||||
"traceback": traceback.format_exc()
|
||||
}), 500
|
||||
Reference in New Issue
Block a user