# 工作器系统 **本文档引用的文件** - [backend/app/workers/scheduler.py](file://backend/app/workers/scheduler.py) - [backend/app/workers/citation_engine.py](file://backend/app/workers/citation_engine.py) - [backend/app/workers/platforms/base.py](file://backend/app/workers/platforms/base.py) - [backend/app/workers/platforms/kimi.py](file://backend/app/workers/platforms/kimi.py) - [backend/app/workers/platforms/wenxin.py](file://backend/app/workers/platforms/wenxin.py) - [backend/app/workers/__init__.py](file://backend/app/workers/__init__.py) - [backend/app/models/query.py](file://backend/app/models/query.py) - [backend/app/models/query_task.py](file://backend/app/models/query_task.py) - [backend/app/models/citation_record.py](file://backend/app/models/citation_record.py) - [backend/app/main.py](file://backend/app/main.py) - [backend/app/database.py](file://backend/app/database.py) - [backend/app/config.py](file://backend/app/config.py) - [backend/requirements.txt](file://backend/requirements.txt) - [backend/app/api/queries.py](file://backend/app/api/queries.py) - [backend/app/api/citations.py](file://backend/app/api/citations.py) ## 目录 1. [引言](#引言) 2. [项目结构](#项目结构) 3. [核心组件](#核心组件) 4. [架构总览](#架构总览) 5. [详细组件分析](#详细组件分析) 6. [依赖分析](#依赖分析) 7. [性能考虑](#性能考虑) 8. [故障排查指南](#故障排查指南) 9. [结论](#结论) 10. [附录](#附录) ## 引言 本文件为 GEO 工作器系统的全面架构文档,聚焦以下主题: - APScheduler 任务调度器的配置与使用:调度策略、并发控制与错误恢复 - 工作器抽象基类(BaseWorker)设计:通用接口、生命周期与状态跟踪 - 平台适配器架构:BasePlatformAdapter 抽象、接口规范与扩展机制 - Kimi 平台适配器实现:Playwright 自动化、页面交互与重试策略 - 文心平台适配器设计:API 封装、响应解析与配置管理 - 工作器注册、启动与停止流程 - 性能监控、资源管理与故障诊断 ## 项目结构 后端采用 FastAPI + SQLAlchemy Async + APScheduler 架构,工作器模块位于 backend/app/workers,包含调度器、引用检测引擎与平台适配器;数据库模型位于 backend/app/models,API 路由位于 backend/app/api。 ```mermaid graph TB subgraph "应用层" API["FastAPI 应用
lifespan 启停"] QUERIES["查询 API 路由"] CITATIONS["引用 API 路由"] end subgraph "工作器层" SCHED["调度器 QueryScheduler"] ENGINE["引用检测引擎 CitationEngine"] KIMI["Kimi 适配器"] WENXIN["文心适配器"] end subgraph "数据层" MODELS["SQLAlchemy 模型
Query/QueryTask/CitationRecord"] DB["AsyncSessionLocal"] end API --> SCHED API --> QUERIES API --> CITATIONS SCHED --> ENGINE ENGINE --> KIMI ENGINE --> WENXIN ENGINE --> MODELS SCHED --> MODELS MODELS --> DB ``` 图表来源 - [backend/app/main.py:13-22](file://backend/app/main.py#L13-L22) - [backend/app/workers/scheduler.py:25-40](file://backend/app/workers/scheduler.py#L25-L40) - [backend/app/workers/citation_engine.py:148-158](file://backend/app/workers/citation_engine.py#L148-L158) - [backend/app/models/query.py:11-55](file://backend/app/models/query.py#L11-L55) - [backend/app/models/query_task.py:11-39](file://backend/app/models/query_task.py#L11-L39) - [backend/app/models/citation_record.py:11-42](file://backend/app/models/citation_record.py#L11-L42) - [backend/app/database.py:12-18](file://backend/app/database.py#L12-L18) 章节来源 - [backend/app/main.py:13-22](file://backend/app/main.py#L13-L22) - [backend/app/workers/__init__.py:1-13](file://backend/app/workers/__init__.py#L1-L13) ## 核心组件 - 调度器 QueryScheduler:基于 APScheduler AsyncIOScheduler,每小时扫描并执行到期的查询任务,负责事件循环与异步任务派发。 - 引用检测引擎 CitationEngine:编排平台适配器、品牌匹配、竞争品牌检测与结果持久化,维护 QueryTask 状态与 Query 下次执行时间。 - 平台适配器:BasePlatformAdapter 定义统一接口,KimiAdapter/WenxinAdapter 实现浏览器自动化与响应稳定检测。 - 数据模型:Query(查询)、QueryTask(任务)、CitationRecord(引用记录)三者通过外键关联,配合索引优化查询性能。 章节来源 - [backend/app/workers/scheduler.py:25-95](file://backend/app/workers/scheduler.py#L25-L95) - [backend/app/workers/citation_engine.py:148-309](file://backend/app/workers/citation_engine.py#L148-L309) - [backend/app/workers/platforms/base.py:4-18](file://backend/app/workers/platforms/base.py#L4-L18) - [backend/app/models/query.py:11-55](file://backend/app/models/query.py#L11-L55) - [backend/app/models/query_task.py:11-39](file://backend/app/models/query_task.py#L11-L39) - [backend/app/models/citation_record.py:11-42](file://backend/app/models/citation_record.py#L11-L42) ## 架构总览 系统通过 FastAPI 应用在 lifespan 中启动调度器,调度器周期性扫描数据库中到期的查询,调用 CitationEngine 执行跨平台检索与分析,并将结果写入数据库。平台适配器通过 Playwright 控制 Chromium 浏览器进行页面交互,具备指数退避重试与响应稳定性检测。 ```mermaid sequenceDiagram participant App as "FastAPI 应用" participant Sched as "QueryScheduler" participant Engine as "CitationEngine" participant DB as "数据库" participant Plat as "平台适配器" App->>Sched : "启动调度器" loop 每小时 Sched->>DB : "查询 active 且 next_query_at <= now()" DB-->>Sched : "查询列表" loop 遍历查询 Sched->>Engine : "execute_query(query, db)" Engine->>DB : "创建/更新 QueryTask" Engine->>Plat : "adapter.query(keyword)" Plat-->>Engine : "原始响应文本" Engine->>Engine : "品牌匹配/竞争品牌检测" Engine->>DB : "写入 CitationRecord" Engine->>DB : "更新 Query.next_query_at" end end ``` 图表来源 - [backend/app/main.py:17-21](file://backend/app/main.py#L17-L21) - [backend/app/workers/scheduler.py:30-90](file://backend/app/workers/scheduler.py#L30-L90) - [backend/app/workers/citation_engine.py:159-234](file://backend/app/workers/citation_engine.py#L159-L234) - [backend/app/models/query.py:27-31](file://backend/app/models/query.py#L27-L31) - [backend/app/models/query_task.py:24-32](file://backend/app/models/query_task.py#L24-L32) - [backend/app/models/citation_record.py:24-29](file://backend/app/models/citation_record.py#L24-L29) ## 详细组件分析 ### 调度器(APScheduler)配置与使用 - 调度策略 - 使用 AsyncIOScheduler,作业类型为间隔触发(每小时一次),作业 ID 为“check_queries”,名称为“检查并执行到期的查询任务”。 - 通过 replace_existing=True 确保重复启动时替换旧作业。 - 并发控制 - 同步包装函数 _run_check 在没有运行中事件循环时使用新事件循环执行;否则在当前事件循环创建任务,避免阻塞。 - 每次检查独立创建任务,避免阻塞后续调度。 - 错误恢复 - 单个查询执行失败会记录错误并继续处理下一个查询,不影响整体调度。 - 关闭时优雅停止调度器并关闭引擎资源。 ```mermaid flowchart TD Start(["启动调度器"]) --> AddJob["添加间隔作业
每小时触发"] AddJob --> StartOK["启动成功"] StartOK --> Loop["每小时执行一次"] Loop --> CheckDB["查询到期的 Query"] CheckDB --> ForEach{"是否有待执行查询?"} ForEach --> |是| ExecOne["_execute_single_query()"] ForEach --> |否| Sleep["等待下一小时"] ExecOne --> TryExec["捕获异常并记录"] TryExec --> Next["继续下一个查询"] Sleep --> Loop Next --> Loop ``` 图表来源 - [backend/app/workers/scheduler.py:30-90](file://backend/app/workers/scheduler.py#L30-L90) 章节来源 - [backend/app/workers/scheduler.py:25-95](file://backend/app/workers/scheduler.py#L25-L95) ### 引擎(CitationEngine)设计与流程 - 组件职责 - 维护平台适配器映射(wenxin/kimi) - 品牌匹配器(精确/别名/模糊)与竞争品牌检测 - 任务状态管理(QueryTask)与下次查询时间计算 - 生命周期与状态 - 每个查询对应多个平台任务,逐个执行并更新 QueryTask 状态(pending → running → success/failed) - 成功时写入 CitationRecord,失败时仍写入一条 cited=False 的记录用于占位 - 数据持久化 - 使用 AsyncSessionLocal 进行事务性读写,提交后刷新对象状态 - 平台扩展 - 新增平台只需在 platforms 字典中注册适配器实例,无需修改引擎主流程 ```mermaid classDiagram class CitationEngine { +platforms : dict +matcher : BrandMatcher +competitor_detector : CompetitorDetector +execute_query(query, db) CitationRecord[] +execute_single_platform(keyword, platform, target_brand, aliases) dict +close() void } class BrandMatcher { +target_brand : str +brand_aliases : str[] +match(text) dict } class CompetitorDetector { +KNOWN_BRANDS : dict +detect(text, target_brand) str[] } class KimiAdapter { +platform_name : str +platform_url : str +query(keyword) str +close() void } class WenxinAdapter { +platform_name : str +platform_url : str +query(keyword) str +close() void } CitationEngine --> KimiAdapter : "使用" CitationEngine --> WenxinAdapter : "使用" CitationEngine --> BrandMatcher : "使用" CitationEngine --> CompetitorDetector : "使用" ``` 图表来源 - [backend/app/workers/citation_engine.py:148-309](file://backend/app/workers/citation_engine.py#L148-L309) - [backend/app/workers/platforms/kimi.py:11-206](file://backend/app/workers/platforms/kimi.py#L11-L206) - [backend/app/workers/platforms/wenxin.py:11-205](file://backend/app/workers/platforms/wenxin.py#L11-L205) 章节来源 - [backend/app/workers/citation_engine.py:148-309](file://backend/app/workers/citation_engine.py#L148-L309) ### 平台适配器架构(BasePlatformAdapter) - 接口规范 - 必须实现异步 query(keyword) -> str,返回平台原始响应文本 - 可选实现 close() 清理资源 - 扩展机制 - 新平台继承 BasePlatformAdapter,设置 platform_name 与 platform_url,实现 query 与可选 close - 在 CitationEngine.platforms 中注册实例即可启用 ```mermaid classDiagram class BasePlatformAdapter { <> +platform_name : str +platform_url : str +query(keyword) str* +close() void* } ``` 图表来源 - [backend/app/workers/platforms/base.py:4-18](file://backend/app/workers/platforms/base.py#L4-L18) 章节来源 - [backend/app/workers/platforms/base.py:4-18](file://backend/app/workers/platforms/base.py#L4-L18) ### Kimi 平台适配器实现 - 浏览器自动化 - 使用 Playwright 启动 headless Chromium,设置视口与 UA - 导航至平台首页,动态查找输入框与发送按钮,支持多种选择器与回退策略 - 页面交互逻辑 - 输入关键词后尝试点击发送按钮或按下 Enter 键 - 等待回复稳定:连续多次检测文本不再变化,超时则返回当前文本 - 错误重试策略 - 最多重试 3 次,指数退避(2^attempt 秒延迟) - 超时与异常转换为 RuntimeError 并记录日志 - 资源管理 - 每次查询结束后关闭 page/context,保证资源释放 ```mermaid sequenceDiagram participant Adapter as "KimiAdapter" participant PW as "Playwright" participant Page as "Page" Adapter->>Adapter : "_ensure_browser()" Adapter->>PW : "启动 Chromium" Adapter->>Page : "new_context() + new_page()" Adapter->>Page : "goto(platform_url)" Adapter->>Page : "查找输入框/发送按钮" Adapter->>Page : "fill(keyword) / press Enter / click Send" Adapter->>Adapter : "_wait_for_response_stable()" Adapter-->>Adapter : "返回稳定文本" Adapter->>Page : "close()" Adapter->>PW : "stop()" ``` 图表来源 - [backend/app/workers/platforms/kimi.py:21-125](file://backend/app/workers/platforms/kimi.py#L21-L125) - [backend/app/workers/platforms/kimi.py:126-197](file://backend/app/workers/platforms/kimi.py#L126-L197) 章节来源 - [backend/app/workers/platforms/kimi.py:11-206](file://backend/app/workers/platforms/kimi.py#L11-L206) ### 文心平台适配器设计 - 设计要点 - 结构与 Kimi 类似,使用 Playwright 控制浏览器,支持多选择器定位输入框与发送按钮 - 等待回复稳定算法一致,超时返回当前文本 - 指数退避重试,异常转为 RuntimeError - 配置管理 - 通过 Config 设置 Playwright 浏览器路径等参数,适配容器环境 章节来源 - [backend/app/workers/platforms/wenxin.py:11-205](file://backend/app/workers/platforms/wenxin.py#L11-L205) - [backend/app/config.py:11-13](file://backend/app/config.py#L11-L13) ### 工作器注册、启动与停止流程 - 注册 - 通过 workers/__init__.py 暴露 CitationEngine、KimiAdapter、WenxinAdapter、QueryScheduler、query_scheduler - 启动 - FastAPI lifespan 中调用 query_scheduler.start(),内部注册 APScheduler 作业并启动 - 停止 - 应用退出时调用 query_scheduler.shutdown(),优雅关闭调度器与引擎资源 ```mermaid sequenceDiagram participant Main as "main.py" participant Lifespan as "lifespan" participant Sched as "QueryScheduler" participant Engine as "CitationEngine" Main->>Lifespan : "应用启动" Lifespan->>Sched : "start()" Sched->>Sched : "add_job(check_queries)" Sched->>Engine : "初始化引擎" Main-->>Lifespan : "yield" Lifespan->>Sched : "shutdown()" Sched->>Engine : "close()" ``` 图表来源 - [backend/app/main.py:13-22](file://backend/app/main.py#L13-L22) - [backend/app/workers/scheduler.py:30-90](file://backend/app/workers/scheduler.py#L30-L90) 章节来源 - [backend/app/main.py:13-22](file://backend/app/main.py#L13-L22) - [backend/app/workers/__init__.py:1-13](file://backend/app/workers/__init__.py#L1-L13) ## 依赖分析 - 外部依赖 - Web/ASGI:FastAPI、Uvicorn - ORM/数据库:SQLAlchemy 2.x、asyncpg、Alembic - 任务调度:APScheduler - 浏览器自动化:Playwright - 配置:Pydantic Settings、python-dotenv - 内部模块耦合 - scheduler 依赖 database 与 models,调用 CitationEngine - citation_engine 依赖 platforms 子模块与 models - platforms 依赖 base 抽象类 - main 依赖 scheduler 并在 lifespan 中启停 ```mermaid graph LR REQ["requirements.txt"] --> FAST["FastAPI"] REQ --> SQL["SQLAlchemy/asyncpg/Alembic"] REQ --> APS["APScheduler"] REQ --> PW["Playwright"] REQ --> PYD["Pydantic Settings"] MAIN["main.py"] --> SCHED["scheduler.py"] SCHED --> ENGINE["citation_engine.py"] ENGINE --> KIMI["platforms/kimi.py"] ENGINE --> WENXIN["platforms/wenxin.py"] ENGINE --> MODELS["models/*.py"] SCHED --> MODELS MODELS --> DB["database.py"] ``` 图表来源 - [backend/requirements.txt:1-35](file://backend/requirements.txt#L1-L35) - [backend/app/main.py:10-21](file://backend/app/main.py#L10-L21) - [backend/app/workers/scheduler.py:18-20](file://backend/app/workers/scheduler.py#L18-L20) - [backend/app/workers/citation_engine.py:13-14](file://backend/app/workers/citation_engine.py#L13-L14) - [backend/app/models/query.py:11-55](file://backend/app/models/query.py#L11-L55) - [backend/app/database.py:6-18](file://backend/app/database.py#L6-L18) 章节来源 - [backend/requirements.txt:1-35](file://backend/requirements.txt#L1-L35) ## 性能考虑 - 调度频率与并发 - 每小时一次的调度频率适合周期性任务;如需更频繁,可调整 APScheduler 触发器 - 检查过程为异步批处理,单个查询失败不会阻塞其他查询 - 数据库访问 - 使用 AsyncSessionLocal,开启索引(如 queries.status、queries.next_query_at)提升查询效率 - 引擎在事务内批量写入,减少往返开销 - 浏览器资源 - 每次查询后及时关闭 page/context,避免内存泄漏 - 重试采用指数退避,降低平台限流风险 - 平台扩展 - 新增平台仅需实现 query/close,通过引擎映射注册,不影响现有流程 ## 故障排查指南 - 调度器未启动 - 确认 lifespan 正常执行,检查日志中“查询调度器已启动” - 如无输出,检查 main.py 中 lifespan 注册与 FastAPI 版本兼容性 - 查询未执行 - 检查 Query.status 是否为 active,next_query_at 是否小于等于当前时间 - 确认数据库连接字符串与表结构正确 - 平台适配器异常 - Playwright 未安装:根据日志提示运行安装命令 - 页面选择器失效:平台 UI 变更导致,需更新选择器策略 - 超时与不稳定:适当增加等待时间或放宽稳定性阈值 - 引擎写入失败 - 检查数据库事务提交与异常捕获,确认 CitationRecord 字段完整性 - 资源泄露 - 确认每次查询后 page/context 已关闭,必要时调用 adapter.close() 章节来源 - [backend/app/workers/scheduler.py:42-90](file://backend/app/workers/scheduler.py#L42-L90) - [backend/app/workers/platforms/kimi.py:21-32](file://backend/app/workers/platforms/kimi.py#L21-L32) - [backend/app/workers/platforms/wenxin.py:21-32](file://backend/app/workers/platforms/wenxin.py#L21-L32) - [backend/app/workers/citation_engine.py:209-228](file://backend/app/workers/citation_engine.py#L209-L228) ## 结论 本系统以 APScheduler 为核心调度器,结合 CitationEngine 的平台编排能力与 Playwright 的浏览器自动化,实现了跨平台的引用检测与分析。通过清晰的抽象与模块化设计,系统具备良好的可扩展性与可维护性。建议在生产环境中进一步完善监控指标、日志分级与平台 UI 变更的自适应策略。 ## 附录 - API 路由概览 - 查询管理:GET/POST/PUT/DELETE /api/v1/queries - 引用数据:GET /api/v1/citations 与 GET /api/v1/citations/stats - 立即执行:POST /api/v1/queries/{query_id}/run-now - 数据模型 ER 关系 ```mermaid erDiagram QUERY { uuid id PK uuid user_id FK string keyword string target_brand json brand_aliases json platforms string frequency string status timestamp last_queried_at timestamp next_query_at } QUERY_TASK { uuid id PK uuid query_id FK string platform string status text error_message timestamp scheduled_at timestamp started_at timestamp completed_at } CITATION_RECORD { uuid id PK uuid query_id FK string platform boolean cited int citation_position text citation_text json competitor_brands text raw_response timestamp queried_at } QUERY ||--o{ QUERY_TASK : "包含" QUERY ||--o{ CITATION_RECORD : "包含" ``` 图表来源 - [backend/app/models/query.py:11-55](file://backend/app/models/query.py#L11-L55) - [backend/app/models/query_task.py:11-39](file://backend/app/models/query_task.py#L11-L39) - [backend/app/models/citation_record.py:11-42](file://backend/app/models/citation_record.py#L11-L42)