From a3897f233ea521e138728a53284dffff67e7e32a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B7=A9=E6=97=AD=E7=BA=A2?= <2250244225@qq.com> Date: Thu, 20 Nov 2025 18:48:08 +0800 Subject: [PATCH 1/7] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=90=8E=E7=AB=AFapi?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3=20=E5=8F=8A=E5=91=BD=E4=BB=A4=E8=A1=8C?= =?UTF-8?q?=E5=90=AF=E5=8A=A8=E6=96=B9=E5=BC=8F=20&=20=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E5=88=86=E5=AF=B9=E7=94=BB=E5=9B=BE=E5=B7=A5?= =?UTF-8?q?=E5=85=B7=E7=BB=93=E6=9E=9C=E5=A4=84=E7=90=86=E7=9A=84prompt=20?= =?UTF-8?q?&=20=E4=BC=98=E5=8C=96=E9=A1=B6=E4=BC=9A=E7=9B=B8=E5=85=B3?= =?UTF-8?q?=E8=A1=A8=E7=BB=93=E6=9E=84=E5=8A=A8=E6=80=81=E5=B5=8C=E5=85=A5?= =?UTF-8?q?prompt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 2 + README.md | 9 +- deepinsight/api/app.py | 309 ++++++++++----- deepinsight/cli/commands/api.py | 84 ++++ deepinsight/cli/main.py | 19 + .../conf_stat_value_mining.py | 12 +- .../core/prompt/conference_best_papers.py | 84 +--- .../core/prompt/conference_submission.py | 368 ++---------------- deepinsight/core/tools/best_paper_analysis.py | 11 +- deepinsight/core/tools/keynote_analysis.py | 2 - deepinsight/core/tools/tavily_search.py | 19 +- deepinsight/service/research/research.py | 136 ++++++- deepinsight/service/schemas/common.py | 11 +- deepinsight/service/schemas/research.py | 5 + deepinsight/utils/db_schema_utils.py | 12 + deepinsight/utils/log_utils.py | 65 ++++ 16 files changed, 625 insertions(+), 523 deletions(-) create mode 100644 deepinsight/cli/commands/api.py create mode 100644 deepinsight/utils/db_schema_utils.py create mode 100644 deepinsight/utils/log_utils.py diff --git a/.gitignore b/.gitignore index eb9b5cd..9393eb6 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,5 @@ deepinsight.db-journal data/ charts/ .DS_Store +logs/ +*.log diff --git a/README.md b/README.md index 0cf6735..75ea1cc 100644 --- a/README.md +++ b/README.md @@ -45,6 +45,11 @@ poetry run alembic upgrade head - 启动研究:`deepinsight research start --topic "人工智能发展趋势"` - 查看帮助:`deepinsight research --help` +- 后端服务(api) + - 启动后端服务:`deepinsight api start --config ./config.yaml` + - 指定专家配置(可选):`deepinsight api start --config ./config.yaml --expert-config ./experts.yaml` + - 也可通过环境变量指定:`DEEPINSIGHT_CONFIG=./config.yaml deepinsight api start` + 提示:可通过环境变量 `DEEPINSIGHT_CONFIG` 指定配置文件路径(默认 `./config.yaml`)。 ### 方式二:Web方式运行 @@ -53,7 +58,9 @@ poetry run alembic upgrade head ``` poetry install -python deepinsight/app.py +deepinsight api start --config ./config.yaml +# 或直接运行脚本: +python deepinsight/api/app.py --config ./config.yaml ``` #### 启动前端服务 diff --git a/deepinsight/api/app.py b/deepinsight/api/app.py index 1421566..fd2305d 100755 --- a/deepinsight/api/app.py +++ b/deepinsight/api/app.py @@ -8,118 +8,241 @@ # MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. # See the Mulan PSL v2 for more details. -import asyncio +import argparse +import logging import os -import uuid -from datetime import datetime -from typing import Optional, Dict - -from fastapi import FastAPI, Request, APIRouter, HTTPException, Query, Body, Depends -from fastapi.middleware.cors import CORSMiddleware -from fastapi.responses import StreamingResponse - -from deepinsight.service.conversation import ConversationService -from deepinsight.service.deep_research import MessageType, DeepResearchService -from deepinsight.service.schemas.conversation import (ConversationListRsp, ConversationListMsg, ConversationListItem, - AddConversationRsp, BodyAddConversation, AddConversationMsg, - ResponseData, DeleteConversationData, RenameConversationData, - BodyGetList) -from deepinsight.service.schemas.chat import GetChatHistoryData, GetChatHistoryStructure, GetChatHistoryRsp - -# 读取环境变量中的 API 前缀 -API_PREFIX = os.getenv("API_PREFIX", "") - -# 创建 FastAPI 实例 -app_instance = FastAPI( - title="DeepInsight API", - description="A streaming chat API for DeepInsight", - version="1.0.0" +import re +from pathlib import Path +from fastapi.responses import StreamingResponse, JSONResponse +from typing import Optional +from urllib.parse import quote + +import dotenv +import uvicorn +from fastapi import FastAPI, APIRouter, Header +from fastapi.responses import HTMLResponse +from fastapi.responses import FileResponse +from starlette import status + +from deepinsight.config.config import load_config +from deepinsight.service.research.research import ResearchService +from deepinsight.service.conference.paper_extractor import PaperExtractionService, PaperParseException +from deepinsight.utils.log_utils import initRootLogger +from deepinsight.core.utils.research_utils import load_expert_config +from deepinsight.service.schemas.common import ResponseModel +from deepinsight.service.schemas.research import ResearchRequest, PPTGenerateRequest, PdfGenerateRequest +from deepinsight.service.schemas.paper_extract import ExtractPaperMetaRequest + +dotenv.load_dotenv(override=True) +initRootLogger("deepinsight") + +DEFAULT_CONFIG_PATH = str(Path(__file__).resolve().parent.parent.parent / 'config.yaml') +DEFAULT_EXPERT_PATH = str(Path(__file__).resolve().parent.parent.parent / 'experts.yaml') + +parser = argparse.ArgumentParser(description="Start DeepInsight API server") +parser.add_argument( + "--config", + type=str, + default=DEFAULT_CONFIG_PATH, + help="Path to config.yaml file" ) -_conversations: Dict[str, ConversationListItem] = {} -# 创建路由 -router = APIRouter() - -# 跨域中间件配置 -app_instance.add_middleware( - CORSMiddleware, - allow_origins=["*"], - allow_credentials=True, - allow_methods=["*"], - allow_headers=["*"], +parser.add_argument( + "--expert_config", + type=str, + default=DEFAULT_EXPERT_PATH, + help="Path to config.yaml file" ) +args = parser.parse_args() +config = load_config(args.config) +research_service = ResearchService(config) +paper_extract_service = PaperExtractionService(config) +# 加载专家数据 +experts = load_expert_config(args.expert_config) +router = APIRouter(tags=["deepinsight"]) -@router.get("/api/conversations", response_model=ConversationListRsp, tags=["conversation"]) -async def get_conversation_list(body: BodyGetList = Depends()): - try: - conversation_list = ConversationService.get_list(user_id=body.user_id, offset=body.offset, limit=body.limit) - return ConversationListRsp( - code=0, - message="OK", - data=ConversationListMsg(conversations=conversation_list) - ) - except Exception as e: - raise HTTPException(status_code=500, detail=str(e)) +@router.get("/health", response_model=ResponseModel[str]) +async def health(): + return ResponseModel(data="healthy") + +@router.get("/deepinsight/charts/image/{file_id}") +async def show_chart_image(file_id: str): + """ + 返回对应的 PNG 图片文件 + """ + safe_pattern = re.compile(r"[\d\w:/-]+") + safe_file_id = "".join(safe_pattern.findall(file_id)) + + chart_dir = os.path.abspath(os.path.join(config.workspace.work_root, config.workspace.chart_image_dir)) + file_name = f"{safe_file_id}.png" + file_path = os.path.abspath(os.path.join(chart_dir, file_name)) + logging.debug(f"image_path: {file_path} {os.path.exists(file_path)}") + + if not os.path.exists(file_path): + return get_json_result(code=100, message="image file not found") -# temporarily deprecated -@router.post("/api/conversation", response_model=AddConversationRsp, tags=["conversation"]) -async def add_conversation( - body: BodyAddConversation = Body(...) -): try: - new_conversation = ConversationService.add_conversation(user_id=body.user_id, title=body.title, - conversation_id=body.conversation_id) - - return AddConversationRsp( - code=0, - message="OK", - data=AddConversationMsg(conversationId=str(new_conversation.conversation_id), - created_time=str(new_conversation.created_time)) - ) + # FileResponse 会自动设置正确的 Content-Type (image/png) + return FileResponse(file_path, media_type="image/png", headers={"Cache-Control": "max-age=120"}) except Exception as e: - raise HTTPException(status_code=500, detail=str(e)) + return get_json_result(code=100, message=repr(e)) -@router.delete("/api/conversation", response_model=ResponseData, tags=["conversation"]) -async def delete_conversation(data: DeleteConversationData = Body(...)): - try: - for cid in data.conversation_list: - ConversationService.del_conversation(conversation_id=cid) - return ResponseData(code=0, message="Deleted", data={}) +@router.get('/deepinsight/charts/{file_id}') +async def show_chart(file_id: str): + safe_pattern = re.compile(r"[\d\w:/-]+") + safe_file_id = "".join(safe_pattern.findall(file_id)) + chart_dir = os.path.abspath(os.path.join(config.workspace.work_root, config.workspace.chart_image_dir)) + file_name = f"{safe_file_id}.html" + file_path = os.path.abspath(os.path.join(chart_dir, file_name)) + logging.debug(f"file_path: {file_path} {os.path.exists(file_path)}") + + if not os.path.exists(file_path): + return get_json_result(code=100, message="file not found") + + try: + with open(file_path, "r", encoding="utf-8") as f: + content = f.read() + return HTMLResponse(content=content, headers={"Cache-Control": "max-age=120"}) except Exception as e: - raise HTTPException(status_code=500, detail=str(e)) + return get_json_result(code=100, message=repr(e)) + + +def get_json_result(code=0, message="success", data=None): + response = {"code": code, "message": message, "data": data} + return JSONResponse(content=response) + + +@router.post("/deepinsight/chat") +async def deepinsight_chat(request: ResearchRequest): + """ + Async endpoint for insight. + """ + logging.info(f"request: {request}") + + async def stream(): + async for event in research_service.chat(request=request): + yield f"data: {event.model_dump_json()}\n\n" + return StreamingResponse(stream(), media_type="text/event-stream") -@router.put("/api/conversation", response_model=ResponseData, tags=["conversation"]) -async def rename_conversation(data: RenameConversationData = Body(...)): + +@router.post("/deepinsight/paper/parse") +async def parse_paper_meta(request: ExtractPaperMetaRequest): + """Parse metadata (title, author, abstract, keywords and number of sections) from a paper in Markdown format.""" try: - conversation, is_succeed = ConversationService.rename_conversation(conversation_id=data.conversation_id, - new_name=data.new_name) - if is_succeed: - return ResponseData(code=0, message="Modified", data={"new_name": data.new_name}) + return await paper_extract_service.extract_and_store(request) + except PaperParseException as e: + return dict(error=str(e)) + + +@router.get("/deepinsight/experts") +async def get_experts(type: Optional[str] = None): + """ + 获取专家信息,按类型分组返回专家名字列表。 + - `type` 参数可选,用于过滤专家类型(reviewer 或 writer)。 + """ + # 按类型分组专家名字 + experts_by_type = {} + for expert in experts: + if expert.type not in experts_by_type: + experts_by_type[expert.type] = [] + experts_by_type[expert.type].append({"prompt_key": expert.prompt_key, "name": expert.name}) + + # 如果提供了 type 参数,返回该类型下的专家名字列表 + if type: + if type in experts_by_type: + return ResponseModel(data={type: experts_by_type[type]}) else: - return ResponseData(code=100, message="Conversation Not Found", data={"new_name": data.new_name}) - except Exception as e: - raise HTTPException(status_code=500, detail=str(e)) - - -@router.get("/api/conversations/{conversation_id}/messages", response_model=GetChatHistoryRsp, tags=["conversation"]) -async def get_conversation_messages(conversation_id: str): - conversation_info = ConversationService.get_conversation_info(conversation_id) - history_present = ConversationService.get_history_messages(conversation_id) - new_data = GetChatHistoryStructure( - conversation_id=conversation_id, - user_id=conversation_info.user_id, - created_time=str(conversation_info.created_time), - title=conversation_info.title, - status=conversation_info.status, - messages=history_present + return get_json_result(code=404, message=f"No experts found for type: {type}", data=None) + + # 否则返回所有类型的专家名字列表 + return ResponseModel(data=experts_by_type) + + + +@router.post("/deepinsight/ppt/generate") +async def ppt_generate(request: PPTGenerateRequest): + pptx_stream, output_name = await research_service.ppt_generate(request=request) + output_name = output_name.split("/")[-1] + encoded_file_name = quote(output_name) + # 返回文件流 + return StreamingResponse( + pptx_stream, + media_type="application/vnd.openxmlformats-officedocument.presentationml.presentation", + headers={"Content-Disposition": f"attachment; filename={encoded_file_name}"} ) - return GetChatHistoryRsp(code=0, message="ok", data=new_data) -app_instance.include_router(router, prefix=API_PREFIX) +@router.post("/deepinsight/pdf/generate") +async def pdf_generate(request: PdfGenerateRequest): + try: + pdf_stream, output_name = await research_service.pdf_generate(request=request) + + # 文件名安全处理 + output_name = output_name.split("/")[-1] + encoded_file_name = quote(output_name) + + return StreamingResponse( + pdf_stream, + media_type="text/pdf; charset=utf-8", + headers={ + "Content-Disposition": f"attachment; filename={encoded_file_name}", + "Content-Type": "application/octet-stream", + }, + ) + + except FileNotFoundError as e: + logging.error(f"{str(e)}") + return JSONResponse( + status_code=status.HTTP_400_BAD_REQUEST, + content={ + "code": status.HTTP_400_BAD_REQUEST, + "message": f"生成失败,部分源文件未找到:{str(e)}", + "data": None + } + ) + + except ValueError as e: + logging.error(f"{str(e)}") + return JSONResponse( + status_code=status.HTTP_400_BAD_REQUEST, + content={ + "code": status.HTTP_400_BAD_REQUEST, + "message": f"生成失败,数据格式错误:{str(e)}", + "data": None + } + ) + + except Exception as e: + logging.error(f"{str(e)}") + return JSONResponse( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + content={ + "code": status.HTTP_500_INTERNAL_SERVER_ERROR, + "message": f"服务器内部错误,请稍后重试:{str(e)}", + "data": None + } + ) + + +app = FastAPI(title="DeepInsight API") + +app.include_router(router, prefix=config.app.api_prefix) + +if __name__ == "__main__": + for route in app.routes: + from fastapi.routing import APIRoute + + if isinstance(route, APIRoute): + print(f"路径: {route.path}, 方法: {route.methods}, 名称: {route.name}") + uvicorn.run( + app, + host=config.app.host, + port=config.app.port, + reload=config.app.reload, + ) diff --git a/deepinsight/cli/commands/api.py b/deepinsight/cli/commands/api.py new file mode 100644 index 0000000..dacb4c3 --- /dev/null +++ b/deepinsight/cli/commands/api.py @@ -0,0 +1,84 @@ +""" +API Server Command + +Provides a CLI subcommand to start the DeepInsight backend API server. +""" + +import argparse +import os +import sys +import subprocess +from typing import Optional + + +class ApiCommand: + """CLI command handler for starting the backend API server.""" + + def __init__(self): + self.version = "1.0.0" + + def _create_parser(self) -> argparse.ArgumentParser: + parser = argparse.ArgumentParser( + prog="deepinsight api", + description="Start the DeepInsight backend API server", + ) + subparsers = parser.add_subparsers(dest="subcommand", help="Operations") + + start_parser = subparsers.add_parser("start", help="Start API server") + start_parser.add_argument( + "--config", + type=str, + required=False, + help="Path to config.yaml (defaults to ./config.yaml or $DEEPINSIGHT_CONFIG)", + ) + start_parser.add_argument( + "--expert-config", + type=str, + required=False, + help="Path to experts.yaml (optional)", + ) + start_parser.add_argument( + "--env", + action="append", + default=[], + help="Extra environment variables in KEY=VALUE form (can be repeated)", + ) + return parser + + def execute(self, args: argparse.Namespace) -> int: + parser = self._create_parser() + parsed = parser.parse_args(sys.argv[2:]) + + if parsed.subcommand != "start": + parser.print_help() + return 1 + + return self._handle_start(parsed) + + def _handle_start(self, args: argparse.Namespace) -> int: + # Resolve config and expert paths + cfg_path: Optional[str] = args.config or os.getenv("DEEPINSIGHT_CONFIG") + # Build the command to run the API module as a script + cmd = [sys.executable, os.path.join("deepinsight", "api", "app.py")] + if cfg_path: + cmd.extend(["--config", cfg_path]) + if getattr(args, "expert_config", None): + cmd.extend(["--expert_config", args.expert_config]) + + # Prepare environment: propagate current env and optional overrides + env = os.environ.copy() + for kv in args.env or []: + if "=" in kv: + k, v = kv.split("=", 1) + env[k] = v + + try: + # Start the server in the foreground; user can Ctrl-C to stop. + proc = subprocess.Popen(cmd, env=env) + proc.wait() + return proc.returncode or 0 + except KeyboardInterrupt: + return 130 + except Exception as e: + print(f"Failed to start API server: {e}") + return 1 \ No newline at end of file diff --git a/deepinsight/cli/main.py b/deepinsight/cli/main.py index 09f867e..c5e6872 100644 --- a/deepinsight/cli/main.py +++ b/deepinsight/cli/main.py @@ -18,6 +18,7 @@ from rich import get_console from deepinsight.cli.commands.research import ResearchCommand from deepinsight.cli.commands.conference import ConferenceCommand +from deepinsight.cli.commands.api import ApiCommand dotenv.load_dotenv(override=True) @@ -52,6 +53,7 @@ class DeepInsightCLI: 'research': ResearchCommand(), 'conference': ConferenceCommand(), + 'api': ApiCommand(), } def _create_parser(self) -> argparse.ArgumentParser: @@ -118,6 +120,18 @@ For more information on a specific command, run: nargs=argparse.REMAINDER, help='Arguments for conference subcommands (parsed by ConferenceCommand)' ) + + # API server command + api_parser = subparsers.add_parser( + 'api', + help='Start backend API server', + description='Start DeepInsight backend API service' + ) + api_parser.add_argument( + 'args', + nargs=argparse.REMAINDER, + help='Arguments for api subcommands (parsed by ApiCommand)' + ) return parser def run(self, args: Optional[List[str]] = None) -> int: @@ -138,6 +152,11 @@ For more information on a specific command, run: if not rest or '--help' in rest or '-h' in rest: ResearchCommand()._create_parser().print_help() return 0 + if parsed_args.command == 'api': + rest = getattr(parsed_args, 'args', []) + if not rest or '--help' in rest or '-h' in rest: + ApiCommand()._create_parser().print_help() + return 0 # Get the appropriate command handler command = self.commands.get(parsed_args.command) diff --git a/deepinsight/core/agent/conference_research/conf_stat_value_mining.py b/deepinsight/core/agent/conference_research/conf_stat_value_mining.py index 5906776..cf24b00 100644 --- a/deepinsight/core/agent/conference_research/conf_stat_value_mining.py +++ b/deepinsight/core/agent/conference_research/conf_stat_value_mining.py @@ -21,6 +21,7 @@ from deepinsight.core.utils.progress_utils import progress_stage from deepinsight.core.utils.research_utils import parse_research_config from deepinsight.core.tools.tavily_search import tavily_search from deepinsight.core.utils.context_utils import DefaultSummarizationMiddleware +from deepinsight.utils.db_schema_utils import get_db_models_source_markdown from integrations.mcps.generate_chart import generate_column_chart, generate_bar_chart, generate_pie_chart @@ -44,10 +45,12 @@ async def get_deep_agents(config: RunnableConfig, prompt_template_name, extent_t llm_model = rc.get_model() prompt_manager = rc.prompt_manager prompt_group: str = rc.prompt_group + vars_to_format = dict(prompt_vars or {}) + vars_to_format.setdefault("db_models_description", get_db_models_source_markdown()) system_prompt = prompt_manager.get_prompt( name=prompt_template_name, group=prompt_group, - ).format(**prompt_vars) + ).format(**vars_to_format) tools = [PythonREPLTool(), tavily_search, generate_wordcloud, generate_column_chart, generate_bar_chart, generate_pie_chart] if extent_tools: @@ -132,7 +135,6 @@ async def tech_topics_node(state: ConferenceStaticState, config: RunnableConfig) if not mem_file_system_instance.exists(output_file): logging.error(f"get tech_topics failed, origin question:{state['origin_question']}") return {"tech_topics": ""} - mem_file_system_instance.sync_with_real_fs(real_dir="./", import_file=output_file) return {"tech_topics": mem_file_system_instance.read(output_file)} @@ -159,7 +161,6 @@ async def research_hotspots_node(state: ConferenceStaticState, config: RunnableC if not mem_file_system_instance.exists(output_file): logging.error(f"get research_hotspots failed, origin question:{state['origin_question']}") return {"research_hotspots": ""} - mem_file_system_instance.sync_with_real_fs(real_dir="./", import_file=output_file) return { "research_hotspots": mem_file_system_instance.read(output_file) } @@ -189,7 +190,6 @@ async def national_tech_profile_node(state: ConferenceStaticState, config: Runna if not mem_file_system_instance.exists(output_file): logging.error(f"get national_tech_profile failed, origin question:{state['origin_question']}") return {"national_tech_profile": ""} - mem_file_system_instance.sync_with_real_fs(real_dir="./", import_file=output_file) return { "national_tech_profile": mem_file_system_instance.read(output_file) } @@ -220,7 +220,6 @@ async def institution_overview_node(state: ConferenceStaticState, config: Runnab if not mem_file_system_instance.exists(output_file): logging.error(f"get institution_overview failed, origin question:{state['origin_question']}") return {"institution_overview": ""} - mem_file_system_instance.sync_with_real_fs(real_dir="./", import_file=output_file) return { "institution_overview": mem_file_system_instance.read(output_file) } @@ -249,7 +248,6 @@ async def inter_institution_collab_node(state: ConferenceStaticState, config: Ru if not mem_file_system_instance.exists(output_file): logging.error(f"get inter_institution_collab failed, origin question:{state['origin_question']}") return {"inter_institution_collab": ""} - mem_file_system_instance.sync_with_real_fs(real_dir="./", import_file=output_file) return { "inter_institution_collab": mem_file_system_instance.read(output_file) } @@ -278,7 +276,6 @@ async def high_potential_tech_transfer_node(state: ConferenceStaticState, config if not mem_file_system_instance.exists(output_file): logging.error(f"get high_potential_tech failed, origin question:{state['origin_question']}") return {"high_potential_tech_transfer": ""} - mem_file_system_instance.sync_with_real_fs(real_dir="./", import_file=output_file) return { "high_potential_tech_transfer": mem_file_system_instance.read(output_file) } @@ -306,7 +303,6 @@ async def academic_leaders_node(state: ConferenceStaticState, config: RunnableCo if not mem_file_system_instance.exists(output_file): logging.error(f"get academic_leaders failed, origin question:{state['origin_question']}") return {"high_potential_tech_transfer": ""} - mem_file_system_instance.sync_with_real_fs(real_dir="./", import_file=output_file) return { "high_potential_tech_transfer": mem_file_system_instance.read(output_file) } diff --git a/deepinsight/core/prompt/conference_best_papers.py b/deepinsight/core/prompt/conference_best_papers.py index 79406f3..e90cd24 100644 --- a/deepinsight/core/prompt/conference_best_papers.py +++ b/deepinsight/core/prompt/conference_best_papers.py @@ -362,7 +362,7 @@ paper_analysis_no_rag_prompt = r""" - 在生成 Markdown 报告时,按内容语义嵌入图片: - 架构或算法流程图 → “关键技术” - 实验结果图 → “技术效果” -- 保留外链形式 `![](https://...)`,不下载图片 +- 图像引用保持工具返回的原始链接或相对路径,不进行改写或补全;示例:`![<图表标题>](<图表链接或相对路径>)` ◆ 第三步:获取并分析论文内容 - 获取摘要、引言、核心方法、实验结果及结论 @@ -495,8 +495,8 @@ paper_analysis_no_rag_prompt = r""" 2. **数据库访问方式**(使用 SQLAlchemy Session): ```python - from databases.connection import Database - from databases.models.conference_paper import Author, Conference, Paper, PaperAuthorRelation + from deepinsight.databases.connection import Database + from deepinsight.databases.models.academic import Author, Conference, Paper, PaperAuthorRelation from sqlalchemy import select, func, desc, distinct with Database().get_session() as session: @@ -505,60 +505,7 @@ paper_analysis_no_rag_prompt = r""" 3. 数据库模型说明: -``` -class Author(PaperBase): - __tablename__ = 'author_table' - - author_id = Column(Integer, primary_key=True, autoincrement=True) - author_name = Column(String(100), nullable=False) - email = Column(String(255)) - affiliation = Column(String(255)) - affiliation_country = Column(String(100)) - affiliation_city = Column(String(100)) - created_at = Column(TIMESTAMP, default=datetime.now) - updated_at = Column(TIMESTAMP, default=datetime.now, onupdate=datetime.now) - - -class Conference(PaperBase): - __tablename__ = 'conference_table' - - conference_id = Column(Integer, primary_key=True, autoincrement=True) - full_name = Column(String(255), nullable=False) - short_name = Column(String(50)) - year = Column(Integer, nullable=False) - location = Column(String(100)) - start_date = Column(Date) - end_date = Column(Date) - website = Column(String(255)) - topics: Mapped[list[str]] = Column(JSON) - created_at = Column(TIMESTAMP, default=datetime.now) - updated_at = Column(TIMESTAMP, default=datetime.now, onupdate=datetime.now) - - -class Paper(PaperBase): - __tablename__ = 'paper_table' - paper_id = Column(Integer, primary_key=True, autoincrement=True) - title = Column(String(255), nullable=False) - conference_id = Column(Integer) # 直接存储ID,不使用ForeignKey - publication_year = Column(Integer) - abstract = Column(Text) - keywords = Column(String(255)) - author_ids = Column(String(500)) # 存储作者ID列表,如 "1,3,5" - reference_ids = Column(String(500)) # 存储参考文献ID列表 - topic = Column(String(100), nullable=True) - created_at = Column(TIMESTAMP, default=datetime.now) - updated_at = Column(TIMESTAMP, default=datetime.now, onupdate=datetime.now) - - -class PaperAuthorRelation(PaperBase): - __tablename__ = 'paper_author_relation_table' - - relation_id = Column(Integer, primary_key=True, autoincrement=True) - paper_id = Column(Integer) # 直接存储ID - author_id = Column(Integer) # 直接存储ID - author_order = Column(Integer, nullable=False) - is_corresponding = Column(Boolean, default=False, nullable=False) - created_at = Column(TIMESTAMP, default=datetime.now) +{{db_models_description}} """ paper_analysis_prompt = r""" @@ -603,20 +550,12 @@ paper_analysis_prompt = r""" **目的**:提取论文中的**核心设计图**与**实验结果图**,辅助后续的结构化报告。 **执行策略**: -* **图像来源与格式强制要求**:优先使用 `retrieval` 工具检索图片资源,且最终在报告中引用的图片**必须**采用下列形式的外链(注意:使用内部IP或确定的IP,不可为 www 域名或外部域名): - - ``` - ![](http://:/parsed-file-images/.jpg) - ``` - - * 要求使用 `http` 协议或根据系统要求的端口(不使用 `www` 或公共域名); - * `` 必须为确定的 IP 地址,跟查询到的IP保持一致,确保准确,不要生成ip,不得使用域名占位符或 CDN 域名; - * 文件路径固定为 `/parsed-file-images/` 目录下的 jpg 文件。 +* **图像来源与格式要求**:优先使用 `retrieval` 工具检索图片资源,最终在报告中引用的图片链接或相对路径应与工具返回值保持一致;示例:`![<图表标题>](<图表链接或相对路径>)`。不得自行构造或替换链接结构。 * 根据论文文本推断图片含义,明确其所表达的内容: * **架构设计/算法流程图** → 表示论文核心技术结构 * **实验结果/对比性能图** → 展示技术效果与性能改进 -* 若 `retrieval` 无图片或不完整,使用网络搜索工具查找相应论文插图;在网络来源获得图片后,若系统流程要求将图片保存到内部解析目录,则需将图片保存为 `parsed-file-images/.jpg` 并在报告中以上述 IP 外链形式引用。若不能保存到该内网路径,必须在报告中明确说明并列出实际可用的图片链接。 +* 若 `retrieval` 无图片或不完整,使用网络搜索工具查找相应论文插图;在网络来源获得图片后,若系统流程要求将图片保存到某目录并返回相对路径或链接,则在报告中按工具返回的路径或链接引用,并在无法保存到预期目录时明确说明并列出实际可用链接或路径。 * **图片筛选规则**:仅保留两张 1. 架构或流程图(体现设计思想) @@ -625,8 +564,7 @@ paper_analysis_prompt = r""" * 架构图 → “关键技术”章节 * 实验图 → “技术效果”章节 -* **强制外链形式**:图片在报告中必须以 `![](http://:/parsed-file-images/.jpg)` 的形式出现,不允许使用内嵌 Base64、附件或其他第三方 CDN 链接。 -* 不可下载或内嵌到 Markdown 文件中;若检索返回的图片原始 URL 不是内部 IP,请在保存步骤中将其转存到内部 `parsed-file-images` 并使用内部 IP 外链(如系统环境允许)。 +* **引用要求**:图片以 Markdown 形式引用为 `![<图表标题>](<图表链接或相对路径>)`,不允许内嵌 Base64 或作为附件。保持与工具返回一致,不强制特定协议或主机格式。 --- @@ -680,7 +618,7 @@ paper_analysis_prompt = r""" * **保存反馈要求**:在保存成功后,必须输出: * 完整文件路径(绝对路径) - * 所使用的图片链接清单,且每个图片链接必须为 `http://:/parsed-file-images/.jpg` 格式 +* 所使用的图片链接或相对路径清单,逐条保持与工具返回一致 * 若保存失败,需说明原因并尝试修复(列出失败原因与下一步修复动作)。 ❗ 注意事项: @@ -736,10 +674,10 @@ paper_analysis_prompt = r""" 用户输入论文名称后,严格按以下顺序执行: 1. 查询论文(优先使用 retrieval) -2. 获取论文相关图片(优先使用 retrieval,最终图片必须为内部 IP 外链形式) +2. 获取论文相关图片(优先使用 retrieval,图片链接或相对路径按工具返回引用) 3. 分析论文内容 -4. 生成报告(图片嵌入语义位置,并以指定 IP 外链引用) -5. 保存 Markdown 文件及图片(并反馈文件路径与图片清单) +4. 生成报告(图片嵌入语义位置,按工具返回的链接或相对路径引用) +5. 保存 Markdown 文件及图片(并反馈文件路径与图片清单,保持链接或路径原样) """ research_system_prompt = r""" diff --git a/deepinsight/core/prompt/conference_submission.py b/deepinsight/core/prompt/conference_submission.py index 0fa75d4..37e249e 100644 --- a/deepinsight/core/prompt/conference_submission.py +++ b/deepinsight/core/prompt/conference_submission.py @@ -41,8 +41,8 @@ academic_leaders_prompt = r""" 2. **数据库访问方式**(使用 SQLAlchemy Session): ```python - from databases.connection import Database - from databases.models.conference_paper import Author, Conference, Paper, PaperAuthorRelation + from deepinsight.databases.connection import Database + from deepinsight.databases.models.academic import Author, Conference, Paper, PaperAuthorRelation from sqlalchemy import select, func, desc, distinct with Database().get_session() as session: @@ -51,61 +51,7 @@ academic_leaders_prompt = r""" 3. 数据库模型说明: -``` -class Author(PaperBase): - __tablename__ = 'author_table' - - author_id = Column(Integer, primary_key=True, autoincrement=True) - author_name = Column(String(100), nullable=False) - email = Column(String(255)) - affiliation = Column(String(255)) - affiliation_country = Column(String(100)) - affiliation_city = Column(String(100)) - created_at = Column(TIMESTAMP, default=datetime.now) - updated_at = Column(TIMESTAMP, default=datetime.now, onupdate=datetime.now) - - -class Conference(PaperBase): - __tablename__ = 'conference_table' - - conference_id = Column(Integer, primary_key=True, autoincrement=True) - full_name = Column(String(255), nullable=False) - short_name = Column(String(50)) - year = Column(Integer, nullable=False) - location = Column(String(100)) - start_date = Column(Date) - end_date = Column(Date) - website = Column(String(255)) - topics: Mapped[list[str]] = Column(JSON) - created_at = Column(TIMESTAMP, default=datetime.now) - updated_at = Column(TIMESTAMP, default=datetime.now, onupdate=datetime.now) - - -class Paper(PaperBase): - __tablename__ = 'paper_table' - - paper_id = Column(Integer, primary_key=True, autoincrement=True) - title = Column(String(255), nullable=False) - conference_id = Column(Integer) # 直接存储ID,不使用ForeignKey - publication_year = Column(Integer) - abstract = Column(Text) - keywords = Column(String(255)) - author_ids = Column(String(500)) # 存储作者ID列表,如 "1,3,5" - reference_ids = Column(String(500)) # 存储参考文献ID列表 - topic = Column(String(100), nullable=True) - created_at = Column(TIMESTAMP, default=datetime.now) - updated_at = Column(TIMESTAMP, default=datetime.now, onupdate=datetime.now) - - -class PaperAuthorRelation(PaperBase): - __tablename__ = 'paper_author_relation_table' - - relation_id = Column(Integer, primary_key=True, autoincrement=True) - paper_id = Column(Integer) # 直接存储ID - author_id = Column(Integer) # 直接存储ID - author_order = Column(Integer, nullable=False) - is_corresponding = Column(Boolean, default=False, nullable=False) - created_at = Column(TIMESTAMP, default=datetime.now) +{{db_models_description}} ## 🧩 学术角色识别规则(必须严格执行) @@ -484,8 +430,8 @@ high_potential_tech_transfer_prompt = r""" 2. **数据库访问方式**(使用 SQLAlchemy Session): ```python - from databases.connection import Database - from databases.models.conference_paper import Author, Conference, Paper, PaperAuthorRelation + from deepinsight.databases.connection import Database + from deepinsight.databases.models.academic import Author, Conference, Paper, PaperAuthorRelation from sqlalchemy import select, func, desc, distinct with Database().get_session() as session: @@ -494,61 +440,7 @@ high_potential_tech_transfer_prompt = r""" 3. 数据库模型说明: -``` -class Author(PaperBase): - __tablename__ = 'author_table' - - author_id = Column(Integer, primary_key=True, autoincrement=True) - author_name = Column(String(100), nullable=False) - email = Column(String(255)) - affiliation = Column(String(255)) - affiliation_country = Column(String(100)) - affiliation_city = Column(String(100)) - created_at = Column(TIMESTAMP, default=datetime.now) - updated_at = Column(TIMESTAMP, default=datetime.now, onupdate=datetime.now) - - -class Conference(PaperBase): - __tablename__ = 'conference_table' - - conference_id = Column(Integer, primary_key=True, autoincrement=True) - full_name = Column(String(255), nullable=False) - short_name = Column(String(50)) - year = Column(Integer, nullable=False) - location = Column(String(100)) - start_date = Column(Date) - end_date = Column(Date) - website = Column(String(255)) - topics: Mapped[list[str]] = Column(JSON) - created_at = Column(TIMESTAMP, default=datetime.now) - updated_at = Column(TIMESTAMP, default=datetime.now, onupdate=datetime.now) - - -class Paper(PaperBase): - __tablename__ = 'paper_table' - - paper_id = Column(Integer, primary_key=True, autoincrement=True) - title = Column(String(255), nullable=False) - conference_id = Column(Integer) # 直接存储ID,不使用ForeignKey - publication_year = Column(Integer) - abstract = Column(Text) - keywords = Column(String(255)) - author_ids = Column(String(500)) # 存储作者ID列表,如 "1,3,5" - reference_ids = Column(String(500)) # 存储参考文献ID列表 - topic = Column(String(100), nullable=True) - created_at = Column(TIMESTAMP, default=datetime.now) - updated_at = Column(TIMESTAMP, default=datetime.now, onupdate=datetime.now) - - -class PaperAuthorRelation(PaperBase): - __tablename__ = 'paper_author_relation_table' - - relation_id = Column(Integer, primary_key=True, autoincrement=True) - paper_id = Column(Integer) # 直接存储ID - author_id = Column(Integer) # 直接存储ID - author_order = Column(Integer, nullable=False) - is_corresponding = Column(Boolean, default=False, nullable=False) - created_at = Column(TIMESTAMP, default=datetime.now) +{{db_models_description}} ## 🧩 分析流程(Execution Requirements) @@ -724,8 +616,8 @@ institution_overview_prompt = r""" 2. **数据库访问方式**(使用 SQLAlchemy Session): ```python - from databases.connection import Database - from databases.models.conference_paper import Author, Conference, Paper, PaperAuthorRelation + from deepinsight.databases.connection import Database + from deepinsight.databases.models.academic import Author, Conference, Paper, PaperAuthorRelation from sqlalchemy import select, func, desc, distinct with Database().get_session() as session: @@ -776,32 +668,26 @@ institution_overview_prompt = r""" ## 🧱 输出结构(Output Structure) -1. 图表链接必须使用 **图表生成工具返回的原始链接**,禁止模型自行生成、修改、补全或替换。 -2. 图表链接的结构为: - http:///api/v1/deepinsight/charts/image/ -3. 其中 `` 和 `` **均由图表生成工具返回**,模型不得推测或伪造。 -4. 输出前需逐字符检查链接,确保与工具返回完全一致。 +1. 图表链接或相对路径必须使用图表生成工具返回的原始值,禁止模型自行生成、修改、补全或替换。 +2. 输出前需逐字符检查链接或路径,确保与工具返回完全一致。 ### 一、图表展示 ** 注意(非常重要)** : -1. 图表链接必须使用 **图表生成工具返回的原始链接**,禁止模型自行生成、修改、补全或替换。 -2. 图表链接的结构为: - http:///api/v1/deepinsight/charts/image/ -3. 其中 `` 和 `` **均由图表生成工具返回**,模型不得推测或伪造。 -4. 输出前需逐字符检查链接,确保与工具返回完全一致。 +1. 图表链接或相对路径必须使用图表生成工具返回的原始值,禁止模型自行生成、修改、补全或替换。 +2. 输出前需逐字符检查链接或路径,确保与工具返回完全一致。 #### 1. 机构排名图表 * **图表类型**:条形图 * **内容说明(备注:上述图表的输出说明,最终报告不需要展示)**:展示机构的论文数量排名(Top 10),并以百分比数据展示。 -* **图表链接**:图表展示参考以下格式:![<图表标题>](http://<图表链接地址>) +* **图表链接**:图表展示参考以下格式:![<图表标题>](<图表链接或相对路径>) #### 2. 产学研类型占比分析 * **图表类型**:饼状图 * **内容说明(备注:上述图表的输出说明,最终报告不需要展示)**:高校(含大学及其学院/系)、企业、国家实验室、其他机构(研究院、独立研究所等),并以百分比数据展示。 -* **图表链接**:图表展示参考以下格式:![<图表标题>](http://<图表链接地址>) +* **图表链接**:图表展示参考以下格式:![<图表标题>](<图表链接或相对路径>) **示例表格字段(仅展示占比 ≥ 10% 的技术优势领域):** @@ -993,8 +879,8 @@ inter_institution_collab_prompt = r""" 2. **数据库访问方式**(使用 SQLAlchemy Session): ```python - from databases.connection import Database - from databases.models.conference_paper import Author, Conference, Paper, PaperAuthorRelation + from deepinsight.databases.connection import Database + from deepinsight.databases.models.academic import Author, Conference, Paper, PaperAuthorRelation from sqlalchemy import select, func, desc, distinct with Database().get_session() as session: @@ -1003,62 +889,7 @@ inter_institution_collab_prompt = r""" 3. 数据库模型说明: -``` -class Author(PaperBase): - __tablename__ = 'author_table' - - author_id = Column(Integer, primary_key=True, autoincrement=True) - author_name = Column(String(100), nullable=False) - email = Column(String(255)) - affiliation = Column(String(255)) - affiliation_country = Column(String(100)) - affiliation_city = Column(String(100)) - created_at = Column(TIMESTAMP, default=datetime.now) - updated_at = Column(TIMESTAMP, default=datetime.now, onupdate=datetime.now) - - -class Conference(PaperBase): - __tablename__ = 'conference_table' - - conference_id = Column(Integer, primary_key=True, autoincrement=True) - full_name = Column(String(255), nullable=False) - short_name = Column(String(50)) - year = Column(Integer, nullable=False) - location = Column(String(100)) - start_date = Column(Date) - end_date = Column(Date) - website = Column(String(255)) - topics: Mapped[list[str]] = Column(JSON) - created_at = Column(TIMESTAMP, default=datetime.now) - updated_at = Column(TIMESTAMP, default=datetime.now, onupdate=datetime.now) - - -class Paper(PaperBase): - __tablename__ = 'paper_table' - - paper_id = Column(Integer, primary_key=True, autoincrement=True) - title = Column(String(255), nullable=False) - conference_id = Column(Integer) # 直接存储ID,不使用ForeignKey - publication_year = Column(Integer) - abstract = Column(Text) - keywords = Column(String(255)) - author_ids = Column(String(500)) # 存储作者ID列表,如 "1,3,5" - reference_ids = Column(String(500)) # 存储参考文献ID列表 - topic = Column(String(100), nullable=True) - created_at = Column(TIMESTAMP, default=datetime.now) - updated_at = Column(TIMESTAMP, default=datetime.now, onupdate=datetime.now) - - -class PaperAuthorRelation(PaperBase): - __tablename__ = 'paper_author_relation_table' - - relation_id = Column(Integer, primary_key=True, autoincrement=True) - paper_id = Column(Integer) # 直接存储ID - author_id = Column(Integer) # 直接存储ID - author_order = Column(Integer, nullable=False) - is_corresponding = Column(Boolean, default=False, nullable=False) - created_at = Column(TIMESTAMP, default=datetime.now) -``` +{{db_models_description}} --- @@ -1090,17 +921,14 @@ class PaperAuthorRelation(PaperBase): ### 一、图表展示(必须包含) ** 注意(非常重要)** : -1. 图表链接必须使用 **图表生成工具返回的原始链接**,禁止模型自行生成、修改、补全或替换。 -2. 图表链接的结构为: - http:///api/v1/deepinsight/charts/image/ -3. 其中 `` 和 `` **均由图表生成工具返回**,模型不得推测或伪造。 -4. 输出前需逐字符检查链接,确保与工具返回完全一致。 +1. 图表链接或相对路径必须使用图表生成工具返回的原始值,禁止模型自行生成、修改、补全或替换。 +2. 输出前需逐字符检查链接或路径,确保与工具返回完全一致。 #### 1. 跨机构合作权重(必选) * **图表类型**:水平条形图 * **内容说明**:展示网络中权重前5的跨机构合作关系及其合作次数/强度。 -* **图表链接**:图表将在以下 HTTP 链接地址中显示:![<图表标题>](http://<图表链接地址>) +* **图表链接**:图表将在以下链接或相对路径中显示:![<图表标题>](<图表链接或相对路径>) --- ### 二、分析报告 @@ -1284,8 +1112,8 @@ national_tech_profile_prompt = r""" 2. **数据库访问方式**(使用 SQLAlchemy Session): ```python - from databases.connection import Database - from databases.models.conference_paper import Author, Conference, Paper, PaperAuthorRelation + from deepinsight.databases.connection import Database + from deepinsight.databases.models.academic import Author, Conference, Paper, PaperAuthorRelation from sqlalchemy import select, func, desc, distinct with Database().get_session() as session: @@ -1294,61 +1122,7 @@ national_tech_profile_prompt = r""" 3. 数据库模型说明: -``` -class Author(PaperBase): - __tablename__ = 'author_table' - - author_id = Column(Integer, primary_key=True, autoincrement=True) - author_name = Column(String(100), nullable=False) - email = Column(String(255)) - affiliation = Column(String(255)) - affiliation_country = Column(String(100)) - affiliation_city = Column(String(100)) - created_at = Column(TIMESTAMP, default=datetime.now) - updated_at = Column(TIMESTAMP, default=datetime.now, onupdate=datetime.now) - - -class Conference(PaperBase): - __tablename__ = 'conference_table' - - conference_id = Column(Integer, primary_key=True, autoincrement=True) - full_name = Column(String(255), nullable=False) - short_name = Column(String(50)) - year = Column(Integer, nullable=False) - location = Column(String(100)) - start_date = Column(Date) - end_date = Column(Date) - website = Column(String(255)) - topics: Mapped[list[str]] = Column(JSON) - created_at = Column(TIMESTAMP, default=datetime.now) - updated_at = Column(TIMESTAMP, default=datetime.now, onupdate=datetime.now) - - -class Paper(PaperBase): - __tablename__ = 'paper_table' - - paper_id = Column(Integer, primary_key=True, autoincrement=True) - title = Column(String(255), nullable=False) - conference_id = Column(Integer) # 直接存储ID,不使用ForeignKey - publication_year = Column(Integer) - abstract = Column(Text) - keywords = Column(String(255)) - author_ids = Column(String(500)) # 存储作者ID列表,如 "1,3,5" - reference_ids = Column(String(500)) # 存储参考文献ID列表 - topic = Column(String(100), nullable=True) - created_at = Column(TIMESTAMP, default=datetime.now) - updated_at = Column(TIMESTAMP, default=datetime.now, onupdate=datetime.now) - - -class PaperAuthorRelation(PaperBase): - __tablename__ = 'paper_author_relation_table' - - relation_id = Column(Integer, primary_key=True, autoincrement=True) - paper_id = Column(Integer) # 直接存储ID - author_id = Column(Integer) # 直接存储ID - author_order = Column(Integer, nullable=False) - is_corresponding = Column(Boolean, default=False, nullable=False) - created_at = Column(TIMESTAMP, default=datetime.now) +{{db_models_description}} --- @@ -1378,17 +1152,14 @@ class PaperAuthorRelation(PaperBase): ### 一、图表展示 ** 注意(非常重要)** : -1. 图表链接必须使用 **图表生成工具返回的原始链接**,禁止模型自行生成、修改、补全或替换。 -2. 图表链接的结构为: - http:///api/v1/deepinsight/charts/image/ -3. 其中 `` 和 `` **均由图表生成工具返回**,模型不得推测或伪造。 -4. 输出前需逐字符检查链接,确保与工具返回完全一致。 +1. 图表链接或相对路径必须使用图表生成工具返回的原始值,禁止模型自行生成、修改、补全或替换。 +2. 输出前需逐字符检查链接或路径,确保与工具返回完全一致。 #### 1. 国家/地区排名图表 * **图表类型**:柱形图 * **内容说明(备注:上述图表的输出说明,最终报告不需要展示)**:展示国家/地区的论文数量排名(Top 10),并以百分比数据展示。 -* **图表链接**:图表展示参考以下格式:![<图表标题>](http://<图表链接地址>) +* **图表链接**:图表展示参考以下格式:![<图表标题>](<图表链接或相对路径>) #### 2. 国家/地区技术优势矩阵 @@ -1497,7 +1268,7 @@ research_hotspots_prompt = r""" # 🎯 学术数据分析助手(Academic Insight Assistant) 你是一名能够通过 **Python 编程与数据库查询** 提取学术会议洞察的智能分析助手。 -你擅长从学术论文数据库中抽取结构化信息、进行统计建模与图表分析(图表链接必须严格使用图表生成工具返回的原始链接),并最终生成高质量的 Markdown 格式分析报告,并输出到指定文件:{{output_file}}。 +你擅长从学术论文数据库中抽取结构化信息、进行统计建模与图表分析(图表链接或相对路径必须严格使用图表生成工具返回的原始值),并最终生成高质量的 Markdown 格式分析报告,并输出到指定文件:{{output_file}}。 --- @@ -1523,8 +1294,8 @@ research_hotspots_prompt = r""" 2. **数据库访问方式**(使用 SQLAlchemy Session): ```python - from databases.connection import Database - from databases.models.conference_paper import Author, Conference, Paper, PaperAuthorRelation + from deepinsight.databases.connection import Database + from deepinsight.databases.models.academic import Author, Conference, Paper, PaperAuthorRelation from sqlalchemy import select, func, desc, distinct with Database().get_session() as session: @@ -1533,62 +1304,7 @@ research_hotspots_prompt = r""" 3. 数据库模型说明: -``` -class Author(PaperBase): - __tablename__ = 'author_table' - - author_id = Column(Integer, primary_key=True, autoincrement=True) - author_name = Column(String(100), nullable=False) - email = Column(String(255)) - affiliation = Column(String(255)) - affiliation_country = Column(String(100)) - affiliation_city = Column(String(100)) - created_at = Column(TIMESTAMP, default=datetime.now) - updated_at = Column(TIMESTAMP, default=datetime.now, onupdate=datetime.now) - - -class Conference(PaperBase): - __tablename__ = 'conference_table' - - conference_id = Column(Integer, primary_key=True, autoincrement=True) - full_name = Column(String(255), nullable=False) - short_name = Column(String(50)) - year = Column(Integer, nullable=False) - location = Column(String(100)) - start_date = Column(Date) - end_date = Column(Date) - website = Column(String(255)) - topics: Mapped[list[str]] = Column(JSON) - created_at = Column(TIMESTAMP, default=datetime.now) - updated_at = Column(TIMESTAMP, default=datetime.now, onupdate=datetime.now) - - -class Paper(PaperBase): - __tablename__ = 'paper_table' - - paper_id = Column(Integer, primary_key=True, autoincrement=True) - title = Column(String(255), nullable=False) - conference_id = Column(Integer) # 直接存储ID,不使用ForeignKey - publication_year = Column(Integer) - abstract = Column(Text) - keywords = Column(String(255)) - author_ids = Column(String(500)) # 存储作者ID列表,如 "1,3,5" - reference_ids = Column(String(500)) # 存储参考文献ID列表 - topic = Column(String(100), nullable=True) - created_at = Column(TIMESTAMP, default=datetime.now) - updated_at = Column(TIMESTAMP, default=datetime.now, onupdate=datetime.now) - - -class PaperAuthorRelation(PaperBase): - __tablename__ = 'paper_author_relation_table' - - relation_id = Column(Integer, primary_key=True, autoincrement=True) - paper_id = Column(Integer) # 直接存储ID - author_id = Column(Integer) # 直接存储ID - author_order = Column(Integer, nullable=False) - is_corresponding = Column(Boolean, default=False, nullable=False) - created_at = Column(TIMESTAMP, default=datetime.now) -``` +{{db_models_description}} ## 🧩 任务执行要求(Execution Requirements) @@ -1618,23 +1334,20 @@ class PaperAuthorRelation(PaperBase): ### 一、图表展示(必须包含) ** 注意(非常重要)** : -1. 图表链接必须使用 **图表生成工具返回的原始链接**,禁止模型自行生成、修改、补全或替换。 -2. 图表链接的结构为: - http:///api/v1/deepinsight/charts/image/ -3. 其中 `` 和 `` **均由图表生成工具返回**,模型不得推测或伪造。 -4. 输出前需逐字符检查链接,确保与工具返回完全一致。 +1. 图表链接或相对路径必须使用图表生成工具返回的原始值,禁止模型自行生成、修改、补全或替换。 +2. 输出前需逐字符检查链接或路径,确保与工具返回完全一致。 #### 1. 关键词分布图 * **图表类型**:Wordcloud * **内容说明**:展示前50个高频关键词(必须使用英文)及其出现频率,直观呈现研究热点分布。 -* **图表链接**:图表展示参考以下格式:![<图表标题>](http://<图表链接地址>),图表链接必须严格使用图表生成工具返回的原始链接 +* **图表链接**:图表展示参考以下格式:![<图表标题>](<图表链接或相对路径>),必须严格使用图表生成工具返回的原始值 #### 2. 关键词组合分析水平条形图 * **分析逻辑**:针对前50关键词,进行两两组合,统计组合出现频率,输出出现频率最高的前10个组合柱状图。 * **内容说明**:揭示跨领域技术融合趋势和热点关联模式。 -* **图表链接**:图表展示参考以下格式:![<图表标题>](http://<图表链接地址>),图表链接必须严格使用图表生成工具返回的原始链接 +* **图表链接**:图表展示参考以下格式:![<图表标题>](<图表链接或相对路径>),必须严格使用图表生成工具返回的原始值 * **表格字段示例**: @@ -1914,8 +1627,8 @@ tech_topics_prompt = r""" 2. **数据库访问方式**(使用 SQLAlchemy Session): ```python - from databases.connection import Database - from databases.models.conference_paper import Author, Conference, Paper, PaperAuthorRelation + from deepinsight.databases.connection import Database + from deepinsight.databases.models.academic import Author, Conference, Paper, PaperAuthorRelation from sqlalchemy import select, func, desc, distinct with Database().get_session() as session: @@ -1969,16 +1682,13 @@ tech_topics_prompt = r""" ### 一、图表展示(必须包含) ** 注意(非常重要)** : -1. 图表链接必须使用 **图表生成工具返回的原始链接**,禁止模型自行生成、修改、补全或替换。 -2. 图表链接的结构为: - http:///api/v1/deepinsight/charts/image/ -3. 其中 `` 和 `` **均由图表生成工具返回**,模型不得推测或伪造。 -4. 输出前需逐字符检查链接,确保与工具返回完全一致。 +1. 图表链接或相对路径必须使用图表生成工具返回的原始值,禁止模型自行生成、修改、补全或替换。 +2. 输出前需逐字符检查链接或路径,确保与工具返回完全一致。 #### 1. 主题分布图(必选) * **图表类型**:饼状图(主题占比)。 * **内容说明**:展示每个主题在整体论文集合中的占比(若主题数过多,仅展示 Top6, 剩余的并合并“other”)。 -* **图表链接**:图表将在以下 HTTP 链接地址中显示:![<图表标题>](http://<图表链接地址>) +* **图表链接**:图表将在以下链接或相对路径中显示:![<图表标题>](<图表链接或相对路径>) --- diff --git a/deepinsight/core/tools/best_paper_analysis.py b/deepinsight/core/tools/best_paper_analysis.py index 54cbc8c..063668c 100644 --- a/deepinsight/core/tools/best_paper_analysis.py +++ b/deepinsight/core/tools/best_paper_analysis.py @@ -11,6 +11,7 @@ from langchain_tavily import TavilySearch from deepinsight.core.tools.file_system import register_fs_tools, MemoryMCPFilesystem from deepinsight.core.utils.research_utils import parse_research_config +from deepinsight.utils.db_schema_utils import get_db_models_source_markdown from deepinsight.core.utils.context_utils import DefaultSummarizationMiddleware # ----------------- 单篇论文解析函数 ----------------- @@ -40,19 +41,19 @@ def analyze_single_paper(paper_info: str, output_dir: str, config: RunnableConfi include_image_descriptions=True, search_depth="advanced", ) - paper_analysis_prompt = rc.prompt_manager.get_prompt( + prompt_template = rc.prompt_manager.get_prompt( name="paper_analysis_no_rag_prompt", group=rc.prompt_group, - ).format(output_dir=output_dir) + ).format(output_dir=output_dir, db_models_description=get_db_models_source_markdown()) tools.append(tavily_instance) if "ragflow" in config["configurable"]: # knowledge_tool = KnowledgeTool() # tools.append(knowledge_tool.knowledge_retrieve) - paper_analysis_prompt = rc.prompt_manager.get_prompt( + prompt_template = rc.prompt_manager.get_prompt( name="paper_analysis_prompt", group=rc.prompt_group, - ).format(output_dir=output_dir) + ).format(output_dir=output_dir, db_models_description=get_db_models_source_markdown()) from deepagents import create_deep_agent # Create the deep agent @@ -60,7 +61,7 @@ def analyze_single_paper(paper_info: str, output_dir: str, config: RunnableConfi agent = create_deep_agent( model=rc.default_model, tools=tools, - system_prompt=paper_analysis_prompt, + system_prompt=prompt_template, ) input_messages = [ { diff --git a/deepinsight/core/tools/keynote_analysis.py b/deepinsight/core/tools/keynote_analysis.py index e06e395..78d101b 100644 --- a/deepinsight/core/tools/keynote_analysis.py +++ b/deepinsight/core/tools/keynote_analysis.py @@ -142,8 +142,6 @@ def batch_analyze_keynotes( Dict[str, bool]: 每个 keynote 对应的分析成功状态(True/False) """ logging.info(f"接收到 keynotes_info,共 {len(keynotes_info)} 个") - logging.info(f"输出路径: {output_dir}") - logging.info(f"执行配置: {config}") result_map: Dict[str, bool] = {} timeout_seconds = 15 * 60 # 15 分钟超时 diff --git a/deepinsight/core/tools/tavily_search.py b/deepinsight/core/tools/tavily_search.py index 51b7423..6af315a 100644 --- a/deepinsight/core/tools/tavily_search.py +++ b/deepinsight/core/tools/tavily_search.py @@ -149,13 +149,18 @@ async def tavily_search( Formatted string containing summarized search results """ # Step 1: Execute search queries asynchronously - search_results = await tavily_search_async( - queries, - max_results=1, - topic=topic, - include_raw_content=True, - config=config - ) + try: + search_results = await tavily_search_async( + queries, + max_results=1, + topic=topic, + include_raw_content=True, + config=config + ) + except Exception as e: + error_message = f"Tavily search failed with error: {type(e).__name__}: {e}" + logging.error(error_message) + return error_message # Step 2: Deduplicate results by URL to avoid processing the same content multiple times unique_results = {} diff --git a/deepinsight/service/research/research.py b/deepinsight/service/research/research.py index 5ef12fb..a50dd40 100644 --- a/deepinsight/service/research/research.py +++ b/deepinsight/service/research/research.py @@ -14,8 +14,14 @@ from re import U import uuid import os import io -from typing import AsyncGenerator, Any, Dict, Set +import asyncio +from typing import AsyncGenerator, Any, Dict, Set, Tuple +import json +import base64 +import logging +from datetime import datetime +from langchain_core.messages import HumanMessage from langgraph.graph.state import CompiledStateGraph from langfuse.langchain import CallbackHandler @@ -30,7 +36,8 @@ from deepinsight.core.agent.conference_research.supervisor import graph as confe from deepinsight.core.agent.deep_research.supervisor import graph as deep_research_graph from deepinsight.core.agent.deep_research.parallel_supervisor import graph as parallel_deep_research_graph from deepinsight.core.agent.conference_research.ppt_generate import graph as ppt_generate_graph -from deepinsight.service.schemas.research import ResearchRequest, SceneType, PPTGenerateRequest +from deepinsight.service.schemas.research import ResearchRequest, SceneType, PPTGenerateRequest, PdfGenerateRequest +from deepinsight.utils.trans_md_to_pdf import save_markdown_as_pdf class ResearchService: @@ -180,7 +187,7 @@ class ResearchService: self, *, request: PPTGenerateRequest, - ) -> AsyncGenerator[StreamEvent, None]: + ) -> Tuple[io.BytesIO, str]: """ Generate PPT based on the conversation history. @@ -233,4 +240,125 @@ class ResearchService: pptx_stream = io.BytesIO() prs.save(pptx_stream) pptx_stream.seek(0) - return pptx_stream, output_name \ No newline at end of file + return pptx_stream, output_name + + async def pdf_generate(self, request: PdfGenerateRequest): + conversation_id = request.conversation_id + model_configs = request.args.llm_options if ( + request.args and request.args.llm_options) else self.config.llms + if len(model_configs) == 0: + raise ValueError(f"Provide at least one LLM configuration") + models, default_model = init_langchain_models_from_llm_config(llm_config=model_configs) + work_root = os.path.abspath(self.config.workspace.work_root) if getattr(self.config, "workspace", None) else os.path.abspath("./data") + base_dir = os.path.join(work_root, "conference_report_result", conversation_id) + os.makedirs(base_dir, exist_ok=True) + json_path = os.path.join(base_dir, "pdf_content.json") + + if os.path.exists(json_path): + with open(json_path, "r", encoding="utf-8") as f: + cached = json.loads(f.read()) + file_name = cached.get("file_name") + pdf_bytes = base64.b64decode(cached.get("content", "")) + buffer = io.BytesIO(pdf_bytes) + buffer.seek(0) + return buffer, file_name + + ordered_files = [ + "conference_overview.md", + "conference_keynotes.md", + "conference_topic.md", + ] + value_mining_dir = os.path.join(base_dir, "conference_value_mining") + value_mining_files = [ + "tech_topics.md", + "national_tech_profile.md", + "institution_overview.md", + "inter_institution_collab.md", + "research_hotspots.md", + "high_potential_tech_transfer.md", + ] + summary_file = "conference_summary.md" + best_papers_dir = os.path.join(base_dir, "conference_best_papers") + + markdown_parts = [] + + for file_name in ordered_files: + file_path = os.path.join(base_dir, file_name) + if os.path.exists(file_path): + with open(file_path, "r", encoding="utf-8") as f: + markdown_parts.append(f.read()) + + if os.path.exists(value_mining_dir): + for vm_file in value_mining_files: + vm_path = os.path.join(value_mining_dir, vm_file) + if os.path.exists(vm_path): + with open(vm_path, "r", encoding="utf-8") as f: + markdown_parts.append(f.read()) + + if os.path.exists(best_papers_dir): + best_papers = sorted( + [f for f in os.listdir(best_papers_dir) if f.endswith(".md")] + ) + for bp in best_papers: + bp_path = os.path.join(best_papers_dir, bp) + with open(bp_path, "r", encoding="utf-8") as f: + markdown_parts.append(f.read()) + + summary_path = os.path.join(base_dir, summary_file) + if os.path.exists(summary_path): + with open(summary_path, "r", encoding="utf-8") as f: + markdown_parts.append(f.read()) + + if not markdown_parts: + raise FileNotFoundError(f"No markdown files found for conversation_id={conversation_id}") + + merged_markdown = "\n\n---\n\n".join(markdown_parts) + + overview_path = os.path.join(base_dir, "conference_overview.md") + report_name = "未知会议" + if os.path.exists(overview_path): + with open(overview_path, "r", encoding="utf-8") as f: + overview_text = f.read() + + prompt = ( + "请从以下文本中提取会议名称和年份,例如“SOSP 2025”或“NeurIPS 2024”。" + "仅返回会议名与年份,不要包含其他文字。\n\n" + f"文本内容:\n{overview_text}" + ) + try: + response = await default_model.with_retry().ainvoke([HumanMessage(content=prompt)]) + report_name = response.content + report_name = report_name.strip().replace("\n", "").replace(":", ":") + except Exception as e: + logging.warning(f"LLM parse conference name error: {e}") + + now = datetime.now() + time_str = now.strftime("%Y年%m月%d日 %H时%M分%S秒") + time_for_filename = now.strftime("%Y%m%d_%H%M%S") + + header_info = ( + f"作者:DeepInsight顶会助手v0.1.0 \n" + f"部门:中软架构与设计管理部 \n" + f"时间:{time_str} \n\n---\n\n" + ) + + final_markdown = header_info + merged_markdown + + file_name = f"{report_name} 洞察报告-{time_for_filename}.pdf" + buffer = io.BytesIO() + output_pdf_path = os.path.join(base_dir, file_name) + await asyncio.to_thread( + save_markdown_as_pdf, + markdown_content=final_markdown, + output_filename=output_pdf_path, + base_url=base_dir, + ) + pdf_bytes = await asyncio.to_thread(lambda p=output_pdf_path: open(p, "rb").read()) + buffer.write(pdf_bytes) + buffer.seek(0) + + cache_data = {"file_name": file_name, "content": base64.b64encode(buffer.getvalue()).decode("utf-8")} + with open(json_path, "w", encoding="utf-8") as f: + f.write(json.dumps(cache_data, ensure_ascii=False, indent=2)) + + return buffer, file_name diff --git a/deepinsight/service/schemas/common.py b/deepinsight/service/schemas/common.py index 9c2bb4d..6c1dba0 100644 --- a/deepinsight/service/schemas/common.py +++ b/deepinsight/service/schemas/common.py @@ -1,8 +1,17 @@ from __future__ import annotations +from typing import Generic, Optional, TypeVar from enum import Enum +from pydantic import BaseModel, Field class OwnerType(str, Enum): """Common owner types for knowledge base binding.""" CONFERENCE = "conference" - # Future owners can be added here, e.g. WORKSPACE = "workspace", USER = "user" \ No newline at end of file + # Future owners can be added here, e.g. WORKSPACE = "workspace", USER = "user" + +T = TypeVar("T") + +class ResponseModel(BaseModel, Generic[T]): + code: int = Field(0, description="Response code") + message: str = Field("ok", description="Response message") + data: Optional[T] = Field(None, description="Response data") \ No newline at end of file diff --git a/deepinsight/service/schemas/research.py b/deepinsight/service/schemas/research.py index 99a24fc..79e1ce8 100644 --- a/deepinsight/service/schemas/research.py +++ b/deepinsight/service/schemas/research.py @@ -60,3 +60,8 @@ class PPTGenerateRequest(BaseModel): conversation_id: str = Field(..., description="Unique identifier of the conversation") args: Optional[ResearchArgs] = Field(None, description="Additional arguments for the conversation") + +class PdfGenerateRequest(BaseModel): + conversation_id: str = Field(..., + description="Unique identifier of the conversation") + args: Optional[ResearchArgs] = Field(None, description="Additional arguments for the conversation") \ No newline at end of file diff --git a/deepinsight/utils/db_schema_utils.py b/deepinsight/utils/db_schema_utils.py new file mode 100644 index 0000000..771e3cd --- /dev/null +++ b/deepinsight/utils/db_schema_utils.py @@ -0,0 +1,12 @@ +import inspect +from deepinsight.databases.models.academic import Author, Conference, Paper, PaperAuthorRelation + +def get_db_models_source_markdown() -> str: + parts = [] + for model in (Author, Conference, Paper, PaperAuthorRelation): + try: + src = inspect.getsource(model) + except Exception: + src = f"class {model.__name__}: pass" + parts.append(src) + return "```python\n" + "\n\n".join(parts) + "\n```" \ No newline at end of file diff --git a/deepinsight/utils/log_utils.py b/deepinsight/utils/log_utils.py new file mode 100644 index 0000000..e86de27 --- /dev/null +++ b/deepinsight/utils/log_utils.py @@ -0,0 +1,65 @@ +import os +import os.path +import logging +from logging.handlers import RotatingFileHandler + +initialized_root_logger = False + +def get_project_base_directory(): + PROJECT_BASE = os.path.abspath( + os.path.join( + os.path.dirname(os.path.realpath(__file__)), + os.pardir, + os.pardir, + ) + ) + return PROJECT_BASE + +def initRootLogger(logfile_basename: str, log_format: str = "%(asctime)-15s %(levelname)-8s [%(process)d:%(name)s:%(funcName)s:%(lineno)d] %(message)s"): + global initialized_root_logger + if initialized_root_logger: + return + initialized_root_logger = True + + logger = logging.getLogger() + logger.handlers.clear() + log_path = os.path.abspath(os.path.join(get_project_base_directory(), "logs", f"{logfile_basename}.log")) + + os.makedirs(os.path.dirname(log_path), exist_ok=True) + formatter = logging.Formatter(log_format) + + handler1 = RotatingFileHandler(log_path, maxBytes=10*1024*1024, backupCount=5) + handler1.setFormatter(formatter) + logger.addHandler(handler1) + + handler2 = logging.StreamHandler() + handler2.setFormatter(formatter) + logger.addHandler(handler2) + + logging.captureWarnings(True) + + LOG_LEVELS = os.environ.get("LOG_LEVELS", "") + pkg_levels = {} + for pkg_name_level in LOG_LEVELS.split(","): + terms = pkg_name_level.split("=") + if len(terms)!= 2: + continue + pkg_name, pkg_level = terms[0], terms[1] + pkg_name = pkg_name.strip() + pkg_level = logging.getLevelName(pkg_level.strip().upper()) + if not isinstance(pkg_level, int): + pkg_level = logging.INFO + pkg_levels[pkg_name] = logging.getLevelName(pkg_level) + + for pkg_name in ['peewee', 'pdfminer']: + if pkg_name not in pkg_levels: + pkg_levels[pkg_name] = logging.getLevelName(logging.WARNING) + if 'root' not in pkg_levels: + pkg_levels['root'] = logging.getLevelName(logging.INFO) + + for pkg_name, pkg_level in pkg_levels.items(): + pkg_logger = logging.getLogger(pkg_name) + pkg_logger.setLevel(pkg_level) + + msg = f"{logfile_basename} log path: {log_path}, log levels: {pkg_levels}" + logger.info(msg) \ No newline at end of file -- Gitee From 0893852feb5815292c732408953aa9f1ee18280f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B7=A9=E6=97=AD=E7=BA=A2?= <2250244225@qq.com> Date: Fri, 21 Nov 2025 15:32:06 +0800 Subject: [PATCH 2/7] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E4=BC=9A=E8=AE=AE?= =?UTF-8?q?=E9=97=AE=E7=AD=94=E8=83=BD=E5=8A=9B=E5=92=8C=E5=AF=B9=E5=BA=94?= =?UTF-8?q?=E5=91=BD=E4=BB=A4=E8=A1=8C=E8=B0=83=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 3 +- config.yaml | 2 + deepinsight/cli/commands/conference.py | 76 +++- deepinsight/cli/main.py | 3 +- .../core/agent/conference_qa/__init__.py | 0 .../core/agent/conference_qa/statistics.py | 52 +++ .../core/agent/conference_qa/supervisor.py | 409 ++++++++++++++++++ deepinsight/core/prompt/conference_qa.py | 212 +++++++++ deepinsight/service/research/research.py | 11 +- deepinsight/service/schemas/research.py | 3 +- 10 files changed, 761 insertions(+), 10 deletions(-) create mode 100644 deepinsight/core/agent/conference_qa/__init__.py create mode 100644 deepinsight/core/agent/conference_qa/statistics.py create mode 100644 deepinsight/core/agent/conference_qa/supervisor.py create mode 100644 deepinsight/core/prompt/conference_qa.py diff --git a/README.md b/README.md index 75ea1cc..5d42a83 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,8 @@ poetry run alembic upgrade head - 会议管理(conference) - 列表:`deepinsight conference list` - 删除:`deepinsight conference remove --id 12` - - 生成知识库:`deepinsight conference generate --name "ICLR 2025" --files-src ./path/to/files` + - 顶会洞察:`deepinsight conference generate --name "ICLR 2025" --files-src ./path/to/files` + - 会议问答:`deepinsight conference qa --name "ICLR 2025" --files-src ./path/to/files --question "今年最佳论文有哪些创新点?"` - 深度研究助手(research) - 启动研究:`deepinsight research start --topic "人工智能发展趋势"` diff --git a/config.yaml b/config.yaml index 81bc650..1f0e0c6 100644 --- a/config.yaml +++ b/config.yaml @@ -42,6 +42,8 @@ prompt_management: groups: deep_research: label: "latest" + conference_qa: + label: "latest" conference_supervisor: label: "latest" conference_overview: diff --git a/deepinsight/cli/commands/conference.py b/deepinsight/cli/commands/conference.py index 7574b68..beb9cbb 100644 --- a/deepinsight/cli/commands/conference.py +++ b/deepinsight/cli/commands/conference.py @@ -28,7 +28,7 @@ from deepinsight.service.schemas.conference import ( from deepinsight.service.research.research import ResearchService from deepinsight.service.schemas.research import ResearchRequest, SceneType, PPTGenerateRequest -from deepinsight.cli.commands.stream import run_research_and_save_report_sync +from deepinsight.cli.commands.stream import run_research_and_save_report_sync, make_report_filename from deepinsight.core.types.graph_config import SearchAPI @@ -55,6 +55,8 @@ class ConferenceCommand: return self._handle_remove(conf_args) elif conf_args.subcommand == 'generate': return self._handle_generate(conf_args) + elif conf_args.subcommand == 'qa': + return self._handle_qa(conf_args) else: parser.print_help() return 1 @@ -62,7 +64,15 @@ class ConferenceCommand: def _create_parser(self) -> argparse.ArgumentParser: parser = argparse.ArgumentParser( prog='deepinsight conference', - description='Conference information management (generate/list/delete)' + description='Conference information management (list/remove/generate/qa)', + formatter_class=argparse.RawDescriptionHelpFormatter, + epilog='''\ +Examples: + deepinsight conference list + deepinsight conference generate --name "ICLR 2025" --files-src ./docs + deepinsight conference qa --name "ICLR 2025" --files-src ./docs --question "今年最佳论文有哪些创新点?" + deepinsight conference remove --id 12 + ''' ) subparsers = parser.add_subparsers(dest='subcommand', help='Operations') @@ -87,6 +97,10 @@ class ConferenceCommand: # Note: --files-src replaces the previous --docs-src for clarity. generate_parser.add_argument('--name', '-n', required=True, help='Conference name including year, e.g., "ICLR 2025"') generate_parser.add_argument('--files-src', '-f', required=True, help='User-provided source directory of files to ingest') + qa_parser = subparsers.add_parser('qa', help='Conference QA based on ingested documents') + qa_parser.add_argument('--name', '-n', required=True, help='Conference name including year, e.g., "ICLR 2025"') + qa_parser.add_argument('--files-src', '-f', required=True, help='User-provided source directory of files to ingest') + qa_parser.add_argument('--question', '-q', required=True, help='User question to answer against the conference knowledge base') return parser def _get_config(self): @@ -183,7 +197,7 @@ class ConferenceCommand: request=ResearchRequest( conversation_id=conv_id, query=query, - scene_type=SceneType.CONFERENCE, + scene_type=SceneType.CONFERENCE_RESEARCH, allow_user_clarification=False, allow_edit_research_brief=False, allow_edit_report_outline=False, @@ -215,4 +229,60 @@ class ConferenceCommand: return 0 except Exception as e: logger.exception("✗ 生成失败") + return 1 + + def _handle_qa(self, args: argparse.Namespace) -> int: + try: + service = self._get_service() + name = args.name.strip() + m = re.search(r'(19|20)\d{2}', name) + if not m: + raise ValueError('No year detected in name, please include a four-digit year like 2025') + year = int(m.group(0)) + full_name = name + base_name_no_year = re.sub(r'[\s\(\[\{,]*' + m.group(0) + r'[\s\)\]\},]*', ' ', name).strip() + if not base_name_no_year: + base_name_no_year = name.replace(m.group(0), '').strip() + short_name = None + compact = re.sub(r'\s+', '', base_name_no_year) + if compact.isupper() and 2 <= len(compact) <= 12: + short_name = compact + req = ConferenceParseDocsRequest( + short_name=short_name, + full_name=full_name, + year=year, + docs_src_dir=args.files_src, + ) + reporter = RichProgressReporter(console=get_console()) + reporter.info("Parsing documents. This may take a while...") + asyncio.run(service.ensure_conference_and_ingest_docs(req, reporter=reporter)) + research_service = ResearchService(self._get_config()) + base = (short_name or full_name).strip() + slug = re.sub(r"\s+", "-", base) + conv_id = f"qa-{slug}-{year}" + query = args.question.strip() + # 生成带有问题前缀与时间戳的唯一文件名,避免同会议不同问题的报告相互覆盖 + result_stem = make_report_filename( + question=query, + expert=f"conference_qa_{(short_name or base_name_no_year).strip()}_{year}", + ) + run_research_and_save_report_sync( + service=research_service, + request=ResearchRequest( + conversation_id=conv_id, + query=query, + scene_type=SceneType.CONFERENCE_QA, + allow_user_clarification=False, + allow_edit_research_brief=False, + allow_edit_report_outline=False, + search_api=[SearchAPI.TAVILY], + ), + result_file_stem=result_stem, + gen_pdf=True, + live=Live(console=get_console()), + ) + print("✓ 问答完成(Markdown/PDF)") + return 0 + except Exception as e: + logger.exception("✗ 问答失败") return 1 \ No newline at end of file diff --git a/deepinsight/cli/main.py b/deepinsight/cli/main.py index c5e6872..abcc94a 100644 --- a/deepinsight/cli/main.py +++ b/deepinsight/cli/main.py @@ -66,6 +66,7 @@ class DeepInsightCLI: Examples: deepinsight conference list deepinsight conference generate --name "ICLR 2025" --files-src ./docs + deepinsight conference qa --name "ICLR 2025" --files-src ./docs --question "今年最佳论文有哪些创新点?" deepinsight research start deepinsight --version @@ -186,4 +187,4 @@ def main() -> int: if __name__ == '__main__': - sys.exit(main()) \ No newline at end of file + sys.exit(main()) diff --git a/deepinsight/core/agent/conference_qa/__init__.py b/deepinsight/core/agent/conference_qa/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/deepinsight/core/agent/conference_qa/statistics.py b/deepinsight/core/agent/conference_qa/statistics.py new file mode 100644 index 0000000..876517a --- /dev/null +++ b/deepinsight/core/agent/conference_qa/statistics.py @@ -0,0 +1,52 @@ +import asyncio +import json +import sys +from typing import Literal, TypedDict, Optional + +from langchain_core.messages import HumanMessage +from langchain.agents import create_agent +from langchain_experimental.tools import PythonREPLTool +from langgraph.graph import StateGraph, MessagesState, START, END +from langgraph.types import Command + +from deepinsight.core.utils.research_utils import parse_research_config +from deepinsight.utils.db_schema_utils import get_db_models_source_markdown + +class State(MessagesState): + next_step: str + + +def create_statistic_agent(llm, config): + rc = parse_research_config(config) + + system_prompt = rc.prompt_manager.get_prompt( + name="static_agent_system_prompt", + group=rc.prompt_group, + ).format(db_models_description=get_db_models_source_markdown()) + agent = create_agent( + model=llm, + tools=[PythonREPLTool()], + system_prompt=system_prompt + ) + + return agent + + +async def statistic_agent_node(state: State, config) -> Command[Literal[END]]: + rc = parse_research_config(config) + statistic_agent = create_statistic_agent(llm=rc.get_model(), config=config) + result = await statistic_agent.ainvoke(state, config=config) + return Command( + update={ + "messages": [ + HumanMessage(content=result["messages"][-1].content, name="statistic_agent") + ] + }, + goto=END, + ) + + +graph_builder = StateGraph(State) +graph_builder.add_node("statistic_agent", statistic_agent_node) +graph_builder.add_edge(START, "statistic_agent") +graph = graph_builder.compile() diff --git a/deepinsight/core/agent/conference_qa/supervisor.py b/deepinsight/core/agent/conference_qa/supervisor.py new file mode 100644 index 0000000..b0dbdcc --- /dev/null +++ b/deepinsight/core/agent/conference_qa/supervisor.py @@ -0,0 +1,409 @@ +import logging +import os +from enum import Enum +from typing import Any, TypedDict, Literal, Annotated, List + +from langchain.agents import create_agent +from langchain.agents.middleware import TodoListMiddleware +from langchain_core.messages import BaseMessage, HumanMessage +from langchain_core.prompts import ChatPromptTemplate +from langchain_core.runnables import RunnableConfig +from langgraph.checkpoint.memory import InMemorySaver +from langgraph.config import get_stream_writer +from langgraph.constants import END +from langgraph.graph import StateGraph, add_messages +from langgraph.types import Command, interrupt +from langmem.short_term import SummarizationNode + +from deepinsight.core.tools.ragflow_retrival import KnowledgeTool +from deepinsight.core.utils.progress_utils import progress_stage +from deepinsight.utils.tavily_key_utils import select_api_key +from deepinsight.core.utils.research_utils import parse_research_config +from deepinsight.core.types.research import FinalResult +from deepinsight.core.agent.conference_research.supervisor import graph as conference_research_graph +from deepinsight.core.agent.conference_qa.statistics import graph as statistics_graph +from deepinsight.core.tools.tavily_search import tavily_search +from deepinsight.core.tools.wordcloud_tool import generate_wordcloud +from deepinsight.service.schemas.research import SceneType +from integrations.mcps.generate_chart import generate_area_chart, generate_bar_chart, generate_column_chart, \ + generate_pie_chart, generate_scatter_chart, generate_line_chart, generate_radar_chart + + +class GraphNodeType(str, Enum): + SUMMARIZER = "summarizer" # 对话摘要节点 + SUPERVISOR = "supervisor" # 监督者节点(任务分配) + ANSWER_COMPOSER = "answer_composer" # 答案汇总节点 + CLARIFY_NODE = "question_clarify" # 问题澄清节点 + PAPER_TEAM = "paper_team" # 论文团队节点 + RETRIVAL_TEAM = "retrival_team" # 检索团队节点 + DEEP_RESEARCH_TEAM = "deep_research_team" # 深度研究团队节点 + CHART_NODE = "chart_node" # 报告(图表)团队节点 + + +# 定义状态格式 +class SupervisorState(TypedDict): + messages: Annotated[List[BaseMessage], add_messages] + context: dict[str, Any] + + +async def summarization_node(state: SupervisorState, config): + rc = parse_research_config(config) + summarizer = SummarizationNode( + model=rc.get_model(), + max_tokens=32768, + max_tokens_before_summary=2048, + max_summary_tokens=16384, + output_messages_key="messages" + ) + result = await summarizer.ainvoke(state) + return result + + +@progress_stage("生成回复") +async def answer_composer_node(state: SupervisorState, config): + rc = parse_research_config(config) + prompt_template = rc.prompt_manager.get_prompt( + name="answer_composer_prompt", + group=rc.prompt_group, + ) + system_prompt = prompt_template.format( + messages=state["messages"] + ) + + response = await rc.get_model().ainvoke([ + {"role": "system", "content": system_prompt} + ]) + + writer = get_stream_writer() + writer(FinalResult( + final_report=response.content + )) + + +def make_supervisor_node(): + def parse_response(response_content: str): + import json + """解析模型返回的内容,提取next_step""" + try: + # 尝试直接解析JSON + logging.debug(response_content) + return json.loads(response_content) + except Exception: + # 如果直接解析失败,尝试提取JSON部分 + start = response_content.find('{') + end = response_content.rfind('}') + 1 + if start != -1 and end != -1: + json_str = response_content[start:end] + return json.loads(json_str) + return None + + async def supervisor_node(state: SupervisorState, config) -> Command[Literal[ + GraphNodeType.CLARIFY_NODE, GraphNodeType.PAPER_TEAM, GraphNodeType.CHART_NODE, + GraphNodeType.ANSWER_COMPOSER]]: + rc = parse_research_config(config) + # 1. 定义新成员和描述 + members = [ + GraphNodeType.CLARIFY_NODE.value, + GraphNodeType.PAPER_TEAM.value, + GraphNodeType.CHART_NODE.value, + GraphNodeType.RETRIVAL_TEAM.value, + GraphNodeType.DEEP_RESEARCH_TEAM.value + ] + + members_description = { + GraphNodeType.CLARIFY_NODE: rc.prompt_manager.get_prompt( + name="clarify_node_prompt", + group=rc.prompt_group, + ).format(), + GraphNodeType.PAPER_TEAM: rc.prompt_manager.get_prompt( + name="paper_team_prompt", + group=rc.prompt_group, + ).format(), + GraphNodeType.RETRIVAL_TEAM: rc.prompt_manager.get_prompt( + name="retrieval_team_prompt", + group=rc.prompt_group, + ).format(), + GraphNodeType.CHART_NODE: rc.prompt_manager.get_prompt( + name="report_team_prompt", + group=rc.prompt_group, + ).format(), + GraphNodeType.DEEP_RESEARCH_TEAM: rc.prompt_manager.get_prompt( + name="deep_research_team_prompt", + group=rc.prompt_group, + ).format(), + } + + members_str = "\n".join([f"- {m}" for m in members]) + member_list_string = ', '.join([f'"{node}"' for node in members]) + members_desc_str = "\n".join( + [f"- **{k.value}**: {v.strip()}" for k, v in members_description.items()] + ) + + prompt_template = rc.prompt_manager.get_prompt( + name="supervisor_prompt", + group=rc.prompt_group, + ) + conf_analysis_supervisor_prompt = prompt_template.format( + members=members_str, + members_description=members_desc_str, + member_list=member_list_string + ) + + messages = [ + {"role": "system", "content": conf_analysis_supervisor_prompt}, + ] + state["messages"] + llm = rc.get_model() + response = await llm.ainvoke(messages) + llm_response = response.content + result = parse_response(llm_response) + if not result or result["next"] == END or result["next"] == GraphNodeType.CLARIFY_NODE.value: + return Command( + goto=GraphNodeType.ANSWER_COMPOSER.value, + update={"messages": {"role": "ai", "content": llm_response}} + ) + + return Command( + goto=result["next"] + ) + + return supervisor_node + + +async def question_clarify_node(state: SupervisorState) -> Command[Literal[GraphNodeType.SUMMARIZER]]: + user_reply = interrupt(state["messages"][-1].content) + return Command(goto=GraphNodeType.SUMMARIZER.value, update={ + "messages": HumanMessage( + content=user_reply + ) + }) + + +@progress_stage("论文统计分析") +async def paper_team_node(state: SupervisorState) -> Command[Literal[GraphNodeType.SUMMARIZER]]: + # 调用 Paper Team 的处理流程 + result = await statistics_graph.ainvoke( + {"messages": [("user", state["messages"][-1].content)]}, + {"recursion_limit": 100}, + ) + return Command(goto=GraphNodeType.SUMMARIZER.value, update={ + "messages": HumanMessage( + content=result["messages"][-1].content, name="paper_team" + ) + }) + + +@progress_stage("论文检索") +async def retrival_team_node(state: SupervisorState, config: RunnableConfig) -> Command[Literal[END]]: + rc = parse_research_config(config) + tools = [tavily_search] + if "ragflow" in config["configurable"]: + logging.info("ragflow in config") + knowledge_tool = KnowledgeTool() + tools.append(knowledge_tool.knowledge_retrieve) + # 调用 retrival Team 的处理流程 + system_prompt = """ + 你是一名专精于学术论文检索与数据分析的智能研究助理。 + 你的任务是根据用户请求,**高效查询学术论文、会议论文及相关作者/机构信息**。 + 你应当优先利用 RAG 检索(ragflow)进行信息查找; + 若 RAG 不可用或返回结果为空,则自动使用 Tavily 搜索工具进行查询。 + + --- + + ### 🎯 工作目标 + 1. **优先使用 RAG 检索知识库(ragflow)获取论文、作者、会议信息。** + 2. **当 RAG 检索无结果或无法使用时,自动切换至 Tavily 搜索。** + 3. **每次查询完成后,主动反思结果是否满足用户问题。** + - 如果结果不完整或不相关,请优化查询语句(query)并重试。 + 4. **最多尝试 5 次查询。** + - 若超过 5 次仍未找到有效结果,则返回检索失败的提示(例如:“未能检索到相关论文或信息”)。 + + --- + + ### 🧰 可用工具 + - **ragflow.knowledge_retrieve**:RAG 检索学术知识库内容。 + - **tavily_search**:从互联网检索学术论文、会议及作者信息。 + + --- + + ### 🧠 检索与反思流程 + + 每次检索请执行以下逻辑: + + 1. **执行查询** + * 优先使用 ragflow 进行知识检索; + * 若 RAG 无法使用或结果为空,则改用 tavily_search。 + + 2. **结果评估** + * 检查结果是否满足用户问题; + * 如果不满足,重写查询语句并重试。 + + 3. **重试机制** + * 最多执行 5 次; + * 超过 5 次仍无结果则返回失败信息。 + + --- + + ### 📘 输出要求 + + * 所有内容必须来源于检索结果,不得编造、估算或推断。 + * 回答要简洁、准确,并与用户问题直接相关。 + * 若涉及数据库查询,请仅使用 PythonREPLTool 和 SQLAlchemy。 + * 不进行统计、趋势分析或额外评论,除非用户明确要求。 + + --- + + ### 📄 输出格式规范(新增) + + 每次输出结果时,请严格按照以下格式组织内容: + + #### ✅ 标准输出格式 + + ``` + <在此展示检索得到的论文摘要、会议介绍或作者信息原文,不做改写> + + 【来源】 + + * 来源类型:RAG 检索 / 网络检索(Tavily) + * 来源名称:<数据库名或网站名,如 “IEEE Xplore”, “ACM Digital Library”, “Google Scholar”, “arXiv”, “SpringerLink” 等> + * 检索时间:<自动填入检索执行的时间,如 2025-11-12 14:35> + * 原始链接(若有):<论文或数据源的具体链接> + + ``` + + #### ✅ 多条结果输出格式 + + 若返回多篇论文或多个来源,请以编号形式列出: + ``` + + <论文摘要或核心内容> + + 【来源】 + + * 来源类型:RAG 检索 + * 来源名称:ACM Digital Library + * 检索时间:2025-11-12 14:35 + * 原始链接:[https://dl.acm.org/](https://dl.acm.org/)... + + + * 来源类型:网络检索(Tavily) + * 来源名称:Google Scholar + * 检索时间:2025-11-12 14:36 + * 原始链接:[https://scholar.google.com/](https://scholar.google.com/)... + + ``` + + --- + + ### 🧩 附加说明 + * 若检索失败,请输出: + ``` + + ❌ 未能检索到相关论文或信息,请尝试更换关键词或调整查询范围。 + + ``` + * 若部分结果存在信息缺失,请明确标注“[信息缺失]”。 + + """ + agent = create_agent( + model=rc.get_model(), + tools=tools, # Many tools + middleware=[TodoListMiddleware()], + system_prompt=system_prompt + ) + result = await agent.ainvoke(state, config=config) + return Command( + goto=GraphNodeType.SUMMARIZER.value, + update={ + "messages": [ + HumanMessage(content=result["messages"][-1].content, name="retrival_team") + ] + } + ) + + +@progress_stage("图表生成") +async def chart_node(state: SupervisorState, config: RunnableConfig) -> Command[Literal[GraphNodeType.SUMMARIZER]]: + rc = parse_research_config(config) + llm = rc.get_model() + + chart_tools = [generate_area_chart, generate_bar_chart, generate_column_chart, generate_pie_chart, + generate_scatter_chart, generate_line_chart, generate_radar_chart, generate_wordcloud] + system_prompt = rc.prompt_manager.get_prompt( + name="report_chart_agent_sys_prompt", + group=rc.prompt_group, + ).format() + agent = create_agent( + model=llm, + tools=chart_tools, + system_prompt=system_prompt + ) + + result = await agent.ainvoke( + { + "user_input": state["messages"][-1].content, + "messages": [ + {"role": "human", "content": state["messages"][-1].content} + ], + "charts": [], + "report": "", + }) + + return Command(goto=GraphNodeType.SUMMARIZER.value, update={ + "messages": HumanMessage( + content=result["messages"][-1].content, name="report_team" + ) + }) + + +@progress_stage("顶会深度研究") +async def deep_research_team_node(state: SupervisorState, config: RunnableConfig) -> Command[Literal[END]]: + # 调用 retrival Team 的处理流程 + if os.getenv("TAVILY_API_KEYS"): + selected_key, all_keys_usage = select_api_key() + if selected_key is None: + logging.error("no tavily key can be used, please set first.") + for key, usage in all_keys_usage.items(): + logging.error(f"API Key: {key} - Plan Limit: {usage['plan_limit']}, Plan Usage: {usage['plan_usage']}") + writer = get_stream_writer() + writer({"result": "no tavily key can be used, please set first."}) + return Command(goto=END) + + parent_configurable = config.get("configurable", {}) + deep_research_config = { + **parent_configurable, + "prompt_group": SceneType.DEEP_RESEARCH.value, + "allow_user_clarification": False, + "allow_edit_research_brief": False, + "allow_edit_report_outline": False, + "allow_publish_result": False, + } + + result = await conference_research_graph.with_config(configurable=deep_research_config).ainvoke( + {"messages": [("user", state["messages"][-1].content)]} + ) + writer = get_stream_writer() + writer({"result": result["messages"][-1].content}) + return Command(goto=END, update={ + "messages": HumanMessage( + content=result["messages"][-1].content, name="deep_research_team" + ) + }) + + +# 构建图 +builder = StateGraph(SupervisorState) +builder.add_node(GraphNodeType.SUMMARIZER.value, summarization_node) +builder.add_node(GraphNodeType.SUPERVISOR.value, make_supervisor_node()) +builder.add_node(GraphNodeType.CLARIFY_NODE.value, question_clarify_node) +builder.add_node(GraphNodeType.PAPER_TEAM.value, paper_team_node) +builder.add_node(GraphNodeType.CHART_NODE.value, chart_node) +builder.add_node(GraphNodeType.RETRIVAL_TEAM.value, retrival_team_node) +builder.add_node(GraphNodeType.DEEP_RESEARCH_TEAM.value, deep_research_team_node) +builder.add_node(GraphNodeType.ANSWER_COMPOSER.value, answer_composer_node) + + +builder.set_entry_point(GraphNodeType.SUMMARIZER.value) +builder.add_edge(GraphNodeType.SUMMARIZER.value, GraphNodeType.SUPERVISOR.value) +builder.add_edge(GraphNodeType.ANSWER_COMPOSER.value, END) +checkpointer = InMemorySaver() +graph = builder.compile(checkpointer=checkpointer) diff --git a/deepinsight/core/prompt/conference_qa.py b/deepinsight/core/prompt/conference_qa.py new file mode 100644 index 0000000..1778004 --- /dev/null +++ b/deepinsight/core/prompt/conference_qa.py @@ -0,0 +1,212 @@ +answer_composer_prompt = fr""" +你是一个答案汇总者(Answer Composer)。 +你的任务是基于用户的问题和提供的信息,生成一个清晰、准确、简洁的最终回答。 + +你将获得: +1. 一份信息列表(可能包含事实、摘要、报告或文档片段)。 +2. 用户的最新问题。 + +要求: +- 仔细理解用户的问题。 +- 综合利用提供的信息来回答,而不是逐字复述。 +- 回答要自然连贯,逻辑清晰。 +- 如果信息存在冲突,请给出合理、平衡的解释。 +- 如有iframe,保留到输出结果。 + +# 交互消息列表: +{{messages}} + +# 输出格式要求:**直接回答用户问题,不要解释别的东西** +""" + +clarify_node_prompt = r""" +当用户的问题模糊不清、缺少关键信息(例如:缺少具体的关键词、时间范围、文档类型等)或者意图不明确时, +调用此员工。它的任务是主动向用户提问,以获取完成后续任务所必需的全部信息。 +""" + +deep_research_team_prompt = r""" +此团队专注于技术领域的深度剖析、趋势预判与核心逻辑拆解,聚焦为用户提供具备专业性、前瞻性的技术洞察。 +主要功能: +1. 拆解特定技术(如 AI、区块链、云计算)的核心原理与架构,分析技术优劣势及优化方向,形成技术细节洞察。 +2. 结合技术脉络与行业场景,预判技术演进趋势,评估对产业的影响,输出趋势洞察报告。 +3. 对比不同技术路径的适配性与风险,为技术选型提供决策洞察支持。 +4. 解读技术前沿动态(如突破性成果、标准更新),提炼核心价值,生成关键信息总结。 +示例提问: +1. 大语言模型注意力机制的核心原理洞察是什么? +2. 未来3年云计算技术趋势的总结怎么写? +3. 工业互联网边缘与云计算协同的技术洞察有哪些? +4. 新量子计算算法的技术突破点总结是什么? +5. 自动驾驶多传感器融合的架构洞察该如何提炼? +""" + +paper_team_prompt = r""" +此团队专注于学术论文的元数据统计与汇总,不解决论文正文/具体技术内容的解析/深度洞察类的问题。 +主要功能包括: +1. 基于会议/期刊论文的元数据(如题目、作者、机构、关键词、摘要、年份、引用数等)进行检索与统计。 +2. 提供论文数量统计、作者/机构分布、主题趋势分析等宏观信息。 +3. 帮助用户快速了解论文集合的整体特征和分布情况,但不回答论文具体研究方法、实验结果或创新点等内容。 +4. 如果用户询问的是需要深入洞察、技术解析或研究建议的问题(例如:"这篇论文的方法论有什么创新?"/"实验结果说明了什么?"/"这个领域未来研究方向是什么?) +不要使用此团队,建议用户使用深度洞察团队。 +""" + +report_chart_agent_sys_prompt = r""" +# 角色 +你是一名专业的数据可视化分析助手,负责基于输入数据调用绘图工具并返回结果。 + +# 任务 +根据输入数据生成图表。工具会返回一个图片的 URL。你必须始终以 JSON 格式输出,且只能包含以下三个字段: +- url: 图表的 URL(字符串)。若图表生成失败或数据不足,则填 ""。 +- description: 针对该图片的简要描述,以及基于数据做的简单分析(字符串)。若图表生成失败则填 ""。 +- question: 当无法生成图表时,写明需要用户补充的信息或说明失败原因(字符串)。若生成成功则填 ""。 + +# 输出要求 +- 输出必须是标准 JSON 对象,键名固定为 "url"、"description"、"question"。 +- 除 JSON 之外,禁止输出任何其他文字、包裹符号、解释、引导语或附加信息。 +- 若图表生成成功:description 必须简洁明了,客观说明图表内容与关键发现。 +- 若图表生成失败:在 question 字段明确告诉用户缺失了什么(如“缺少时间字段,无法绘制折线图”)。 +- 生成图表会返回两种类型的url接口,请根据用户指定确定使用那种url,只能使用一种形式的url,默认采用html格式的url: + 返回数据为html格式url:http://:/api/v1/deepinsight/charts/ + 返回数据为image(png格式)url:http://:/api/v1/deepinsight/charts/image/ +- 使用中文回答。 + +# 输出示例(成功情况) +{ + "url": "http://:/api/v1/deepinsight/charts/", + "description": "折线图显示销售额在3月至8月持续上升,4月有小幅回落后在6月开始快速增长。", + "question": "" +} + +# 输出示例(失败情况) +{ + "url": "", + "description": "", + "question": "无法生成图表:缺少时间字段。请提供完整的按月数据。" +} + +# 约束 +- 在任何情况下都【绝对】不允许编造数据!! +""" + +report_team_prompt = r""" +此团队专注于内容的组织、撰写和最终呈现,如果需要数据来源,需要先调用paper_team进行查询。 +主要功能: +1. 依据用户提供的数据与绘图指令,生成符合要求、清晰美观的图表。 +2. 理解并压缩原文内容,提取关键信息,形成简明扼要的摘要,同时保留原文的主要思想与逻辑。 +""" + +retrieval_team_prompt = r""" +此团队专注于面向具体内容的深入检索,重点回答涉及论文正文、技术细节或跨源知识的问题。 +主要功能包括: +1. 检索和提取某一具体论文的研究方法、实验结果、核心创新点等详细内容。 +2. 支持技术主题的细粒度信息检索与知识点解析(不限于学术论文,还可扩展至知识库、互联网和内网资料)。 +""" + +static_agent_system_prompt = r""" +你是一名专精于学术会议数据检索与处理的资深数据分析师。 +你可以仅使用 PythonREPLTool() 进行数据库查询与基础数据处理。 +所有信息必须直接来源于数据库;不得编造、估算或推断数据。 + +1. **可用工具:** +- PythonREPLTool:仅用于执行数据库查询与简单的数据格式化。 + 示例: + ```python + with Database().get_session() as session: + result = session.execute( + select(Paper.title, Paper.publication_year) + .where(Paper.conference_id == 3) + ).all() + print(result) +```` + +2. **数据库访问(使用 SQLAlchemy Session):** + +```python +from deepinsight.databases.connection import Database +from deepinsight.databases.models.academic import Author, Conference, Paper, PaperAuthorRelation +from sqlalchemy import select, func, desc, distinct + +with Database().get_session() as session: + # 示例:获取指定年份的所有论文 + result = session.execute( + select(Paper.paper_id, Paper.title) + .where(Paper.publication_year == 2021) + ).all() + print(result) +``` + +3. **数据库模型说明:** + *(使用以下模型进行查询、连接和聚合操作;不得假设或引用这些表之外的数据。)* +{{db_models_description}} +--- + +4. **使用准则:** + +* 仅可直接从数据库中获取和处理数据。 +* 除非用户用明确要求,否则不进行进行任何可视化、统计分析或趋势解释,也不拆分相对应的任务。 +* 不得生成、假设或推测数据库中未明确存在的信息。 +* 仅执行用户明确提出的任务或问题。 +* 输出内容应严格限定于回答用户的问题或展示请求的数据,不添加额外评论或分析。 +""" + +supervisor_prompt = r""" +你是一个资深的AI多智能体团队的研究负责人(Team Leader),专注于高层次的研究战略、规划、对员工的高效任务分配。你的核心目标是借助可用的员工最大程度 +地主导研究用户问题。请接收用户的当前请求,制定一个有效的研究计划,并通过将任务委派给合适的员工来完成计划的所有步骤。 +你自己不需要负责具体的任务,计划里面的所有任务都交由可用的员工负责(除非没有可用的员工完成某项步骤你才自己负责具体的任务执行)。 +注意:deep_research_team是针对学术会议的洞察,只要用户任务是针对某个指定的学术会议进行洞察分析,才能指定任务到deep_research_team,例如: 对2025年SSSA学术会议进行洞察 + +# 你的可选员工团队: +{{members}} + +# 员工职责描述: +{{members_description}} +# 工作流程: +遵循以下流程分解用户的问题并制定一个出色的研究计划。要充分、深入地思考用户的任务,全面理解其意图并决定接下来的行动。 +1. 如果用户的请求不够明确、缺乏关键信息,你必须返回 **澄清节点**,并明确告诉用户需要补充哪些信息。 +2. 仔细分析用户的最新请求,根据上述“员工职责描述”对用户问题进行逐步求解,在执行每个子任务时选择最适合的员工并尽量保证让你的员工只专注一件事情。 +3. 请根据用户问题的难易程度决定分的步骤数,你不用一开始制定完整的执行计划,而是一个步骤一个步骤往下执行即可。 +4. 如果需要调用某位员工,你必须对用户的请求进行改写,确保任务描述清晰、完整、自洽,并且包括完成任务所需的数据等完整信息,但是注意不要过度发散。 +5. 如果用户的请求是感谢、打招呼或任务明显已结束,或者是一个无法由任何员工处理的请求,你应该判定任务完成。 +6. **“请补充说明:”。“任务说明:”后面的内容回复语言请保持和用户输入语言一致。** + +# 输出格式要求(返回JSON,只返回以下三种格式之一): +- 如果需要澄清: +{"next": "question_clarify", "task":"<你需要用户补充的内容>"} +- 如果需要分配任务: +{"next": "<成员名称>", "task":"<你重写后的完整任务以及完成任务所需的额外信息和数据>"} +- 如果任务已完成或无需处理: +{"next": "__end__", "task":""} + +# 备注 +# 指令 +- 若解答包含多条数据,必须将数据整理并交由合适的组件生成图表 +- 图表类型仅限 "line" | "bar" | "scatter" | "area" | "pie" | "column" | "radar",禁止使用其他类型 +- 在不同组件之间传递信息时,必须确保数据的完整性,例如涉及论文、作者等信息时需完整传递 +- 当涉及图表生成时,先获取完整数据,再将其交由负责绘制的组件;在非绘图场景下,可直接输出结果 +- 在多轮对话中,即使已有答案,也必须交由相应组件进一步验证或扩展,不得直接回答 +- 当用户输入中包含英文缩写时,指令中必须同时包含缩写和对应的英文全称 + +# 示例: +- 用户输入: "帮我研究一下大模型幻觉的问题" +输出: +{"next": "question_clarify", "task":"你希望研究幻觉问题的角度,例如:成因、评估方法还是解决方案?"} + +- 用户输入: "2024 google IO大会洞察" +输出: +{"next": "deep_research_team", "task":"2024年google IO大会分析"} + +- 用户输入: "查找近三年关于 'Chain of Thought' 在代码生成领域应用的所有高被引论文" +输出: +{"next": "paper_team_node", "task":"请检索近三年关于 'Chain of Thought' 在代码生成领域应用的高被引论文,并输出论文标题、作者、年份和引用次数。"} + +- 用户输入: "查我查询下论文的xxxx的核心创新点" +输出: +{"next": "paper_team_node", "task":"检索论文xxxx的内容,并找到对应的创新点。"} + +- 用户输入: "报告写得不错,多谢" +输出: +{"next": "__end__", "task":""} + +# 注意事项 +- 你必须指派给员工回答问题,而不是自己直接回答!! +- 无论你的团队解决过多少次问题,你的任务都只能是指派给员工[{{member_list}}]中的一个解答,不可以直接回答!! +""" diff --git a/deepinsight/service/research/research.py b/deepinsight/service/research/research.py index a50dd40..02dc8e0 100644 --- a/deepinsight/service/research/research.py +++ b/deepinsight/service/research/research.py @@ -32,7 +32,8 @@ from deepinsight.service.streaming.stream_adapter import StreamEventAdapter from deepinsight.service.ppt.template_service import PPTTemplateService from deepinsight.utils.llm_utils import init_langchain_models_from_llm_config from deepinsight.utils.common import safe_get -from deepinsight.core.agent.conference_research.supervisor import graph as conference_graph +from deepinsight.core.agent.conference_qa.supervisor import graph as conference_qa_graph +from deepinsight.core.agent.conference_research.supervisor import graph as conference_research_graph from deepinsight.core.agent.deep_research.supervisor import graph as deep_research_graph from deepinsight.core.agent.deep_research.parallel_supervisor import graph as parallel_deep_research_graph from deepinsight.core.agent.conference_research.ppt_generate import graph as ppt_generate_graph @@ -81,7 +82,7 @@ class ResearchService: # Determine prompt group for this scene # Conference graph expects prompts under the 'conference_supervisor' group module - if (req.scene_type or SceneType.DEEP_RESEARCH) == SceneType.CONFERENCE: + if req.scene_type == SceneType.CONFERENCE_RESEARCH: prompt_group = "conference_supervisor" else: # Fallback group name; supervisor graph is only used for conference @@ -147,8 +148,10 @@ class ResearchService: def _select_scene_graph(self, request: ResearchRequest) -> CompiledStateGraph: """根据场景类型选择对应的 LangGraph。""" scene_type = request.scene_type or SceneType.DEEP_RESEARCH - if scene_type == SceneType.CONFERENCE: - return conference_graph + if scene_type == SceneType.CONFERENCE_QA: + return conference_qa_graph + elif scene_type == SceneType.CONFERENCE_RESEARCH: + return conference_research_graph elif scene_type == SceneType.DEEP_RESEARCH: if request.parallel_expert_review_enable and request.review_experts: return parallel_deep_research_graph diff --git a/deepinsight/service/schemas/research.py b/deepinsight/service/schemas/research.py index 79e1ce8..0e06bb9 100644 --- a/deepinsight/service/schemas/research.py +++ b/deepinsight/service/schemas/research.py @@ -12,7 +12,8 @@ from deepinsight.config.llm_config import LLMConfig class SceneType(str, Enum): """场景类型枚举,用于选择具体的图实现。""" DEEP_RESEARCH = "deep_research" - CONFERENCE = "conference" + CONFERENCE_RESEARCH = "conference_research" + CONFERENCE_QA = "conference_qa" class ResearchArgs(BaseModel): -- Gitee From 9759a62f74f32344cc9c72952eeb54372f85cae8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B7=A9=E6=97=AD=E7=BA=A2?= <2250244225@qq.com> Date: Fri, 21 Nov 2025 18:10:15 +0800 Subject: [PATCH 3/7] =?UTF-8?q?=E7=94=BB=E5=9B=BE=E5=B7=A5=E5=85=B7?= =?UTF-8?q?=E9=80=9A=E8=BF=87=E9=85=8D=E7=BD=AE=E6=94=AF=E6=8C=81=E7=9B=B8?= =?UTF-8?q?=E5=AF=B9=E8=B7=AF=E5=BE=84=E5=92=8Capi=E4=B8=A4=E7=A7=8D?= =?UTF-8?q?=E6=96=B9=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 20 ++++++++ config.yaml | 6 ++- deepinsight/config/workspace_config.py | 10 ++++ .../agent/conference_research/supervisor.py | 24 +++++---- deepinsight/core/tools/wordcloud_tool.py | 28 +++++++++-- .../service/streaming/stream_adapter.py | 2 +- integrations/mcps/generate_chart.py | 49 ++++++++++++------- 7 files changed, 105 insertions(+), 34 deletions(-) diff --git a/README.md b/README.md index 5d42a83..a897f15 100644 --- a/README.md +++ b/README.md @@ -53,6 +53,26 @@ poetry run alembic upgrade head 提示:可通过环境变量 `DEEPINSIGHT_CONFIG` 指定配置文件路径(默认 `./config.yaml`)。 +### 图表图片路径配置(image_path_mode & image_base_url) +- 在 `config.yaml` 的 `workspace` 段控制图表图片 URL 的返回策略: + - `image_path_mode`: `relative` 或 `base_url` + - `image_base_url`: 当使用 `base_url` 模式时用于拼接的基础 URL(例如 `http://127.0.0.1:8888/api/v1/deepinsight/charts/image`)。 +- 推荐设置: + - 命令行/离线生成 PDF 与 Markdown:`image_path_mode: relative` + - API/Web 预览:`image_path_mode: base_url` 并设置 `image_base_url` 指向你的服务地址。 +- 返回示例: + - `relative` → `../../charts/.png` + - `base_url` → `http://:/api/v1/deepinsight/charts/image/` +- 配置示例: + ```yaml + workspace: + work_root: ./data + chart_image_dir: charts + image_path_mode: base_url + image_base_url: http://127.0.0.1:8888/api/v1/deepinsight/charts/image + ``` + 若在命令行模式,请将 `image_path_mode` 设为 `relative`,其余保持默认即可。 + ### 方式二:Web方式运行 #### 启动后端服务 diff --git a/config.yaml b/config.yaml index 1f0e0c6..31ed87d 100644 --- a/config.yaml +++ b/config.yaml @@ -22,8 +22,12 @@ workspace: work_root: ./data # 会议洞察报告 PPT 模板路径(支持环境变量展开,如 ${PPT_TEMPLATE_PATH}) conference_ppt_template_path: ./templates/conference_template.pptx - # 图表图片保存目录(相对 work_root) chart_image_dir: charts + # 使用相对路径还是 base_url 模式返回图表图片 URL + # - relative: 直接返回图片相对路径,适合本地命令行,如:/deepinsight/charts/image/chart_123.png + # - base_url: 拼接 base_url,适合api模式,如:http://127.0.0.1:8888/api/v1/deepinsight/charts/image/chart_123.png + image_path_mode: base_url + image_base_url: http://127.0.0.1:8888/api/v1/deepinsight/charts/image # RAG 相关工作路径配置 # 将作为所有 RAG 本地数据的前缀目录,例如: diff --git a/deepinsight/config/workspace_config.py b/deepinsight/config/workspace_config.py index 2113d1e..144de0a 100644 --- a/deepinsight/config/workspace_config.py +++ b/deepinsight/config/workspace_config.py @@ -16,6 +16,16 @@ class WorkspaceConfig(BaseModel): description="Relative image save directory under work_root", ) + image_base_url: str | None = Field( + default=None, + description="Base URL for serving chart images", + ) + + image_path_mode: str = Field( + default="relative", + description="Path mode for image return: relative | base_url", + ) + conference_ppt_template_path: str | None = Field( default=None, description="PPT 模板路径(用于会议洞察报告生成)", diff --git a/deepinsight/core/agent/conference_research/supervisor.py b/deepinsight/core/agent/conference_research/supervisor.py index 87728ea..2961d29 100644 --- a/deepinsight/core/agent/conference_research/supervisor.py +++ b/deepinsight/core/agent/conference_research/supervisor.py @@ -134,7 +134,13 @@ async def question_clarify_node(state: ConferenceState, config: RunnableConfig): ) else: return Command( - goto=result.particapant_members, + goto=[ + ConferenceGraphNodeType.CONFERENCE_OVERVIEW, + ConferenceGraphNodeType.CONFERENCE_SUBMISSION, + ConferenceGraphNodeType.CONFERENCE_KEYNOTE, + ConferenceGraphNodeType.CONFERENCE_TOPIC, + ConferenceGraphNodeType.CONFERENCE_BEST_PAPER, + ], ) @@ -248,8 +254,8 @@ async def insight_summary_node(state: ConferenceState, config: RunnableConfig): ).format() output_file = f"/{str(rc.run_id)}/conference_summary.md" logging.debug( - f"conference_best_papers_summary:{state['conference_best_papers_summary']}, conference_topic:{state.get('conference_topic', '')}") - user_prompt = f"学术会议价值论文列表:{state['conference_best_papers_summary']},会议主题相关信息:{state.get('conference_topic', '')},保存到路径:{output_file} " + f"conference_best_papers_summary:{state.get('conference_best_papers_summary', '')}, conference_topic:{state.get('conference_topic', '')}") + user_prompt = f"学术会议价值论文列表:{state.get('conference_best_papers_summary', '')},会议主题相关信息:{state.get('conference_topic', '')},保存到路径:{output_file} " tools = register_fs_tools(fs_instance) tool_instance = TavilySearch( max_results=2, @@ -295,12 +301,12 @@ async def insight_summary_node(state: ConferenceState, config: RunnableConfig): state['conference_summary'] = fs_instance.read_file(f"{output_dir}/conference_summary.md") full_text = ( - state['conference_overview'] + '\n\n\n' + - state['conference_submission'] + '\n\n\n' + - state['conference_keynotes'] + '\n\n\n' + - state['conference_topic'] + '\n\n\n' + - state['conference_best_papers'] + '\n\n\n' + - state['conference_summary'] + state.get('conference_overview', '') + '\n\n\n' + + state.get('conference_submission', '') + '\n\n\n' + + state.get('conference_keynotes', '') + '\n\n\n' + + state.get('conference_topic', '') + '\n\n\n' + + state.get('conference_best_papers', '') + '\n\n\n' + + state.get('conference_summary', '') ) # 3. 把输出吐到前端; writer = get_stream_writer() diff --git a/deepinsight/core/tools/wordcloud_tool.py b/deepinsight/core/tools/wordcloud_tool.py index 530246a..f70c907 100644 --- a/deepinsight/core/tools/wordcloud_tool.py +++ b/deepinsight/core/tools/wordcloud_tool.py @@ -11,30 +11,50 @@ from deepinsight.config.config import load_config, Config WORK_ROOT: str | None = None CHART_IMAGE_DIR_REL: str | None = None CHART_IMAGE_DIR_ABS: str | None = None +IMAGE_BASE_URL: str | None = None +IMAGE_PATH_MODE: str | None = None def _init_paths_from_config(config_path: str | None): - global WORK_ROOT, CHART_IMAGE_DIR_REL, CHART_IMAGE_DIR_ABS + global WORK_ROOT, CHART_IMAGE_DIR_REL, CHART_IMAGE_DIR_ABS, IMAGE_BASE_URL, IMAGE_PATH_MODE config: Config | None = None - if config_path: + resolved_path = config_path + if resolved_path and os.path.exists(resolved_path): try: - config = load_config(config_path) + config = load_config(resolved_path) except Exception: config = None + else: + fallback = os.path.join(os.getcwd(), "config.yaml") + if os.path.exists(fallback): + try: + config = load_config(fallback) + except Exception: + config = None if config and getattr(config, "workspace", None): WORK_ROOT = config.workspace.work_root or "./data" CHART_IMAGE_DIR_REL = config.workspace.chart_image_dir or "charts" + IMAGE_BASE_URL = ( + config.workspace.image_base_url + or f"http://127.0.0.1:{getattr(config.app, 'port', 8888)}{getattr(config.app, 'api_prefix', '/api/v1')}/deepinsight/charts/image" + ) + IMAGE_PATH_MODE = config.workspace.image_path_mode or "relative" else: WORK_ROOT = "./data" CHART_IMAGE_DIR_REL = "charts" + IMAGE_BASE_URL = None + IMAGE_PATH_MODE = "relative" CHART_IMAGE_DIR_ABS = os.path.abspath(os.path.join(WORK_ROOT, CHART_IMAGE_DIR_REL)) os.makedirs(CHART_IMAGE_DIR_ABS, exist_ok=True) def _rel_tool_path(filename: str) -> str: if WORK_ROOT is None or CHART_IMAGE_DIR_REL is None: - _init_paths_from_config(os.environ.get("DEEPINSIGHT_CONFIG_PATH")) + _init_paths_from_config(None) image_dir_name = CHART_IMAGE_DIR_REL.lstrip("./") if CHART_IMAGE_DIR_REL else "charts" + if (IMAGE_PATH_MODE or "relative").lower() == "base_url" and (IMAGE_BASE_URL or ""): + file_id = os.path.splitext(filename)[0] + return f"{IMAGE_BASE_URL}/{file_id}" return f"../../{image_dir_name}/{filename}" diff --git a/deepinsight/service/streaming/stream_adapter.py b/deepinsight/service/streaming/stream_adapter.py index 024ac58..cbd40b6 100644 --- a/deepinsight/service/streaming/stream_adapter.py +++ b/deepinsight/service/streaming/stream_adapter.py @@ -148,7 +148,7 @@ class StreamEventAdapter: try: parsed = json.loads(message_chunk.content) except Exception as e: - logging.error(f"Failed to parse ToolMessage: {e}, raw={message_chunk.content}") + # logging.error(f"Failed to parse ToolMessage: {e}, raw={message_chunk.content}") parsed = {"raw": message_chunk.content} yield StreamEvent( diff --git a/integrations/mcps/generate_chart.py b/integrations/mcps/generate_chart.py index f0b2148..b4b6331 100644 --- a/integrations/mcps/generate_chart.py +++ b/integrations/mcps/generate_chart.py @@ -15,16 +15,14 @@ from mcp.server.fastmcp import FastMCP WORK_ROOT: str | None = None CHART_IMAGE_DIR_REL: str | None = None CHART_IMAGE_DIR_ABS: str | None = None +IMAGE_BASE_URL: str | None = None +IMAGE_PATH_MODE: str | None = None -def _resolve_config_path_from_args_env() -> str | None: - """优先使用命令行指定的 config.yaml;否则读取环境变量 DEEPINSIGHT_CONFIG;再回退到当前工作目录下的 config.yaml。""" +def _resolve_config_path() -> str | None: + """优先使用命令行指定的 config.yaml;否则回退到当前工作目录下的 config.yaml。""" if len(sys.argv) == 2: return sys.argv[1] - env_path = os.environ.get("DEEPINSIGHT_CONFIG") - if env_path: - return env_path - # fallback to ./config.yaml fallback = os.path.join(os.getcwd(), "config.yaml") return fallback if os.path.exists(fallback) else None @@ -34,20 +32,35 @@ def _init_paths_from_config(config_path: str | None): - workspace.work_root: 基础工作目录(相对工程根,默认 ./data) - workspace.chart_image_dir: 图片保存目录(相对 work_root,默认 charts) """ - global WORK_ROOT, CHART_IMAGE_DIR_REL, CHART_IMAGE_DIR_ABS + global WORK_ROOT, CHART_IMAGE_DIR_REL, CHART_IMAGE_DIR_ABS, IMAGE_BASE_URL, IMAGE_PATH_MODE config: Config | None = None - if config_path: + resolved_path = config_path + if resolved_path and os.path.exists(resolved_path): try: - config = load_config(config_path) + config = load_config(resolved_path) except Exception as e: - logging.warning(f"Failed to load config via deepinsight loader at {config_path}: {e}. Using defaults.") + logging.warning(f"Failed to load config via deepinsight loader at {resolved_path}: {e}. Using defaults.") + else: + fallback = os.path.join(os.getcwd(), "config.yaml") + if os.path.exists(fallback): + try: + config = load_config(fallback) + except Exception as e: + logging.warning(f"Failed to load default config at {fallback}: {e}. Using defaults.") if config and getattr(config, "workspace", None): WORK_ROOT = config.workspace.work_root or "./data" CHART_IMAGE_DIR_REL = config.workspace.chart_image_dir or "charts" + IMAGE_BASE_URL = ( + config.workspace.image_base_url + or f"http://127.0.0.1:{getattr(config.app, 'port', 8888)}{getattr(config.app, 'api_prefix', '/api/v1')}/deepinsight/charts/image" + ) + IMAGE_PATH_MODE = config.workspace.image_path_mode or "relative" else: WORK_ROOT = "./data" CHART_IMAGE_DIR_REL = "charts" + IMAGE_BASE_URL = None + IMAGE_PATH_MODE = "relative" CHART_IMAGE_DIR_ABS = os.path.abspath(os.path.join(WORK_ROOT, CHART_IMAGE_DIR_REL)) os.makedirs(CHART_IMAGE_DIR_ABS, exist_ok=True) @@ -56,14 +69,13 @@ mcp = FastMCP(name="mcp-chart") def _rel_tool_path(filename: str) -> str: - """将文件名转换为工具返回的相对路径格式 '../..//'""" if WORK_ROOT is None or CHART_IMAGE_DIR_REL is None: - # 若未初始化,按默认进行一次初始化 - _init_paths_from_config(os.environ.get("DEEPINSIGHT_CONFIG_PATH")) - # 规范化 work_root 与相对图片目录,去掉开头的 './' + _init_paths_from_config(None) image_dir_name = CHART_IMAGE_DIR_REL.lstrip("./") if CHART_IMAGE_DIR_REL else "charts" - rel = f"{image_dir_name}/{filename}" - return f"../../{rel}" + if (IMAGE_PATH_MODE or "relative").lower() == "base_url" and (IMAGE_BASE_URL or ""): + file_id = os.path.splitext(filename)[0] + return f"{IMAGE_BASE_URL}/{file_id}" + return f"../../{image_dir_name}/{filename}" def save_chart(fig, width=1000, height=600) -> str: @@ -442,10 +454,9 @@ def generate_radar_chart( # 强制以stdio模式启动,无网络通信 if __name__ == "__main__": - # 支持通过命令行参数或环境变量传入 config.yaml 路径 + # 支持通过命令行参数传入 config.yaml 路径;否则默认当前目录 config.yaml # 命令行:python generate_chart.py /path/to/config.yaml - # 环境变量:export DEEPINSIGHT_CONFIG_PATH=/path/to/config.yaml - cfg_path = _resolve_config_path_from_args_env() + cfg_path = _resolve_config_path() _init_paths_from_config(cfg_path) print("Starting chart generator in STDIO mode (no network required)...") mcp.run(transport="stdio") -- Gitee From d2da5f797240b5081838fcd574975d25c0a11722 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B7=A9=E6=97=AD=E7=BA=A2?= <2250244225@qq.com> Date: Sat, 22 Nov 2025 17:36:32 +0800 Subject: [PATCH 4/7] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=8E=A5=E5=8F=A3?= =?UTF-8?q?=E5=8F=82=E6=95=B0=EF=BC=8Cquery=E6=9B=BF=E6=8D=A2=E4=B8=BAmess?= =?UTF-8?q?age=EF=BC=8C=E6=A8=A1=E5=9E=8B=E5=8F=82=E6=95=B0=E4=BF=AE?= =?UTF-8?q?=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- deepinsight/cli/commands/conference.py | 15 +++++- deepinsight/cli/commands/research.py | 14 ++++-- deepinsight/cli/commands/stream.py | 9 +++- deepinsight/config/llm_config.py | 2 +- deepinsight/service/research/research.py | 31 +++++++++--- deepinsight/service/schemas/research.py | 20 +++++--- .../service/streaming/stream_adapter.py | 49 +++++++++++++++++-- deepinsight/utils/llm_utils.py | 49 ++++++++++++++----- 8 files changed, 153 insertions(+), 36 deletions(-) diff --git a/deepinsight/cli/commands/conference.py b/deepinsight/cli/commands/conference.py index beb9cbb..42821ff 100644 --- a/deepinsight/cli/commands/conference.py +++ b/deepinsight/cli/commands/conference.py @@ -28,6 +28,7 @@ from deepinsight.service.schemas.conference import ( from deepinsight.service.research.research import ResearchService from deepinsight.service.schemas.research import ResearchRequest, SceneType, PPTGenerateRequest +from deepinsight.service.schemas.streaming import Message, MessageContent, MessageContentType from deepinsight.cli.commands.stream import run_research_and_save_report_sync, make_report_filename from deepinsight.core.types.graph_config import SearchAPI @@ -196,7 +197,12 @@ Examples: service=research_service, request=ResearchRequest( conversation_id=conv_id, - query=query, + messages=[ + Message( + content=MessageContent(text=query), + content_type=MessageContentType.plain_text, + ) + ], scene_type=SceneType.CONFERENCE_RESEARCH, allow_user_clarification=False, allow_edit_research_brief=False, @@ -270,7 +276,12 @@ Examples: service=research_service, request=ResearchRequest( conversation_id=conv_id, - query=query, + messages=[ + Message( + content=MessageContent(text=query), + content_type=MessageContentType.plain_text, + ) + ], scene_type=SceneType.CONFERENCE_QA, allow_user_clarification=False, allow_edit_research_brief=False, diff --git a/deepinsight/cli/commands/research.py b/deepinsight/cli/commands/research.py index 53834aa..34153c6 100644 --- a/deepinsight/cli/commands/research.py +++ b/deepinsight/cli/commands/research.py @@ -15,6 +15,7 @@ from deepinsight.config.config import load_config from deepinsight.config.config import Config from deepinsight.service.research.research import ResearchService from deepinsight.service.schemas.research import ResearchRequest, SceneType +from deepinsight.service.schemas.streaming import Message, MessageContent, MessageContentType from deepinsight.core.types.graph_config import SearchAPI from deepinsight.cli.commands.stream import ( run_research_and_save_report_sync, @@ -119,7 +120,12 @@ def run_generate_report( def create_one_generate(expert_name): return ResearchRequest( conversation_id=conversation_id, - query=question, + messages=[ + Message( + content=MessageContent(text=question), + content_type=MessageContentType.plain_text, + ) + ], scene_type=SceneType.DEEP_RESEARCH, search_api=search_types, expert_review_enable=False, @@ -161,7 +167,7 @@ def run_generate_report( for each in report_filenames: with open(get_with_md_file_name(each, conversation_id, "research_result"), "r", encoding="utf-8") as f: all_sub_reports.append(f.read()) - models, default_model = init_langchain_models_from_llm_config(insight_service.config.llms) + models, default_model = init_langchain_models_from_llm_config(insight_service.get_default_config()) summary_prompt = ( PromptManager(insight_service.config.prompt_management) .get_prompt(name="summary_prompt", group="summary_experts") @@ -227,7 +233,7 @@ def run_expert_review(question: str, insight_service: ResearchService, conversat with open(real_name, "r", encoding="utf-8") as f: question = f.read() expert_names = choose_expert(require_one=True, expert_type="reviewer", live=live) - models, default_model = init_langchain_models_from_llm_config(insight_service.config.llms) + models, default_model = init_langchain_models_from_llm_config(insight_service.get_default_config()) export_review_subgraph = build_expert_review_graph( [ExpertDef(name=each, prompt_key=each, type="reviewer") for each in expert_names] ) @@ -317,4 +323,4 @@ def run_insight(config: Config, gen_pdf: bool = True, initial_topic: str | None conversation_id=conversation_id, live=live, ) - return 0 \ No newline at end of file + return 0 diff --git a/deepinsight/cli/commands/stream.py b/deepinsight/cli/commands/stream.py index 340602c..438fcc2 100644 --- a/deepinsight/cli/commands/stream.py +++ b/deepinsight/cli/commands/stream.py @@ -36,6 +36,8 @@ from deepinsight.service.schemas.streaming import ( EventType, MessageToolCallContent, MessageContentType, + Message, + MessageContent, ) # ANSI escape helpers @@ -518,7 +520,12 @@ async def _process_request(service: ResearchService, request: ResearchRequest, l live.stop() user_input = await ask_user(prompt_text=prompt_text, mode=stream_event.event, live=live) new_request = deepcopy(request) - new_request.query = user_input + new_request.messages = [ + Message( + content=MessageContent(text=user_input), + content_type=MessageContentType.plain_text, + ) + ] try: await agen.aclose() except Exception: diff --git a/deepinsight/config/llm_config.py b/deepinsight/config/llm_config.py index f41899d..b0ad594 100644 --- a/deepinsight/config/llm_config.py +++ b/deepinsight/config/llm_config.py @@ -22,7 +22,7 @@ class LLMConfig(BaseModel): - setting: 生成参数(LLMSetting,可选) """ - type: str = Field(..., description="LLM provider, e.g., openai, deepseek, anthropic") + type: Optional[str] = Field(None, description="LLM provider, e.g., openai, deepseek, anthropic") model: str = Field(..., description="Model name, e.g., gpt-4") base_url: Optional[str] = Field(None, description="Model API base URL") api_key: Optional[str] = Field(None, description="Model API key") diff --git a/deepinsight/service/research/research.py b/deepinsight/service/research/research.py index 02dc8e0..2f860de 100644 --- a/deepinsight/service/research/research.py +++ b/deepinsight/service/research/research.py @@ -37,7 +37,7 @@ from deepinsight.core.agent.conference_research.supervisor import graph as confe from deepinsight.core.agent.deep_research.supervisor import graph as deep_research_graph from deepinsight.core.agent.deep_research.parallel_supervisor import graph as parallel_deep_research_graph from deepinsight.core.agent.conference_research.ppt_generate import graph as ppt_generate_graph -from deepinsight.service.schemas.research import ResearchRequest, SceneType, PPTGenerateRequest, PdfGenerateRequest +from deepinsight.service.schemas.research import ResearchRequest, SceneType, PPTGenerateRequest, PdfGenerateRequest, ArgOptionsGeneric, LLMConfig from deepinsight.utils.trans_md_to_pdf import save_markdown_as_pdf @@ -69,8 +69,10 @@ class ResearchService: def _build_graph_config(self, req: ResearchRequest) -> dict: """Build a graph_config with request-first precedence, falling back to config.yaml.""" - # Prefer request-provided LLM configs, else use system defaults - model_configs = req.args.llm_options if (getattr(req, "args", None) and getattr(req.args, "llm_options", None)) else self.config.llms + # Prefer request-provided LLM configs, else use system defaults (wrapped) + model_configs = req.args.llm_options if ( + getattr(req, "args", None) and getattr(req.args, "llm_options", None) + ) else self.get_default_config() models, default_model = init_langchain_models_from_llm_config(model_configs) # Read scenario-specific flags and filters (typed access) with request override @@ -167,7 +169,7 @@ class ResearchService: Execute the research chat and yield StreamEvent. Parameters: - - request: ResearchRequest with conversation_id, query and optional args + - request: ResearchRequest with conversation_id, messages and optional args - scene_type: 从请求中读取,选择对应的 graph """ graph_config = self._build_graph_config(request) @@ -180,7 +182,7 @@ class ResearchService: scene_graph = self._select_scene_graph(request) async for event in adapter.run_graph( graph=scene_graph, - query=request.query, + messages=request.messages, graph_config=graph_config, conversation_id=request.conversation_id, ): @@ -200,7 +202,7 @@ class ResearchService: # 选择模型配置:优先使用请求参数中的 llm_options,其次使用全局配置 model_configs = request.args.llm_options if ( getattr(request, "args", None) and getattr(request.args, "llm_options", None) - ) else self.config.llms + ) else self.get_default_config() if len(model_configs) == 0: raise ValueError(f"Provide at least one LLM configuration") models, default_model = init_langchain_models_from_llm_config(model_configs) @@ -248,7 +250,7 @@ class ResearchService: async def pdf_generate(self, request: PdfGenerateRequest): conversation_id = request.conversation_id model_configs = request.args.llm_options if ( - request.args and request.args.llm_options) else self.config.llms + request.args and request.args.llm_options) else self.get_default_config() if len(model_configs) == 0: raise ValueError(f"Provide at least one LLM configuration") models, default_model = init_langchain_models_from_llm_config(llm_config=model_configs) @@ -365,3 +367,18 @@ class ResearchService: f.write(json.dumps(cache_data, ensure_ascii=False, indent=2)) return buffer, file_name + + def get_default_config(self) -> List[ArgOptionsGeneric[LLMConfig]]: + return [ + ArgOptionsGeneric( + type=each.type, + params=LLMConfig( + type=each.type, + model=each.model, + base_url=each.base_url, + api_key=each.api_key, + setting=each.setting, + ), + ) + for each in self.config.llms + ] diff --git a/deepinsight/service/schemas/research.py b/deepinsight/service/schemas/research.py index 0e06bb9..296ebf5 100644 --- a/deepinsight/service/schemas/research.py +++ b/deepinsight/service/schemas/research.py @@ -1,12 +1,20 @@ from __future__ import annotations -from typing import Optional, List +from typing import Optional, List, TypeVar, Generic from enum import Enum from pydantic import BaseModel, Field, ConfigDict from deepinsight.core.types.graph_config import SearchAPI from deepinsight.config.llm_config import LLMConfig +from deepinsight.service.schemas.streaming import Message + + +T = TypeVar("T") + +class ArgOptionsGeneric(BaseModel, Generic[T]): + type: str = Field(..., description="Arg option item type") + params: T = Field(..., description="Arg option item params") class SceneType(str, Enum): @@ -18,9 +26,9 @@ class SceneType(str, Enum): class ResearchArgs(BaseModel): """Optional arguments to customize research.""" - llm_options: Optional[List[LLMConfig]] = Field( - default=None, - description="Override default LLM configs; if absent, use config.yaml", + llm_options: Optional[List[ArgOptionsGeneric[LLMConfig]]] = Field( + default=None, + description="LLM arguments" ) @@ -30,7 +38,7 @@ class ResearchRequest(BaseModel): model_config = ConfigDict(use_enum_values=True) conversation_id: str = Field(..., description="Unique identifier of the conversation/session") - query: str = Field(..., description="User input to start or resume research") + messages: List[Message] = Field(..., description="List of messages in the conversation") scene_type: Optional[SceneType] = Field( None, description="Conversation scene type: research or conference", @@ -65,4 +73,4 @@ class PPTGenerateRequest(BaseModel): class PdfGenerateRequest(BaseModel): conversation_id: str = Field(..., description="Unique identifier of the conversation") - args: Optional[ResearchArgs] = Field(None, description="Additional arguments for the conversation") \ No newline at end of file + args: Optional[ResearchArgs] = Field(None, description="Additional arguments for the conversation") diff --git a/deepinsight/service/streaming/stream_adapter.py b/deepinsight/service/streaming/stream_adapter.py index cbd40b6..93a4acc 100644 --- a/deepinsight/service/streaming/stream_adapter.py +++ b/deepinsight/service/streaming/stream_adapter.py @@ -19,6 +19,8 @@ from deepinsight.service.schemas.streaming import ( MessageContentType as ResponseMessageContentType, MessageToolCallContent, StreamEvent, + Message, + MessageContentType, ) from deepinsight.core.types import ( @@ -57,10 +59,32 @@ class StreamEventAdapter: self.tool_call_stream_block_nodes = set(tool_call_stream_block_nodes or []) self.blocked_tool_names = set(blocked_tool_names or []) + def _convert_messages_to_langchain(self, messages: List[Message]) -> List[Any]: + """Convert List[Message] to List[BaseMessage] for LangChain.""" + langchain_messages = [] + for msg in messages: + if msg.content_type == MessageContentType.plain_text and msg.content.text: + langchain_messages.append(HumanMessage(content=msg.content.text)) + elif msg.content_type == MessageContentType.tool_call and msg.content.tool_calls: + # For tool calls, we might need to create ToolMessage or handle differently + # For now, we'll extract text if available or skip + for tool_call in msg.content.tool_calls: + if tool_call.result: + # If there's a result, create a ToolMessage + tool_content = json.dumps(tool_call.result) if isinstance(tool_call.result, dict) else str(tool_call.result) + langchain_messages.append( + ToolMessage( + content=tool_content, + tool_call_id=tool_call.id or "", + name=tool_call.name or "", + ) + ) + return langchain_messages + async def run_graph( self, graph: CompiledStateGraph, - query: str, + messages: List[Message], graph_config: Optional[RunnableConfig] = None, stream_modes: Optional[List[str]] = None, conversation_id: Optional[str] = None, @@ -69,21 +93,38 @@ class StreamEventAdapter: Parameters - graph: a LangGraph/LangChain graph-like object exposing `astream(...)` - - query: user query string + - messages: list of messages in the conversation - graph_config: configuration dict passed into graph execution - stream_modes: modes requested from graph, e.g. ["messages", "custom", "updates"] """ graph_config = graph_config or {} stream_modes = stream_modes or ["messages", "custom", "updates"] tool_call_accumulator = {} + + # Validate messages + if not messages: + raise ValueError("Messages list cannot be empty") + + # Convert Message to LangChain BaseMessage + langchain_messages = self._convert_messages_to_langchain(messages) + if not langchain_messages: + raise ValueError("No valid messages could be converted from the input messages list") + init_state = { - "messages": [HumanMessage(content=query)], + "messages": langchain_messages, } state: StateSnapshot = graph.get_state(config=graph_config) # Resolve conversation id from function arg first, fallback to graph_config resolved_conversation_id = conversation_id or graph_config.get("conversation_id") + # Extract the last plain text message for resume command if needed + resume_content = "" + for msg in reversed(messages): + if msg.content_type == MessageContentType.plain_text and msg.content.text: + resume_content = msg.content.text + break + # Call the underlying graph's streaming API if not state.interrupts: async for namespace, mode, data in graph.astream( @@ -104,7 +145,7 @@ class StreamEventAdapter: else: async for namespace, mode, data in graph.astream( Command( - resume=query, + resume=resume_content, ), config=graph_config, subgraphs=True, diff --git a/deepinsight/utils/llm_utils.py b/deepinsight/utils/llm_utils.py index b596602..03dd460 100644 --- a/deepinsight/utils/llm_utils.py +++ b/deepinsight/utils/llm_utils.py @@ -10,6 +10,7 @@ from langchain_openai import ChatOpenAI from deepinsight.config.config import Config from deepinsight.config.llm_config import LLMConfig +from deepinsight.service.schemas.research import ArgOptionsGeneric from lightrag.llm.openai import openai_complete_if_cache @@ -42,7 +43,7 @@ def _normalize_settings_kwargs(setting: Any) -> Dict[str, Any]: def init_langchain_models_from_llm_config( - llm_config: List[LLMConfig], + llm_config: List[LLMConfig | ArgOptionsGeneric[LLMConfig]], ) -> Tuple[Dict[str, BaseChatModel], BaseChatModel]: """ 初始化 LangChain 所需的聊天模型集合,并返回默认模型。 @@ -54,16 +55,42 @@ def init_langchain_models_from_llm_config( models: Dict[str, BaseChatModel] = {} default_model: Optional[BaseChatModel] = None + def _extract_fields(item: Any) -> tuple[str, str, Optional[str], Optional[str], Any]: + """ + Extract (provider, model, base_url, api_key, setting) from either LLMConfig + or ArgOptionsGeneric[LLMConfig]-like objects. + """ + # ArgOptionsGeneric + if hasattr(item, "params") and hasattr(item, "type"): + provider = getattr(item, "type") + params = getattr(item, "params") + model = getattr(params, "model", None) + base_url = getattr(params, "base_url", None) + api_key = getattr(params, "api_key", None) + setting = getattr(params, "setting", None) + return provider, model, base_url, api_key, setting + # Plain LLMConfig + provider = getattr(item, "type", None) + model = getattr(item, "model", None) + base_url = getattr(item, "base_url", None) + api_key = getattr(item, "api_key", None) + setting = getattr(item, "setting", None) + return provider, model, base_url, api_key, setting + for each in llm_config: - key = f"{each.type}:{each.model}" - settings_kwargs = _normalize_settings_kwargs(each.setting) + provider, model_name, base_url, api_key, setting = _extract_fields(each) + if not provider or not model_name: + logging.error(f"Invalid LLM item, missing provider/model: {each}") + continue + key = f"{provider}:{model_name}" + settings_kwargs = _normalize_settings_kwargs(setting) settings_kwargs.setdefault("timeout", 300) try: model = init_chat_model( - model_provider=each.type, - model=each.model, - api_key=each.api_key, - base_url=each.base_url, + model_provider=provider, + model=model_name, + api_key=api_key, + base_url=base_url, **settings_kwargs, ) models[key] = model @@ -77,9 +104,9 @@ def init_langchain_models_from_llm_config( f"Cannot directly init model {key} via init_chat_model, falling back to ChatOpenAI. Error: {e}" ) model = ChatOpenAI( - model=each.model, - api_key=each.api_key, - base_url=each.base_url, + model=model_name, + api_key=api_key, + base_url=base_url, **settings_kwargs, ) models[key] = model @@ -191,4 +218,4 @@ def init_lightrag_llm_model_func(cfg: Config) -> Callable[..., Any]: **merged_kwargs, ) - return llm_model_func \ No newline at end of file + return llm_model_func -- Gitee From 6a09f0a7ebdcf7decd05314f5acb55cbb32ffb40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B7=A9=E6=97=AD=E7=BA=A2?= <2250244225@qq.com> Date: Mon, 24 Nov 2025 14:24:29 +0800 Subject: [PATCH 5/7] =?UTF-8?q?=E6=9B=B4=E6=96=B0ppt=E6=A8=A1=E6=9D=BF?= =?UTF-8?q?=E4=BB=A5=E5=8F=8A=E7=9B=B8=E5=85=B3=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../agent/conference_research/ppt_generate.py | 650 +++++++++++++++--- deepinsight/core/tools/file_download.py | 16 +- deepinsight/service/ppt/template_service.py | 447 ++++++++---- templates/conference_template.pptx | Bin 2530035 -> 2621245 bytes 4 files changed, 854 insertions(+), 259 deletions(-) diff --git a/deepinsight/core/agent/conference_research/ppt_generate.py b/deepinsight/core/agent/conference_research/ppt_generate.py index cfb5311..7b3a87a 100644 --- a/deepinsight/core/agent/conference_research/ppt_generate.py +++ b/deepinsight/core/agent/conference_research/ppt_generate.py @@ -5,7 +5,7 @@ import json import logging import os from pathlib import PurePosixPath -from typing import Annotated, Any, Dict, List, Literal, Optional, TypedDict, Union, get_args, get_origin +from typing import Annotated, Any, Dict, List, Literal, Optional, TypedDict, Union, get_args, get_origin, Callable, Type from pydantic import BaseModel, Field from langchain_core.messages import BaseMessage, HumanMessage, AIMessage @@ -106,13 +106,21 @@ class PPTGraphNodeType(str, Enum): SAVE_PPT_JSON = "save_ppt_json" GENERATE_OVERVIEW_PAGE = "generate_overview_page" - GENERATE_SUBMISSION_PAGE = "generate_submission_page" GENERATE_KEYNOTES_PAGE = "generate_keynotes_page" GENERATE_TOPIC_CONTENT_PAGE = "generate_topic_content_page" GENERATE_TOPIC_DETAILS_PAGE = "generate_topic_details_page" GENERATE_BEST_PAPERS_PAGE = "generate_best_papers_page" GENERATE_SUMMARY_PAGE = "generate_summary_page" + GENERATE_TECH_THEME_PAGE = "generate_tech_theme_page" + GENERATE_RESEARCH_HOTSPOT_COLLAB_01_PAGE = "generate_research_hotspot_collab_01_page" + GENERATE_RESEARCH_HOTSPOT_COLLAB_02_PAGE = "generate_research_hotspot_collab_02_page" + GENERATE_COUNTRY_TECH_FEATURE_PAGE = "generate_country_tech_feature_page" + GENERATE_INSTITUTION_TECH_FEATURE_PAGE = "generate_institution_tech_feature_page" + GENERATE_INSTITUTION_TECH_STRENGTH_PAGE = "generate_institution_tech_strength_page" + GENERATE_INSTITUTION_COOPERATION_PAGE = "generate_institution_cooperation_page" + GENERATE_HIGH_POTENTIAL_TECH_TRANSFER_PAGE = "generate_high_potential_tech_transfer_page" + def __str__(self): return self.value @@ -123,13 +131,21 @@ class PPTState(TypedDict): ppt_json: Optional[List[Dict[str, Any]]] sections: Optional[Dict[str, Any]] overview_json: Optional[Any] - submission_json: Optional[List[Any]] keynote_json: Optional[Any] topic_content_json: Optional[Any] topic_details_json: Optional[List[Any]] best_papers_json: Optional[List[Any]] summary_json: Optional[Any] + tech_theme_page_json: Optional[Any] + research_hotspot_collab_01_page_json: Optional[Any] + research_hotspot_collab_02_page_json: Optional[Any] + country_tech_feature_page_json: Optional[Any] + institution_tech_feature_page_json: Optional[Any] + institution_tech_strength_page_json: Optional[Any] + institution_cooperation_page_json: Optional[Any] + high_potential_tech_transfer_page_json: Optional[Any] + # ========== 通用结构 ========== class ImageContent(BaseModel): @@ -153,6 +169,106 @@ class BasePage(BaseModel): # ========== 各类型页面定义 ========== +class TechThemePageContent(BaseModel): + tech_field_png: Optional[ImageContent] = Field(None, description="技术主题分析图") + key_tech_intro: Optional[str] = Field(None, description="技术主题分析介绍,长度100-200,请从原文中的以下内容获取对应信息,并且精简对应内容(事实描述用一句话略写)并保留全部主要信息:1.主题概览、2.趋势分析、3.主题展望,对于每部分内容用段落形式,标题需带有序号且加粗,内容中关键信息用红色标记,换行时不要空行;") + key_tech_summary: Optional[str] = Field(None, description="一段话,技术主题总结与洞察,长度100-200,如果原文中有一句话总结 内容,则直接借鉴原文,但内容要求禁止空泛的总结句,直接、具体地切入主题,如第一句不以“基于”开头,关键内容使用黄色标记,但不要整个字段内容都是黄色的") + +class TechThemePage(BasePage): + type: str = "tech_theme_page" + content: TechThemePageContent + + +# =============== C. 研究热点与跨区域技术合作(01) =============== +class ResearchHotspotCollab01PageContent(BaseModel): + keyword_cloud_png: Optional[ImageContent] = Field(None, description="关键词云图") + keyword_intro: Optional[str] = Field(None, description="关键词与研究热点介绍,长度100-200,请从原文中的以下内容获取对应信息,并且精简对应内容(事实描述用一句话略写)并保留全部主要信息:1. 关键词分布概述、2. 关键词趋势分析、3. 技术领域融合分布概述、4. 技术领域融合分析,对于每部分内容用段落形式,标题需带有序号且加粗,内容中关键信息用红色标记,换行时不要空行") + keyword_couple_analysis_png: Optional[ImageContent] = Field(None, + description="关键词耦合分析图") + keyword_summary: Optional[str] = Field(None, description="一段话,仅对关键词相关内容进行总结,不需要涉及和主题相关内容,长度100字以内,如果原文中有一句话总结 内容,则直接借鉴原文,但内容要求禁止空泛的总结句,直接、具体地切入主题,如第一句不以“基于”开头,;关键内容使用黄色标记,但不要整个字段内容都是黄色的") + +class ResearchHotspotCollab01Page(BasePage): + type: str = "research_hotspot_collab_01_page" + content: ResearchHotspotCollab01PageContent + + +# =============== D. 研究热点与跨区域技术合作(02) =============== +class ResearchHotspotCollab02PageContent(BaseModel): + keyword_topic_csv: Optional[TableContent] = Field(None, description="关键词主题分析表格") + keyword_topic_intro: Optional[str] = Field(None, description="关键词主题分布介绍,长度100-200,请从原文中的以下内容获取对应信息,并且精简对应内容(事实描述用一句话略写)并保留全部主要信息,标题加粗:1.概述、2.技术趋势,对于每部分内容用段落形式,标题需带有序号且加粗,内容中关键信息用红色标记,换行时不要空行") + keyword_topic_summary: Optional[str] = Field(None, description="一段话,关键词主题总结与趋势洞察,如果原文中有一句话总结 内容,则直接借鉴原文,但内容要求禁止空泛的总结句,直接、具体地切入主题,如第一句不以“基于”开头,长度100字左右;关键内容使用黄色标记,但不要整个字段内容都是黄色的") + +class ResearchHotspotCollab02Page(BasePage): + type: str = "research_hotspot_collab_02_page" + content: ResearchHotspotCollab02PageContent + + +# =============== E. 国家/地区技术特征分析 =============== +class CountryTechFeaturePageContent(BaseModel): + country_tech_top_png: Optional[ImageContent] = Field(None, + description="国家/地区技术热度图") + country_tech_strength_csv: Optional[TableContent] = Field(None, + description="国家/地区技术强度表格,通常国家地区众多,因此精简原始数据,每个国家或地区选取占比最高的两条记录,如美国只可以出现两行,中国只可出现两行,例如 国家/地区,技术优势领域,占比\n美国,大数据与机器学习系统,34.2%\n美国,操作系统,14.4%\n中国,大数据与机器学习系统,45.5%\n中国,文件与存储系统,16.2% ...") + country_tech_intro: Optional[str] = Field(None, description="国家/地区技术特征介绍,长度100-200,请从原文中的以下内容获取对应信息,并且精简对应内容(事实描述用一句话略写)并保留全部主要信息,标题加粗:1.概述、2.中国技术特征,对于每部分内容用段落形式,标题需带有序号且加粗,内容中关键信息用红色标记,换行时不要空行;内容要求禁止空泛的总结句,直接、具体地切入主题") + country_tech_summary: Optional[str] = Field(None, description="一段话,国家/地区技术特征总结,如果原文中有一句话总结 内容,则直接借鉴原文,但内容要求禁止空泛的总结句,直接、具体地切入主题,如第一句不以“基于”开头,长度100字左右;关键内容使用黄色标记,但不要整个字段内容都是黄色的") + +class CountryTechFeaturePage(BasePage): + type: str = "country_tech_feature_page" + content: CountryTechFeaturePageContent + + +# =============== F. 机构技术特征分析 =============== +class InstitutionTechFeaturePageContent(BaseModel): + top_institution_png: Optional[ImageContent] = Field(None, + description="领先机构分布图") + institution_tech_feat_intro: Optional[str] = Field(None, description="机构技术特征介绍,长度100-200,请从原文中的以下内容获取对应信息,并且精简对应内容(事实描述用一句话略写)并保留全部主要信息:1.概述、2.机构研究重点、3.产学研分析、4.中国机构概述,对于每部分内容用段落形式,标题需带有序号且加粗,内容中关键信息用红色标记,换行时不要空行;内容要求禁止空泛的总结句,直接、具体地切入主题;涉及到 企业 高校 字样用红色标记") + compony_school_analysis_png: Optional[ImageContent] = Field(None, + description="企业与高校分布分析图") + institution_tech_feat_summary: Optional[str] = Field(None, description="一段话,总结机构技术特征,长度100字左右,如果原文中有一句话总结 内容,则直接借鉴原文,但内容要求禁止空泛的总结句,直接、具体地切入主题,如第一句不以“基于”开头,;关键内容使用黄色标记,但不要整个字段内容都是黄色的") + + +class InstitutionTechFeaturePage(BasePage): + type: str = "institution_tech_feature_page" + content: InstitutionTechFeaturePageContent + + +# =============== G. 机构技术优势分析 =============== +class InstitutionTechStrengthPageContent(BaseModel): + university_tech_strength_csv: Optional[TableContent] = Field(None, + description="高校技术强度表格,通常高校众多,因此精简原始数据,每个高校选取占比最高的一条记录即可,总行数最多不要超过8条") + compony_tech_strength_csv: Optional[TableContent] = Field(None, + description="企业技术强度表格,通常企业众多,因此精简原始数据,每个企业选取占比最高的两条记录即可") + institution_tech_strength_intro: Optional[str] = Field(None, description="机构技术优势介绍,长度100-200,请从原文中的以下内容获取对应信息,并且精简对应内容(事实描述用一句话略写)并保留全部主要信息:1.高校技术优势分析及趋势、2.企业技术优势分析及趋势总结、3.启示,对于每部分内容用段落形式,标题需带有序号且加粗,内容中关键信息用红色标记,换行时不要空行;内容要求禁止空泛的总结句,直接、具体地切入主题") + institution_tech_strength_summary: Optional[str] = Field(None, description="一段话,机构技术优势总结,长度100-200,如果原文中有一句话总结 内容,则直接借鉴原文,但内容要求禁止空泛的总结句,直接、具体地切入主题,如第一句不以“基于”开头,;关键内容使用黄色标记,但不要整个字段内容都是黄色的") + +class InstitutionTechStrengthPage(BasePage): + type: str = "institution_tech_strength_page" + content: InstitutionTechStrengthPageContent + + +# =============== H. 跨机构合作网络分析 =============== +class InstitutionCooperationPageContent(BaseModel): + institution_cooperation_png: Optional[ImageContent] = Field(None, + description="跨机构合作网络图") + institution_cooperation_intro: Optional[str] = Field(None, description="跨机构合作网络介绍,长度100-200,请从原文中的以下内容获取对应信息,并且精简对应内容(事实描述用一句话略写)并保留全部主要信息:1.合作网络概述、2.TOP3合作网络、3.企业合作网络、4.华为合作网络,对于每部分内容用段落形式,标题需带有序号且加粗,内容中关键信息用红色标记,换行时不要空行;内容要求禁止空泛的总结句,直接、具体地切入主题") + institution_cooperation_summary: Optional[str] = Field(None, description="一段话,跨机构合作网络总结与洞察,长度100-200,如果原文中有一句话总结 内容,则直接借鉴原文,但内容要求禁止空泛的总结句,直接、具体地切入主题,如第一句不以“基于”开头,;关键内容使用黄色标记,但不要整个字段内容都是黄色的") + +class InstitutionCooperationPage(BasePage): + type: str = "institution_cooperation_page" + content: InstitutionCooperationPageContent + + +# =============== I. 高潜技术转化分析 =============== +class HighPotentialTechTransferPageContent(BaseModel): + high_potential_csv: Optional[TableContent] = Field(None, + description="高潜技术转化相关数据表格") + high_potential_intro: Optional[str] = Field(None, description="高潜技术转化分析介绍,长度100-200,请从原文中的以下内容获取对应信息,并且精简对应内容(事实描述用一句话略写)并保留全部主要信息:1.概述、2.Top3高潜技术、3.业务启示,对于每部分内容用段落形式,标题需带有序号且加粗,内容中关键信息用红色标记,换行时不要空行;内容要求禁止空泛的总结句,直接、具体地切入主题") + high_potential_summary: Optional[str] = Field(None, description="一段话,高潜技术转化总结与趋势洞察,长度100-200,如果原文中有一句话总结 内容,则直接借鉴原文,但内容要求禁止空泛的总结句,直接、具体地切入主题,如第一句不以“基于”开头,;关键内容使用黄色标记,但不要整个字段内容都是黄色的") + +class HighPotentialTechTransferPage(BasePage): + type: str = "high_potential_tech_transfer_page" + content: HighPotentialTechTransferPageContent + class CoverPageContent(BaseModel): conference_name: Optional[str] = Field(None, description="会议名称") @@ -172,7 +288,7 @@ class ContentPage(BasePage): # --- Conference Overview --- class ConfOverviewPageContent(BaseModel): conf_name: Optional[str] = Field(None, description="会议名称,长度10以内") - conf_info: Optional[str] = Field(None, description="会议基本信息概述,长度200-300,"+CONFERENCE_OVERVIEW_EXAMPLE) + conf_info: Optional[str] = Field(None, description="会议基本信息概述,长度200-300," + CONFERENCE_OVERVIEW_EXAMPLE) organizer_level: Optional[str] = Field(None, description="会议级别,长度128以内") conf_topics: Optional[str] = Field(None, description="会议主题介绍,长度128以内") conf_loc: Optional[str] = Field(None, description="会议地点,长度50以内") @@ -182,7 +298,10 @@ class ConfOverviewPageContent(BaseModel): conf_committee: Optional[str] = Field(None, description="会议委员会,长度80以内") conf_institution: Optional[str] = Field(None, description="会议主要机构,长度80以内") submit_papers: Optional[str] = Field(None, description="会议投稿情况概述,长度80以内") - total_trend: Optional[str] = Field(None, description="会议论文总体趋势分析描述,使用markdown列表写法列出多条,长度300-400"+DEFAULT_LIST_STYLE_DESC) + total_trend: Optional[str] = Field( + None, + description="会议论文总体趋势分析描述,使用markdown列表写法列出多条,长度300-400" + DEFAULT_LIST_STYLE_DESC + ) class ConfOverviewPage(BasePage): @@ -239,7 +358,8 @@ class FirstAuthorPage(BasePage): # --- Coauthor --- class CoauthorPageContent(BaseModel): - coauthor_statistic_csv: Optional[TableContent] = Field(None, description="合作作者统计表格内容") + coauthor_statistic_csv: Optional[TableContent] = Field(None, + description="合作作者统计表格内容") class CoauthorPage(BasePage): @@ -247,26 +367,73 @@ class CoauthorPage(BasePage): content: CoauthorPageContent -# --- Submission Page --- -class SubmissionPageContent(BaseModel): - research_fields: Optional[ResearchFieldsPageContent] = Field(None, description="论文主题领域分布") - country_analysis: Optional[CountryAnalysisPageContent] = Field(None, description="论文投稿国家/地区分布分析") - institution_analysis: Optional[InstitutionAnalysisPageContent] = Field(None, description="论文投稿机构分布分析") - first_author: Optional[FirstAuthorPageContent] = Field(None, description="论文第一作者分析") - coauthor: Optional[CoauthorPageContent] = Field(None, description="论文合作作者分析") - - # --- Keynote Page --- class KeynotePageContent(BaseModel): - keynote_title: Optional[str] = Field(None, description="主旨演讲标题") - speaker: Optional[str] = Field(None, description="主旨演讲者,长度50-100") - keynote_abstract: Optional[str] = Field(None, description="主旨演讲摘要,长度150-300") - keynote_background: Optional[str] = Field(None, description="主旨演讲why,长度150-300,优先从源数据对应的why里面获取") - keynote_objective: Optional[str] = Field(None, description="主旨演讲what,长度150-300,优先从源数据对应的what里面获取") - keynote_method: Optional[str] = Field(None, description="主旨演讲how,长度150-300,优先从源数据对应的how里面获取") - keynote_inspiration: Optional[str] = Field(None, description="主旨演讲对业务启示,长度150-300") - keynote_summary: Optional[str] = Field(None, description="主旨演讲总结,长度128-240") - keynote_picture: Optional[ImageContent] = Field(None, description="演讲嘉宾照片,如果源数据里面有,则必须填写") + keynote_title: Optional[str] = Field( + None, + description="主旨演讲标题,需准确概括演讲核心主题,体现前瞻性和专业性" + ) + + speaker: Optional[str] = Field( + None, + description="""演讲嘉宾信息(长度50-100字)。 +核心要点:突出嘉宾与主题的关联性及权威性; +撰写特点:简洁凝练,聚焦“身份标签+核心成就”,优先选择与主题直接相关的经历; +示例方向:XX大学计算机科学系教授,ACM Fellow,长期深耕人工智能生成式模型领域,主导开发了XX模型。""" + ) + + keynote_abstract: Optional[str] = Field( + None, + description="""主要内容和思想(长度100-200字)。 +核心要点:梳理逻辑框架与核心观点,提炼最具价值的思想主张; +撰写特点:结构化呈现(背景铺垫-核心观点-论据支撑),突出创新性和前瞻性,标注打破传统认知的关键思想; +示例方向:首先分析XX技术的“效率瓶颈”与“伦理争议”,接着提出“XX融合架构”解决方案,最后强调“技术向善”思想。""" + ) + + keynote_background: Optional[str] = Field( + None, + description="""主旨演讲why(为何重要/为何关注,长度100-200字,优先从源数据对应的why获取)。 +核心要点:阐明时代背景、行业痛点或战略意义,回答“为何值得关注”; +撰写特点:结合宏观趋势与实际需求,从行业价值、技术突破等角度切入,用数据/案例增强说服力; +示例方向:全球XX市场年复合增长率达XX%,但面临“落地成本高”痛点,该演讲方案可降低成本XX%,为行业规避风险提供参考。""" + ) + + keynote_objective: Optional[str] = Field( + None, + description="""主旨演讲what(核心是什么/解决什么问题,长度100-200字,优先从源数据对应的what获取)。 +核心要点:明确聚焦的核心问题及提出的核心概念、方案; +撰写特点:精准聚焦,用“问题-答案”逻辑呈现,可对比传统做法与新方式凸显差异; +示例方向:核心问题是“如何在保证XX模型精度的前提下降低算力依赖”,提出“轻量化蒸馏+动态剪枝”策略,实现精度损失 str: return json.dumps(template, indent=2, ensure_ascii=False) +def make_generate_page( + page_content_cls: Type[BaseModel], + page_model_cls: Type[BaseModel], + md_filename: str, + return_key: str, + prompt_name: str = "default", + tools: list = None, +) -> Callable[[object, object], object]: + """ + 生成一个异步 page 生成函数的闭包。 + 参数: + - page_content_cls: Pydantic 模型类,用于生成 response_format(如 TechThemePageContent) + - page_model_cls: 返回的 page wrapper 类(如 TechThemePage) + - md_filename: 在 state['sections'] 中查找的 md 文件名(字符串) + - return_key: 返回字典中的 key 名称(例如 'tech_theme_page_json') + - prompt_name: 使用的 prompt 模板名称(默认 'default') + - tools: 可选的工具列表(默认 [download_file_from_url] 在调用处传入或 None) + + 返回: + - 一个 async 函数 (state: PPTState, config: RunnableConfig) -> dict | None + """ + if tools is None: + tools = [download_file_from_url] + + async def _generate(state: "PPTState", config: "RunnableConfig"): + md_content = state["sections"].get(md_filename, "") + if not md_content: + logging.warning(f"Source markdown {md_filename!r} is empty for {return_key}") + return + + rc = parse_research_config(config) + prompt = rc.prompt_manager.get_prompt( + name=prompt_name, + group=rc.prompt_group + ).format( + response_format=generate_json_template(page_content_cls), + ) + + llm = rc.get_model() + agent = create_agent( + model=llm, + system_prompt=prompt, + tools=tools, + response_format=page_content_cls + ) + + try: + response = await agent.with_retry().ainvoke( + input=dict(messages=[HumanMessage(content=md_content)]) + ) + except Exception as e: + logging.exception(f"Error invoking agent for {return_key}: {e}") + return + + structured_response = response.get("structured_response") + if not structured_response: + logging.warning(f"LLM generated empty structured_response for {return_key}") + return + + # page_model_cls 期望形如 TechThemePage(content=structured_response) + try: + page_obj = page_model_cls(content=structured_response) + except Exception as e: + # 兼容一些 Page 类可能需要额外字段的情况 + logging.exception(f"Failed to construct page model for {return_key}: {e}") + return + + return {return_key: page_obj} + + return _generate + + async def generate_overview_page(state: PPTState, config: RunnableConfig): md_content = state["sections"].get("conference_overview.md", "") if not md_content: @@ -536,60 +895,13 @@ async def generate_overview_page(state: PPTState, config: RunnableConfig): ) - -async def generate_submission_page(state: PPTState, config: RunnableConfig): - md_content = state["sections"].get("conference_submission.md", "") - if not md_content: - logging.warning(f"Submission page is empty") - return - rc = parse_research_config(config) - prompt = rc.prompt_manager.get_prompt("default", rc.prompt_group).format( - response_format=generate_json_template(SubmissionPageContent), - ) - llm = rc.default_model - agent = create_agent( - model=llm, - system_prompt=prompt, - tools=[download_file_from_url], - response_format=ToolStrategy(SubmissionPageContent) - ) - response = await agent.with_retry().ainvoke( - input=dict( - messages=[HumanMessage(content=state["sections"].get("conference_submission.md", ""))] - ) - ) - structured_response: Optional[SubmissionPageContent] = response.get("structured_response") - if not structured_response: - logging.warning(f"LLM generate submission response is empty") - return - return dict( - submission_json=[ - ResearchFieldsPage( - content=structured_response.research_fields - ), - CountryAnalysisPage( - content=structured_response.country_analysis - ), - InstitutionAnalysisPage( - content=structured_response.institution_analysis - ), - FirstAuthorPage( - content=structured_response.first_author - ), - CoauthorPage( - content=structured_response.coauthor - ), - ] - ) - - async def generate_keynotes_page(state: PPTState, config: RunnableConfig): md_content = state["sections"].get("conference_keynotes.md", "") if not md_content: logging.warning(f"Keynote page is empty") return rc = parse_research_config(config) - prompt = rc.prompt_manager.get_prompt("default", rc.prompt_group).format( + prompt = rc.prompt_manager.get_prompt("keynote", rc.prompt_group).format( response_format=generate_json_template(KeynotePageContentList), ) llm = rc.default_model @@ -655,7 +967,7 @@ async def generate_topic_details_page(state: PPTState, config: RunnableConfig): logging.warning(f"Topic details page is empty") return rc = parse_research_config(config) - prompt = rc.prompt_manager.get_prompt("default", rc.prompt_group).format( + prompt = rc.prompt_manager.get_prompt("topic_detail", rc.prompt_group).format( response_format=generate_json_template(TopicDetailPageContentList), ) llm = rc.default_model @@ -758,9 +1070,10 @@ async def generate_summary_page(state: PPTState, config: RunnableConfig): async def assemble_ppt_json(state: PPTState, config: RunnableConfig): - if state["ppt_json"] is not None: + if state.get("ppt_json") is not None: return state - # 先 cover_page + + # ------------------ cover page ------------------ cover = { "type": "cover_page", "content": { @@ -779,37 +1092,59 @@ async def assemble_ppt_json(state: PPTState, config: RunnableConfig): cover["content"]["date"] = formatted_date pages: List[Dict[str, Any]] = [] pages.append(cover) - # skip_fill page + + # ------------------ skip_fill page ------------------ pages.append({"type": "content_page", "skip_fill": True}) - # 接着 overview页面 - if state.get("overview_json") is not None: - pages.append(state["overview_json"].model_dump(by_alias=True)) - # submission / total analysis - if state.get("submission_json") is not None: - for each in state["submission_json"]: - pages.append(each.model_dump(by_alias=True)) - # keynotes + + # ------------------ overview page ------------------ + if ov is not None: + pages.append(ov.model_dump(by_alias=True)) + + + # ------------------ 新增 8 个页面 ------------------ + new_pages_keys = [ + "tech_theme_page_json", + "research_hotspot_collab_01_page_json", + "research_hotspot_collab_02_page_json", + "country_tech_feature_page_json", + "institution_tech_feature_page_json", + "institution_tech_strength_page_json", + "institution_cooperation_page_json", + "high_potential_tech_transfer_page_json", + ] + + for key in new_pages_keys: + page_obj = state.get(key) + if page_obj is not None: + pages.append(page_obj.model_dump(by_alias=True)) + + # ------------------ keynotes ------------------ if state.get("keynote_json") is not None: for each in state["keynote_json"]: pages.append(each.model_dump(by_alias=True)) - # topic content + + # ------------------ topic content ------------------ if state.get("topic_content_json") is not None: pages.append(state["topic_content_json"].model_dump(by_alias=True)) - # topic details + + # ------------------ topic details ------------------ for t in state.get("topic_details_json", []): pages.append(t.model_dump(by_alias=True)) - # best papers + + # ------------------ best papers ------------------ for bp in state.get("best_papers_json", []): pages.append(bp.model_dump(by_alias=True)) - # summary page + + # ------------------ summary page ------------------ if state.get("summary_json") is not None: pages.append(state["summary_json"].model_dump(by_alias=True)) - # 将图片路径进行归一化,保证 PPT 模板服务可直接读取 - rc = parse_research_config(config) - _normalize_image_paths_in_pages(pages, rc) + # ------------------ 保存 ppt_json ------------------ state["ppt_json"] = pages + # 将图片路径进行归一化,保证 PPT 模板服务可直接读取 + rc = parse_research_config(config) + _normalize_image_paths_in_pages(pages, rc) time_for_filename = now.strftime("%Y%m%d%H%M%S") current_thread_work_root = os.path.join(rc.work_root, "conference_report_result", rc.thread_id) @@ -839,7 +1174,6 @@ builder = StateGraph(PPTState) builder.add_node(PPTGraphNodeType.CHECK_EXISTING_PPT, check_existing_ppt) builder.add_node(PPTGraphNodeType.LOAD_CONFERENCE_SECTIONS, load_conference_sections) builder.add_node(PPTGraphNodeType.GENERATE_OVERVIEW_PAGE, generate_overview_page) -builder.add_node(PPTGraphNodeType.GENERATE_SUBMISSION_PAGE, generate_submission_page) builder.add_node(PPTGraphNodeType.GENERATE_KEYNOTES_PAGE, generate_keynotes_page) builder.add_node(PPTGraphNodeType.GENERATE_TOPIC_CONTENT_PAGE, generate_topic_content_page) builder.add_node(PPTGraphNodeType.GENERATE_TOPIC_DETAILS_PAGE, generate_topic_details_page) @@ -847,6 +1181,86 @@ builder.add_node(PPTGraphNodeType.GENERATE_BEST_PAPERS_PAGE, generate_best_paper builder.add_node(PPTGraphNodeType.GENERATE_SUMMARY_PAGE, generate_summary_page) builder.add_node(PPTGraphNodeType.ASSEMBLE_PPT_JSON, assemble_ppt_json) builder.add_node(PPTGraphNodeType.SAVE_PPT_JSON, save_ppt_json) +builder.add_node( + PPTGraphNodeType.GENERATE_TECH_THEME_PAGE, + make_generate_page( + TechThemePageContent, + TechThemePage, + md_filename="tech_topics.md", + return_key="tech_theme_page_json" + ) +) + +builder.add_node( + PPTGraphNodeType.GENERATE_RESEARCH_HOTSPOT_COLLAB_01_PAGE, + make_generate_page( + ResearchHotspotCollab01PageContent, + ResearchHotspotCollab01Page, + md_filename="research_hotspots.md", + return_key="research_hotspot_collab_01_page_json" + ) +) + +builder.add_node( + PPTGraphNodeType.GENERATE_RESEARCH_HOTSPOT_COLLAB_02_PAGE, + make_generate_page( + ResearchHotspotCollab02PageContent, + ResearchHotspotCollab02Page, + md_filename="research_hotspots.md", + return_key="research_hotspot_collab_02_page_json" + ) +) + +builder.add_node( + PPTGraphNodeType.GENERATE_COUNTRY_TECH_FEATURE_PAGE, + make_generate_page( + CountryTechFeaturePageContent, + CountryTechFeaturePage, + md_filename="national_tech_profile.md", + return_key="country_tech_feature_page_json" + ) +) + +builder.add_node( + PPTGraphNodeType.GENERATE_INSTITUTION_TECH_FEATURE_PAGE, + make_generate_page( + InstitutionTechFeaturePageContent, + InstitutionTechFeaturePage, + md_filename="institution_overview.md", + return_key="institution_tech_feature_page_json" + ) +) + +builder.add_node( + PPTGraphNodeType.GENERATE_INSTITUTION_TECH_STRENGTH_PAGE, + make_generate_page( + InstitutionTechStrengthPageContent, + InstitutionTechStrengthPage, + md_filename="institution_overview.md", + return_key="institution_tech_strength_page_json" + ) +) + +builder.add_node( + PPTGraphNodeType.GENERATE_INSTITUTION_COOPERATION_PAGE, + make_generate_page( + InstitutionCooperationPageContent, + InstitutionCooperationPage, + md_filename="inter_institution_collab.md", + return_key="institution_cooperation_page_json" + ) +) + +builder.add_node( + PPTGraphNodeType.GENERATE_HIGH_POTENTIAL_TECH_TRANSFER_PAGE, + make_generate_page( + HighPotentialTechTransferPageContent, + HighPotentialTechTransferPage, + md_filename="high_potential_tech_transfer.md", + return_key="high_potential_tech_transfer_page_json" + ) +) + # 添加边 builder.set_entry_point(PPTGraphNodeType.CHECK_EXISTING_PPT) @@ -862,20 +1276,36 @@ def after_check_exsiting_ppt(state: PPTState, config: RunnableConfig): builder.add_conditional_edges(PPTGraphNodeType.CHECK_EXISTING_PPT, after_check_exsiting_ppt) builder.add_edge(PPTGraphNodeType.LOAD_CONFERENCE_SECTIONS, PPTGraphNodeType.GENERATE_OVERVIEW_PAGE) -builder.add_edge(PPTGraphNodeType.LOAD_CONFERENCE_SECTIONS, PPTGraphNodeType.GENERATE_SUBMISSION_PAGE) builder.add_edge(PPTGraphNodeType.LOAD_CONFERENCE_SECTIONS, PPTGraphNodeType.GENERATE_KEYNOTES_PAGE) builder.add_edge(PPTGraphNodeType.LOAD_CONFERENCE_SECTIONS, PPTGraphNodeType.GENERATE_TOPIC_CONTENT_PAGE) builder.add_edge(PPTGraphNodeType.LOAD_CONFERENCE_SECTIONS, PPTGraphNodeType.GENERATE_TOPIC_DETAILS_PAGE) builder.add_edge(PPTGraphNodeType.LOAD_CONFERENCE_SECTIONS, PPTGraphNodeType.GENERATE_BEST_PAPERS_PAGE) builder.add_edge(PPTGraphNodeType.LOAD_CONFERENCE_SECTIONS, PPTGraphNodeType.GENERATE_SUMMARY_PAGE) +builder.add_edge(PPTGraphNodeType.LOAD_CONFERENCE_SECTIONS, PPTGraphNodeType.GENERATE_TECH_THEME_PAGE) +builder.add_edge(PPTGraphNodeType.LOAD_CONFERENCE_SECTIONS, PPTGraphNodeType.GENERATE_RESEARCH_HOTSPOT_COLLAB_01_PAGE) +builder.add_edge(PPTGraphNodeType.LOAD_CONFERENCE_SECTIONS, PPTGraphNodeType.GENERATE_RESEARCH_HOTSPOT_COLLAB_02_PAGE) +builder.add_edge(PPTGraphNodeType.LOAD_CONFERENCE_SECTIONS, PPTGraphNodeType.GENERATE_COUNTRY_TECH_FEATURE_PAGE) +builder.add_edge(PPTGraphNodeType.LOAD_CONFERENCE_SECTIONS, PPTGraphNodeType.GENERATE_INSTITUTION_TECH_FEATURE_PAGE) +builder.add_edge(PPTGraphNodeType.LOAD_CONFERENCE_SECTIONS, PPTGraphNodeType.GENERATE_INSTITUTION_TECH_STRENGTH_PAGE) +builder.add_edge(PPTGraphNodeType.LOAD_CONFERENCE_SECTIONS, PPTGraphNodeType.GENERATE_INSTITUTION_COOPERATION_PAGE) +builder.add_edge(PPTGraphNodeType.LOAD_CONFERENCE_SECTIONS, PPTGraphNodeType.GENERATE_HIGH_POTENTIAL_TECH_TRANSFER_PAGE) + builder.add_edge(PPTGraphNodeType.GENERATE_OVERVIEW_PAGE, PPTGraphNodeType.ASSEMBLE_PPT_JSON) -builder.add_edge(PPTGraphNodeType.GENERATE_SUBMISSION_PAGE, PPTGraphNodeType.ASSEMBLE_PPT_JSON) builder.add_edge(PPTGraphNodeType.GENERATE_KEYNOTES_PAGE, PPTGraphNodeType.ASSEMBLE_PPT_JSON) builder.add_edge(PPTGraphNodeType.GENERATE_TOPIC_CONTENT_PAGE, PPTGraphNodeType.ASSEMBLE_PPT_JSON) builder.add_edge(PPTGraphNodeType.GENERATE_TOPIC_DETAILS_PAGE, PPTGraphNodeType.ASSEMBLE_PPT_JSON) builder.add_edge(PPTGraphNodeType.GENERATE_BEST_PAPERS_PAGE, PPTGraphNodeType.ASSEMBLE_PPT_JSON) builder.add_edge(PPTGraphNodeType.GENERATE_SUMMARY_PAGE, PPTGraphNodeType.ASSEMBLE_PPT_JSON) +builder.add_edge(PPTGraphNodeType.GENERATE_TECH_THEME_PAGE, PPTGraphNodeType.ASSEMBLE_PPT_JSON) +builder.add_edge(PPTGraphNodeType.GENERATE_RESEARCH_HOTSPOT_COLLAB_01_PAGE, PPTGraphNodeType.ASSEMBLE_PPT_JSON) +builder.add_edge(PPTGraphNodeType.GENERATE_RESEARCH_HOTSPOT_COLLAB_02_PAGE, PPTGraphNodeType.ASSEMBLE_PPT_JSON) +builder.add_edge(PPTGraphNodeType.GENERATE_COUNTRY_TECH_FEATURE_PAGE, PPTGraphNodeType.ASSEMBLE_PPT_JSON) +builder.add_edge(PPTGraphNodeType.GENERATE_INSTITUTION_TECH_FEATURE_PAGE, PPTGraphNodeType.ASSEMBLE_PPT_JSON) +builder.add_edge(PPTGraphNodeType.GENERATE_INSTITUTION_TECH_STRENGTH_PAGE, PPTGraphNodeType.ASSEMBLE_PPT_JSON) +builder.add_edge(PPTGraphNodeType.GENERATE_INSTITUTION_COOPERATION_PAGE, PPTGraphNodeType.ASSEMBLE_PPT_JSON) +builder.add_edge(PPTGraphNodeType.GENERATE_HIGH_POTENTIAL_TECH_TRANSFER_PAGE, PPTGraphNodeType.ASSEMBLE_PPT_JSON) + builder.add_edge(PPTGraphNodeType.ASSEMBLE_PPT_JSON, PPTGraphNodeType.SAVE_PPT_JSON) builder.add_edge(PPTGraphNodeType.SAVE_PPT_JSON, END) diff --git a/deepinsight/core/tools/file_download.py b/deepinsight/core/tools/file_download.py index f793972..f6e635b 100644 --- a/deepinsight/core/tools/file_download.py +++ b/deepinsight/core/tools/file_download.py @@ -35,23 +35,11 @@ def _is_http_url(url: str) -> bool: return False -def _looks_like_image_by_ext(url: str) -> bool: - """Heuristic: check common image extensions to avoid unnecessary downloads.""" - try: - ext = os.path.splitext(url.split("?")[0])[1].lower() - return ext in {".png", ".jpg", ".jpeg", ".gif", ".bmp", ".tiff", ".webp"} - except Exception: - return False - - def _is_web_image(url: str) -> bool: """ - Determine whether the given HTTP/HTTPS URL points to an image resource - using extension heuristics only. Does not perform any header requests. + Determine whether the given URL is a valid HTTP/HTTPS URL. """ - if not _is_http_url(url): - return False - return _looks_like_image_by_ext(url) + return _is_http_url(url) @tool("download_file_from_url", return_direct=False) diff --git a/deepinsight/service/ppt/template_service.py b/deepinsight/service/ppt/template_service.py index a448032..32ae17f 100644 --- a/deepinsight/service/ppt/template_service.py +++ b/deepinsight/service/ppt/template_service.py @@ -3,7 +3,7 @@ from __future__ import annotations import io import json import os -from typing import Dict, Any, Tuple +from typing import Dict, Any, Tuple, List from pathlib import Path import json import re @@ -20,21 +20,24 @@ SLIDE_INDEX_MAP = { "cover_page": 0, "content_page": 1, "conf_overview_page": 2, - "research_fields_page": 3, - "country_analysis_page": 4, - "institution_analysis_page": 5, - "first_author_page": 6, - "coauthor_page": 7, - "keynote_page": 8, - "topic_content_page": 9, - "topic_detail_page": 10, - "valuable_paper_page": 11, - "conf_summary_page": 12, + "tech_theme_page": 3, + "research_hotspot_collab_01_page": 4, + "research_hotspot_collab_02_page": 5, + "country_tech_feature_page": 6, + "institution_tech_feature_page": 7, + "institution_tech_strength_page": 8, + "institution_cooperation_page": 9, + "high_potential_tech_transfer_page": 10, + "keynote_page": 11, + "topic_content_page": 12, + "topic_detail_page": 13, + "valuable_paper_page": 14, + "conf_summary_page": 15, } TABLE_DEFAULT_STYLE={ "font_name": "微软雅黑", - "font_size": 11, + "font_size": 8, "bold": False, "color": [0, 0, 0], "align": PP_ALIGN.LEFT, @@ -42,7 +45,7 @@ TABLE_DEFAULT_STYLE={ # 表头样式 "header_font_name": "微软雅黑", - "header_font_size": 13, + "header_font_size": 9, "header_bold": True, "header_color": [0, 0, 0], "header_bg_color": [233, 233, 233], # 蓝色背景 @@ -50,13 +53,24 @@ TABLE_DEFAULT_STYLE={ # 尺寸控制 "row_height": None, - "first_col_width": None + "first_col_width": 1.2 } +topic_table_style = deepcopy(TABLE_DEFAULT_STYLE) +topic_table_style["first_col_width"] = 2 +topic_table_style["font_size"] = 11 +topic_table_style["header_font_size"] = 13 +high_potential_table_stype = deepcopy(TABLE_DEFAULT_STYLE) +high_potential_table_stype["first_col_width"] = 3.5 +institution_tech_table_stype = deepcopy(TABLE_DEFAULT_STYLE) +institution_tech_table_stype["first_col_width"] = 2.5 +hotpots_table_stype = deepcopy(TABLE_DEFAULT_STYLE) +hotpots_table_stype["font_size"] = 10 + STYLE_CONFIG = { "cover_page": { - "conference_name": {"font_size": 44, "bold": True, "color": [192, 0, 0], "align": PP_ALIGN.LEFT}, - "date": {"font_size": 24, "bold": False, "color": [0, 0, 0], "align": PP_ALIGN.LEFT}, + "CONFERENCE_NAME": {"font_size": 44, "bold": True, "color": [192, 0, 0], "align": PP_ALIGN.LEFT}, + "DATE": {"font_size": 24, "bold": False, "color": [0, 0, 0], "align": PP_ALIGN.LEFT}, }, "content_page": {}, "conf_overview_page": { @@ -72,24 +86,67 @@ STYLE_CONFIG = { "submit_papers": {"font_size": 12, "bold": False, "color": [50, 50, 50]}, "total_trend": {"font_size": 12, "bold": False, "color": [0, 0, 0]}, }, - "research_fields_page": { - "research_trend": {"font_size": 12, "bold": False, "color": [0, 0, 0]}, - "research_fields_png": {"width": 5, "height": 4}, + + # === 新增:技术主题分析 === + "tech_theme_page": { + "tech_field_png": {}, + "key_tech_intro": {"font_size": 12, "bold": False, "color": [0, 0, 0]}, + "key_tech_summary": {"font_size": 12, "bold": False, "color": [255, 255, 255]}, }, - "country_analysis_page": { - "country_trend": {"font_size": 12, "bold": False, "color": [0, 0, 0]}, - "country_png": {"width": 5, "height": 4}, + + # === 新增:研究热点与跨区域技术合作 01 === + "research_hotspot_collab_01_page": { + "keyword_cloud_png": {}, + "keyword_intro": {"font_size": 12, "bold": False, "color": [0, 0, 0]}, + "keyword_couple_analysis_png": {}, + "keyword_summary": {"font_size": 12, "bold": False, "color": [255, 255, 255]}, }, - "institution_analysis_page": { - "institution_trend": {"font_size": 12, "bold": False, "color": [0, 0, 0]}, - "institution_png": {"width": 5, "height": 4}, + + # === 新增:研究热点与跨区域技术合作 02 === + "research_hotspot_collab_02_page": { + "keyword_topic_csv": hotpots_table_stype, # 重用已有的表格样式或按需替换 + "keyword_topic_intro": {"font_size": 12, "bold": False, "color": [0, 0, 0]}, + "keyword_topic_summary": {"font_size": 12, "bold": False, "color": [255, 255, 255]}, }, - "first_author_page": { - "first_author_statistic_csv": TABLE_DEFAULT_STYLE + + # === 新增:国家/地区技术特征分析 === + "country_tech_feature_page": { + "country_tech_top_png": {}, + "country_tech_strength_csv": TABLE_DEFAULT_STYLE, + "country_tech_intro": {"font_size": 12, "bold": False, "color": [0, 0, 0]}, + "country_tech_summary": {"font_size": 12, "bold": False, "color": [255, 255, 255]}, }, - "coauthor_page": { - "coauthor_statistic_csv": TABLE_DEFAULT_STYLE + + # === 新增:机构技术特征分析 === + "institution_tech_feature_page": { + "top_institution_png": {}, + "institution_tech_feat_intro": {"font_size": 12, "bold": False, "color": [0, 0, 0]}, + "compony_school_analysis_png": {}, + }, + + # === 新增:机构技术优势分析 === + "institution_tech_strength_page": { + "university_tech_strength_csv": institution_tech_table_stype, + "compony_tech_strength_csv": institution_tech_table_stype, + "institution_tech_strength_intro": {"font_size": 12, "bold": False, "color": [0, 0, 0]}, + "institution_tech_strength_summary": {"font_size": 12, "bold": False, "color": [255, 255, 255]}, }, + + # === 新增:跨机构合作网络分析 === + "institution_cooperation_page": { + "institution_cooperation_png": {}, + "institution_cooperation_intro": {"font_size": 11, "bold": False, "color": [0, 0, 0]}, + "institution_cooperation_summary": {"font_size": 12, "bold": False, "color": [255, 255, 255]}, + }, + + # === 新增:高潜技术转化分析 === + "high_potential_tech_transfer_page": { + "high_potential_csv": high_potential_table_stype, + "high_potential_intro": {"font_size": 11, "bold": False, "color": [0, 0, 0]}, + "high_potential_summary": {"font_size": 12, "bold": False, "color": [255, 255, 255]}, + }, + + # === 后续原有页面(序号顺延) === "keynote_page": { "keynote_title": {"font_size": 28, "bold": True, "color": [153, 0, 0]}, "speaker": {"font_size": 12, "bold": False, "color": [0, 0, 0]}, @@ -99,10 +156,11 @@ STYLE_CONFIG = { "keynote_objective": {"font_size": 12, "bold": False, "color": [0, 0, 0]}, "keynote_method": {"font_size": 12, "bold": False, "color": [0, 0, 0]}, "keynote_inspiration": {"font_size": 12, "bold": False, "color": [0, 0, 0]}, - "keynote_picture": {"width": 3.5, "height": 2.5}, + "keynote_pic1_png": {}, + "keynote_pic2_png": {}, }, "topic_content_page": { - "topic_content_csv": TABLE_DEFAULT_STYLE + "topic_content_csv": topic_table_style }, "topic_detail_page": { "topic_title": {"font_size": 24, "bold": True, "color": [153, 0, 0]}, @@ -113,15 +171,17 @@ STYLE_CONFIG = { "topic_inspiration": {"font_size": 12, "bold": False, "color": [0, 0, 0]}, }, "valuable_paper_page": { - "paper_title": {"font_size": 24, "bold": True, "color": [153, 0, 0]}, + "tech_topic": {"font_size": 11, "bold": True, "color": [255, 255, 255]}, + "paper_title": {"font_size": 9, "bold": False, "color": [0, 0, 0]}, + "paper_headline": {"font_size": 24, "bold": True, "color": [153, 0, 0]}, "paper_background": {"font_size": 12, "bold": False, "color": [0, 0, 0]}, "paper_challenges": {"font_size": 12, "bold": False, "color": [0, 0, 0]}, "paper_tech_resource": {"font_size": 12, "bold": False, "color": [0, 0, 0]}, "paper_key_tech": {"font_size": 12, "bold": False, "color": [0, 0, 0]}, "paper_result": {"font_size": 12, "bold": False, "color": [0, 0, 0]}, "paper_summary": {"font_size": 12, "bold": False, "color": [255, 255, 255]}, - "key_tech_png": {"width_cm": 7.4, "height_cm": 3}, - "exp_result_png": {"width_cm": 7.4, "height_cm": 3}, + "key_tech_png": {}, + "exp_result_png": {}, }, "conf_summary_page": { "key_trends": {"font_size": 12, "bold": False, "color": [0, 0, 0]}, @@ -273,7 +333,6 @@ class PPTTemplateService: height = Inches(conf.get("height")) if conf.get("height") else shape.height width = Cm(conf.get("width_cm")) if conf.get("width_cm") else width height = Cm(conf.get("height_cm")) if conf.get("height_cm") else height - print(image_path) try: slide.shapes.add_picture(image_path, left, top, width=width, height=height) except Exception as e: @@ -282,7 +341,6 @@ class PPTTemplateService: slide.shapes._spTree.remove(shape.element) # 删除模板图占位 - def _add_solid_fill_to_tcPr(self, tcPr, rgb_tuple): """ 在单元格 tcPr 内附加一个 @@ -321,48 +379,42 @@ class PPTTemplateService: left, top = template_shape.left, template_shape.top - # 计算总宽度(EMU),优先使用 conf width(英寸),否则用模板占位的宽(EMU) + # sizes width_in = conf.get("width", None) height_in = conf.get("height", None) total_width = Inches(width_in) if width_in else template_shape.width total_height = Inches(height_in) if height_in else template_shape.height - # 创建表格 table_shape = slide.shapes.add_table(n_rows, n_cols, left, top, total_width, total_height) table = table_shape.table - # 样式配置 + # styles font_name = conf.get("font_name", "Microsoft YaHei") font_size = Pt(conf.get("font_size", 11)) if conf.get("font_size") else Pt(11) bold = conf.get("bold", False) - color = conf.get("color", [0, 0, 0]) + color = conf.get("color", [0,0,0]) align = conf.get("align", PP_ALIGN.CENTER) - # header header_font_name = conf.get("header_font_name", font_name) header_font_size = Pt(conf.get("header_font_size", int(font_size.pt)+1)) if conf.get("header_font_size") else Pt(int(font_size.pt)+1) header_bold = conf.get("header_bold", True) - header_color = conf.get("header_color", [255, 255, 255]) + header_color = conf.get("header_color", [255,255,255]) header_align = conf.get("header_align", PP_ALIGN.CENTER) - header_bg_color = conf.get("header_bg_color", None) # RGB or None - bg_color = conf.get("bg_color", None) # RGB or None + header_bg_color = conf.get("header_bg_color", None) - row_height_in = conf.get("row_height", None) # inches or None - first_col_width_in = conf.get("first_col_width", None) # inches or None + row_height_in = conf.get("row_height", None) # inches + first_col_width_in = conf.get("first_col_width", None) # inches - # === 计算并分配列宽(EMU) === - # 如果只有一列,直接使用总宽 + # distribute column widths (same logic as your last version) if n_cols == 1: try: table.columns[0].width = total_width except Exception: pass else: - # 将 first_col_width(若存在)换算为 EMU if first_col_width_in: first_col_emu = Inches(first_col_width_in) remaining = total_width - first_col_emu - # 防御性:如果 remaining <= 0,则把所有列平均 if remaining <= 0: per_col = total_width // n_cols for j in range(n_cols): @@ -371,12 +423,10 @@ class PPTTemplateService: except Exception: pass else: - # 首列 try: table.columns[0].width = first_col_emu except Exception: pass - # 平均分配剩余给其他列 per_col = remaining // (n_cols - 1) for j in range(1, n_cols): try: @@ -384,7 +434,6 @@ class PPTTemplateService: except Exception: pass else: - # 没有首列宽度,所有列等分 per_col = total_width // n_cols for j in range(n_cols): try: @@ -392,7 +441,7 @@ class PPTTemplateService: except Exception: pass - # === 行高 === + # set row heights if provided if row_height_in: try: for r in table.rows: @@ -400,43 +449,121 @@ class PPTTemplateService: except Exception: pass - # 填充数据并应用样式 + # helper: create paragraphs + runs from markdown-like text + bold_pattern = re.compile(r'\*\*(.+?)\*\*') + + def _fill_cell_with_markdown(cell, text, is_header=False): + """ + text: may contain '\n' for multiple paragraphs, and **bold** markers. + Apply header or normal styles accordingly. + """ + # clear existing text_frame + tf = cell.text_frame + tf.clear() + + lines = text.splitlines() + + for idx, line in enumerate(lines): + if "\\n" in line: + line=line.replace("\\n", "\n") + if idx == 0: + para = tf.paragraphs[0] + para.clear() + else: + para = tf.add_paragraph() + para.clear() + + # alignment + try: + para.alignment = header_align if is_header else align + except Exception: + pass + + last = 0 + any_bold = False + for m in bold_pattern.finditer(line): + any_bold = True + s, e = m.span() + # preceding + if s > last: + seg = line[last:s] + if seg: + run = para.add_run() + run.text = seg + # normal run style + if not is_header: + if font_name: run.font.name = font_name + run.font.size = font_size + run.font.bold = bold + run.font.color.rgb = RGBColor(*color) + else: + if header_font_name: run.font.name = header_font_name + run.font.size = header_font_size + run.font.bold = header_bold + run.font.color.rgb = RGBColor(*header_color) + # bold segment + inner = m.group(1) + run = para.add_run() + run.text = inner + if not is_header: + if font_name: run.font.name = font_name + run.font.size = font_size + run.font.bold = True + run.font.color.rgb = RGBColor(*color) + else: + if header_font_name: run.font.name = header_font_name + run.font.size = header_font_size + run.font.bold = True + run.font.color.rgb = RGBColor(*header_color) + last = e + # trailing + if last < len(line): + trailing = line[last:] + if trailing: + run = para.add_run() + run.text = trailing + if not is_header: + if font_name: run.font.name = font_name + run.font.size = font_size + run.font.bold = bold + run.font.color.rgb = RGBColor(*color) + else: + if header_font_name: run.font.name = header_font_name + run.font.size = header_font_size + run.font.bold = header_bold + run.font.color.rgb = RGBColor(*header_color) + + # if no bold at all and no runs created (unlikely), write whole line + if not any_bold and not para.runs: + run = para.add_run() + run.text = line + if not is_header: + if font_name: run.font.name = font_name + run.font.size = font_size + run.font.bold = bold + run.font.color.rgb = RGBColor(*color) + else: + if header_font_name: run.font.name = header_font_name + run.font.size = header_font_size + run.font.bold = header_bold + run.font.color.rgb = RGBColor(*header_color) + + # populate table for i, row_vals in enumerate(rows): + is_header = (i == 0) for j in range(n_cols): val = row_vals[j] if j < len(row_vals) else "" cell = table.cell(i, j) - # 设置文本 - cell.text = str(val) - - # 应用段落与 run 样式 - for p in cell.text_frame.paragraphs: - p.alignment = header_align if i == 0 else align - # 确保至少有 run(通常有) - if not p.runs: - continue - for run in p.runs: - if i == 0: - # header - if header_font_name: - run.font.name = header_font_name - if header_font_size: - run.font.size = header_font_size - run.font.bold = header_bold - run.font.color.rgb = RGBColor(*header_color) - else: - if font_name: - run.font.name = font_name - if font_size: - run.font.size = font_size - run.font.bold = bold - run.font.color.rgb = RGBColor(*color) + # if val is not string, coerce + cell_text = "" if val is None else str(val) + _fill_cell_with_markdown(cell, cell_text, is_header=is_header) - # 表头背景色(用 OxmlElement 安全添加) - if i == 0 and header_bg_color: + # header background if requested + if is_header and header_bg_color: try: tc = cell._tc tcPr = tc.get_or_add_tcPr() - # 添加 solidFill + # add solidFill solidFill = OxmlElement('a:solidFill') srgbClr = OxmlElement('a:srgbClr') hexval = "%02X%02X%02X" % tuple(header_bg_color) @@ -446,22 +573,7 @@ class PPTTemplateService: except Exception: pass - if i > 0 and bg_color: - try: - tc = cell._tc - tcPr = tc.get_or_add_tcPr() - # 添加 solidFill - solidFill = OxmlElement('a:solidFill') - srgbClr = OxmlElement('a:srgbClr') - hexval = "%02X%02X%02X" % tuple(bg_color) - srgbClr.set('val', hexval) - solidFill.append(srgbClr) - tcPr.append(solidFill) - except Exception: - pass - - - # 最后尽量删除模板占位 shape(best-effort) + # remove template placeholder shape (best-effort) try: slide.shapes._spTree.remove(template_shape.element) except Exception: @@ -472,9 +584,11 @@ class PPTTemplateService: Robust Markdown-lite -> PPT paragraphs renderer. Fixes invisible-char-before-* issue by normalizing lines before detecting bullets. Supports: - - bullet lines starting with '* ', '- ', '+ ' (real bullet via para.level=0) - - inline **bold** anywhere (including inside bullets) - - newline -> new paragraph + ◦ bullet lines starting with '* ', '- ', '+ ' (real bullet via para.level=0) + ◦ inline bold anywhere (including inside bullets) using **bold** + ◦ newline -> new paragraph + ◦ color segments using ... or ... (both accepted) + conf supports: font_name, font_size (pt), bold (default), color [R,G,B], align (PP_ALIGN) """ if not hasattr(shape, "text_frame"): @@ -486,7 +600,7 @@ class PPTTemplateService: font_name = conf.get("font_name", "Microsoft YaHei") font_size = Pt(conf.get("font_size")) if conf.get("font_size") else None default_bold = conf.get("bold", None) - color = conf.get("color", None) + conf_color = conf.get("color", None) align = conf.get("align", None) tf = shape.text_frame @@ -494,11 +608,16 @@ class PPTTemplateService: lines = raw_text.splitlines() - def _create_run(paragraph, txt, make_bold=None): + def _create_run(paragraph, txt, make_bold=None, color_rgb=None): + if not txt: + return None run = paragraph.add_run() run.text = txt if font_name: - run.font.name = font_name + try: + run.font.name = font_name + except Exception: + pass if font_size: run.font.size = font_size # bold precedence: explicit make_bold (True/False) > default_bold if provided @@ -506,16 +625,72 @@ class PPTTemplateService: run.font.bold = make_bold elif default_bold is not None: run.font.bold = default_bold - if color: - run.font.color.rgb = RGBColor(*color) + # color: color_rgb (tuple) overrides conf_color + if color_rgb: + try: + run.font.color.rgb = RGBColor(*color_rgb) + except Exception: + pass + elif conf_color: + try: + run.font.color.rgb = RGBColor(*conf_color) + except Exception: + pass return run + # helper: split a line into segments [(color_rgb_or_None, text), ...] + def _split_color_segments(line): + segments = [] + # opening tag: + open_pat = re.compile(r'', + re.IGNORECASE) + # closing tag can be or (allow spaces and case-insensitive) + close_pat = re.compile(r'(?:|<\s*color\s*/\s*>)', re.IGNORECASE) + pos = 0 + while pos < len(line): + m = open_pat.search(line, pos) + if not m: + remainder = line[pos:] + if remainder: + segments.append((None, remainder)) + break + start, end = m.span() + # text before opening tag + if start > pos: + before = line[pos:start] + if before: + segments.append((None, before)) + # parse rgb + try: + r, g, b = int(m.group(1)), int(m.group(2)), int(m.group(3)) + # clamp 0..255 + r = max(0, min(255, r)); g = max(0, min(255, g)); b = max(0, min(255, b)) + rgb = (r, g, b) + except Exception: + rgb = None + # find closing tag after the opening tag + close_m = close_pat.search(line, end) + if not close_m: + # no close tag: take rest of line + content = line[end:] + segments.append((rgb, content)) + break + else: + cstart, cend = close_m.span() + content = line[end:cstart] + segments.append((rgb, content)) + pos = cend + # continue scanning after close + return segments + first_para = True + bold_pat = re.compile(r'\*\*(.+?)\*\*') + for orig_line in lines: # Normalize leading characters that commonly break ^\s*\* detection: - # remove BOM, zero-width-space, non-breaking space, left/right quotes, and surrounding control chars line = orig_line.lstrip('\ufeff\u200b\u00A0 \t"\'\u201c\u201d\u2018\u2019') - + if not line.strip(): + continue # After stripping control/invisible chars, detect bullet at line start is_bullet = bool(re.match(r'^[\*\-\+]\s+', line)) @@ -526,7 +701,7 @@ class PPTTemplateService: # Get paragraph: first exists by default if first_para: para = tf.paragraphs[0] - para.clear() # remove any default run + para.clear() first_para = False else: para = tf.add_paragraph() @@ -546,31 +721,33 @@ class PPTTemplateService: except Exception: pass - # parse inline bold segments using non-greedy finditer - last_idx = 0 - bold_found = False - for m in re.finditer(r'\*\*(.+?)\*\*', line): - bold_found = True - s, e = m.span() - # text before bold - if s > last_idx: - seg = line[last_idx:s] - if seg: - _create_run(para, seg, make_bold=None) - # bold text - inner = m.group(1) - _create_run(para, inner, make_bold=True) - last_idx = e - # trailing text after last bold - if last_idx < len(line): - trailing = line[last_idx:] - if trailing: - _create_run(para, trailing, make_bold=None) - - # if no bold matches and paragraph has no runs (shouldn't happen because we added runs), - # ensure we add the whole line - if not bold_found and not para.runs: - _create_run(para, line, make_bold=None) + # split into color segments + segments = _split_color_segments(line) + + # For each color segment, further split into bold/non-bold parts and create runs + for seg_color, seg_text in segments: + if not seg_text: + continue + last_idx = 0 + for m in bold_pat.finditer(seg_text): + s, e = m.span() + # text before bold + if s > last_idx: + pre = seg_text[last_idx:s] + if pre: + _create_run(para, pre, make_bold=None, color_rgb=seg_color) + # bold text (inner) + inner = m.group(1) + _create_run(para, inner, make_bold=True, color_rgb=seg_color) + last_idx = e + if last_idx < len(seg_text): + trailing = seg_text[last_idx:] + if trailing: + _create_run(para, trailing, make_bold=None, color_rgb=seg_color) + + # Ensure at least one run exists + if not para.runs: + _create_run(para, line, make_bold=None, color_rgb=None) def delete_slides(self, pres, indices: List[int]): sldIdLst = pres.slides._sldIdLst diff --git a/templates/conference_template.pptx b/templates/conference_template.pptx index 8eb5a3571f914401b20112f077fc1d0b8985ce08..10570498012bdcc23222f4af8fe0a952e4a5821c 100644 GIT binary patch delta 206262 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

