530 lines
25 KiB
Markdown
530 lines
25 KiB
Markdown
# AI平台集成
|
||
|
||
<cite>
|
||
**本文档引用的文件**
|
||
- [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/platforms/tongyi.py](file://backend/app/workers/platforms/tongyi.py)
|
||
- [backend/app/workers/platforms/doubao.py](file://backend/app/workers/platforms/doubao.py)
|
||
- [backend/app/workers/platforms/qingyan.py](file://backend/app/workers/platforms/qingyan.py)
|
||
- [backend/app/workers/platforms/tiangong.py](file://backend/app/workers/platforms/tiangong.py)
|
||
- [backend/app/workers/platforms/xinghuo.py](file://backend/app/workers/platforms/xinghuo.py)
|
||
- [backend/app/workers/platforms/search_engine.py](file://backend/app/workers/platforms/search_engine.py)
|
||
- [backend/app/workers/citation_engine.py](file://backend/app/workers/citation_engine.py)
|
||
- [backend/app/config.py](file://backend/app/config.py)
|
||
- [backend/app/models/query.py](file://backend/app/models/query.py)
|
||
- [backend/app/models/citation_record.py](file://backend/app/models/citation_record.py)
|
||
- [backend/app/models/query_task.py](file://backend/app/models/query_task.py)
|
||
- [backend/app/workers/scheduler.py](file://backend/app/workers/scheduler.py)
|
||
- [backend/app/api/citations.py](file://backend/app/api/citations.py)
|
||
- [backend/app/services/citation.py](file://backend/app/services/citation.py)
|
||
- [frontend/lib/platforms.ts](file://frontend/lib/platforms.ts)
|
||
- [tests/test_citation_engine.py](file://tests/test_citation_engine.py)
|
||
- [backend/requirements.txt](file://backend/requirements.txt)
|
||
</cite>
|
||
|
||
## 更新摘要
|
||
**变更内容**
|
||
- 新增5个基于搜索引擎的AI平台适配器(通义千问、豆包、智谱清言、天工AI、讯飞星火)
|
||
- 替代原有的Playwright浏览器自动化适配器架构
|
||
- 新增智能搜索引擎模块,提供DuckDuckGo和Wikipedia双回退机制
|
||
- 更新前端平台映射以支持新平台
|
||
- 保持相同的引用检测引擎和调度器架构
|
||
|
||
## 目录
|
||
1. [简介](#简介)
|
||
2. [项目结构](#项目结构)
|
||
3. [核心组件](#核心组件)
|
||
4. [架构总览](#架构总览)
|
||
5. [详细组件分析](#详细组件分析)
|
||
6. [依赖分析](#依赖分析)
|
||
7. [性能考虑](#性能考虑)
|
||
8. [故障排查指南](#故障排查指南)
|
||
9. [结论](#结论)
|
||
10. [附录](#附录)
|
||
|
||
## 简介
|
||
本项目是一个AI平台集成系统,支持通过统一适配器接口对接多个大模型平台(如通义千问、豆包、智谱清言、天工AI、讯飞星火)。系统包含以下能力:
|
||
- 适配器架构:以抽象基类为统一接口,扩展新的AI平台只需实现query方法。
|
||
- 搜索引擎集成:基于DuckDuckGo和Wikipedia的智能搜索引擎,提供稳定的回退机制。
|
||
- 引用检测引擎:对平台返回内容进行品牌匹配、竞争品牌识别与置信度评分,生成引用记录。
|
||
- 定时调度:基于APScheduler的异步调度器,周期性检查并执行到期查询任务。
|
||
- API与服务层:提供查询与统计接口,支持立即执行、导出CSV等功能。
|
||
|
||
## 项目结构
|
||
后端采用分层架构:
|
||
- workers:工作流与平台适配器、引用检测引擎、调度器
|
||
- models:数据库ORM模型(查询、引用记录、任务)
|
||
- services:业务服务(查询统计、触发执行、导出)
|
||
- api:FastAPI路由与对外接口
|
||
- config:应用配置(环境变量读取)
|
||
|
||
```mermaid
|
||
graph TB
|
||
subgraph "前端"
|
||
FE["前端应用<br/>platforms.ts"]
|
||
end
|
||
subgraph "后端"
|
||
API["API 层<br/>citations.py"]
|
||
SVC["服务层<br/>services/citation.py"]
|
||
SCH["调度器<br/>workers/scheduler.py"]
|
||
CE["引用检测引擎<br/>workers/citation_engine.py"]
|
||
AD_T["适配器: 通义千问<br/>workers/platforms/tongyi.py"]
|
||
AD_D["适配器: 豆包<br/>workers/platforms/doubao.py"]
|
||
AD_Q["适配器: 智谱清言<br/>workers/platforms/qingyan.py"]
|
||
AD_G["适配器: 天工AI<br/>workers/platforms/tiangong.py"]
|
||
AD_X["适配器: 讯飞星火<br/>workers/platforms/xinghuo.py"]
|
||
SE["搜索引擎<br/>workers/platforms/search_engine.py"]
|
||
CFG["配置<br/>app/config.py"]
|
||
DB_Q["模型: Query<br/>models/query.py"]
|
||
DB_CR["模型: CitationRecord<br/>models/citation_record.py"]
|
||
DB_QT["模型: QueryTask<br/>models/query_task.py"]
|
||
end
|
||
FE --> API
|
||
API --> SVC
|
||
SVC --> SCH
|
||
SCH --> CE
|
||
CE --> AD_T
|
||
CE --> AD_D
|
||
CE --> AD_Q
|
||
CE --> AD_G
|
||
CE --> AD_X
|
||
AD_T --> SE
|
||
AD_D --> SE
|
||
AD_Q --> SE
|
||
AD_G --> SE
|
||
AD_X --> SE
|
||
CE --> DB_CR
|
||
CE --> DB_QT
|
||
CE --> DB_Q
|
||
SE --> CFG
|
||
```
|
||
|
||
**图表来源**
|
||
- [backend/app/api/citations.py:1-78](file://backend/app/api/citations.py#L1-L78)
|
||
- [backend/app/services/citation.py:1-269](file://backend/app/services/citation.py#L1-L269)
|
||
- [backend/app/workers/scheduler.py:1-95](file://backend/app/workers/scheduler.py#L1-L95)
|
||
- [backend/app/workers/citation_engine.py:1-330](file://backend/app/workers/citation_engine.py#L1-L330)
|
||
- [backend/app/workers/platforms/tongyi.py:1-38](file://backend/app/workers/platforms/tongyi.py#L1-L38)
|
||
- [backend/app/workers/platforms/doubao.py:1-38](file://backend/app/workers/platforms/doubao.py#L1-L38)
|
||
- [backend/app/workers/platforms/qingyan.py:1-38](file://backend/app/workers/platforms/qingyan.py#L1-L38)
|
||
- [backend/app/workers/platforms/tiangong.py:1-38](file://backend/app/workers/platforms/tiangong.py#L1-L38)
|
||
- [backend/app/workers/platforms/xinghuo.py:1-38](file://backend/app/workers/platforms/xinghuo.py#L1-L38)
|
||
- [backend/app/workers/platforms/search_engine.py:1-174](file://backend/app/workers/platforms/search_engine.py#L1-L174)
|
||
- [backend/app/config.py:1-17](file://backend/app/config.py#L1-L17)
|
||
- [backend/app/models/query.py:1-55](file://backend/app/models/query.py#L1-L55)
|
||
- [backend/app/models/citation_record.py:1-42](file://backend/app/models/citation_record.py#L1-L42)
|
||
- [backend/app/models/query_task.py:1-39](file://backend/app/models/query_task.py#L1-L39)
|
||
|
||
**章节来源**
|
||
- [backend/app/api/citations.py:1-78](file://backend/app/api/citations.py#L1-L78)
|
||
- [backend/app/services/citation.py:1-269](file://backend/app/services/citation.py#L1-L269)
|
||
- [backend/app/workers/scheduler.py:1-95](file://backend/app/workers/scheduler.py#L1-L95)
|
||
- [backend/app/workers/citation_engine.py:1-330](file://backend/app/workers/citation_engine.py#L1-L330)
|
||
- [backend/app/workers/platforms/base.py:1-18](file://backend/app/workers/platforms/base.py#L1-L18)
|
||
- [backend/app/workers/platforms/tongyi.py:1-38](file://backend/app/workers/platforms/tongyi.py#L1-L38)
|
||
- [backend/app/workers/platforms/doubao.py:1-38](file://backend/app/workers/platforms/doubao.py#L1-L38)
|
||
- [backend/app/workers/platforms/qingyan.py:1-38](file://backend/app/workers/platforms/qingyan.py#L1-L38)
|
||
- [backend/app/workers/platforms/tiangong.py:1-38](file://backend/app/workers/platforms/tiangong.py#L1-L38)
|
||
- [backend/app/workers/platforms/xinghuo.py:1-38](file://backend/app/workers/platforms/xinghuo.py#L1-L38)
|
||
- [backend/app/workers/platforms/search_engine.py:1-174](file://backend/app/workers/platforms/search_engine.py#L1-L174)
|
||
- [backend/app/config.py:1-17](file://backend/app/config.py#L1-L17)
|
||
- [backend/app/models/query.py:1-55](file://backend/app/models/query.py#L1-L55)
|
||
- [backend/app/models/citation_record.py:1-42](file://backend/app/models/citation_record.py#L1-L42)
|
||
- [backend/app/models/query_task.py:1-39](file://backend/app/models/query_task.py#L1-L39)
|
||
- [frontend/lib/platforms.ts:1-24](file://frontend/lib/platforms.ts#L1-L24)
|
||
|
||
## 核心组件
|
||
- 抽象适配器基类:定义统一的平台名称、URL以及查询接口,便于扩展新平台。
|
||
- 搜索引擎适配器(通义千问/豆包/智谱清言/天工AI/讯飞星火):基于DuckDuckGo和Wikipedia的智能搜索引擎,提供稳定的回退机制。
|
||
- 引用检测引擎:品牌匹配(精确/别名/模糊)、竞争品牌识别、置信度评分与记录生成。
|
||
- 调度器:定时扫描到期查询,调用引擎执行并更新任务状态。
|
||
- API与服务:提供查询列表、统计、立即执行、导出CSV等接口。
|
||
- 数据模型:Query、CitationRecord、QueryTask支撑查询生命周期与结果存储。
|
||
|
||
**章节来源**
|
||
- [backend/app/workers/platforms/base.py:1-18](file://backend/app/workers/platforms/base.py#L1-L18)
|
||
- [backend/app/workers/platforms/tongyi.py:1-38](file://backend/app/workers/platforms/tongyi.py#L1-L38)
|
||
- [backend/app/workers/platforms/doubao.py:1-38](file://backend/app/workers/platforms/doubao.py#L1-L38)
|
||
- [backend/app/workers/platforms/qingyan.py:1-38](file://backend/app/workers/platforms/qingyan.py#L1-L38)
|
||
- [backend/app/workers/platforms/tiangong.py:1-38](file://backend/app/workers/platforms/tiangong.py#L1-L38)
|
||
- [backend/app/workers/platforms/xinghuo.py:1-38](file://backend/app/workers/platforms/xinghuo.py#L1-L38)
|
||
- [backend/app/workers/platforms/search_engine.py:1-174](file://backend/app/workers/platforms/search_engine.py#L1-L174)
|
||
- [backend/app/workers/citation_engine.py:1-330](file://backend/app/workers/citation_engine.py#L1-L330)
|
||
- [backend/app/workers/scheduler.py:1-95](file://backend/app/workers/scheduler.py#L1-L95)
|
||
- [backend/app/api/citations.py:1-78](file://backend/app/api/citations.py#L1-L78)
|
||
- [backend/app/services/citation.py:1-269](file://backend/app/services/citation.py#L1-L269)
|
||
- [backend/app/models/query.py:1-55](file://backend/app/models/query.py#L1-L55)
|
||
- [backend/app/models/citation_record.py:1-42](file://backend/app/models/citation_record.py#L1-L42)
|
||
- [backend/app/models/query_task.py:1-39](file://backend/app/models/query_task.py#L1-L39)
|
||
|
||
## 架构总览
|
||
系统通过"适配器 + 引擎 + 调度器"的解耦方式实现多平台接入与统一处理流程。前端通过API触发查询与查看统计;调度器按频率驱动查询;引擎负责跨平台数据采集与分析;服务层提供数据访问与导出能力。所有平台现在都通过搜索引擎获取内容,提供更稳定的回退机制。
|
||
|
||
```mermaid
|
||
sequenceDiagram
|
||
participant FE as "前端"
|
||
participant API as "API 层"
|
||
participant SVC as "服务层"
|
||
participant SCH as "调度器"
|
||
participant CE as "引用检测引擎"
|
||
participant AD as "平台适配器"
|
||
participant SE as "搜索引擎"
|
||
participant DB as "数据库"
|
||
FE->>API : 触发立即查询
|
||
API->>SVC : trigger_query_now()
|
||
SVC->>DB : 写入 QueryTask(状态 pending)
|
||
Note over SCH,DB : 定时任务扫描 next_query_at<=now 的查询
|
||
SCH->>CE : execute_query(query)
|
||
CE->>AD : query(keyword)
|
||
AD->>SE : fetch_search_content(platform_name, keyword)
|
||
SE-->>AD : 搜索结果文本
|
||
AD-->>CE : 原始响应文本
|
||
CE->>CE : 品牌匹配/竞争品牌识别
|
||
CE->>DB : 写入 CitationRecord
|
||
CE->>DB : 更新 Query.next_query_at
|
||
API-->>FE : 返回任务状态/查询结果
|
||
```
|
||
|
||
**图表来源**
|
||
- [backend/app/api/citations.py:59-78](file://backend/app/api/citations.py#L59-L78)
|
||
- [backend/app/services/citation.py:204-234](file://backend/app/services/citation.py#L204-L234)
|
||
- [backend/app/workers/scheduler.py:51-84](file://backend/app/workers/scheduler.py#L51-L84)
|
||
- [backend/app/workers/citation_engine.py:177-254](file://backend/app/workers/citation_engine.py#L177-L254)
|
||
- [backend/app/workers/platforms/tongyi.py:16-33](file://backend/app/workers/platforms/tongyi.py#L16-L33)
|
||
- [backend/app/workers/platforms/search_engine.py:163-174](file://backend/app/workers/platforms/search_engine.py#L163-L174)
|
||
- [backend/app/models/query.py:29-31](file://backend/app/models/query.py#L29-L31)
|
||
- [backend/app/models/citation_record.py:11-42](file://backend/app/models/citation_record.py#L11-L42)
|
||
- [backend/app/models/query_task.py:11-39](file://backend/app/models/query_task.py#L11-L39)
|
||
|
||
## 详细组件分析
|
||
|
||
### 适配器架构与扩展机制
|
||
- 抽象基类定义
|
||
- 平台标识:platform_name、platform_url
|
||
- 统一接口:query(keyword)返回原始响应文本;可选close()释放资源
|
||
- 扩展步骤
|
||
- 继承BasePlatformAdapter
|
||
- 实现query与可选close
|
||
- 在CitationEngine的platforms映射中注册实例
|
||
- 设计优势
|
||
- 解耦平台差异,统一调用入口
|
||
- 易于新增平台与替换实现
|
||
- 基于搜索引擎的适配器无需复杂的浏览器自动化
|
||
|
||
```mermaid
|
||
classDiagram
|
||
class BasePlatformAdapter {
|
||
+string platform_name
|
||
+string platform_url
|
||
+query(keyword) str
|
||
+close() void
|
||
}
|
||
class TongyiAdapter {
|
||
+platform_name = "tongyi"
|
||
+platform_url = "https : //tongyi.aliyun.com/qianwen"
|
||
+query(keyword) str
|
||
+_do_query(keyword) str
|
||
+close() void
|
||
}
|
||
class DoubaoAdapter {
|
||
+platform_name = "doubao"
|
||
+platform_url = "https : //www.doubao.com/"
|
||
+query(keyword) str
|
||
+_do_query(keyword) str
|
||
+close() void
|
||
}
|
||
class QingyanAdapter {
|
||
+platform_name = "qingyan"
|
||
+platform_url = "https : //chatglm.cn/"
|
||
+query(keyword) str
|
||
+_do_query(keyword) str
|
||
+close() void
|
||
}
|
||
class TiangongAdapter {
|
||
+platform_name = "tiangong"
|
||
+platform_url = "https : //www.tiangong.cn/"
|
||
+query(keyword) str
|
||
+_do_query(keyword) str
|
||
+close() void
|
||
}
|
||
class XinghuoAdapter {
|
||
+platform_name = "xinghuo"
|
||
+platform_url = "https : //xinghuo.xfyun.cn/"
|
||
+query(keyword) str
|
||
+_do_query(keyword) str
|
||
+close() void
|
||
}
|
||
BasePlatformAdapter <|-- TongyiAdapter
|
||
BasePlatformAdapter <|-- DoubaoAdapter
|
||
BasePlatformAdapter <|-- QingyanAdapter
|
||
BasePlatformAdapter <|-- TiangongAdapter
|
||
BasePlatformAdapter <|-- XinghuoAdapter
|
||
```
|
||
|
||
**图表来源**
|
||
- [backend/app/workers/platforms/base.py:4-17](file://backend/app/workers/platforms/base.py#L4-L17)
|
||
- [backend/app/workers/platforms/tongyi.py:10-38](file://backend/app/workers/platforms/tongyi.py#L10-L38)
|
||
- [backend/app/workers/platforms/doubao.py:10-38](file://backend/app/workers/platforms/doubao.py#L10-L38)
|
||
- [backend/app/workers/platforms/qingyan.py:10-38](file://backend/app/workers/platforms/qingyan.py#L10-L38)
|
||
- [backend/app/workers/platforms/tiangong.py:10-38](file://backend/app/workers/platforms/tiangong.py#L10-L38)
|
||
- [backend/app/workers/platforms/xinghuo.py:10-38](file://backend/app/workers/platforms/xinghuo.py#L10-L38)
|
||
|
||
**章节来源**
|
||
- [backend/app/workers/platforms/base.py:1-18](file://backend/app/workers/platforms/base.py#L1-L18)
|
||
- [backend/app/workers/platforms/tongyi.py:1-38](file://backend/app/workers/platforms/tongyi.py#L1-L38)
|
||
- [backend/app/workers/platforms/doubao.py:1-38](file://backend/app/workers/platforms/doubao.py#L1-L38)
|
||
- [backend/app/workers/platforms/qingyan.py:1-38](file://backend/app/workers/platforms/qingyan.py#L1-L38)
|
||
- [backend/app/workers/platforms/tiangong.py:1-38](file://backend/app/workers/platforms/tiangong.py#L1-L38)
|
||
- [backend/app/workers/platforms/xinghuo.py:1-38](file://backend/app/workers/platforms/xinghuo.py#L1-L38)
|
||
|
||
### 搜索引擎适配器实现
|
||
- 搜索引擎模式
|
||
- 所有平台适配器现在都基于fetch_search_content函数
|
||
- 通过DuckDuckGo搜索关键词,自动回退到Wikipedia
|
||
- 提供指数退避重试机制(最多3次尝试)
|
||
- 搜索策略
|
||
- 组合关键词与目标品牌,确保搜索结果包含品牌信息
|
||
- 优先使用DuckDuckGo HTML搜索,自动检测结果有效性
|
||
- 当DuckDuckGo受限时自动回退到Wikipedia API
|
||
- 错误处理
|
||
- 每次尝试失败都会记录警告日志
|
||
- 最终失败时抛出异常,便于上层处理
|
||
- 适配器close方法为空实现,因为无需浏览器资源管理
|
||
|
||
```mermaid
|
||
flowchart TD
|
||
Start(["开始查询"]) --> Combine["组合关键词: keyword + target_brand"]
|
||
Combine --> TryDDG["尝试DuckDuckGo搜索"]
|
||
TryDDG --> Valid{"结果有效?"}
|
||
Valid --> |是| Parse["解析搜索结果"]
|
||
Valid --> |否| Wiki["回退到Wikipedia搜索"]
|
||
Parse --> Return["返回搜索文本"]
|
||
Wiki --> Parse
|
||
Return --> End(["结束"])
|
||
```
|
||
|
||
**图表来源**
|
||
- [backend/app/workers/platforms/tongyi.py:16-33](file://backend/app/workers/platforms/tongyi.py#L16-L33)
|
||
- [backend/app/workers/platforms/search_engine.py:163-174](file://backend/app/workers/platforms/search_engine.py#L163-L174)
|
||
- [backend/app/workers/platforms/search_engine.py:79-144](file://backend/app/workers/platforms/search_engine.py#L79-L144)
|
||
|
||
**章节来源**
|
||
- [backend/app/workers/platforms/tongyi.py:1-38](file://backend/app/workers/platforms/tongyi.py#L1-L38)
|
||
- [backend/app/workers/platforms/doubao.py:1-38](file://backend/app/workers/platforms/doubao.py#L1-L38)
|
||
- [backend/app/workers/platforms/qingyan.py:1-38](file://backend/app/workers/platforms/qingyan.py#L1-L38)
|
||
- [backend/app/workers/platforms/tiangong.py:1-38](file://backend/app/workers/platforms/tiangong.py#L1-L38)
|
||
- [backend/app/workers/platforms/xinghuo.py:1-38](file://backend/app/workers/platforms/xinghuo.py#L1-L38)
|
||
- [backend/app/workers/platforms/search_engine.py:1-174](file://backend/app/workers/platforms/search_engine.py#L1-L174)
|
||
|
||
### 智能搜索引擎模块
|
||
- DuckDuckGo搜索实现
|
||
- 使用HTML版本搜索,无需API密钥
|
||
- 支持多种结果块格式的解析
|
||
- 自动检测非结果页面并回退
|
||
- Wikipedia回退机制
|
||
- 通过Wikipedia API获取词条摘要
|
||
- 自动清理HTML标记和引用格式
|
||
- 提供稳定可靠的备用搜索源
|
||
- 搜索内容提取
|
||
- 统一的HTML清理和文本提取
|
||
- 支持标题和摘要的组合输出
|
||
- 限制最大字符数防止内容过长
|
||
|
||
**章节来源**
|
||
- [backend/app/workers/platforms/search_engine.py:1-174](file://backend/app/workers/platforms/search_engine.py#L1-L174)
|
||
|
||
### 引用检测引擎工作原理
|
||
- 品牌匹配策略
|
||
- 精确匹配:命中目标品牌,置信度1.0
|
||
- 别名匹配:命中别名,置信度0.9
|
||
- 模糊匹配:基于序列相似度阈值,返回最高相似度及置信度
|
||
- 结果包含是否引用、置信度、匹配类型、段落位置、上下文片段
|
||
- 竞争品牌识别
|
||
- 预定义行业品牌集合,从文本中识别除目标品牌外的竞争品牌
|
||
- 置信度评分机制
|
||
- 精确命中1.0,别名0.9,模糊按相似度取值并四舍五入
|
||
- 引擎执行流程
|
||
- 构建BrandMatcher,遍历查询配置的平台
|
||
- 调用适配器获取原始响应,执行匹配与竞争品牌检测
|
||
- 生成CitationRecord并写入数据库,更新Query.next_query_at
|
||
|
||
```mermaid
|
||
flowchart TD
|
||
Q["输入: 关键词/目标品牌/别名"] --> BuildMatcher["构建BrandMatcher"]
|
||
BuildMatcher --> ForEachPlat{"遍历平台"}
|
||
ForEachPlat --> QueryRaw["调用适配器.query()"]
|
||
QueryRaw --> Match["品牌匹配(match)"]
|
||
Match --> Competitor["竞争品牌检测(detect)"]
|
||
Competitor --> Record["生成CitationRecord"]
|
||
Record --> Persist["写入数据库"]
|
||
Persist --> NextTime["更新Query.next_query_at"]
|
||
NextTime --> ForEachPlat
|
||
ForEachPlat --> Done["完成"]
|
||
```
|
||
|
||
**图表来源**
|
||
- [backend/app/workers/citation_engine.py:177-254](file://backend/app/workers/citation_engine.py#L177-L254)
|
||
- [backend/app/workers/citation_engine.py:256-287](file://backend/app/workers/citation_engine.py#L256-L287)
|
||
- [backend/app/models/citation_record.py:11-42](file://backend/app/models/citation_record.py#L11-L42)
|
||
- [backend/app/models/query.py:29-31](file://backend/app/models/query.py#L29-L31)
|
||
|
||
**章节来源**
|
||
- [backend/app/workers/citation_engine.py:1-330](file://backend/app/workers/citation_engine.py#L1-L330)
|
||
- [tests/test_citation_engine.py:1-54](file://tests/test_citation_engine.py#L1-L54)
|
||
|
||
### 定时调度与任务管理
|
||
- 调度器
|
||
- 使用APScheduler的AsyncIOScheduler,每小时检查一次
|
||
- 查找status='active'且next_query_at<=now的查询
|
||
- 逐个调用CitationEngine.execute_query并更新QueryTask状态
|
||
- 任务模型
|
||
- QueryTask记录平台、状态、错误信息与时间戳
|
||
- 支持pending/running/success/failed状态流转
|
||
|
||
```mermaid
|
||
sequenceDiagram
|
||
participant S as "调度器"
|
||
participant DB as "数据库"
|
||
participant CE as "引用检测引擎"
|
||
participant QT as "QueryTask"
|
||
S->>DB : 查询 active 且到期的 Query
|
||
DB-->>S : 返回待执行查询列表
|
||
loop 遍历查询
|
||
S->>QT : 创建/更新 QueryTask
|
||
S->>CE : execute_query(query)
|
||
CE-->>S : 返回 CitationRecord 列表
|
||
S->>DB : 更新 QueryTask 状态/时间
|
||
end
|
||
```
|
||
|
||
**图表来源**
|
||
- [backend/app/workers/scheduler.py:51-84](file://backend/app/workers/scheduler.py#L51-L84)
|
||
- [backend/app/models/query_task.py:11-39](file://backend/app/models/query_task.py#L11-L39)
|
||
|
||
**章节来源**
|
||
- [backend/app/workers/scheduler.py:1-95](file://backend/app/workers/scheduler.py#L1-L95)
|
||
- [backend/app/models/query_task.py:1-39](file://backend/app/models/query_task.py#L1-L39)
|
||
|
||
### API与服务层
|
||
- API路由
|
||
- 列表查询、统计、立即执行查询
|
||
- 立即执行返回任务状态与消息
|
||
- 服务层
|
||
- 权限校验:仅允许用户访问自己的查询
|
||
- 统计聚合:总查询数、引用数、引用率、按平台分布、趋势
|
||
- 导出CSV:将引用记录导出为CSV字符串
|
||
|
||
**章节来源**
|
||
- [backend/app/api/citations.py:1-78](file://backend/app/api/citations.py#L1-L78)
|
||
- [backend/app/services/citation.py:1-269](file://backend/app/services/citation.py#L1-L269)
|
||
|
||
## 依赖分析
|
||
- 外部依赖
|
||
- FastAPI、SQLAlchemy、APScheduler、httpx、Pydantic Settings等
|
||
- 内部模块耦合
|
||
- CitationEngine依赖适配器与数据库模型
|
||
- 所有适配器依赖search_engine模块
|
||
- Scheduler依赖CitationEngine与Query模型
|
||
- API与Service层依赖数据库与权限控制
|
||
|
||
```mermaid
|
||
graph LR
|
||
REQ["requirements.txt"] --> FA["FastAPI"]
|
||
REQ --> SA["SQLAlchemy"]
|
||
REQ --> AP["APScheduler"]
|
||
REQ --> HTTPX["httpx"]
|
||
REQ --> PYD["Pydantic Settings"]
|
||
CE["CitationEngine"] --> AD1["TongyiAdapter"]
|
||
CE --> AD2["DoubaoAdapter"]
|
||
CE --> AD3["QingyanAdapter"]
|
||
CE --> AD4["TiangongAdapter"]
|
||
CE --> AD5["XinghuoAdapter"]
|
||
CE --> DB1["CitationRecord"]
|
||
CE --> DB2["QueryTask"]
|
||
CE --> DB3["Query"]
|
||
AD1 --> SE["SearchEngine"]
|
||
AD2 --> SE
|
||
AD3 --> SE
|
||
AD4 --> SE
|
||
AD5 --> SE
|
||
SCH["Scheduler"] --> CE
|
||
API["API"] --> SVC["Service"]
|
||
SVC --> DB1
|
||
SVC --> DB3
|
||
```
|
||
|
||
**图表来源**
|
||
- [backend/requirements.txt:1-36](file://backend/requirements.txt#L1-L36)
|
||
- [backend/app/workers/citation_engine.py:1-330](file://backend/app/workers/citation_engine.py#L1-L330)
|
||
- [backend/app/workers/scheduler.py:1-95](file://backend/app/workers/scheduler.py#L1-L95)
|
||
- [backend/app/api/citations.py:1-78](file://backend/app/api/citations.py#L1-L78)
|
||
- [backend/app/services/citation.py:1-269](file://backend/app/services/citation.py#L1-L269)
|
||
|
||
**章节来源**
|
||
- [backend/requirements.txt:1-36](file://backend/requirements.txt#L1-L36)
|
||
|
||
## 性能考虑
|
||
- 搜索引擎优化
|
||
- DuckDuckGo搜索无需API密钥,成本低且稳定
|
||
- Wikipedia回退机制确保搜索成功率
|
||
- 指数退避减少对搜索引擎的压力
|
||
- 资源管理
|
||
- 适配器无需浏览器资源,内存占用更低
|
||
- 搜索引擎调用使用异步HTTP客户端
|
||
- 响应稳定性
|
||
- 搜索结果比网页自动化更稳定
|
||
- 双回退机制提高成功率
|
||
- 数据库性能
|
||
- Query与CitationRecord的关键字段建立索引,优化查询性能
|
||
- 异步调度
|
||
- 使用AsyncIOScheduler与异步数据库连接,提升并发效率
|
||
|
||
## 故障排查指南
|
||
- 搜索引擎访问失败
|
||
- 现象:DuckDuckGo搜索失败或被限制
|
||
- 处理:自动回退到Wikipedia,检查网络连接
|
||
- Wikipedia API调用失败
|
||
- 现象:Wikipedia搜索返回空结果
|
||
- 处理:检查关键词有效性,确认Wikipedia服务可用
|
||
- 搜索结果为空
|
||
- 现象:适配器返回空字符串
|
||
- 处理:尝试更具体的关键词,检查搜索引擎状态
|
||
- 查询任务失败
|
||
- 现象:QueryTask状态为failed并记录错误信息
|
||
- 处理:查看错误日志,确认搜索引擎可用性与网络状况
|
||
|
||
**章节来源**
|
||
- [backend/app/workers/platforms/search_engine.py:139-144](file://backend/app/workers/platforms/search_engine.py#L139-L144)
|
||
- [backend/app/workers/platforms/tongyi.py:22-29](file://backend/app/workers/platforms/tongyi.py#L22-L29)
|
||
- [backend/app/workers/citation_engine.py:231-247](file://backend/app/workers/citation_engine.py#L231-L247)
|
||
|
||
## 结论
|
||
该系统通过适配器模式实现了对多平台的统一接入,现在采用基于搜索引擎的稳定架构,结合智能回退机制与引用检测引擎,提供了从查询、匹配到统计与导出的完整能力。搜索引擎模式相比浏览器自动化具有更高的稳定性、更低的成本和更好的可扩展性。调度器保障了周期性任务的可靠执行,API与服务层为前端与运维提供了清晰的接口。未来可在搜索引擎优化、稳定性与性能优化方面持续演进。
|
||
|
||
## 附录
|
||
|
||
### 新AI平台接入扩展指南与最佳实践
|
||
- 扩展步骤
|
||
- 新建适配器类继承BasePlatformAdapter,实现query与可选close
|
||
- 在CitationEngine的platforms映射中注册新适配器实例
|
||
- 在前端platforms.ts中添加平台映射与展示项
|
||
- 最佳实践
|
||
- 明确定义platform_name与platform_url
|
||
- 统一异常处理与日志记录
|
||
- 使用指数退避与搜索引擎回退提升鲁棒性
|
||
- 合理设置超时与重试次数
|
||
- 在close中确保资源释放(如需)
|
||
- 为新平台编写单元测试覆盖关键场景
|
||
- 搜索引擎适配器开发要点
|
||
- 直接复用fetch_search_content函数
|
||
- 不需要复杂的浏览器自动化逻辑
|
||
- 注重错误处理和日志记录
|
||
- 考虑关键词组合策略以提高搜索准确性
|
||
|
||
**章节来源**
|
||
- [backend/app/workers/platforms/base.py:4-17](file://backend/app/workers/platforms/base.py#L4-L17)
|
||
- [backend/app/workers/citation_engine.py:164-175](file://backend/app/workers/citation_engine.py#L164-L175)
|
||
- [frontend/lib/platforms.ts:1-24](file://frontend/lib/platforms.ts#L1-L24)
|
||
- [backend/app/workers/platforms/search_engine.py:163-174](file://backend/app/workers/platforms/search_engine.py#L163-L174) |