he0bjr9;evB}pp8ZX) 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

  • Vsi~PG~{q(WVqG5OY#YFB!GYYc;^5Vzq^80{ebrXQ$jN* zPC6Xexz%^bNkKjzfI})GIfzd9sDFlx55geemKglstnZ&u{X=k+I^KT=)jkYIY2*HP zP>mySlpM}~2UYb9hJs+m{Kujw9)&^93L)NTB0DSCt3g2Y(1q`$=(EPYgAu8K$YA8x zYzS4CkADXv&RCJb$nT~Q;3pGsPJx$H|7<5r(DuNCioyhZ*G)np%zsrlv>o(;Bg&@W zM1XfI|0$82X&B@$i|w!W#RMbvgIvlC9Q)6j_-Aa)EDQ@hgootb=D_&JiExr+=o}|R z=r+>k`k$%z&cg))932y$@Qub(Z~d`wP*5g;o!-fv$aQy!PB;hciPpO8BF%=tI#sQW zyd5tagSIAxwBABmXD>RbiHre0s@ee=BDw&B{5gDRGyArn3cxx7kYSQ<;IKdX-;~Uf zatLrVM!|y&Yy1EoU`zzk0O^$zrIZ2ZOPPfX2|s{Az`22#zuBHu(_I!%05y?_*ZKlv4vHF03%@K^L zKPyUEw5bJ%*7mEB`}h=u=;KEhe_S=+e$HXQ0!*atGIAH|F+dj(`kNe7C#<*Yu*;SM zIHlkQO!4HnnIRCfn@F~<;|*4q0Bk)Pu=SIz0}3FyKKkO7805QkeFv?qK?t9;-V zI-oTdz-oV-FTuTKg%2uZFr9|N{%a3cVO_vh8{|Py>r=GQ0y~aeV8`(zz=Lbq!VBJokAscxFMD@P U*oy>r6nB(qKtI|`oPdV^3lLe_F#rGn delta 111021 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%0AlD_szTT!W#MErK*b_}+vsYiag-2XY5_nQp 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%0AWe09G%$(GtkFQ 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 -- Gitee From 07378fecda3b5252ff22c079c90f5d8a61a5e5db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B7=A9=E6=97=AD=E7=BA=A2?= <2250244225@qq.com> Date: Tue, 25 Nov 2025 10:09:01 +0800 Subject: [PATCH 6/7] =?UTF-8?q?=E5=88=B7=E6=96=B0=E6=9C=80=E6=96=B0?= =?UTF-8?q?=E4=BE=9D=E8=B5=96=EF=BC=8C=E5=A2=9E=E5=8A=A0=E7=BC=BA=E5=B0=91?= =?UTF-8?q?=E7=9A=84=E4=BE=9D=E8=B5=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- poetry.lock | 18 +++++++++++++++++- pyproject.toml | 15 ++++++++------- 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/poetry.lock b/poetry.lock index f8b1e88..fb04d11 100644 --- a/poetry.lock +++ b/poetry.lock @@ -3286,6 +3286,22 @@ files = [ langchain-core = ">=1.0.0,<2.0.0" langchain-openai = ">=1.0.0,<2.0.0" +[[package]] +name = "langchain-experimental" +version = "0.4.0" +description = "Building applications with LLMs through composability" +optional = false +python-versions = "<4.0,>=3.10" +groups = ["main"] +files = [ + {file = "langchain_experimental-0.4.0-py3-none-any.whl", hash = "sha256:50306e75218e3a3f002de3dd879d719addd6481284b1a282292fac46a130f4a1"}, + {file = "langchain_experimental-0.4.0.tar.gz", hash = "sha256:16bb5c9810e1908c0e2d82cd000bb434bb437b8977507e4dbfe5f25800f431fd"}, +] + +[package.dependencies] +langchain-community = ">=0.4.0,<1.0.0" +langchain-core = ">=1.0.0,<2.0.0" + [[package]] name = "langchain-google-genai" version = "2.1.12" @@ -8142,4 +8158,4 @@ sqlite-async = ["aiosqlite"] [metadata] lock-version = "2.1" python-versions = ">=3.11,<3.13" -content-hash = "d11b4565aaf4d89dab71e123839fd8423020ee5f9c4591cc31668c216b8840f4" +content-hash = "731dc6abf0bd030f9824da972e0c268aea8e30e2534c9b2f62f6fe7cf67a81e8" diff --git a/pyproject.toml b/pyproject.toml index 261cd32..682cc94 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -11,10 +11,11 @@ license = { text = "MIT" } # 应用依赖(按用户提供清单) dependencies = [ - "langfuse >=3.0.6", - "langgraph >=0.1", + "langfuse >= 3.0.6", + "langgraph >= 1.0.3", "langmem >= 0.0.20", - "langchain >= 1.0", + "langchain >= 1.0.7", + "langchain-experimental >= 0.4.0", # llm dependency "langchain-openai >= 1.0", @@ -32,9 +33,9 @@ dependencies = [ "langchain-community >= 0.4", "langchain-mcp-adapters >= 0.1", - "SQLAlchemy >=2.0,<3.0", - "alembic >=1.10", - "python-dotenv >=1.0", + "SQLAlchemy >= 2.0, < 3.0", + "alembic >= 1.10", + "python-dotenv >= 1.0", "fastapi >= 0.1", "uvicorn >= 0.10", "tavily-python >= 0.7.13", @@ -46,7 +47,7 @@ dependencies = [ "fastmcp >= 2.0", "arxiv >= 2.0", "kaleido == 0.2.1", - "deepagents >= 0.2", + "deepagents >= 0.2.7", "python-pptx >= 1.0", "plotly >= 6.0", "camel-ai == 0.2.60", -- Gitee From 1b75103e542401f8b72171ec9c9d99802b59de4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B7=A9=E6=97=AD=E7=BA=A2?= <2250244225@qq.com> Date: Tue, 25 Nov 2025 10:27:08 +0800 Subject: [PATCH 7/7] chore: remove comments in pyproject.toml --- pyproject.toml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 682cc94..f5a1bd0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -9,7 +9,7 @@ readme = "README.md" requires-python = ">=3.11,<3.13" license = { text = "MIT" } -# 应用依赖(按用户提供清单) + dependencies = [ "langfuse >= 3.0.6", "langgraph >= 1.0.3", @@ -17,7 +17,7 @@ dependencies = [ "langchain >= 1.0.7", "langchain-experimental >= 0.4.0", - # llm dependency + "langchain-openai >= 1.0", "langchain-deepseek >= 1.0", "langchain-anthropic >= 0.3", @@ -64,7 +64,7 @@ sqlite_async = ["aiosqlite >=0.18"] requires = ["poetry-core>=1.0"] build-backend = "poetry.core.masonry.api" -# Poetry 仍用于打包入口与包收集,保持与项目结构一致 + [tool.poetry] packages = [ { include = "deepinsight" }, -- Gitee