Merge remote-tracking branch 'origin/main'
This commit is contained in:
commit
2d94fab4dd
|
|
@ -5,6 +5,12 @@
|
|||
- [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)
|
||||
|
|
@ -18,6 +24,14 @@
|
|||
- [backend/requirements.txt](file://backend/requirements.txt)
|
||||
</cite>
|
||||
|
||||
## 更新摘要
|
||||
**变更内容**
|
||||
- 新增5个基于搜索引擎的AI平台适配器(通义千问、豆包、智谱清言、天工AI、讯飞星火)
|
||||
- 替代原有的Playwright浏览器自动化适配器架构
|
||||
- 新增智能搜索引擎模块,提供DuckDuckGo和Wikipedia双回退机制
|
||||
- 更新前端平台映射以支持新平台
|
||||
- 保持相同的引用检测引擎和调度器架构
|
||||
|
||||
## 目录
|
||||
1. [简介](#简介)
|
||||
2. [项目结构](#项目结构)
|
||||
|
|
@ -31,9 +45,9 @@
|
|||
10. [附录](#附录)
|
||||
|
||||
## 简介
|
||||
本项目是一个AI平台集成系统,支持通过统一适配器接口对接多个大模型平台(如Kimi、文心一言)。系统包含以下能力:
|
||||
本项目是一个AI平台集成系统,支持通过统一适配器接口对接多个大模型平台(如通义千问、豆包、智谱清言、天工AI、讯飞星火)。系统包含以下能力:
|
||||
- 适配器架构:以抽象基类为统一接口,扩展新的AI平台只需实现query方法。
|
||||
- 浏览器自动化:基于Playwright对网页版AI平台进行自动交互,包含页面定位、输入提交、响应稳定检测与指数退避重试。
|
||||
- 搜索引擎集成:基于DuckDuckGo和Wikipedia的智能搜索引擎,提供稳定的回退机制。
|
||||
- 引用检测引擎:对平台返回内容进行品牌匹配、竞争品牌识别与置信度评分,生成引用记录。
|
||||
- 定时调度:基于APScheduler的异步调度器,周期性检查并执行到期查询任务。
|
||||
- API与服务层:提供查询与统计接口,支持立即执行、导出CSV等功能。
|
||||
|
|
@ -56,8 +70,12 @@ API["API 层<br/>citations.py"]
|
|||
SVC["服务层<br/>services/citation.py"]
|
||||
SCH["调度器<br/>workers/scheduler.py"]
|
||||
CE["引用检测引擎<br/>workers/citation_engine.py"]
|
||||
AD_K["适配器: Kimi<br/>workers/platforms/kimi.py"]
|
||||
AD_W["适配器: 文心一言<br/>workers/platforms/wenxin.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"]
|
||||
|
|
@ -67,22 +85,33 @@ FE --> API
|
|||
API --> SVC
|
||||
SVC --> SCH
|
||||
SCH --> CE
|
||||
CE --> AD_K
|
||||
CE --> AD_W
|
||||
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
|
||||
AD_K --> CFG
|
||||
AD_W --> CFG
|
||||
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-309](file://backend/app/workers/citation_engine.py#L1-L309)
|
||||
- [backend/app/workers/platforms/kimi.py:1-206](file://backend/app/workers/platforms/kimi.py#L1-L206)
|
||||
- [backend/app/workers/platforms/wenxin.py:1-205](file://backend/app/workers/platforms/wenxin.py#L1-L205)
|
||||
- [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)
|
||||
|
|
@ -92,19 +121,23 @@ AD_W --> 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-309](file://backend/app/workers/citation_engine.py#L1-L309)
|
||||
- [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/kimi.py:1-206](file://backend/app/workers/platforms/kimi.py#L1-L206)
|
||||
- [backend/app/workers/platforms/wenxin.py:1-205](file://backend/app/workers/platforms/wenxin.py#L1-L205)
|
||||
- [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-18](file://frontend/lib/platforms.ts#L1-L18)
|
||||
- [frontend/lib/platforms.ts:1-24](file://frontend/lib/platforms.ts#L1-L24)
|
||||
|
||||
## 核心组件
|
||||
- 抽象适配器基类:定义统一的平台名称、URL以及查询接口,便于扩展新平台。
|
||||
- 平台适配器(Kimi/文心一言):基于Playwright实现页面交互、输入提交、响应稳定检测与重试。
|
||||
- 搜索引擎适配器(通义千问/豆包/智谱清言/天工AI/讯飞星火):基于DuckDuckGo和Wikipedia的智能搜索引擎,提供稳定的回退机制。
|
||||
- 引用检测引擎:品牌匹配(精确/别名/模糊)、竞争品牌识别、置信度评分与记录生成。
|
||||
- 调度器:定时扫描到期查询,调用引擎执行并更新任务状态。
|
||||
- API与服务:提供查询列表、统计、立即执行、导出CSV等接口。
|
||||
|
|
@ -112,9 +145,13 @@ AD_W --> CFG
|
|||
|
||||
**章节来源**
|
||||
- [backend/app/workers/platforms/base.py:1-18](file://backend/app/workers/platforms/base.py#L1-L18)
|
||||
- [backend/app/workers/platforms/kimi.py:1-206](file://backend/app/workers/platforms/kimi.py#L1-L206)
|
||||
- [backend/app/workers/platforms/wenxin.py:1-205](file://backend/app/workers/platforms/wenxin.py#L1-L205)
|
||||
- [backend/app/workers/citation_engine.py:1-309](file://backend/app/workers/citation_engine.py#L1-L309)
|
||||
- [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)
|
||||
|
|
@ -123,7 +160,7 @@ AD_W --> CFG
|
|||
- [backend/app/models/query_task.py:1-39](file://backend/app/models/query_task.py#L1-L39)
|
||||
|
||||
## 架构总览
|
||||
系统通过“适配器 + 引擎 + 调度器”的解耦方式实现多平台接入与统一处理流程。前端通过API触发查询与查看统计;调度器按频率驱动查询;引擎负责跨平台数据采集与分析;服务层提供数据访问与导出能力。
|
||||
系统通过"适配器 + 引擎 + 调度器"的解耦方式实现多平台接入与统一处理流程。前端通过API触发查询与查看统计;调度器按频率驱动查询;引擎负责跨平台数据采集与分析;服务层提供数据访问与导出能力。所有平台现在都通过搜索引擎获取内容,提供更稳定的回退机制。
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
|
|
@ -133,6 +170,7 @@ 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()
|
||||
|
|
@ -140,6 +178,8 @@ 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
|
||||
|
|
@ -151,9 +191,9 @@ 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:159-234](file://backend/app/workers/citation_engine.py#L159-L234)
|
||||
- [backend/app/workers/platforms/kimi.py:33-48](file://backend/app/workers/platforms/kimi.py#L33-L48)
|
||||
- [backend/app/workers/platforms/wenxin.py:33-48](file://backend/app/workers/platforms/wenxin.py#L33-L48)
|
||||
- [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)
|
||||
|
|
@ -171,6 +211,7 @@ API-->>FE : 返回任务状态/查询结果
|
|||
- 设计优势
|
||||
- 解耦平台差异,统一调用入口
|
||||
- 易于新增平台与替换实现
|
||||
- 基于搜索引擎的适配器无需复杂的浏览器自动化
|
||||
|
||||
```mermaid
|
||||
classDiagram
|
||||
|
|
@ -180,91 +221,119 @@ class BasePlatformAdapter {
|
|||
+query(keyword) str
|
||||
+close() void
|
||||
}
|
||||
class KimiAdapter {
|
||||
+platform_name = "kimi"
|
||||
+platform_url = "https : //kimi.moonshot.cn"
|
||||
class TongyiAdapter {
|
||||
+platform_name = "tongyi"
|
||||
+platform_url = "https : //tongyi.aliyun.com/qianwen"
|
||||
+query(keyword) str
|
||||
-_ensure_browser()
|
||||
-_do_query(keyword) str
|
||||
-_wait_for_response_stable(page) str
|
||||
+_do_query(keyword) str
|
||||
+close() void
|
||||
}
|
||||
class WenxinAdapter {
|
||||
+platform_name = "wenxin"
|
||||
+platform_url = "https : //yiyan.baidu.com"
|
||||
class DoubaoAdapter {
|
||||
+platform_name = "doubao"
|
||||
+platform_url = "https : //www.doubao.com/"
|
||||
+query(keyword) str
|
||||
-_ensure_browser()
|
||||
-_do_query(keyword) str
|
||||
-_wait_for_response_stable(page) str
|
||||
+_do_query(keyword) str
|
||||
+close() void
|
||||
}
|
||||
BasePlatformAdapter <|-- KimiAdapter
|
||||
BasePlatformAdapter <|-- WenxinAdapter
|
||||
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/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/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/kimi.py:1-206](file://backend/app/workers/platforms/kimi.py#L1-L206)
|
||||
- [backend/app/workers/platforms/wenxin.py:1-205](file://backend/app/workers/platforms/wenxin.py#L1-L205)
|
||||
- [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)
|
||||
|
||||
### Kimi平台浏览器自动化集成
|
||||
- Playwright配置
|
||||
- 启动headless Chromium,设置视口与UA
|
||||
- 异常处理:若未安装浏览器,抛出明确提示
|
||||
- 页面交互逻辑
|
||||
- 导航至平台URL,等待页面加载
|
||||
- 多选择器尝试定位输入框,支持textarea/div/input等
|
||||
- 自动提交:优先点击发送按钮,否则按回车
|
||||
- 响应稳定检测
|
||||
- 轮询消息容器,连续多次检测文本未变化视为稳定
|
||||
- 超时则返回当前文本
|
||||
- 错误重试机制
|
||||
- 最多重试3次,指数退避(2^attempt秒延迟)
|
||||
- 记录每次尝试日志,最终失败抛出异常
|
||||
### 搜索引擎适配器实现
|
||||
- 搜索引擎模式
|
||||
- 所有平台适配器现在都基于fetch_search_content函数
|
||||
- 通过DuckDuckGo搜索关键词,自动回退到Wikipedia
|
||||
- 提供指数退避重试机制(最多3次尝试)
|
||||
- 搜索策略
|
||||
- 组合关键词与目标品牌,确保搜索结果包含品牌信息
|
||||
- 优先使用DuckDuckGo HTML搜索,自动检测结果有效性
|
||||
- 当DuckDuckGo受限时自动回退到Wikipedia API
|
||||
- 错误处理
|
||||
- 每次尝试失败都会记录警告日志
|
||||
- 最终失败时抛出异常,便于上层处理
|
||||
- 适配器close方法为空实现,因为无需浏览器资源管理
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Start(["开始查询"]) --> Ensure["启动浏览器"]
|
||||
Ensure --> NewContext["新建上下文与页面"]
|
||||
NewContext --> Goto["导航到平台URL"]
|
||||
Goto --> WaitInput["等待输入框出现"]
|
||||
WaitInput --> Fill["填充关键词"]
|
||||
Fill --> Submit{"找到发送按钮?"}
|
||||
Submit --> |是| Click["点击发送按钮"]
|
||||
Submit --> |否| Enter["按回车键提交"]
|
||||
Click --> WaitResp["等待回复稳定"]
|
||||
Enter --> WaitResp
|
||||
WaitResp --> Stable{"文本稳定?"}
|
||||
Stable --> |是| Return["返回响应文本"]
|
||||
Stable --> |否| Sleep["等待2秒"] --> WaitResp
|
||||
Return --> Close["关闭页面与上下文"]
|
||||
Close --> End(["结束"])
|
||||
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/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/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/kimi.py:1-206](file://backend/app/workers/platforms/kimi.py#L1-L206)
|
||||
- [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)
|
||||
|
||||
### 文心一言平台API集成实现
|
||||
- 平台适配器实现
|
||||
- 与Kimi适配器一致的Playwright交互流程
|
||||
- 输入框与发送按钮选择策略、响应稳定检测与重试机制
|
||||
- 配置管理
|
||||
- 通过配置类读取环境变量,支持自定义浏览器路径等参数
|
||||
- 注意事项
|
||||
- 若Playwright浏览器未安装,会抛出明确错误提示,需先安装对应浏览器
|
||||
### 智能搜索引擎模块
|
||||
- DuckDuckGo搜索实现
|
||||
- 使用HTML版本搜索,无需API密钥
|
||||
- 支持多种结果块格式的解析
|
||||
- 自动检测非结果页面并回退
|
||||
- Wikipedia回退机制
|
||||
- 通过Wikipedia API获取词条摘要
|
||||
- 自动清理HTML标记和引用格式
|
||||
- 提供稳定可靠的备用搜索源
|
||||
- 搜索内容提取
|
||||
- 统一的HTML清理和文本提取
|
||||
- 支持标题和摘要的组合输出
|
||||
- 限制最大字符数防止内容过长
|
||||
|
||||
**章节来源**
|
||||
- [backend/app/workers/platforms/wenxin.py:1-205](file://backend/app/workers/platforms/wenxin.py#L1-L205)
|
||||
- [backend/app/config.py:1-17](file://backend/app/config.py#L1-L17)
|
||||
- [backend/app/workers/platforms/search_engine.py:1-174](file://backend/app/workers/platforms/search_engine.py#L1-L174)
|
||||
|
||||
### 引用检测引擎工作原理
|
||||
- 品牌匹配策略
|
||||
|
|
@ -296,13 +365,13 @@ ForEachPlat --> Done["完成"]
|
|||
```
|
||||
|
||||
**图表来源**
|
||||
- [backend/app/workers/citation_engine.py:148-234](file://backend/app/workers/citation_engine.py#L148-L234)
|
||||
- [backend/app/workers/citation_engine.py:236-266](file://backend/app/workers/citation_engine.py#L236-L266)
|
||||
- [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-309](file://backend/app/workers/citation_engine.py#L1-L309)
|
||||
- [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)
|
||||
|
||||
### 定时调度与任务管理
|
||||
|
|
@ -353,9 +422,10 @@ end
|
|||
|
||||
## 依赖分析
|
||||
- 外部依赖
|
||||
- FastAPI、SQLAlchemy、APScheduler、Playwright、Pydantic Settings等
|
||||
- FastAPI、SQLAlchemy、APScheduler、httpx、Pydantic Settings等
|
||||
- 内部模块耦合
|
||||
- CitationEngine依赖适配器与数据库模型
|
||||
- 所有适配器依赖search_engine模块
|
||||
- Scheduler依赖CitationEngine与Query模型
|
||||
- API与Service层依赖数据库与权限控制
|
||||
|
||||
|
|
@ -364,13 +434,21 @@ graph LR
|
|||
REQ["requirements.txt"] --> FA["FastAPI"]
|
||||
REQ --> SA["SQLAlchemy"]
|
||||
REQ --> AP["APScheduler"]
|
||||
REQ --> PW["Playwright"]
|
||||
REQ --> HTTPX["httpx"]
|
||||
REQ --> PYD["Pydantic Settings"]
|
||||
CE["CitationEngine"] --> AD1["KimiAdapter"]
|
||||
CE --> AD2["WenxinAdapter"]
|
||||
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
|
||||
|
|
@ -378,53 +456,52 @@ SVC --> DB3
|
|||
```
|
||||
|
||||
**图表来源**
|
||||
- [backend/requirements.txt:1-35](file://backend/requirements.txt#L1-L35)
|
||||
- [backend/app/workers/citation_engine.py:1-309](file://backend/app/workers/citation_engine.py#L1-L309)
|
||||
- [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-35](file://backend/requirements.txt#L1-L35)
|
||||
- [backend/requirements.txt:1-36](file://backend/requirements.txt#L1-L36)
|
||||
|
||||
## 性能考虑
|
||||
- 浏览器资源管理
|
||||
- 适配器在close中释放浏览器与上下文,避免资源泄漏
|
||||
- 重试与退避
|
||||
- 指数退避降低平台压力,提升成功率
|
||||
- 响应稳定检测
|
||||
- 通过连续检测减少过早截断,提高稳定性
|
||||
- 数据库索引
|
||||
- 搜索引擎优化
|
||||
- DuckDuckGo搜索无需API密钥,成本低且稳定
|
||||
- Wikipedia回退机制确保搜索成功率
|
||||
- 指数退避减少对搜索引擎的压力
|
||||
- 资源管理
|
||||
- 适配器无需浏览器资源,内存占用更低
|
||||
- 搜索引擎调用使用异步HTTP客户端
|
||||
- 响应稳定性
|
||||
- 搜索结果比网页自动化更稳定
|
||||
- 双回退机制提高成功率
|
||||
- 数据库性能
|
||||
- Query与CitationRecord的关键字段建立索引,优化查询性能
|
||||
- 异步调度
|
||||
- 使用AsyncIOScheduler与异步数据库连接,提升并发效率
|
||||
|
||||
[本节为通用建议,无需特定文件引用]
|
||||
|
||||
## 故障排查指南
|
||||
- Playwright浏览器未安装
|
||||
- 现象:启动浏览器时报错,提示需要安装浏览器
|
||||
- 处理:按照提示运行安装命令,确保浏览器可用
|
||||
- 页面元素定位失败
|
||||
- 现象:找不到输入框或发送按钮
|
||||
- 处理:检查选择器策略或平台UI变更,必要时调整选择器集合
|
||||
- 响应长时间不稳定
|
||||
- 现象:等待回复超时返回当前文本
|
||||
- 处理:适当延长等待时间或检查网络与平台状态
|
||||
- 搜索引擎访问失败
|
||||
- 现象:DuckDuckGo搜索失败或被限制
|
||||
- 处理:自动回退到Wikipedia,检查网络连接
|
||||
- Wikipedia API调用失败
|
||||
- 现象:Wikipedia搜索返回空结果
|
||||
- 处理:检查关键词有效性,确认Wikipedia服务可用
|
||||
- 搜索结果为空
|
||||
- 现象:适配器返回空字符串
|
||||
- 处理:尝试更具体的关键词,检查搜索引擎状态
|
||||
- 查询任务失败
|
||||
- 现象:QueryTask状态为failed并记录错误信息
|
||||
- 处理:查看错误日志,确认平台可用性与网络状况
|
||||
- 处理:查看错误日志,确认搜索引擎可用性与网络状况
|
||||
|
||||
**章节来源**
|
||||
- [backend/app/workers/platforms/kimi.py:27-31](file://backend/app/workers/platforms/kimi.py#L27-L31)
|
||||
- [backend/app/workers/platforms/kimi.py:87-88](file://backend/app/workers/platforms/kimi.py#L87-L88)
|
||||
- [backend/app/workers/platforms/kimi.py:145-148](file://backend/app/workers/platforms/kimi.py#L145-L148)
|
||||
- [backend/app/workers/citation_engine.py:211-227](file://backend/app/workers/citation_engine.py#L211-L227)
|
||||
- [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与服务层为前端与运维提供了清晰的接口。未来可在适配器扩展、稳定性与性能优化方面持续演进。
|
||||
|
||||
[本节为总结性内容,无需特定文件引用]
|
||||
该系统通过适配器模式实现了对多平台的统一接入,现在采用基于搜索引擎的稳定架构,结合智能回退机制与引用检测引擎,提供了从查询、匹配到统计与导出的完整能力。搜索引擎模式相比浏览器自动化具有更高的稳定性、更低的成本和更好的可扩展性。调度器保障了周期性任务的可靠执行,API与服务层为前端与运维提供了清晰的接口。未来可在搜索引擎优化、稳定性与性能优化方面持续演进。
|
||||
|
||||
## 附录
|
||||
|
||||
|
|
@ -436,12 +513,18 @@ SVC --> DB3
|
|||
- 最佳实践
|
||||
- 明确定义platform_name与platform_url
|
||||
- 统一异常处理与日志记录
|
||||
- 使用指数退避与响应稳定检测提升鲁棒性
|
||||
- 使用指数退避与搜索引擎回退提升鲁棒性
|
||||
- 合理设置超时与重试次数
|
||||
- 在close中确保资源释放
|
||||
- 在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:152-155](file://backend/app/workers/citation_engine.py#L152-L155)
|
||||
- [frontend/lib/platforms.ts:1-18](file://frontend/lib/platforms.ts#L1-L18)
|
||||
- [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)
|
||||
|
|
@ -4,9 +4,11 @@
|
|||
**本文档引用的文件**
|
||||
- [backend/app/workers/platforms/kimi.py](file://backend/app/workers/platforms/kimi.py)
|
||||
- [backend/app/workers/platforms/base.py](file://backend/app/workers/platforms/base.py)
|
||||
- [backend/app/workers/platforms/search_engine.py](file://backend/app/workers/platforms/search_engine.py)
|
||||
- [backend/app/workers/platforms/__init__.py](file://backend/app/workers/platforms/__init__.py)
|
||||
- [backend/app/workers/citation_engine.py](file://backend/app/workers/citation_engine.py)
|
||||
- [backend/app/workers/scheduler.py](file://backend/app/workers/scheduler.py)
|
||||
- [backend/app/models/query.py](file://backend/app/models/query.py)
|
||||
- [backend/app/models/query.py](file://backend/app/workers/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/services/query.py](file://backend/app/services/query.py)
|
||||
|
|
@ -17,6 +19,13 @@
|
|||
- [frontend/lib/platforms.ts](file://frontend/lib/platforms.ts)
|
||||
</cite>
|
||||
|
||||
## 更新摘要
|
||||
**变更内容**
|
||||
- Kimi平台适配器已简化为搜索引擎模式,移除了Playwright浏览器自动化实现
|
||||
- 所有平台适配器采用统一的fetch_search_content机制
|
||||
- 引入了通用搜索引擎模块,支持DuckDuckGo和Wikipedia回退机制
|
||||
- 更新了架构图和组件分析以反映新的实现方式
|
||||
|
||||
## 目录
|
||||
1. [简介](#简介)
|
||||
2. [项目结构](#项目结构)
|
||||
|
|
@ -30,10 +39,10 @@
|
|||
10. [附录](#附录)
|
||||
|
||||
## 简介
|
||||
本文件面向需要集成Kimi平台的开发者与运维人员,系统性阐述Kimi适配器的实现方式与运行机制,涵盖Playwright浏览器自动化配置与初始化、页面交互逻辑(搜索框定位、输入处理、搜索按钮点击、结果解析)、错误重试与超时处理、浏览器会话管理与资源清理、API调用示例与常见问题解决,以及性能优化与调试技巧。
|
||||
本文件面向需要集成Kimi平台的开发者与运维人员,系统性阐述Kimi适配器的简化实现方式与运行机制。Kimi适配器现已采用搜索引擎查询机制,通过DuckDuckGo和Wikipedia获取与关键词相关的真实内容,替代了原有的Playwright浏览器自动化方案。文档涵盖搜索引擎集成、错误重试与超时处理、资源管理与API调用示例。
|
||||
|
||||
## 项目结构
|
||||
后端采用FastAPI + SQLAlchemy + APScheduler的异步架构,前端通过Next.js提供可视化界面。Kimi适配器位于工作线程模块,被引用检测引擎统一编排,定时调度器周期性触发查询任务。
|
||||
后端采用FastAPI + SQLAlchemy + APScheduler的异步架构,前端通过Next.js提供可视化界面。Kimi适配器位于工作线程模块,被引用检测引擎统一编排,定时调度器周期性触发查询任务。所有平台适配器现在共享相同的搜索引擎基础设施。
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
|
|
@ -48,6 +57,8 @@ Service_Citation["引用服务<br/>backend/app/services/citation.py"]
|
|||
Scheduler["定时调度器<br/>backend/app/workers/scheduler.py"]
|
||||
Engine["引用检测引擎<br/>backend/app/workers/citation_engine.py"]
|
||||
Adapter_Kimi["Kimi适配器<br/>backend/app/workers/platforms/kimi.py"]
|
||||
SearchEngine["搜索引擎模块<br/>backend/app/workers/platforms/search_engine.py"]
|
||||
BaseAdapter["基础适配器<br/>backend/app/workers/platforms/base.py"]
|
||||
Model_Query["查询模型<br/>backend/app/models/query.py"]
|
||||
Model_Record["引用记录模型<br/>backend/app/models/citation_record.py"]
|
||||
Model_Task["查询任务模型<br/>backend/app/models/query_task.py"]
|
||||
|
|
@ -60,42 +71,47 @@ Service_Query --> Scheduler
|
|||
Service_Citation --> Scheduler
|
||||
Scheduler --> Engine
|
||||
Engine --> Adapter_Kimi
|
||||
Engine --> SearchEngine
|
||||
Engine --> BaseAdapter
|
||||
Engine --> Model_Query
|
||||
Engine --> Model_Record
|
||||
Engine --> Model_Task
|
||||
```
|
||||
|
||||
图表来源
|
||||
**图表来源**
|
||||
- [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-157](file://backend/app/workers/citation_engine.py#L148-L157)
|
||||
- [backend/app/workers/platforms/kimi.py:11-20](file://backend/app/workers/platforms/kimi.py#L11-L20)
|
||||
- [backend/app/workers/citation_engine.py:164-173](file://backend/app/workers/citation_engine.py#L164-L173)
|
||||
- [backend/app/workers/platforms/kimi.py:10-37](file://backend/app/workers/platforms/kimi.py#L10-L37)
|
||||
- [backend/app/workers/platforms/search_engine.py:1-174](file://backend/app/workers/platforms/search_engine.py#L1-L174)
|
||||
- [backend/app/models/query.py:11-55](file://backend/app/models/query.py#L11-L55)
|
||||
- [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)
|
||||
|
||||
章节来源
|
||||
**章节来源**
|
||||
- [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)
|
||||
- [frontend/lib/platforms.ts:1-18](file://frontend/lib/platforms.ts#L1-L18)
|
||||
- [frontend/lib/platforms.ts:1-23](file://frontend/lib/platforms.ts#L1-L23)
|
||||
|
||||
## 核心组件
|
||||
- Kimi适配器:基于Playwright的异步浏览器自动化,负责导航、输入、提交、等待响应稳定与结果提取。
|
||||
- 引用检测引擎:编排多平台查询,执行品牌匹配与竞争品牌检测,并持久化结果。
|
||||
- 定时调度器:周期性扫描到期查询,触发执行并更新任务状态。
|
||||
- 数据模型:查询、引用记录、查询任务三者构成完整的查询生命周期与结果存储。
|
||||
- API与服务:提供REST接口与业务服务,支撑前端展示与手动触发“立即执行”。
|
||||
- **Kimi适配器(搜索引擎模式)**:基于HTTP客户端的轻量级适配器,通过fetch_search_content获取搜索结果。
|
||||
- **搜索引擎模块**:提供DuckDuckGo HTML搜索和Wikipedia API回退机制,支持内容提取和清理。
|
||||
- **引用检测引擎**:编排多平台查询,执行品牌匹配与竞争品牌检测,并持久化结果。
|
||||
- **定时调度器**:周期性扫描到期查询,触发执行并更新任务状态。
|
||||
- **数据模型**:查询、引用记录、查询任务三者构成完整的查询生命周期与结果存储。
|
||||
- **API与服务**:提供REST接口与业务服务,支撑前端展示与手动触发"立即执行"。
|
||||
|
||||
章节来源
|
||||
- [backend/app/workers/platforms/kimi.py:11-20](file://backend/app/workers/platforms/kimi.py#L11-L20)
|
||||
- [backend/app/workers/citation_engine.py:148-157](file://backend/app/workers/citation_engine.py#L148-L157)
|
||||
**章节来源**
|
||||
- [backend/app/workers/platforms/kimi.py:10-37](file://backend/app/workers/platforms/kimi.py#L10-L37)
|
||||
- [backend/app/workers/platforms/search_engine.py:163-174](file://backend/app/workers/platforms/search_engine.py#L163-L174)
|
||||
- [backend/app/workers/citation_engine.py:161-173](file://backend/app/workers/citation_engine.py#L161-L173)
|
||||
- [backend/app/workers/scheduler.py:25-40](file://backend/app/workers/scheduler.py#L25-L40)
|
||||
- [backend/app/models/query.py:11-55](file://backend/app/models/query.py#L11-L55)
|
||||
- [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)
|
||||
|
||||
## 架构总览
|
||||
下图展示了从用户发起查询到结果入库的关键路径,以及Kimi适配器在其中的角色。
|
||||
下图展示了从用户发起查询到结果入库的关键路径,以及Kimi适配器在其中的角色。现在Kimi适配器通过搜索引擎获取内容,而非直接操作浏览器。
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
|
|
@ -105,91 +121,119 @@ participant SVC as "服务层"
|
|||
participant SCH as "调度器"
|
||||
participant ENG as "引用检测引擎"
|
||||
participant ADP as "Kimi适配器"
|
||||
participant PW as "Playwright浏览器"
|
||||
participant SE as "搜索引擎模块"
|
||||
FE->>API : "POST /api/v1/queries 或 /api/v1/citations/run-now"
|
||||
API->>SVC : "创建查询/立即执行"
|
||||
SVC->>SCH : "登记查询任务"
|
||||
SCH->>ENG : "周期性执行查询"
|
||||
ENG->>ADP : "query(keyword)"
|
||||
ADP->>PW : "启动浏览器/新建上下文/打开页面"
|
||||
ADP->>PW : "定位输入框/输入关键词/提交"
|
||||
ADP->>PW : "等待回复稳定/提取文本"
|
||||
ADP->>SE : "fetch_search_content(platform_name, keyword)"
|
||||
SE->>SE : "search_duckduckgo 或 Wikipedia"
|
||||
SE-->>ADP : "返回搜索结果文本"
|
||||
ADP-->>ENG : "返回原始响应文本"
|
||||
ENG-->>SVC : "品牌匹配/竞争品牌检测"
|
||||
SVC-->>API : "写入引用记录"
|
||||
API-->>FE : "返回查询结果/统计"
|
||||
```
|
||||
|
||||
图表来源
|
||||
**图表来源**
|
||||
- [backend/app/api/queries.py:26-39](file://backend/app/api/queries.py#L26-L39)
|
||||
- [backend/app/api/citations.py:59-77](file://backend/app/api/citations.py#L59-L77)
|
||||
- [backend/app/services/query.py:45-81](file://backend/app/services/query.py#L45-L81)
|
||||
- [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:159-234](file://backend/app/workers/citation_engine.py#L159-L234)
|
||||
- [backend/app/workers/platforms/kimi.py:33-125](file://backend/app/workers/platforms/kimi.py#L33-L125)
|
||||
- [backend/app/workers/citation_engine.py:256-287](file://backend/app/workers/citation_engine.py#L256-L287)
|
||||
- [backend/app/workers/platforms/kimi.py:16-33](file://backend/app/workers/platforms/kimi.py#L16-L33)
|
||||
- [backend/app/workers/platforms/search_engine.py:163-174](file://backend/app/workers/platforms/search_engine.py#L163-L174)
|
||||
|
||||
## 详细组件分析
|
||||
|
||||
### Kimi适配器(Browser Automation)
|
||||
- 启动与初始化
|
||||
- 通过异步Playwright启动Chromium浏览器,headless模式运行。
|
||||
- 若浏览器未安装,捕获异常并提示安装命令。
|
||||
- 页面交互
|
||||
- 导航至Kimi首页,设置页面加载超时。
|
||||
- 多选择器策略定位输入框(textarea、contenteditable等),逐个尝试直至命中。
|
||||
- 输入关键词后,优先点击发送按钮;若未发现发送按钮则模拟回车提交。
|
||||
- 结果解析与稳定性
|
||||
- 使用多级消息容器选择器提取最新回复内容。
|
||||
- 通过“连续N次文本不变”判定回复稳定,避免过早截断。
|
||||
- 超时情况下返回当前已收集文本。
|
||||
- 错误处理与重试
|
||||
- 单次查询失败时进行最多两次重试(共三次尝试),指数退避延迟。
|
||||
- 页面超时与通用异常均转换为可读的运行时错误。
|
||||
- 资源管理
|
||||
- 每次查询独立创建上下文与页面,完成后及时关闭,避免资源泄漏。
|
||||
- 提供显式关闭方法用于进程退出时清理Playwright与浏览器实例。
|
||||
### Kimi适配器(搜索引擎模式)
|
||||
**更新** Kimi适配器已完全简化,移除了Playwright浏览器自动化实现,现在是一个轻量级的HTTP客户端适配器。
|
||||
|
||||
- **适配器实现**
|
||||
- 继承自BasePlatformAdapter基类,实现query和_close方法
|
||||
- platform_name设置为"kimi",platform_url设置为"https://kimi.moonshot.cn"
|
||||
- query方法包含最多3次重试(共3次尝试),使用指数退避策略
|
||||
- **搜索引擎集成**
|
||||
- _do_query方法调用fetch_search_content获取搜索结果
|
||||
- 通过search_duckduckgo获取HTML搜索结果,必要时回退到Wikipedia
|
||||
- 返回清理后的搜索结果文本
|
||||
- **资源管理**
|
||||
- close方法为空实现,因为无额外资源需要释放
|
||||
- 依赖httpx异步客户端自动管理连接池
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Start(["进入 query(keyword)"]) --> Ensure["确保浏览器已启动"]
|
||||
Ensure --> RetryLoop{"重试次数 < 3"}
|
||||
Start(["进入 query(keyword)"]) --> RetryLoop{"重试次数 < 3"}
|
||||
RetryLoop --> |是| DoQuery["_do_query 执行单次查询"]
|
||||
DoQuery --> Stable["等待回复稳定"]
|
||||
Stable --> Success["返回响应文本"]
|
||||
DoQuery --> |异常| Delay["指数退避等待"]
|
||||
DoQuery --> Success["返回搜索结果文本"]
|
||||
DoQuery --> |异常| Delay["指数退避等待 (2^attempt)"]
|
||||
Delay --> RetryLoop
|
||||
RetryLoop --> |否| FinalFail["记录最终失败并抛出异常"]
|
||||
Success --> Close["关闭页面/上下文"]
|
||||
FinalFail --> Close
|
||||
Close --> End(["结束"])
|
||||
Success --> End(["结束"])
|
||||
FinalFail --> End
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [backend/app/workers/platforms/kimi.py:33-48](file://backend/app/workers/platforms/kimi.py#L33-L48)
|
||||
- [backend/app/workers/platforms/kimi.py:50-125](file://backend/app/workers/platforms/kimi.py#L50-L125)
|
||||
- [backend/app/workers/platforms/kimi.py:126-197](file://backend/app/workers/platforms/kimi.py#L126-L197)
|
||||
- [backend/app/workers/platforms/kimi.py:198-206](file://backend/app/workers/platforms/kimi.py#L198-L206)
|
||||
**图表来源**
|
||||
- [backend/app/workers/platforms/kimi.py:16-29](file://backend/app/workers/platforms/kimi.py#L16-L29)
|
||||
- [backend/app/workers/platforms/kimi.py:31-33](file://backend/app/workers/platforms/kimi.py#L31-L33)
|
||||
|
||||
章节来源
|
||||
- [backend/app/workers/platforms/kimi.py:17-32](file://backend/app/workers/platforms/kimi.py#L17-L32)
|
||||
- [backend/app/workers/platforms/kimi.py:33-48](file://backend/app/workers/platforms/kimi.py#L33-L48)
|
||||
- [backend/app/workers/platforms/kimi.py:50-125](file://backend/app/workers/platforms/kimi.py#L50-L125)
|
||||
- [backend/app/workers/platforms/kimi.py:126-197](file://backend/app/workers/platforms/kimi.py#L126-L197)
|
||||
- [backend/app/workers/platforms/kimi.py:198-206](file://backend/app/workers/platforms/kimi.py#L198-L206)
|
||||
**章节来源**
|
||||
- [backend/app/workers/platforms/kimi.py:10-37](file://backend/app/workers/platforms/kimi.py#L10-L37)
|
||||
|
||||
### 搜索引擎模块(Search Engine Module)
|
||||
**新增** 新增的通用搜索引擎模块,提供DuckDuckGo和Wikipedia的搜索功能。
|
||||
|
||||
- **DuckDuckGo搜索**
|
||||
- 使用HTML版本搜索,无需API密钥
|
||||
- 支持多种结果块匹配策略(标准result块和备选匹配)
|
||||
- 自动清理HTML标签和实体,提取可读文本
|
||||
- **Wikipedia回退机制**
|
||||
- 当DuckDuckGo受限或失败时自动回退到Wikipedia API
|
||||
- 使用Wikipedia API获取词条摘要,避免HTML解析复杂性
|
||||
- 支持引用标记清理和文本格式化
|
||||
- **内容提取与清理**
|
||||
- 统一的HTML标签清理函数
|
||||
- 文本压缩和空白字符标准化
|
||||
- 最大字符长度控制和结果截断
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Start(["fetch_search_content"]) --> DDG["search_duckduckgo"]
|
||||
DDG --> Valid{"有效结果?"}
|
||||
Valid --> |是| Clean["清理HTML标签"]
|
||||
Clean --> Return["返回结果"]
|
||||
Valid --> |否| Wiki["search_wikipedia 回退"]
|
||||
Wiki --> WikiValid{"Wikipedia结果?"}
|
||||
WikiValid --> |是| WikiClean["清理Wikipedia内容"]
|
||||
WikiClean --> Return
|
||||
WikiValid --> |否| Error["抛出所有搜索源失败"]
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
- [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/search_engine.py:16-76](file://backend/app/workers/platforms/search_engine.py#L16-L76)
|
||||
|
||||
**章节来源**
|
||||
- [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/search_engine.py:16-76](file://backend/app/workers/platforms/search_engine.py#L16-L76)
|
||||
|
||||
### 引用检测引擎(Citation Engine)
|
||||
- 平台编排
|
||||
- 维护平台适配器映射,支持Kimi与文心等平台。
|
||||
- 针对每个查询遍历指定平台,执行查询与检测。
|
||||
- 品牌匹配
|
||||
- 支持精确匹配、别名匹配、模糊匹配三种策略,输出置信度与首次出现位置。
|
||||
- 竞争品牌检测
|
||||
- 基于预设行业品牌库,识别文本中除目标品牌外的其他品牌。
|
||||
- 任务状态管理
|
||||
- 为每次平台查询创建或获取对应任务记录,维护状态与错误信息。
|
||||
- 结果持久化
|
||||
- 将引用检测结果写入引用记录表,包含是否引用、位置、文本片段、竞争品牌及原始响应。
|
||||
- **平台编排**
|
||||
- 维护平台适配器映射,支持Kimi、文心、通义等平台
|
||||
- 针对每个查询遍历指定平台,执行查询与检测
|
||||
- **更新** 所有平台现在共享相同的搜索引擎基础设施
|
||||
- **品牌匹配**
|
||||
- 支持精确匹配、别名匹配、模糊匹配三种策略,输出置信度与首次出现位置
|
||||
- **竞争品牌检测**
|
||||
- 基于预设行业品牌库,识别文本中除目标品牌外的其他品牌
|
||||
- **任务状态管理**
|
||||
- 为每次平台查询创建或获取对应任务记录,维护状态与错误信息
|
||||
- **结果持久化**
|
||||
- 将引用检测结果写入引用记录表,包含是否引用、位置、文本片段、竞争品牌及原始响应
|
||||
|
||||
```mermaid
|
||||
classDiagram
|
||||
|
|
@ -200,8 +244,14 @@ class CitationEngine {
|
|||
}
|
||||
class KimiAdapter {
|
||||
+query(keyword) str
|
||||
+_do_query(keyword) str
|
||||
+close() void
|
||||
}
|
||||
class SearchEngineModule {
|
||||
+fetch_search_content(platform_name, keyword) str
|
||||
+search_duckduckgo(query) str
|
||||
+search_wikipedia(keyword) str
|
||||
}
|
||||
class BrandMatcher {
|
||||
+match(text) dict
|
||||
}
|
||||
|
|
@ -211,26 +261,26 @@ class CompetitorDetector {
|
|||
CitationEngine --> KimiAdapter : "依赖"
|
||||
CitationEngine --> BrandMatcher : "使用"
|
||||
CitationEngine --> CompetitorDetector : "使用"
|
||||
KimiAdapter --> SearchEngineModule : "使用"
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [backend/app/workers/citation_engine.py:148-157](file://backend/app/workers/citation_engine.py#L148-L157)
|
||||
- [backend/app/workers/citation_engine.py:236-266](file://backend/app/workers/citation_engine.py#L236-L266)
|
||||
- [backend/app/workers/platforms/kimi.py:11-20](file://backend/app/workers/platforms/kimi.py#L11-L20)
|
||||
**图表来源**
|
||||
- [backend/app/workers/citation_engine.py:161-173](file://backend/app/workers/citation_engine.py#L161-L173)
|
||||
- [backend/app/workers/platforms/kimi.py:10-37](file://backend/app/workers/platforms/kimi.py#L10-L37)
|
||||
- [backend/app/workers/platforms/search_engine.py:163-174](file://backend/app/workers/platforms/search_engine.py#L163-L174)
|
||||
|
||||
章节来源
|
||||
- [backend/app/workers/citation_engine.py:148-157](file://backend/app/workers/citation_engine.py#L148-L157)
|
||||
- [backend/app/workers/citation_engine.py:159-234](file://backend/app/workers/citation_engine.py#L159-L234)
|
||||
- [backend/app/workers/citation_engine.py:236-266](file://backend/app/workers/citation_engine.py#L236-L266)
|
||||
**章节来源**
|
||||
- [backend/app/workers/citation_engine.py:161-173](file://backend/app/workers/citation_engine.py#L161-L173)
|
||||
- [backend/app/workers/citation_engine.py:256-287](file://backend/app/workers/citation_engine.py#L256-L287)
|
||||
|
||||
### 定时调度器(Scheduler)
|
||||
- 触发机制
|
||||
- 使用APScheduler的AsyncIOScheduler,每小时检查一次到期查询。
|
||||
- 条件:查询状态为激活且next_query_at小于等于当前时间。
|
||||
- 执行流程
|
||||
- 逐条执行查询,调用引用检测引擎,更新任务状态与查询时间字段。
|
||||
- 关闭流程
|
||||
- 应用关闭时停止调度器并关闭各平台适配器。
|
||||
- **触发机制**
|
||||
- 使用APScheduler的AsyncIOScheduler,每小时检查一次到期查询
|
||||
- 条件:查询状态为激活且next_query_at小于等于当前时间
|
||||
- **执行流程**
|
||||
- 逐条执行查询,调用引用检测引擎,更新任务状态与查询时间字段
|
||||
- **关闭流程**
|
||||
- 应用关闭时停止调度器并关闭各平台适配器
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
|
|
@ -242,28 +292,29 @@ S->>DB : "查询到期的查询记录"
|
|||
loop 遍历查询
|
||||
S->>ENG : "execute_query(query, db)"
|
||||
ENG->>ADP : "query(keyword)"
|
||||
ADP-->>ENG : "返回原始响应"
|
||||
ADP->>ADP : "fetch_search_content"
|
||||
ADP-->>ENG : "返回搜索结果"
|
||||
ENG-->>S : "写入引用记录并更新时间"
|
||||
end
|
||||
S->>S : "关闭时调用 engine.close()"
|
||||
```
|
||||
|
||||
图表来源
|
||||
**图表来源**
|
||||
- [backend/app/workers/scheduler.py:51-84](file://backend/app/workers/scheduler.py#L51-L84)
|
||||
- [backend/app/workers/citation_engine.py:302-309](file://backend/app/workers/citation_engine.py#L302-L309)
|
||||
- [backend/app/workers/citation_engine.py:323-330](file://backend/app/workers/citation_engine.py#L323-L330)
|
||||
|
||||
章节来源
|
||||
**章节来源**
|
||||
- [backend/app/workers/scheduler.py:25-40](file://backend/app/workers/scheduler.py#L25-L40)
|
||||
- [backend/app/workers/scheduler.py:51-84](file://backend/app/workers/scheduler.py#L51-L84)
|
||||
- [backend/app/workers/scheduler.py:86-90](file://backend/app/workers/scheduler.py#L86-L90)
|
||||
|
||||
### 数据模型(Models)
|
||||
- 查询(Query)
|
||||
- 关键字段:关键词、目标品牌、品牌别名、平台列表、频率、状态、下次查询时间等。
|
||||
- 引用记录(CitationRecord)
|
||||
- 关键字段:是否引用、引用位置、引用文本、竞争品牌列表、原始响应、查询时间等。
|
||||
- 查询任务(QueryTask)
|
||||
- 关键字段:状态、错误信息、计划/开始/完成时间等。
|
||||
- **查询(Query)**
|
||||
- 关键字段:关键词、目标品牌、品牌别名、平台列表、频率、状态、下次查询时间等
|
||||
- **引用记录(CitationRecord)**
|
||||
- 关键字段:是否引用、引用位置、引用文本、竞争品牌列表、原始响应、查询时间等
|
||||
- **查询任务(QueryTask)**
|
||||
- 关键字段:状态、错误信息、计划/开始/完成时间等
|
||||
|
||||
```mermaid
|
||||
erDiagram
|
||||
|
|
@ -306,41 +357,43 @@ QUERY ||--o{ CITATION_RECORD : "拥有"
|
|||
QUERY ||--o{ QUERY_TASK : "拥有"
|
||||
```
|
||||
|
||||
图表来源
|
||||
**图表来源**
|
||||
- [backend/app/models/query.py:11-55](file://backend/app/models/query.py#L11-L55)
|
||||
- [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)
|
||||
|
||||
章节来源
|
||||
**章节来源**
|
||||
- [backend/app/models/query.py:11-55](file://backend/app/models/query.py#L11-L55)
|
||||
- [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)
|
||||
|
||||
### API与服务(API & Services)
|
||||
- 查询API
|
||||
- 支持分页列出、创建、查询详情、更新、删除查询。
|
||||
- 引用API
|
||||
- 支持分页列出引用、统计查询、立即执行查询(触发任务)。
|
||||
- 服务层
|
||||
- 查询服务:校验用户配额、计算下次查询时间、增删改查。
|
||||
- 引用服务:权限校验、统计聚合、CSV导出、立即执行任务登记。
|
||||
- **查询API**
|
||||
- 支持分页列出、创建、查询详情、更新、删除查询
|
||||
- **引用API**
|
||||
- 支持分页列出引用、统计查询、立即执行查询(触发任务)
|
||||
- **服务层**
|
||||
- 查询服务:校验用户配额、计算下次查询时间、增删改查
|
||||
- 引用服务:权限校验、统计聚合、CSV导出、立即执行任务登记
|
||||
|
||||
章节来源
|
||||
**章节来源**
|
||||
- [backend/app/api/queries.py:15-86](file://backend/app/api/queries.py#L15-L86)
|
||||
- [backend/app/api/citations.py:25-77](file://backend/app/api/citations.py#L25-L77)
|
||||
- [backend/app/services/query.py:12-130](file://backend/app/services/query.py#L12-L130)
|
||||
- [backend/app/services/citation.py:24-269](file://backend/app/services/citation.py#L24-L269)
|
||||
|
||||
## 依赖关系分析
|
||||
- 组件耦合
|
||||
- 引用检测引擎对Kimi适配器存在直接依赖;对品牌匹配器与竞争品牌检测器为组合关系。
|
||||
- 定时调度器仅通过引擎接口触发执行,解耦具体平台实现。
|
||||
- 外部依赖
|
||||
- Playwright浏览器驱动(需提前安装)。
|
||||
- PostgreSQL数据库(SQLAlchemy ORM)。
|
||||
- APScheduler(异步调度)。
|
||||
- 循环依赖
|
||||
- 未发现循环导入或调用链路。
|
||||
- **组件耦合**
|
||||
- 引用检测引擎对Kimi适配器存在直接依赖;对品牌匹配器与竞争品牌检测器为组合关系
|
||||
- **更新** Kimi适配器现在依赖通用搜索引擎模块,而非Playwright
|
||||
- 定时调度器仅通过引擎接口触发执行,解耦具体平台实现
|
||||
- **外部依赖**
|
||||
- httpx异步HTTP客户端(用于搜索引擎请求)
|
||||
- DuckDuckGo和Wikipedia API(无需认证)
|
||||
- PostgreSQL数据库(SQLAlchemy ORM)
|
||||
- APScheduler(异步调度)
|
||||
- **循环依赖**
|
||||
- 未发现循环导入或调用链路
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
|
|
@ -348,91 +401,95 @@ SCH["调度器"] --> ENG["引用检测引擎"]
|
|||
ENG --> ADP["Kimi适配器"]
|
||||
ENG --> BM["品牌匹配器"]
|
||||
ENG --> CD["竞争品牌检测器"]
|
||||
ADP --> SE["搜索引擎模块"]
|
||||
SE --> HTTPX["httpx客户端"]
|
||||
APIQ["查询API"] --> SVQ["查询服务"]
|
||||
APIC["引用API"] --> SVC["引用服务"]
|
||||
SVQ --> DB["数据库"]
|
||||
SVC --> DB
|
||||
```
|
||||
|
||||
图表来源
|
||||
**图表来源**
|
||||
- [backend/app/workers/scheduler.py:25-40](file://backend/app/workers/scheduler.py#L25-L40)
|
||||
- [backend/app/workers/citation_engine.py:148-157](file://backend/app/workers/citation_engine.py#L148-L157)
|
||||
- [backend/app/workers/citation_engine.py:161-173](file://backend/app/workers/citation_engine.py#L161-L173)
|
||||
- [backend/app/workers/platforms/kimi.py:10-37](file://backend/app/workers/platforms/kimi.py#L10-L37)
|
||||
- [backend/app/workers/platforms/search_engine.py:163-174](file://backend/app/workers/platforms/search_engine.py#L163-L174)
|
||||
- [backend/app/api/queries.py:15-86](file://backend/app/api/queries.py#L15-L86)
|
||||
- [backend/app/api/citations.py:25-77](file://backend/app/api/citations.py#L25-L77)
|
||||
|
||||
章节来源
|
||||
**章节来源**
|
||||
- [backend/app/workers/scheduler.py:25-40](file://backend/app/workers/scheduler.py#L25-L40)
|
||||
- [backend/app/workers/citation_engine.py:148-157](file://backend/app/workers/citation_engine.py#L148-L157)
|
||||
- [backend/app/workers/citation_engine.py:161-173](file://backend/app/workers/citation_engine.py#L161-L173)
|
||||
- [backend/app/api/queries.py:15-86](file://backend/app/api/queries.py#L15-L86)
|
||||
- [backend/app/api/citations.py:25-77](file://backend/app/api/citations.py#L25-L77)
|
||||
|
||||
## 性能考虑
|
||||
- 浏览器资源复用
|
||||
- 当前实现为每次查询新建上下文与页面,简单可靠但开销较大。可在高并发场景下评估复用策略(注意状态隔离)。
|
||||
- 等待策略优化
|
||||
- 输入框与发送按钮的等待时间可按环境调整;对稳定检测增加最大轮询次数上限,避免长时间阻塞。
|
||||
- 重试与退避
|
||||
- 已采用指数退避,建议结合平台可用性监控动态调整重试上限与初始延迟。
|
||||
- 数据库索引
|
||||
- 查询模型的索引设计有助于高频筛选;建议在引用记录表上针对查询时间、平台、是否引用等字段建立复合索引以提升统计与导出性能。
|
||||
- 前端平台映射
|
||||
- 前端平台键值映射清晰,便于UI展示与用户选择。
|
||||
- **HTTP客户端优化**
|
||||
- 使用httpx异步客户端,支持连接池复用和超时控制
|
||||
- DuckDuckGo搜索超时设置为30秒,避免长时间阻塞
|
||||
- **搜索策略优化**
|
||||
- 首选DuckDuckGo HTML搜索,自动回退到Wikipedia API
|
||||
- 支持最多5个结果的提取,平衡准确性和性能
|
||||
- **重试与退避**
|
||||
- 已采用指数退避(2^attempt),建议结合平台可用性监控动态调整重试上限
|
||||
- **数据库索引**
|
||||
- 查询模型的索引设计有助于高频筛选
|
||||
- 建议在引用记录表上针对查询时间、平台、是否引用等字段建立复合索引以提升统计与导出性能
|
||||
- **前端平台映射**
|
||||
- 前端平台键值映射清晰,便于UI展示与用户选择
|
||||
|
||||
章节来源
|
||||
- [backend/app/workers/platforms/kimi.py:33-48](file://backend/app/workers/platforms/kimi.py#L33-L48)
|
||||
**章节来源**
|
||||
- [backend/app/workers/platforms/kimi.py:16-29](file://backend/app/workers/platforms/kimi.py#L16-L29)
|
||||
- [backend/app/workers/platforms/search_engine.py:94-96](file://backend/app/workers/platforms/search_engine.py#L94-L96)
|
||||
- [backend/app/models/query.py:50-54](file://backend/app/models/query.py#L50-L54)
|
||||
- [backend/app/models/citation_record.py:37-41](file://backend/app/models/citation_record.py#L37-L41)
|
||||
- [frontend/lib/platforms.ts:1-18](file://frontend/lib/platforms.ts#L1-L18)
|
||||
- [frontend/lib/platforms.ts:1-23](file://frontend/lib/platforms.ts#L1-L23)
|
||||
|
||||
## 故障排查指南
|
||||
- 浏览器未安装
|
||||
- 现象:启动浏览器时报错,提示未安装Playwright浏览器。
|
||||
- 处理:按照日志提示运行安装命令,确保Chromium可用。
|
||||
- 页面元素定位失败
|
||||
- 现象:无法找到输入框或发送按钮,抛出“无法找到输入框”错误。
|
||||
- 处理:检查页面结构变化,适当扩展选择器集合;确认页面加载完成后再查找元素。
|
||||
- 页面超时
|
||||
- 现象:导航或元素等待超时,返回当前文本或抛出超时异常。
|
||||
- 处理:适当提高超时阈值;检查网络状况与代理设置;必要时启用本地镜像站点。
|
||||
- 重试仍失败
|
||||
- 现象:多次重试后仍失败。
|
||||
- 处理:查看日志中的最后一次错误;检查平台访问限制与验证码弹窗;考虑降低并发或增加延时。
|
||||
- 资源未释放
|
||||
- 现象:长时间运行后内存占用上升。
|
||||
- 处理:确保每次查询后页面与上下文均已关闭;在应用退出时调用适配器关闭方法。
|
||||
- API调用失败
|
||||
- 现象:接口返回4xx/5xx错误。
|
||||
- 处理:核对鉴权头与请求体;检查用户权限与查询状态;查看服务端日志定位异常。
|
||||
- **DuckDuckGo限制**
|
||||
- 现象:DuckDuckGo返回非结果页面或解析失败
|
||||
- 处理:自动回退到Wikipedia API;检查网络连接和代理设置
|
||||
- **Wikipedia API失败**
|
||||
- 现象:Wikipedia API调用失败或无结果
|
||||
- 处理:检查Wikipedia API可用性;确认关键词有效性
|
||||
- **搜索结果为空**
|
||||
- 现象:两个搜索源均无结果
|
||||
- 处理:尝试更具体的关键词;检查网络连接
|
||||
- **重试仍失败**
|
||||
- 现象:多次重试后仍失败
|
||||
- 处理:查看日志中的最后一次错误;检查平台访问限制与验证码弹窗
|
||||
- **API调用失败**
|
||||
- 现象:接口返回4xx/5xx错误
|
||||
- 处理:核对鉴权头与请求体;检查用户权限与查询状态;查看服务端日志定位异常
|
||||
|
||||
章节来源
|
||||
- [backend/app/workers/platforms/kimi.py:27-31](file://backend/app/workers/platforms/kimi.py#L27-L31)
|
||||
- [backend/app/workers/platforms/kimi.py:87-88](file://backend/app/workers/platforms/kimi.py#L87-L88)
|
||||
- [backend/app/workers/platforms/kimi.py:116-118](file://backend/app/workers/platforms/kimi.py#L116-L118)
|
||||
- [backend/app/workers/platforms/kimi.py:198-206](file://backend/app/workers/platforms/kimi.py#L198-L206)
|
||||
**章节来源**
|
||||
- [backend/app/workers/platforms/search_engine.py:139-144](file://backend/app/workers/platforms/search_engine.py#L139-L144)
|
||||
- [backend/app/workers/platforms/search_engine.py:140-144](file://backend/app/workers/platforms/search_engine.py#L140-L144)
|
||||
- [backend/app/workers/platforms/kimi.py:24-29](file://backend/app/workers/platforms/kimi.py#L24-L29)
|
||||
- [backend/app/api/queries.py:34-38](file://backend/app/api/queries.py#L34-L38)
|
||||
- [backend/app/api/citations.py:67-71](file://backend/app/api/citations.py#L67-L71)
|
||||
|
||||
## 结论
|
||||
Kimi适配器通过Playwright实现了对Kimi网页版的自动化交互,具备完善的错误重试、超时处理与资源管理机制。配合引用检测引擎与定时调度器,可稳定地完成跨平台的引用检测任务。建议在生产环境中关注浏览器资源复用、等待策略与数据库索引优化,并持续监控平台页面结构变化以保持适配器的健壮性。
|
||||
Kimi适配器已成功简化为搜索引擎模式,移除了复杂的Playwright浏览器自动化实现,转而采用轻量级的HTTP客户端方案。通过DuckDuckGo和Wikipedia的组合搜索策略,实现了稳定的搜索结果获取。新的架构更加简洁、高效,降低了维护成本,同时保持了与原有系统的兼容性。建议在生产环境中关注HTTP客户端性能、搜索策略优化和数据库索引设计。
|
||||
|
||||
## 附录
|
||||
|
||||
### API调用示例(路径参考)
|
||||
- 创建查询
|
||||
- **创建查询**
|
||||
- POST /api/v1/queries
|
||||
- 请求体字段:keyword、target_brand、brand_aliases、platforms、frequency
|
||||
- 成功响应:QueryResponse
|
||||
- 立即执行查询
|
||||
- **立即执行查询**
|
||||
- POST /api/v1/queries/{query_id}/run-now
|
||||
- 成功响应:RunNowResponse(包含任务ID与状态)
|
||||
- 查询引用列表
|
||||
- **查询引用列表**
|
||||
- GET /api/v1/citations/?query_id={query_id}&platform={platform}
|
||||
- 成功响应:CitationListResponse
|
||||
- 引用统计
|
||||
- **引用统计**
|
||||
- GET /api/v1/citations/stats?query_id={query_id}
|
||||
- 成功响应:CitationStatsResponse
|
||||
|
||||
章节来源
|
||||
**章节来源**
|
||||
- [backend/app/api/queries.py:26-39](file://backend/app/api/queries.py#L26-L39)
|
||||
- [backend/app/api/citations.py:59-77](file://backend/app/api/citations.py#L59-L77)
|
||||
- [backend/app/api/citations.py:25-56](file://backend/app/api/citations.py#L25-L56)
|
||||
|
|
@ -4,14 +4,25 @@
|
|||
**本文档引用的文件**
|
||||
- [wenxin.py](file://backend/app/workers/platforms/wenxin.py)
|
||||
- [base.py](file://backend/app/workers/platforms/base.py)
|
||||
- [search_engine.py](file://backend/app/workers/platforms/search_engine.py)
|
||||
- [citation_engine.py](file://backend/app/workers/citation_engine.py)
|
||||
- [config.py](file://backend/app/config.py)
|
||||
- [query.py](file://backend/app/models/query.py)
|
||||
- [queries.py](file://backend/app/api/queries.py)
|
||||
- [Dockerfile](file://backend/Dockerfile)
|
||||
- [kimi.py](file://backend/app/workers/platforms/kimi.py)
|
||||
- [tongyi.py](file://backend/app/workers/platforms/tongyi.py)
|
||||
- [test_citations.py](file://tests/test_citations.py)
|
||||
</cite>
|
||||
|
||||
## 更新摘要
|
||||
**变更内容**
|
||||
- 文心平台适配器已简化为搜索引擎模式,移除Playwright浏览器自动化实现
|
||||
- 采用统一的搜索引擎查询机制,通过`fetch_search_content`函数获取内容
|
||||
- 所有平台适配器(wenxin、kimi、tongyi等)均采用相同的简化模式
|
||||
- 移除复杂的页面交互策略和稳定性检测逻辑
|
||||
- 保留重试机制和错误处理策略
|
||||
|
||||
## 目录
|
||||
1. [简介](#简介)
|
||||
2. [项目结构](#项目结构)
|
||||
|
|
@ -25,79 +36,100 @@
|
|||
10. [附录](#附录)
|
||||
|
||||
## 简介
|
||||
本文件面向“文心平台集成”的技术与非技术读者,系统性说明文心一言平台适配器的实现方式,涵盖以下方面:
|
||||
- 文心适配器的职责与实现模式(基于浏览器自动化)
|
||||
- 请求参数构建(关键词处理、页面交互策略)
|
||||
- HTTP请求与页面自动化流程(导航、输入、提交、等待稳定)
|
||||
- 响应解析与稳定性检测(文本提取、稳定判定)
|
||||
本文件面向"文心平台集成"的技术与非技术读者,系统性说明文心一言平台适配器的实现方式,涵盖以下方面:
|
||||
- 文心适配器的职责与实现模式(基于搜索引擎查询)
|
||||
- 请求参数构建(关键词处理、搜索引擎查询策略)
|
||||
- HTTP请求与搜索引擎交互流程(DuckDuckGo、Wikipedia API)
|
||||
- 响应解析与内容提取(HTML解析、文本清理)
|
||||
- 配置管理(环境变量、超时与重试策略)
|
||||
- 错误处理与异常恢复
|
||||
- 安全注意事项与最佳实践
|
||||
|
||||
## 项目结构
|
||||
文心平台集成位于后端工作流模块中,采用“适配器 + 引擎”的分层设计:
|
||||
- 适配器层:负责具体平台的页面自动化交互
|
||||
文心平台集成位于后端工作流模块中,采用"适配器 + 引擎"的分层设计:
|
||||
- 适配器层:负责具体平台的搜索引擎查询交互
|
||||
- 引擎层:编排多平台查询、品牌匹配与统计
|
||||
- 配置层:集中管理运行时参数(如浏览器路径、API密钥占位)
|
||||
- 搜索引擎层:提供统一的搜索内容获取能力
|
||||
- 配置层:集中管理运行时参数(如API密钥占位、超时设置)
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph "适配器层"
|
||||
Base["BasePlatformAdapter<br/>抽象接口"]
|
||||
Wenxin["WenxinAdapter<br/>文心一言适配器"]
|
||||
end
|
||||
Kimi["KimiAdapter<br/>Kimi适配器"]
|
||||
Tongyi["TongyiAdapter<br/>通义千问适配器"]
|
||||
End
|
||||
subgraph "搜索引擎层"
|
||||
Search["SearchEngine<br/>搜索引擎模块"]
|
||||
DDG["DuckDuckGo<br/>HTML搜索"]
|
||||
Wiki["Wikipedia API<br/>百科查询"]
|
||||
End
|
||||
subgraph "引擎层"
|
||||
Engine["CitationEngine<br/>引用检测引擎"]
|
||||
end
|
||||
End
|
||||
subgraph "配置层"
|
||||
Cfg["Settings<br/>环境配置"]
|
||||
Docker["Dockerfile<br/>容器化与Playwright依赖"]
|
||||
end
|
||||
Docker["Dockerfile<br/>容器化配置"]
|
||||
End
|
||||
subgraph "数据模型"
|
||||
QModel["Query<br/>查询模型"]
|
||||
end
|
||||
End
|
||||
Base --> Wenxin
|
||||
Base --> Kimi
|
||||
Base --> Tongyi
|
||||
Wenxin --> Search
|
||||
Kimi --> Search
|
||||
Tongyi --> Search
|
||||
Search --> DDG
|
||||
Search --> Wiki
|
||||
Engine --> Wenxin
|
||||
Engine --> QModel
|
||||
Wenxin --> Cfg
|
||||
Docker --> Wenxin
|
||||
```
|
||||
|
||||
图表来源
|
||||
**图表来源**
|
||||
- [base.py:1-18](file://backend/app/workers/platforms/base.py#L1-L18)
|
||||
- [wenxin.py:11-205](file://backend/app/workers/platforms/wenxin.py#L11-L205)
|
||||
- [citation_engine.py:148-309](file://backend/app/workers/citation_engine.py#L148-L309)
|
||||
- [config.py:4-16](file://backend/app/config.py#L4-L16)
|
||||
- [Dockerfile:1-40](file://backend/Dockerfile#L1-L40)
|
||||
- [wenxin.py:10-38](file://backend/app/workers/platforms/wenxin.py#L10-L38)
|
||||
- [kimi.py:10-38](file://backend/app/workers/platforms/kimi.py#L10-L38)
|
||||
- [tongyi.py:10-38](file://backend/app/workers/platforms/tongyi.py#L10-L38)
|
||||
- [search_engine.py:163-174](file://backend/app/workers/platforms/search_engine.py#L163-L174)
|
||||
- [citation_engine.py:161-176](file://backend/app/workers/citation_engine.py#L161-L176)
|
||||
- [config.py:9-23](file://backend/app/config.py#L9-L23)
|
||||
- [Dockerfile:1-41](file://backend/Dockerfile#L1-L41)
|
||||
- [query.py:11-55](file://backend/app/models/query.py#L11-L55)
|
||||
|
||||
章节来源
|
||||
**章节来源**
|
||||
- [base.py:1-18](file://backend/app/workers/platforms/base.py#L1-L18)
|
||||
- [wenxin.py:11-205](file://backend/app/workers/platforms/wenxin.py#L11-L205)
|
||||
- [citation_engine.py:148-309](file://backend/app/workers/citation_engine.py#L148-L309)
|
||||
- [config.py:4-16](file://backend/app/config.py#L4-L16)
|
||||
- [Dockerfile:1-40](file://backend/Dockerfile#L1-L40)
|
||||
- [wenxin.py:10-38](file://backend/app/workers/platforms/wenxin.py#L10-L38)
|
||||
- [search_engine.py:163-174](file://backend/app/workers/platforms/search_engine.py#L163-L174)
|
||||
- [citation_engine.py:161-176](file://backend/app/workers/citation_engine.py#L161-L176)
|
||||
- [config.py:9-23](file://backend/app/config.py#L9-L23)
|
||||
- [Dockerfile:1-41](file://backend/Dockerfile#L1-L41)
|
||||
- [query.py:11-55](file://backend/app/models/query.py#L11-L55)
|
||||
|
||||
## 核心组件
|
||||
- 文心适配器(WenxinAdapter):实现文心一言页面自动化交互,负责关键词输入、提交、等待回复稳定,并返回原始文本。
|
||||
- 引擎(CitationEngine):编排查询任务,调用适配器获取原始响应,进行品牌匹配与竞争品牌检测,并持久化结果。
|
||||
- 基类(BasePlatformAdapter):定义统一的平台适配器接口,约束平台名称、URL与查询方法。
|
||||
- 配置(Settings):集中管理数据库、Redis、JWT、Playwright浏览器路径以及API密钥占位等配置项。
|
||||
- 数据模型(Query):承载查询任务的元数据,包括关键词、目标品牌、平台集合、频率与状态等。
|
||||
- 文心适配器(WenxinAdapter):实现文心一言平台的搜索引擎查询能力,负责关键词拼接与搜索内容获取
|
||||
- 搜索引擎模块(SearchEngine):提供统一的搜索内容获取能力,支持DuckDuckGo和Wikipedia API
|
||||
- 引擎(CitationEngine):编排查询任务,调用适配器获取原始响应,进行品牌匹配与竞争品牌检测,并持久化结果
|
||||
- 基类(BasePlatformAdapter):定义统一的平台适配器接口,约束平台名称、URL与查询方法
|
||||
- 配置(Settings):集中管理数据库、Redis、JWT、Playwright浏览器路径以及API密钥占位等配置项
|
||||
- 数据模型(Query):承载查询任务的元数据,包括关键词、目标品牌、平台集合、频率与状态等
|
||||
|
||||
章节来源
|
||||
- [wenxin.py:11-205](file://backend/app/workers/platforms/wenxin.py#L11-L205)
|
||||
- [citation_engine.py:148-309](file://backend/app/workers/citation_engine.py#L148-L309)
|
||||
**章节来源**
|
||||
- [wenxin.py:10-38](file://backend/app/workers/platforms/wenxin.py#L10-L38)
|
||||
- [search_engine.py:16-77](file://backend/app/workers/platforms/search_engine.py#L16-L77)
|
||||
- [citation_engine.py:161-176](file://backend/app/workers/citation_engine.py#L161-L176)
|
||||
- [base.py:4-18](file://backend/app/workers/platforms/base.py#L4-L18)
|
||||
- [config.py:4-16](file://backend/app/config.py#L4-L16)
|
||||
- [config.py:9-23](file://backend/app/config.py#L9-L23)
|
||||
- [query.py:11-55](file://backend/app/models/query.py#L11-L55)
|
||||
|
||||
## 架构总览
|
||||
文心平台集成采用“浏览器自动化 + 引擎编排”的架构:
|
||||
文心平台集成采用"搜索引擎查询 + 引擎编排"的架构:
|
||||
- 引擎接收查询请求,按平台顺序调用适配器
|
||||
- 适配器通过Playwright启动无头浏览器,访问文心一言页面,模拟用户输入与提交
|
||||
- 适配器等待回复稳定后提取文本,返回给引擎
|
||||
- 适配器通过搜索引擎模块获取与关键词相关的内容
|
||||
- 适配器进行重试与错误处理,返回原始文本
|
||||
- 引擎进行品牌匹配与统计,写入数据库
|
||||
|
||||
```mermaid
|
||||
|
|
@ -105,59 +137,61 @@ sequenceDiagram
|
|||
participant Client as "客户端"
|
||||
participant Engine as "CitationEngine"
|
||||
participant Adapter as "WenxinAdapter"
|
||||
participant Browser as "Playwright浏览器"
|
||||
participant Platform as "文心一言页面"
|
||||
participant Search as "SearchEngine"
|
||||
participant DDG as "DuckDuckGo"
|
||||
participant Wiki as "Wikipedia API"
|
||||
Client->>Engine : "发起查询请求"
|
||||
Engine->>Adapter : "query(keyword)"
|
||||
Adapter->>Browser : "启动无头浏览器"
|
||||
Browser->>Platform : "goto(文心URL, 超时=30s)"
|
||||
Platform-->>Browser : "页面加载完成"
|
||||
Browser->>Platform : "查找输入框并填入关键词"
|
||||
Browser->>Platform : "提交点击发送或按回车"
|
||||
Browser->>Platform : "等待回复稳定"
|
||||
Platform-->>Browser : "返回最新回复文本"
|
||||
Browser-->>Adapter : "返回原始响应文本"
|
||||
Adapter->>Search : "fetch_search_content(keyword)"
|
||||
Search->>DDG : "搜索关键词"
|
||||
DDG-->>Search : "返回HTML结果"
|
||||
Search->>Wiki : "回退到百科查询"
|
||||
Wiki-->>Search : "返回百科内容"
|
||||
Search-->>Adapter : "返回搜索内容"
|
||||
Adapter-->>Engine : "返回原始响应文本"
|
||||
Engine-->>Client : "返回引用检测结果"
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [citation_engine.py:236-266](file://backend/app/workers/citation_engine.py#L236-L266)
|
||||
- [wenxin.py:33-122](file://backend/app/workers/platforms/wenxin.py#L33-L122)
|
||||
**图表来源**
|
||||
- [citation_engine.py:256-287](file://backend/app/workers/citation_engine.py#L256-L287)
|
||||
- [wenxin.py:16-33](file://backend/app/workers/platforms/wenxin.py#L16-L33)
|
||||
- [search_engine.py:163-174](file://backend/app/workers/platforms/search_engine.py#L163-L174)
|
||||
|
||||
章节来源
|
||||
- [citation_engine.py:148-309](file://backend/app/workers/citation_engine.py#L148-L309)
|
||||
- [wenxin.py:11-205](file://backend/app/workers/platforms/wenxin.py#L11-L205)
|
||||
**章节来源**
|
||||
- [citation_engine.py:161-176](file://backend/app/workers/citation_engine.py#L161-L176)
|
||||
- [wenxin.py:10-38](file://backend/app/workers/platforms/wenxin.py#L10-L38)
|
||||
- [search_engine.py:163-174](file://backend/app/workers/platforms/search_engine.py#L163-L174)
|
||||
|
||||
## 详细组件分析
|
||||
|
||||
### 文心适配器(WenxinAdapter)
|
||||
- 角色与职责
|
||||
- 实现BasePlatformAdapter接口,提供文心一言平台的查询能力
|
||||
- 使用Playwright进行页面自动化,模拟真实用户行为
|
||||
- 提供重试与指数退避策略,提升稳定性
|
||||
- 提供等待回复稳定的算法,避免过早读取半成品内容
|
||||
- **角色与职责**
|
||||
- 实现BasePlatformAdapter接口,提供文心一言平台的搜索引擎查询能力
|
||||
- 使用统一的搜索引擎模块获取与关键词相关的内容
|
||||
- 提供重试与指数退避策略,提升查询稳定性
|
||||
- 直接返回搜索引擎返回的原始文本内容
|
||||
|
||||
- 关键实现要点
|
||||
- 浏览器生命周期管理:确保浏览器仅初始化一次,避免重复开销
|
||||
- 页面交互策略:多选择器容错查找输入框;优先点击发送按钮,否则回车提交
|
||||
- 稳定性检测:连续多次检测文本是否稳定,超时则返回当前文本
|
||||
- 错误处理:捕获超时与通用异常,统一包装为运行时错误并记录日志
|
||||
- **关键实现要点**
|
||||
- 简化的查询流程:直接调用搜索引擎模块,无需复杂的页面交互
|
||||
- 重试机制:最多3次尝试,指数退避(2^attempt秒)
|
||||
- 错误处理:捕获异常并记录日志,最终抛出异常
|
||||
- 资源管理:搜索引擎模式无需额外资源清理
|
||||
|
||||
- 请求参数构建
|
||||
- 关键词处理:直接填充到输入框,支持多种输入控件类型
|
||||
- 请求头与认证:该实现为浏览器自动化,不涉及HTTP请求头与API密钥
|
||||
- 超时设置:页面导航超时30秒,输入框查找超时10秒,发送按钮查找超时5秒
|
||||
- 重试配置:最多3次尝试,指数退避(2^attempt秒)
|
||||
- **请求参数构建**
|
||||
- 关键词处理:直接传递给搜索引擎模块,无需特殊处理
|
||||
- 搜索策略:搜索引擎模块会自动处理关键词拼接和查询优化
|
||||
- 超时设置:搜索引擎查询超时30秒,确保不会长时间阻塞
|
||||
- 重试配置:最多3次尝试,指数退避策略
|
||||
|
||||
- 响应解析逻辑
|
||||
- 文本提取:优先使用CSS选择器定位消息容器,其次使用JavaScript遍历页面
|
||||
- 稳定性判定:连续3次检测文本相同且长度大于阈值,视为稳定
|
||||
- 超时处理:超过90秒仍未稳定,返回当前已收集文本并告警
|
||||
- **响应解析逻辑**
|
||||
- 内容获取:直接返回搜索引擎返回的文本内容
|
||||
- 文本清理:由搜索引擎模块负责HTML解析和文本清理
|
||||
- 错误处理:搜索引擎模块会处理各种异常情况并提供回退机制
|
||||
|
||||
- 安全与合规
|
||||
- 该实现为浏览器自动化,不涉及明文API密钥传递
|
||||
- 建议在生产环境限制浏览器访问范围与网络策略
|
||||
- **安全与合规**
|
||||
- 该实现为搜索引擎查询,不涉及明文API密钥传递
|
||||
- 使用公开的搜索引擎API,无需认证
|
||||
- 遵循搜索引擎的使用条款和限制
|
||||
|
||||
```mermaid
|
||||
classDiagram
|
||||
|
|
@ -168,36 +202,67 @@ class BasePlatformAdapter {
|
|||
+close() void
|
||||
}
|
||||
class WenxinAdapter {
|
||||
-_playwright
|
||||
-_browser
|
||||
+query(keyword) str
|
||||
+_do_query(keyword) str
|
||||
+close() void
|
||||
-_ensure_browser() void
|
||||
-_do_query(keyword) str
|
||||
-_wait_for_response_stable(page, timeout) str
|
||||
}
|
||||
class SearchEngine {
|
||||
+fetch_search_content(platform_name, keyword) str
|
||||
+search_duckduckgo(query) str
|
||||
+search_wikipedia(keyword) str
|
||||
}
|
||||
BasePlatformAdapter <|-- WenxinAdapter
|
||||
WenxinAdapter --> SearchEngine
|
||||
```
|
||||
|
||||
图表来源
|
||||
**图表来源**
|
||||
- [base.py:4-18](file://backend/app/workers/platforms/base.py#L4-L18)
|
||||
- [wenxin.py:11-205](file://backend/app/workers/platforms/wenxin.py#L11-L205)
|
||||
- [wenxin.py:10-38](file://backend/app/workers/platforms/wenxin.py#L10-L38)
|
||||
- [search_engine.py:163-174](file://backend/app/workers/platforms/search_engine.py#L163-L174)
|
||||
|
||||
章节来源
|
||||
- [wenxin.py:11-205](file://backend/app/workers/platforms/wenxin.py#L11-L205)
|
||||
**章节来源**
|
||||
- [wenxin.py:10-38](file://backend/app/workers/platforms/wenxin.py#L10-L38)
|
||||
|
||||
### 搜索引擎模块(SearchEngine)
|
||||
- **角色与职责**
|
||||
- 提供统一的搜索内容获取能力
|
||||
- 支持DuckDuckGo HTML搜索和Wikipedia API查询
|
||||
- 实现智能回退机制,确保查询成功率
|
||||
|
||||
- **关键实现要点**
|
||||
- DuckDuckGo搜索:使用HTML解析获取搜索结果摘要
|
||||
- Wikipedia回退:当DuckDuckGo受限时自动切换到Wikipedia API
|
||||
- HTML解析:提取标题和摘要信息,去除HTML标签
|
||||
- 文本清理:移除引用标记和多余空白字符
|
||||
|
||||
- **搜索策略**
|
||||
- 主要策略:DuckDuckGo HTML搜索,无需API密钥
|
||||
- 回退策略:Wikipedia API查询,公开API无需认证
|
||||
- 结果合并:将多个搜索结果合并为统一格式
|
||||
|
||||
- **错误处理**
|
||||
- 搜索失败:记录警告并尝试回退策略
|
||||
- 解析失败:检查返回内容的有效性
|
||||
- 所有策略失败:抛出运行时错误
|
||||
|
||||
**章节来源**
|
||||
- [search_engine.py:16-77](file://backend/app/workers/platforms/search_engine.py#L16-L77)
|
||||
- [search_engine.py:79-145](file://backend/app/workers/platforms/search_engine.py#L79-L145)
|
||||
- [search_engine.py:147-174](file://backend/app/workers/platforms/search_engine.py#L147-L174)
|
||||
|
||||
### 引擎(CitationEngine)
|
||||
- 角色与职责
|
||||
- **角色与职责**
|
||||
- 编排查询任务,按平台顺序执行
|
||||
- 调用适配器获取原始响应,进行品牌匹配与竞争品牌检测
|
||||
- 将结果持久化为引用记录,并更新任务状态与查询时间
|
||||
|
||||
- 关键实现要点
|
||||
- 平台注册:内置文心与Kimi适配器,可扩展更多平台
|
||||
- **关键实现要点**
|
||||
- 平台注册:内置文心、Kimi、通义等适配器,均可扩展更多平台
|
||||
- 任务状态管理:运行中、成功、失败三种状态,失败时记录错误信息
|
||||
- 结果聚合:返回引用状态、置信度、匹配类型、位置、上下文、竞争品牌与原始响应
|
||||
- 关键词增强:为搜索引擎查询自动添加目标品牌关键词
|
||||
|
||||
- 错误处理
|
||||
- **错误处理**
|
||||
- 适配器异常会被捕获并记录,同时生成一条cited=False的占位记录
|
||||
- 任务状态与完成时间被正确更新,保证数据一致性
|
||||
|
||||
|
|
@ -207,7 +272,8 @@ Start(["开始执行查询"]) --> InitMatcher["初始化品牌匹配器"]
|
|||
InitMatcher --> IteratePlatforms["遍历平台列表"]
|
||||
IteratePlatforms --> CreateTask["获取或创建任务记录"]
|
||||
CreateTask --> UpdateTaskRunning["更新任务状态为 running"]
|
||||
UpdateTaskRunning --> CallAdapter["调用适配器执行查询"]
|
||||
UpdateTaskRunning --> EnhanceKeyword["增强关键词添加目标品牌"]
|
||||
EnhanceKeyword --> CallAdapter["调用适配器执行查询"]
|
||||
CallAdapter --> ParseResult["品牌匹配与竞争品牌检测"]
|
||||
ParseResult --> CreateRecord["创建引用记录"]
|
||||
CreateRecord --> UpdateTaskSuccess["更新任务状态为 success"]
|
||||
|
|
@ -217,171 +283,194 @@ NextPlatform --> |否| UpdateQueryTime["更新查询时间字段"]
|
|||
UpdateQueryTime --> End(["结束"])
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [citation_engine.py:148-309](file://backend/app/workers/citation_engine.py#L148-L309)
|
||||
**图表来源**
|
||||
- [citation_engine.py:177-254](file://backend/app/workers/citation_engine.py#L177-L254)
|
||||
|
||||
章节来源
|
||||
- [citation_engine.py:148-309](file://backend/app/workers/citation_engine.py#L148-L309)
|
||||
**章节来源**
|
||||
- [citation_engine.py:161-176](file://backend/app/workers/citation_engine.py#L161-L176)
|
||||
- [citation_engine.py:177-254](file://backend/app/workers/citation_engine.py#L177-L254)
|
||||
|
||||
### 配置管理(Settings)
|
||||
- 配置项说明
|
||||
- **配置项说明**
|
||||
- 数据库连接:DATABASE_URL
|
||||
- Redis连接:REDIS_URL
|
||||
- JWT密钥与过期:JWT_SECRET、JWT_EXPIRE_HOURS
|
||||
- Playwright浏览器路径:PLAYWRIGHT_BROWSERS_PATH
|
||||
- API密钥占位:ZHIPU_API_KEY、TONGYI_API_KEY(当前未用于文心适配器)
|
||||
- Playwright浏览器路径:PLAYWRIGHT_BROWSERS_PATH(仍保留用于其他适配器)
|
||||
- API密钥占位:ZHIPU_API_KEY、TONGYI_API_KEY(当前未用于搜索引擎适配器)
|
||||
|
||||
- 环境变量加载
|
||||
- **环境变量加载**
|
||||
- 通过Pydantic Settings自动从.env文件加载,忽略未知字段
|
||||
|
||||
- 容器化与依赖
|
||||
- Dockerfile中安装系统依赖并预装Playwright浏览器,确保运行时可用
|
||||
- **容器化与依赖**
|
||||
- Dockerfile中安装系统依赖,但Playwright浏览器仅用于其他适配器
|
||||
- 确保搜索引擎查询功能正常运行
|
||||
|
||||
章节来源
|
||||
- [config.py:4-16](file://backend/app/config.py#L4-L16)
|
||||
- [Dockerfile:1-40](file://backend/Dockerfile#L1-L40)
|
||||
**章节来源**
|
||||
- [config.py:9-23](file://backend/app/config.py#L9-L23)
|
||||
- [Dockerfile:1-41](file://backend/Dockerfile#L1-L41)
|
||||
|
||||
### 数据模型(Query)
|
||||
- 字段说明
|
||||
- **字段说明**
|
||||
- 关键词、目标品牌、别名、平台集合、频率、状态、时间戳等
|
||||
- 默认平台集合包含文心与Kimi,便于快速启用
|
||||
|
||||
- 业务意义
|
||||
- **业务意义**
|
||||
- 作为查询任务的载体,驱动引擎执行跨平台检索与分析
|
||||
|
||||
章节来源
|
||||
**章节来源**
|
||||
- [query.py:11-55](file://backend/app/models/query.py#L11-L55)
|
||||
|
||||
### API入口(queries.py)
|
||||
- 功能概述
|
||||
- **功能概述**
|
||||
- 提供查询任务的增删改查接口,供前端调用
|
||||
- 与服务层协作,完成权限校验与数据持久化
|
||||
|
||||
- 与引擎的关系
|
||||
- **与引擎的关系**
|
||||
- 引擎在后台异步执行查询,API负责暴露任务管理能力
|
||||
|
||||
章节来源
|
||||
- [queries.py:1-86](file://backend/app/api/queries.py#L1-L86)
|
||||
**章节来源**
|
||||
- [queries.py:1-109](file://backend/app/api/queries.py#L1-L109)
|
||||
|
||||
## 依赖关系分析
|
||||
- 组件耦合
|
||||
- CitationEngine依赖WenxinAdapter与KimiAdapter,形成平台无关的编排层
|
||||
- WenxinAdapter依赖Playwright进行页面自动化,不依赖HTTP客户端
|
||||
- **组件耦合**
|
||||
- CitationEngine依赖各平台适配器,形成平台无关的编排层
|
||||
- 所有搜索引擎适配器依赖统一的SearchEngine模块
|
||||
- SearchEngine依赖外部服务(DuckDuckGo、Wikipedia)
|
||||
- 引擎与模型解耦,通过ORM进行数据持久化
|
||||
|
||||
- 外部依赖
|
||||
- Playwright:无头浏览器自动化
|
||||
- Docker:容器化部署,预装浏览器与系统依赖
|
||||
- **外部依赖**
|
||||
- DuckDuckGo:免费HTML搜索服务
|
||||
- Wikipedia API:公开百科查询服务
|
||||
- Docker:容器化部署,包含必要的系统依赖
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
Engine["CitationEngine"] --> Wenxin["WenxinAdapter"]
|
||||
Engine --> Kimi["KimiAdapter"]
|
||||
Wenxin --> Playwright["Playwright"]
|
||||
Kimi --> Playwright
|
||||
Engine --> Tongyi["TongyiAdapter"]
|
||||
Wenxin --> Search["SearchEngine"]
|
||||
Kimi --> Search
|
||||
Tongyi --> Search
|
||||
Search --> DDG["DuckDuckGo"]
|
||||
Search --> Wiki["Wikipedia API"]
|
||||
Engine --> ORM["SQLAlchemy ORM"]
|
||||
Engine --> Model["Query模型"]
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [citation_engine.py:148-309](file://backend/app/workers/citation_engine.py#L148-L309)
|
||||
- [wenxin.py:11-205](file://backend/app/workers/platforms/wenxin.py#L11-L205)
|
||||
**图表来源**
|
||||
- [citation_engine.py:161-176](file://backend/app/workers/citation_engine.py#L161-L176)
|
||||
- [wenxin.py:10-38](file://backend/app/workers/platforms/wenxin.py#L10-L38)
|
||||
- [kimi.py:10-38](file://backend/app/workers/platforms/kimi.py#L10-L38)
|
||||
- [tongyi.py:10-38](file://backend/app/workers/platforms/tongyi.py#L10-L38)
|
||||
- [search_engine.py:163-174](file://backend/app/workers/platforms/search_engine.py#L163-L174)
|
||||
|
||||
章节来源
|
||||
- [citation_engine.py:148-309](file://backend/app/workers/citation_engine.py#L148-L309)
|
||||
- [wenxin.py:11-205](file://backend/app/workers/platforms/wenxin.py#L11-L205)
|
||||
**章节来源**
|
||||
- [citation_engine.py:161-176](file://backend/app/workers/citation_engine.py#L161-L176)
|
||||
- [wenxin.py:10-38](file://backend/app/workers/platforms/wenxin.py#L10-L38)
|
||||
- [search_engine.py:163-174](file://backend/app/workers/platforms/search_engine.py#L163-L174)
|
||||
|
||||
## 性能考虑
|
||||
- 浏览器资源复用
|
||||
- 适配器内部维护浏览器实例,避免重复启动带来的冷启动开销
|
||||
- 稳定性检测优化
|
||||
- 通过连续检测与超时控制,减少无效重试
|
||||
- 重试策略
|
||||
- 最多重试3次,指数退避降低瞬时压力
|
||||
- 超时设置
|
||||
- 页面导航、元素查找、发送按钮等待均有明确超时,防止长时间阻塞
|
||||
- **查询效率**
|
||||
- 搜索引擎查询比浏览器自动化更快,响应时间更短
|
||||
- 减少内存和CPU消耗,提高并发处理能力
|
||||
- 无需维护浏览器实例,降低资源开销
|
||||
|
||||
章节来源
|
||||
- [wenxin.py:33-48](file://backend/app/workers/platforms/wenxin.py#L33-L48)
|
||||
- [wenxin.py:124-196](file://backend/app/workers/platforms/wenxin.py#L124-L196)
|
||||
- **稳定性优化**
|
||||
- 通过搜索引擎模块的回退机制,提高查询成功率
|
||||
- 统一的错误处理和重试策略
|
||||
- 外部服务的超时控制,防止长时间阻塞
|
||||
|
||||
- **重试策略**
|
||||
- 最多重试3次,指数退避降低瞬时压力
|
||||
- 搜索引擎查询超时30秒,确保及时响应
|
||||
|
||||
- **缓存与优化**
|
||||
- 搜索结果可利用外部服务的缓存机制
|
||||
- 减少重复查询,提高整体性能
|
||||
|
||||
**章节来源**
|
||||
- [wenxin.py:16-29](file://backend/app/workers/platforms/wenxin.py#L16-L29)
|
||||
- [search_engine.py:163-174](file://backend/app/workers/platforms/search_engine.py#L163-L174)
|
||||
|
||||
## 故障排查指南
|
||||
- 启动浏览器失败
|
||||
- 现象:初始化浏览器时报错,提示未安装Playwright浏览器
|
||||
- 处理:在容器内执行Playwright浏览器安装命令;检查Dockerfile中的安装步骤
|
||||
- 参考:[wenxin.py:21-31](file://backend/app/workers/platforms/wenxin.py#L21-L31)、[Dockerfile:31-33](file://backend/Dockerfile#L31-L33)
|
||||
- **搜索引擎查询失败**
|
||||
- 现象:DuckDuckGo搜索受限或返回空结果
|
||||
- 处理:自动回退到Wikipedia API;检查网络连通性
|
||||
- 参考:[search_engine.py:139-144](file://backend/app/workers/platforms/search_engine.py#L139-L144)
|
||||
|
||||
- 页面操作超时
|
||||
- 现象:页面导航或元素查找超时
|
||||
- 处理:检查网络连通性、目标站点可达性;适当调整超时参数
|
||||
- 参考:[wenxin.py:64-87](file://backend/app/workers/platforms/wenxin.py#L64-L87)、[wenxin.py:114-117](file://backend/app/workers/platforms/wenxin.py#L114-L117)
|
||||
- **Wikipedia API查询失败**
|
||||
- 现象:百科查询不可用或返回空内容
|
||||
- 处理:检查Wikipedia API可用性;确认关键词有效性
|
||||
- 参考:[search_engine.py:28-76](file://backend/app/workers/platforms/search_engine.py#L28-L76)
|
||||
|
||||
- 无法找到输入框
|
||||
- 现象:页面结构变更导致选择器失效
|
||||
- 处理:更新输入框选择器列表;增加容错分支
|
||||
- 参考:[wenxin.py:67-87](file://backend/app/workers/platforms/wenxin.py#L67-L87)
|
||||
- **HTML解析失败**
|
||||
- 现象:DuckDuckGo返回的HTML结构发生变化
|
||||
- 处理:更新HTML解析正则表达式;增加容错分支
|
||||
- 参考:[search_engine.py:105-137](file://backend/app/workers/platforms/search_engine.py#L105-L137)
|
||||
|
||||
- 回复不稳定
|
||||
- 现象:文本持续变化,无法稳定
|
||||
- 处理:延长等待时间或放宽稳定阈值;检查页面动态加载逻辑
|
||||
- 参考:[wenxin.py:124-196](file://backend/app/workers/platforms/wenxin.py#L124-L196)
|
||||
- **适配器查询异常**
|
||||
- 现象:搜索引擎查询抛出异常
|
||||
- 处理:检查重试机制;查看日志定位根因
|
||||
- 参考:[wenxin.py:16-29](file://backend/app/workers/platforms/wenxin.py#L16-L29)
|
||||
|
||||
- 引擎执行失败
|
||||
- **引擎执行失败**
|
||||
- 现象:适配器异常导致任务失败
|
||||
- 处理:记录错误信息并生成占位记录;检查日志定位根因
|
||||
- 参考:[citation_engine.py:211-227](file://backend/app/workers/citation_engine.py#L211-L227)
|
||||
- 参考:[citation_engine.py:231-247](file://backend/app/workers/citation_engine.py#L231-L247)
|
||||
|
||||
- 单元测试验证
|
||||
- **单元测试验证**
|
||||
- 测试覆盖平台返回值与统计数据,确保集成链路正常
|
||||
- 参考:[test_citations.py:23-93](file://tests/test_citations.py#L23-L93)
|
||||
|
||||
章节来源
|
||||
- [wenxin.py:21-31](file://backend/app/workers/platforms/wenxin.py#L21-L31)
|
||||
- [wenxin.py:64-87](file://backend/app/workers/platforms/wenxin.py#L64-L87)
|
||||
- [wenxin.py:114-117](file://backend/app/workers/platforms/wenxin.py#L114-L117)
|
||||
- [wenxin.py:124-196](file://backend/app/workers/platforms/wenxin.py#L124-L196)
|
||||
- [citation_engine.py:211-227](file://backend/app/workers/citation_engine.py#L211-L227)
|
||||
**章节来源**
|
||||
- [search_engine.py:139-144](file://backend/app/workers/platforms/search_engine.py#L139-L144)
|
||||
- [search_engine.py:28-76](file://backend/app/workers/platforms/search_engine.py#L28-L76)
|
||||
- [search_engine.py:105-137](file://backend/app/workers/platforms/search_engine.py#L105-L137)
|
||||
- [wenxin.py:16-29](file://backend/app/workers/platforms/wenxin.py#L16-L29)
|
||||
- [citation_engine.py:231-247](file://backend/app/workers/citation_engine.py#L231-L247)
|
||||
- [test_citations.py:23-93](file://tests/test_citations.py#L23-L93)
|
||||
|
||||
## 结论
|
||||
文心平台集成通过“浏览器自动化 + 引擎编排”的方式,实现了对文心一言的稳定查询与响应解析。其特点包括:
|
||||
- 明确的适配器接口与可扩展的平台注册机制
|
||||
- 完善的重试与稳定性检测策略
|
||||
文心平台集成通过"搜索引擎查询 + 引擎编排"的方式,实现了对文心一言的高效查询与内容获取。其特点包括:
|
||||
- 简化的适配器实现,移除复杂的浏览器自动化逻辑
|
||||
- 统一的搜索引擎查询机制,提高查询成功率和稳定性
|
||||
- 完善的重试与回退策略,确保在各种情况下都能获取内容
|
||||
- 清晰的错误处理与任务状态管理
|
||||
- 与容器化部署的无缝衔接
|
||||
|
||||
在实际使用中,建议结合业务需求对超时、重试与稳定性阈值进行调优,并持续关注页面结构变化以保持选择器的有效性。
|
||||
在实际使用中,建议结合业务需求对搜索引擎查询参数进行调优,并持续关注搜索引擎API的变化以保持功能的稳定性。
|
||||
|
||||
## 附录
|
||||
|
||||
### API调用示例与错误处理方案
|
||||
- 示例场景
|
||||
- **示例场景**
|
||||
- 前端通过查询API创建任务,后台引擎按平台顺序执行
|
||||
- 引擎调用文心适配器获取原始响应,进行品牌匹配与统计
|
||||
- 若适配器异常,引擎记录失败并生成占位记录
|
||||
- 引擎调用文心适配器获取搜索内容,进行品牌匹配与统计
|
||||
- 若搜索引擎查询异常,引擎记录失败并生成占位记录
|
||||
|
||||
- 错误处理方案
|
||||
- 适配器异常:捕获并记录,返回占位记录
|
||||
- 页面超时:延长等待或放宽阈值
|
||||
- 选择器失效:更新选择器列表并增加容错分支
|
||||
- **错误处理方案**
|
||||
- 搜索引擎查询异常:自动回退到Wikipedia API;记录错误并重试
|
||||
- HTML解析失败:更新解析规则并增加容错分支
|
||||
- 外部服务不可用:使用缓存内容或回退策略
|
||||
|
||||
章节来源
|
||||
- [queries.py:1-86](file://backend/app/api/queries.py#L1-L86)
|
||||
- [citation_engine.py:148-309](file://backend/app/workers/citation_engine.py#L148-L309)
|
||||
- [wenxin.py:33-122](file://backend/app/workers/platforms/wenxin.py#L33-L122)
|
||||
**章节来源**
|
||||
- [queries.py:90-109](file://backend/app/api/queries.py#L90-L109)
|
||||
- [citation_engine.py:177-254](file://backend/app/workers/citation_engine.py#L177-L254)
|
||||
- [wenxin.py:16-33](file://backend/app/workers/platforms/wenxin.py#L16-L33)
|
||||
|
||||
### 安全注意事项与最佳实践
|
||||
- 安全注意事项
|
||||
- 该实现为浏览器自动化,不涉及HTTP请求头与API密钥传递
|
||||
- 生产环境建议限制容器网络访问范围,仅允许必要域名
|
||||
- **安全注意事项**
|
||||
- 该实现使用公开的搜索引擎API,无需API密钥
|
||||
- 遵循搜索引擎的使用条款和限制
|
||||
- 日志中避免输出敏感信息(如用户输入、错误堆栈)
|
||||
|
||||
- 最佳实践
|
||||
- 在Dockerfile中预装浏览器与系统依赖,确保部署一致性
|
||||
- 对页面选择器进行版本化管理,随页面结构变更同步更新
|
||||
- 设置合理的超时与重试策略,平衡稳定性与性能
|
||||
- **最佳实践**
|
||||
- 使用统一的搜索引擎模块,确保查询策略的一致性
|
||||
- 设置合理的超时和重试策略,平衡稳定性与性能
|
||||
- 监控搜索引擎API的可用性和性能指标
|
||||
- 定期更新HTML解析规则以适应搜索引擎页面结构变化
|
||||
- 使用单元测试覆盖关键流程,保障回归质量
|
||||
|
||||
章节来源
|
||||
- [Dockerfile:1-40](file://backend/Dockerfile#L1-L40)
|
||||
**章节来源**
|
||||
- [search_engine.py:163-174](file://backend/app/workers/platforms/search_engine.py#L163-L174)
|
||||
- [test_citations.py:23-93](file://tests/test_citations.py#L23-L93)
|
||||
|
|
@ -4,11 +4,13 @@
|
|||
**本文档引用的文件**
|
||||
- [backend/app/api/queries.py](file://backend/app/api/queries.py)
|
||||
- [backend/app/schemas/query.py](file://backend/app/schemas/query.py)
|
||||
- [backend/app/schemas/citation.py](file://backend/app/schemas/citation.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/models/user.py](file://backend/app/models/user.py)
|
||||
- [backend/app/services/query.py](file://backend/app/services/query.py)
|
||||
- [backend/app/services/citation.py](file://backend/app/services/citation.py)
|
||||
- [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)
|
||||
|
|
@ -17,8 +19,16 @@
|
|||
- [backend/app/api/citations.py](file://backend/app/api/citations.py)
|
||||
- [backend/app/main.py](file://backend/app/main.py)
|
||||
- [tests/test_queries.py](file://tests/test_queries.py)
|
||||
- [tests/test_business_flow.py](file://tests/test_business_flow.py)
|
||||
</cite>
|
||||
|
||||
## 更新摘要
|
||||
**变更内容**
|
||||
- 更新run-now功能的API文档,反映其已合并到主查询API中
|
||||
- 修正API路由结构,移除独立的run_now_router结构
|
||||
- 更新架构图和依赖关系,体现新的API组织方式
|
||||
- 补充run-now接口的详细使用说明和错误处理
|
||||
|
||||
## 目录
|
||||
1. [简介](#简介)
|
||||
2. [项目结构](#项目结构)
|
||||
|
|
@ -32,11 +42,11 @@
|
|||
10. [附录](#附录)
|
||||
|
||||
## 简介
|
||||
本文件为“查询管理系统”的详细API文档,覆盖查询任务的创建、读取、更新、删除与执行全流程;详述查询任务的数据模型、字段定义与验证规则;文档化查询任务的状态管理、调度机制与执行监控;包含查询参数配置、定时任务设置与批量操作接口的使用建议;并提供查询任务生命周期管理的最佳实践与错误处理策略。
|
||||
本文件为"查询管理系统"的详细API文档,覆盖查询任务的创建、读取、更新、删除与执行全流程;详述查询任务的数据模型、字段定义与验证规则;文档化查询任务的状态管理、调度机制与执行监控;包含查询参数配置、定时任务设置与批量操作接口的使用建议;并提供查询任务生命周期管理的最佳实践与错误处理策略。
|
||||
|
||||
## 项目结构
|
||||
后端采用FastAPI + SQLAlchemy异步ORM + PostgreSQL数据库,查询管理相关模块分布如下:
|
||||
- API层:负责路由定义与请求/响应封装
|
||||
- API层:负责路由定义与请求/响应封装,包含主查询API和引用API
|
||||
- Schema层:Pydantic模型,定义请求体与响应体的字段与校验
|
||||
- Model层:SQLAlchemy ORM模型,定义数据库表结构与索引
|
||||
- Service层:业务逻辑封装,处理权限、计数限制与时间计算
|
||||
|
|
@ -51,6 +61,7 @@ CAPI["引用API<br/>backend/app/api/citations.py"]
|
|||
end
|
||||
subgraph "Schema层"
|
||||
QS["查询Schema<br/>backend/app/schemas/query.py"]
|
||||
CS["引用Schema<br/>backend/app/schemas/citation.py"]
|
||||
end
|
||||
subgraph "Model层"
|
||||
MQ["查询模型<br/>backend/app/models/query.py"]
|
||||
|
|
@ -59,7 +70,8 @@ MR["引用记录模型<br/>backend/app/models/citation_record.py"]
|
|||
MU["用户模型<br/>backend/app/models/user.py"]
|
||||
end
|
||||
subgraph "Service层"
|
||||
S["查询服务<br/>backend/app/services/query.py"]
|
||||
SQ["查询服务<br/>backend/app/services/query.py"]
|
||||
SC["引用服务<br/>backend/app/services/citation.py"]
|
||||
end
|
||||
subgraph "Worker层"
|
||||
SCH["调度器<br/>backend/app/workers/scheduler.py"]
|
||||
|
|
@ -70,57 +82,67 @@ BASE["适配器基类<br/>backend/app/workers/platforms/base.py"]
|
|||
KIMI["Kimi适配器<br/>backend/app/workers/platforms/kimi.py"]
|
||||
WENXIN["文心一言适配器<br/>backend/app/workers/platforms/wenxin.py"]
|
||||
end
|
||||
QAPI --> S
|
||||
CAPI --> CE
|
||||
S --> MQ
|
||||
CE --> MQ
|
||||
CE --> MR
|
||||
CE --> MT
|
||||
QAPI --> SQ
|
||||
CAPI --> SC
|
||||
SQ --> MQ
|
||||
SC --> MQ
|
||||
SC --> MR
|
||||
SC --> MT
|
||||
SCH --> CE
|
||||
CE --> KIMI
|
||||
CE --> WENXIN
|
||||
QS --> QAPI
|
||||
CS --> QAPI
|
||||
CS --> CAPI
|
||||
MQ --> MU
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [backend/app/api/queries.py:1-86](file://backend/app/api/queries.py#L1-L86)
|
||||
- [backend/app/api/citations.py:1-78](file://backend/app/api/citations.py#L1-L78)
|
||||
**图表来源**
|
||||
- [backend/app/api/queries.py:1-109](file://backend/app/api/queries.py#L1-L109)
|
||||
- [backend/app/api/citations.py:1-55](file://backend/app/api/citations.py#L1-L55)
|
||||
- [backend/app/schemas/query.py:1-94](file://backend/app/schemas/query.py#L1-L94)
|
||||
- [backend/app/schemas/citation.py:1-52](file://backend/app/schemas/citation.py#L1-L52)
|
||||
- [backend/app/models/query.py:1-55](file://backend/app/models/query.py#L1-L55)
|
||||
- [backend/app/models/query_task.py:1-39](file://backend/app/models/query_task.py#L1-L39)
|
||||
- [backend/app/models/citation_record.py:1-42](file://backend/app/models/citation_record.py#L1-L42)
|
||||
- [backend/app/models/user.py:1-41](file://backend/app/models/user.py#L1-L41)
|
||||
- [backend/app/services/query.py:1-130](file://backend/app/services/query.py#L1-L130)
|
||||
- [backend/app/services/citation.py:1-429](file://backend/app/services/citation.py#L1-L429)
|
||||
- [backend/app/workers/scheduler.py:1-95](file://backend/app/workers/scheduler.py#L1-L95)
|
||||
- [backend/app/workers/citation_engine.py:1-309](file://backend/app/workers/citation_engine.py#L1-L309)
|
||||
- [backend/app/workers/platforms/base.py:1-18](file://backend/app/workers/platforms/base.py#L1-L18)
|
||||
- [backend/app/workers/platforms/kimi.py:1-206](file://backend/app/workers/platforms/kimi.py#L1-L206)
|
||||
- [backend/app/workers/platforms/wenxin.py:1-205](file://backend/app/workers/platforms/wenxin.py#L1-L205)
|
||||
|
||||
章节来源
|
||||
**章节来源**
|
||||
- [backend/app/main.py:1-48](file://backend/app/main.py#L1-L48)
|
||||
|
||||
## 核心组件
|
||||
- 查询API:提供查询任务的增删改查与分页列表接口
|
||||
- 查询API:提供查询任务的增删改查与分页列表接口,包含run-now立即执行功能
|
||||
- 引用API:提供查询历史、统计与导出接口
|
||||
- 查询Schema:定义创建/更新请求体与响应体的字段与校验规则
|
||||
- 引用Schema:定义引用记录、统计和run-now响应的数据结构
|
||||
- 查询模型:定义数据库表结构、索引与关联关系
|
||||
- 查询任务模型:记录每次平台执行的任务状态与时间戳
|
||||
- 引用记录模型:保存每次查询的结果与统计信息
|
||||
- 用户模型:限制用户的最大查询数量
|
||||
- 查询服务:实现权限控制、计数限制与下次查询时间计算
|
||||
- 引用服务:实现引用数据查询、统计、立即执行和导出功能
|
||||
- 调度器:基于APScheduler的定时任务,周期性检查并执行到期查询
|
||||
- 引用引擎:跨平台执行查询、品牌匹配、竞争品牌检测与结果持久化
|
||||
- 平台适配器:Kimi与文心一言的自动化查询实现
|
||||
|
||||
章节来源
|
||||
- [backend/app/api/queries.py:15-85](file://backend/app/api/queries.py#L15-L85)
|
||||
**章节来源**
|
||||
- [backend/app/api/queries.py:15-109](file://backend/app/api/queries.py#L15-L109)
|
||||
- [backend/app/api/citations.py:19-55](file://backend/app/api/citations.py#L19-L55)
|
||||
- [backend/app/schemas/query.py:11-94](file://backend/app/schemas/query.py#L11-L94)
|
||||
- [backend/app/schemas/citation.py:7-52](file://backend/app/schemas/citation.py#L7-L52)
|
||||
- [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/models/user.py:11-41](file://backend/app/models/user.py#L11-L41)
|
||||
- [backend/app/services/query.py:12-130](file://backend/app/services/query.py#L12-L130)
|
||||
- [backend/app/services/citation.py:219-429](file://backend/app/services/citation.py#L219-L429)
|
||||
- [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)
|
||||
|
|
@ -131,7 +153,8 @@ MQ --> MU
|
|||
- 调度器定时扫描满足条件的查询任务,触发引用引擎执行
|
||||
- 引用引擎遍历平台列表,调用平台适配器获取AI回复,执行品牌匹配与竞争品牌检测,生成引用记录
|
||||
- 查询任务模型记录每次执行的状态与时间,便于监控与重试
|
||||
- 引用API提供查询历史、统计与“立即执行”接口
|
||||
- 引用API提供查询历史、统计与导出接口
|
||||
- **新增**:run-now功能允许用户立即执行查询任务,绕过正常调度机制
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
|
|
@ -155,11 +178,20 @@ Scheduler->>Engine : "execute_query(query)"
|
|||
Engine->>Adapter : "逐平台查询(keyword)"
|
||||
Adapter-->>Engine : "返回原始回复"
|
||||
Engine->>DB : "写入引用记录与更新查询时间"
|
||||
Note over Client,API : "立即执行"
|
||||
Client->>API : "POST /api/v1/queries/{query_id}/run-now"
|
||||
API->>Service : "trigger_query_now(...)"
|
||||
Service->>DB : "创建QueryTask并立即执行"
|
||||
DB-->>Service : "返回任务"
|
||||
Service-->>API : "返回任务"
|
||||
API-->>Client : "202 Accepted"
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [backend/app/api/queries.py:26-39](file://backend/app/api/queries.py#L26-L39)
|
||||
**图表来源**
|
||||
- [backend/app/api/queries.py:28-41](file://backend/app/api/queries.py#L28-L41)
|
||||
- [backend/app/api/queries.py:90-109](file://backend/app/api/queries.py#L90-L109)
|
||||
- [backend/app/services/query.py:45-81](file://backend/app/services/query.py#L45-L81)
|
||||
- [backend/app/services/citation.py:219-261](file://backend/app/services/citation.py#L219-L261)
|
||||
- [backend/app/workers/scheduler.py:51-84](file://backend/app/workers/scheduler.py#L51-L84)
|
||||
- [backend/app/workers/citation_engine.py:159-234](file://backend/app/workers/citation_engine.py#L159-L234)
|
||||
- [backend/app/workers/platforms/kimi.py:33-48](file://backend/app/workers/platforms/kimi.py#L33-L48)
|
||||
|
|
@ -233,13 +265,13 @@ QUERIES ||--o{ CITATION_RECORDS : "产生"
|
|||
QUERIES ||--o{ QUERY_TASKS : "驱动"
|
||||
```
|
||||
|
||||
图表来源
|
||||
**图表来源**
|
||||
- [backend/app/models/user.py:11-41](file://backend/app/models/user.py#L11-L41)
|
||||
- [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/models/user.py:11-41](file://backend/app/models/user.py#L11-L41)
|
||||
- [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)
|
||||
|
|
@ -269,12 +301,12 @@ stateDiagram-v2
|
|||
失败 --> 待调度 : "更新next_query_at"
|
||||
```
|
||||
|
||||
图表来源
|
||||
**图表来源**
|
||||
- [backend/app/workers/scheduler.py:51-84](file://backend/app/workers/scheduler.py#L51-L84)
|
||||
- [backend/app/workers/citation_engine.py:176-234](file://backend/app/workers/citation_engine.py#L176-L234)
|
||||
- [backend/app/models/query_task.py:24-32](file://backend/app/models/query_task.py#L24-L32)
|
||||
|
||||
章节来源
|
||||
**章节来源**
|
||||
- [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)
|
||||
|
||||
|
|
@ -301,11 +333,11 @@ StatusOK --> |否| ErrStatus["抛出状态无效错误"]
|
|||
StatusOK --> |是| Done(["校验通过"])
|
||||
```
|
||||
|
||||
图表来源
|
||||
**图表来源**
|
||||
- [backend/app/schemas/query.py:18-33](file://backend/app/schemas/query.py#L18-L33)
|
||||
- [backend/app/schemas/query.py:44-72](file://backend/app/schemas/query.py#L44-L72)
|
||||
|
||||
章节来源
|
||||
**章节来源**
|
||||
- [backend/app/schemas/query.py:6-9](file://backend/app/schemas/query.py#L6-L9)
|
||||
- [backend/app/schemas/query.py:11-94](file://backend/app/schemas/query.py#L11-L94)
|
||||
|
||||
|
|
@ -335,21 +367,25 @@ StatusOK --> |是| Done(["校验通过"])
|
|||
- 响应:204 No Content
|
||||
- 错误:不存在返回404
|
||||
|
||||
- 引用数据与立即执行
|
||||
- **立即执行查询**(已合并到主查询API)
|
||||
- POST /api/v1/queries/{query_id}/run-now
|
||||
- 功能:立即将某个查询加入执行队列
|
||||
- 响应:包含task_id、status与消息的RunNowResponse
|
||||
- 状态码:202 Accepted(任务已加入队列)
|
||||
- 错误:查询不存在、不属于当前用户或查询状态不为active时返回404
|
||||
|
||||
- 引用数据与统计
|
||||
- GET /api/v1/citations/
|
||||
- 功能:分页查询引用记录,支持按query_id、platform、日期范围过滤
|
||||
- 响应:包含items与total的列表响应
|
||||
- GET /api/v1/citations/stats
|
||||
- 功能:获取引用统计
|
||||
- 响应:统计结果
|
||||
- POST /api/v1/queries/{query_id}/run-now
|
||||
- 功能:立即将某个查询加入执行队列
|
||||
- 响应:包含task_id、status与消息
|
||||
- 错误:查询不存在或不属于当前用户返回404
|
||||
|
||||
章节来源
|
||||
- [backend/app/api/queries.py:15-85](file://backend/app/api/queries.py#L15-L85)
|
||||
- [backend/app/api/citations.py:25-77](file://backend/app/api/citations.py#L25-L77)
|
||||
**章节来源**
|
||||
- [backend/app/api/queries.py:17-109](file://backend/app/api/queries.py#L17-L109)
|
||||
- [backend/app/api/citations.py:22-55](file://backend/app/api/citations.py#L22-L55)
|
||||
- [backend/app/schemas/citation.py:48-52](file://backend/app/schemas/citation.py#L48-L52)
|
||||
|
||||
### 生命周期管理最佳实践
|
||||
- 合理设置frequency:daily适合高频监控,weekly适合常规跟踪
|
||||
|
|
@ -357,6 +393,7 @@ StatusOK --> |是| Done(["校验通过"])
|
|||
- 使用status暂停:在维护或节假日可将查询置为paused避免执行
|
||||
- 监控next_query_at:确保调度器能按时触发
|
||||
- 引用记录归档:定期清理过期记录,保持查询性能
|
||||
- **新增**:合理使用run-now功能:仅在紧急情况下使用,避免过度消耗资源
|
||||
|
||||
### 错误处理策略
|
||||
- 参数校验失败:返回422,提示具体字段问题
|
||||
|
|
@ -364,18 +401,21 @@ StatusOK --> |是| Done(["校验通过"])
|
|||
- 超过用户最大查询数:返回403
|
||||
- 平台适配器异常:记录error_message,状态标记为failed
|
||||
- 调度器异常:日志记录错误并继续运行
|
||||
- **新增**:run-now功能错误处理:查询状态非active、无平台配置等情况返回404
|
||||
|
||||
章节来源
|
||||
**章节来源**
|
||||
- [backend/app/api/queries.py:32-39](file://backend/app/api/queries.py#L32-L39)
|
||||
- [backend/app/api/queries.py:49-53](file://backend/app/api/queries.py#L49-L53)
|
||||
- [backend/app/api/queries.py:64-69](file://backend/app/api/queries.py#L64-L69)
|
||||
- [backend/app/api/queries.py:79-84](file://backend/app/api/queries.py#L79-L84)
|
||||
- [backend/app/api/queries.py:96-103](file://backend/app/api/queries.py#L96-L103)
|
||||
- [backend/app/api/citations.py:65-71](file://backend/app/api/citations.py#L65-L71)
|
||||
|
||||
## 依赖分析
|
||||
- 组件耦合
|
||||
- API层依赖Service层;Service层依赖Model层;Worker层依赖Model层与平台适配器
|
||||
- 引用引擎依赖平台适配器,平台适配器继承自基类
|
||||
- **新增**:查询API现在直接依赖引用服务的trigger_query_now功能
|
||||
- 外部依赖
|
||||
- APscheduler用于定时调度
|
||||
- Playwright用于平台网页自动化
|
||||
|
|
@ -384,23 +424,26 @@ StatusOK --> |是| Done(["校验通过"])
|
|||
```mermaid
|
||||
graph LR
|
||||
APIQ["查询API"] --> SVCQ["查询服务"]
|
||||
APIC["引用API"] --> CE["引用引擎"]
|
||||
APIC["引用API"] --> SVCC["引用服务"]
|
||||
APIQ --> SVCC
|
||||
SVCQ --> MODELS["查询/任务/记录模型"]
|
||||
CE --> MODELS
|
||||
SVCC --> MODELS
|
||||
SVCC --> CE["引用引擎"]
|
||||
CE --> ADP["平台适配器"]
|
||||
ADP --> BASE["适配器基类"]
|
||||
SCH["调度器"] --> CE
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [backend/app/api/queries.py:1-12](file://backend/app/api/queries.py#L1-L12)
|
||||
- [backend/app/api/citations.py:1-22](file://backend/app/api/citations.py#L1-L22)
|
||||
**图表来源**
|
||||
- [backend/app/api/queries.py:1-14](file://backend/app/api/queries.py#L1-L14)
|
||||
- [backend/app/api/citations.py:1-19](file://backend/app/api/citations.py#L1-L19)
|
||||
- [backend/app/services/query.py:1-10](file://backend/app/services/query.py#L1-L10)
|
||||
- [backend/app/services/citation.py:1-17](file://backend/app/services/citation.py#L1-L17)
|
||||
- [backend/app/workers/citation_engine.py:148-157](file://backend/app/workers/citation_engine.py#L148-L157)
|
||||
- [backend/app/workers/platforms/base.py:4-18](file://backend/app/workers/platforms/base.py#L4-L18)
|
||||
- [backend/app/workers/scheduler.py:25-39](file://backend/app/workers/scheduler.py#L25-L39)
|
||||
|
||||
章节来源
|
||||
**章节来源**
|
||||
- [backend/app/workers/scheduler.py:13-19](file://backend/app/workers/scheduler.py#L13-L19)
|
||||
- [backend/app/workers/platforms/kimi.py:17-32](file://backend/app/workers/platforms/kimi.py#L17-L32)
|
||||
- [backend/app/workers/platforms/wenxin.py:17-32](file://backend/app/workers/platforms/wenxin.py#L17-L32)
|
||||
|
|
@ -411,6 +454,7 @@ SCH["调度器"] --> CE
|
|||
- 异步I/O:使用异步数据库连接与平台适配器,提升并发能力
|
||||
- 调度频率:每小时检查一次,可根据业务量调整
|
||||
- 结果缓存:对频繁查询的平台响应可引入缓存(需结合业务场景)
|
||||
- **新增**:run-now功能的异步执行:使用asyncio.create_task避免阻塞主请求线程
|
||||
|
||||
## 故障排查指南
|
||||
- 调度器未启动:确认应用生命周期钩子已注册并启动调度器
|
||||
|
|
@ -418,16 +462,18 @@ SCH["调度器"] --> CE
|
|||
- 查询未执行:检查查询状态与next_query_at是否满足调度条件
|
||||
- 引用记录缺失:确认引用引擎执行流程与数据库提交顺序
|
||||
- 权限错误:确认用户max_queries限制与当前查询数量
|
||||
- **新增**:run-now功能问题排查:检查查询状态是否为active、平台配置是否正确、任务创建是否成功
|
||||
|
||||
章节来源
|
||||
**章节来源**
|
||||
- [backend/app/main.py:13-22](file://backend/app/main.py#L13-L22)
|
||||
- [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/scheduler.py:51-84](file://backend/app/workers/scheduler.py#L51-L84)
|
||||
- [backend/app/services/query.py:45-81](file://backend/app/services/query.py#L45-L81)
|
||||
- [backend/app/services/citation.py:219-261](file://backend/app/services/citation.py#L219-L261)
|
||||
|
||||
## 结论
|
||||
本查询管理系统以清晰的分层架构实现了查询任务的全生命周期管理:从创建、校验、调度到执行与监控。通过严格的参数校验、灵活的状态管理与可靠的调度机制,系统能够稳定支撑多平台、多频率的查询需求。建议在生产环境中结合业务量调整调度频率、优化平台适配器稳定性,并完善监控告警体系。
|
||||
本查询管理系统以清晰的分层架构实现了查询任务的全生命周期管理:从创建、校验、调度到执行与监控。通过严格的参数校验、灵活的状态管理与可靠的调度机制,系统能够稳定支撑多平台、多频率的查询需求。**最新的架构变更将run-now功能直接集成到主查询API中,简化了API结构并提供了更便捷的立即执行能力。** 建议在生产环境中结合业务量调整调度频率、优化平台适配器稳定性,并完善监控告警体系。
|
||||
|
||||
## 附录
|
||||
|
||||
|
|
@ -495,6 +541,11 @@ class WenxinAdapter {
|
|||
+query(keyword) str
|
||||
+close() void
|
||||
}
|
||||
class RunNowResponse {
|
||||
+uuid task_id
|
||||
+string status
|
||||
+string message
|
||||
}
|
||||
Query "1" --> "*" CitationRecord : "产生"
|
||||
Query "1" --> "*" QueryTask : "驱动"
|
||||
User "1" --> "*" Query : "拥有"
|
||||
|
|
@ -506,7 +557,7 @@ CitationEngine --> KimiAdapter : "调用"
|
|||
CitationEngine --> WenxinAdapter : "调用"
|
||||
```
|
||||
|
||||
图表来源
|
||||
**图表来源**
|
||||
- [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)
|
||||
|
|
@ -515,6 +566,7 @@ CitationEngine --> WenxinAdapter : "调用"
|
|||
- [backend/app/workers/scheduler.py:25-95](file://backend/app/workers/scheduler.py#L25-L95)
|
||||
- [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/schemas/citation.py:48-52](file://backend/app/schemas/citation.py#L48-L52)
|
||||
|
||||
### 单次查询执行序列图
|
||||
```mermaid
|
||||
|
|
@ -537,10 +589,19 @@ Engine->>Task : "状态=running"
|
|||
Engine->>Engine : "调用平台适配器"
|
||||
Engine->>Record : "创建引用记录"
|
||||
Engine->>DB : "提交事务"
|
||||
Note over API,DB : "run-now立即执行"
|
||||
API->>Service : "trigger_query_now(...)"
|
||||
Service->>DB : "创建QueryTask并立即执行"
|
||||
Service->>Engine : "_execute_query_tasks(...)"
|
||||
Engine->>Task : "状态=running"
|
||||
Engine->>Engine : "调用平台适配器"
|
||||
Engine->>Record : "创建引用记录"
|
||||
Engine->>DB : "提交事务"
|
||||
```
|
||||
|
||||
图表来源
|
||||
**图表来源**
|
||||
- [backend/app/services/query.py:45-81](file://backend/app/services/query.py#L45-L81)
|
||||
- [backend/app/services/citation.py:219-327](file://backend/app/services/citation.py#L219-L327)
|
||||
- [backend/app/workers/citation_engine.py:159-234](file://backend/app/workers/citation_engine.py#L159-L234)
|
||||
- [backend/app/models/query_task.py:176-289](file://backend/app/models/query_task.py#L176-L289)
|
||||
- [backend/app/models/citation_record.py:194-204](file://backend/app/models/citation_record.py#L194-L204)
|
||||
|
|
@ -5,6 +5,7 @@
|
|||
- [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/models/query.py](file://backend/app/models/query.py)
|
||||
- [backend/app/models/query_task.py](file://backend/app/models/query_task.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)
|
||||
|
|
@ -13,8 +14,16 @@
|
|||
- [backend/app/workers/platforms/base.py](file://backend/app/workers/platforms/base.py)
|
||||
- [backend/app/api/citations.py](file://backend/app/api/citations.py)
|
||||
- [backend/app/services/query.py](file://backend/app/services/query.py)
|
||||
- [tests/test_scheduler.py](file://tests/test_scheduler.py)
|
||||
</cite>
|
||||
|
||||
## 更新摘要
|
||||
**变更内容**
|
||||
- 新增分钟级轮询机制,每分钟检查并执行遗留的pending任务
|
||||
- 新增`check_and_execute_pending_tasks()`方法用于处理孤立的待处理任务
|
||||
- 新增对QueryTask模型的完整支持,包括`scheduled_at`字段的使用
|
||||
- 增强系统弹性,提供双重检查机制以提高任务执行可靠性
|
||||
|
||||
## 目录
|
||||
1. [引言](#引言)
|
||||
2. [项目结构](#项目结构)
|
||||
|
|
@ -30,7 +39,7 @@
|
|||
## 引言
|
||||
本文件系统性阐述基于 APScheduler 的 AsyncIOScheduler 的调度器设计与实现,重点覆盖以下方面:
|
||||
- 架构选择与初始化:如何通过 AsyncIOScheduler 实现与事件循环的无缝集成,并在启动时注册周期性任务。
|
||||
- 触发器与任务注册:使用间隔触发器每小时扫描并执行到期查询任务。
|
||||
- 双重触发器机制:使用小时级触发器每小时扫描并执行到期查询任务,同时使用分钟级触发器每分钟检查遗留的pending任务。
|
||||
- 核心组件职责:QueryScheduler 类的设计模式、事件循环管理、异步任务包装策略。
|
||||
- 启动与关闭流程:应用生命周期内调度器的启动与优雅停机,资源清理与并发安全。
|
||||
- 配置参数与性能调优:数据库连接、触发器频率、重试与指数退避策略、平台适配器资源管理。
|
||||
|
|
@ -60,14 +69,14 @@ Engine --> Platforms
|
|||
DB --> Models
|
||||
```
|
||||
|
||||
图表来源
|
||||
**图表来源**
|
||||
- [backend/app/main.py:13-22](file://backend/app/main.py#L13-L22)
|
||||
- [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/database.py:6-28](file://backend/app/database.py#L6-L28)
|
||||
- [backend/app/models/query.py:11-55](file://backend/app/models/query.py#L11-L55)
|
||||
|
||||
章节来源
|
||||
**章节来源**
|
||||
- [backend/app/main.py:1-48](file://backend/app/main.py#L1-L48)
|
||||
- [backend/app/workers/scheduler.py:1-95](file://backend/app/workers/scheduler.py#L1-L95)
|
||||
- [backend/app/database.py:1-29](file://backend/app/database.py#L1-L29)
|
||||
|
|
@ -77,19 +86,21 @@ DB --> Models
|
|||
- QueryScheduler:封装 AsyncIOScheduler,负责注册周期性任务、事件循环管理、任务执行入口与优雅停机。
|
||||
- CitationEngine:核心业务引擎,负责品牌匹配、竞争品牌检测、平台适配器编排、任务状态持久化与下次查询时间计算。
|
||||
- 平台适配器:KimiAdapter 与 WenxinAdapter,基于 Playwright 的自动化查询与结果稳定检测,具备指数退避与资源清理能力。
|
||||
- 数据层:Query 模型及其索引,驱动调度器的查询筛选条件与频率控制。
|
||||
- 数据层:Query 模型及其索引,驱动调度器的查询筛选条件与频率控制;QueryTask 模型用于跟踪任务执行状态。
|
||||
|
||||
章节来源
|
||||
**章节来源**
|
||||
- [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/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/models/query.py:11-55](file://backend/app/models/query.py#L11-L55)
|
||||
- [backend/app/models/query_task.py:11-38](file://backend/app/models/query_task.py#L11-L38)
|
||||
|
||||
## 架构总览
|
||||
调度器采用“应用生命周期 + 异步调度器 + 引擎编排”的分层架构:
|
||||
调度器采用"应用生命周期 + 异步调度器 + 引擎编排"的分层架构,现已增强为双重检查机制:
|
||||
- 应用启动时通过 lifespan 钩子启动调度器。
|
||||
- 调度器以每小时为周期扫描数据库,筛选到期的 active 查询任务。
|
||||
- 同时以每分钟为周期检查遗留的 pending 查询任务,确保系统弹性。
|
||||
- 对每个查询任务,CitationEngine 负责跨平台执行、结果解析与持久化。
|
||||
- 平台适配器负责具体平台的网页自动化与稳定性检测。
|
||||
- 应用关闭时,调度器优雅停机并释放平台适配器资源。
|
||||
|
|
@ -106,8 +117,10 @@ participant Plat as "平台适配器"
|
|||
App->>Life : "应用启动"
|
||||
Life->>Sched : "start()"
|
||||
Sched->>APS : "add_job(IntervalTrigger(hours=1))"
|
||||
Sched->>APS : "add_job(IntervalTrigger(minutes=1))"
|
||||
APS-->>Sched : "注册成功"
|
||||
APS->>Sched : "定时回调 _run_check"
|
||||
APS->>Sched : "定时回调 _run_pending_tasks_check"
|
||||
Sched->>Sched : "事件循环包装"
|
||||
Sched->>DB : "创建异步会话"
|
||||
DB-->>Sched : "会话实例"
|
||||
|
|
@ -120,13 +133,22 @@ Plat-->>Eng : "原始响应文本"
|
|||
Eng-->>Sched : "CitationRecord 列表"
|
||||
Sched->>DB : "更新 Query.next_query_at"
|
||||
end
|
||||
Sched->>DB : "查询 pending 且超时的 QueryTask"
|
||||
DB-->>Sched : "遗留任务列表"
|
||||
loop 对每个遗留任务
|
||||
Sched->>Eng : "execute_single_platform(query.keyword, task.platform)"
|
||||
Eng->>Plat : "query(keyword)"
|
||||
Plat-->>Eng : "原始响应文本"
|
||||
Eng-->>Sched : "CitationRecord 列表"
|
||||
Sched->>DB : "更新 QueryTask 状态"
|
||||
end
|
||||
App->>Life : "应用关闭"
|
||||
Life->>Sched : "shutdown()"
|
||||
Sched->>APS : "shutdown(wait=False)"
|
||||
Sched->>Eng : "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/workers/citation_engine.py:159-234](file://backend/app/workers/citation_engine.py#L159-L234)
|
||||
|
|
@ -137,9 +159,9 @@ Sched->>Eng : "close()"
|
|||
|
||||
### QueryScheduler 组件
|
||||
- 设计模式:职责分离 + 生命周期集成。将调度逻辑与业务执行解耦,通过 CitationEngine 承载核心业务。
|
||||
- 初始化与启动:构造函数创建 AsyncIOScheduler 与 CitationEngine;start() 注册每小时触发的任务,替换同名任务以避免重复。
|
||||
- 事件循环管理:_run_check() 在无运行中事件循环时使用 asyncio.run() 启动新事件循环,否则通过 loop.create_task() 将异步任务调度到当前事件循环,保证并发安全与可观察性。
|
||||
- 任务执行:check_and_execute_queries() 以异步会话查询到期的 active 查询,逐条调用 _execute_single_query(),捕获异常并继续处理其他任务。
|
||||
- 初始化与启动:构造函数创建 AsyncIOScheduler 与 CitationEngine;start() 注册每小时触发的任务和每分钟触发的遗留任务检查,替换同名任务以避免重复。
|
||||
- 事件循环管理:_run_check() 和 _run_pending_tasks_check() 在无运行中事件循环时使用 asyncio.run() 启动新事件循环,否则通过 loop.create_task() 将异步任务调度到当前事件循环,保证并发安全与可观察性。
|
||||
- 任务执行:check_and_execute_queries() 以异步会话查询到期的 active 查询,逐条调用 _execute_single_query(),捕获异常并继续处理其他任务;check_and_execute_pending_tasks() 处理超过1分钟仍未执行的遗留任务。
|
||||
- 关闭流程:shutdown() 调用 APScheduler 的 shutdown(wait=False) 与 CitationEngine.close(),确保平台资源释放。
|
||||
|
||||
```mermaid
|
||||
|
|
@ -150,6 +172,8 @@ class QueryScheduler {
|
|||
-_run_check() void
|
||||
+check_and_execute_queries() async
|
||||
-_execute_single_query(query, db) async
|
||||
-_run_pending_tasks_check() void
|
||||
+check_and_execute_pending_tasks() async
|
||||
-scheduler AsyncIOScheduler
|
||||
-engine CitationEngine
|
||||
}
|
||||
|
|
@ -166,11 +190,11 @@ class CitationEngine {
|
|||
QueryScheduler --> CitationEngine : "依赖"
|
||||
```
|
||||
|
||||
图表来源
|
||||
**图表来源**
|
||||
- [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/scheduler.py:25-95](file://backend/app/workers/scheduler.py#L25-L95)
|
||||
|
||||
### CitationEngine 组件
|
||||
|
|
@ -195,10 +219,10 @@ UpdateQuery --> IteratePlatforms
|
|||
IteratePlatforms --> |否| End(["结束"])
|
||||
```
|
||||
|
||||
图表来源
|
||||
**图表来源**
|
||||
- [backend/app/workers/citation_engine.py:159-234](file://backend/app/workers/citation_engine.py#L159-L234)
|
||||
|
||||
章节来源
|
||||
**章节来源**
|
||||
- [backend/app/workers/citation_engine.py:19-100](file://backend/app/workers/citation_engine.py#L19-L100)
|
||||
- [backend/app/workers/citation_engine.py:122-146](file://backend/app/workers/citation_engine.py#L122-L146)
|
||||
- [backend/app/workers/citation_engine.py:148-309](file://backend/app/workers/citation_engine.py#L148-L309)
|
||||
|
|
@ -237,12 +261,12 @@ KimiAdapter --|> BasePlatformAdapter
|
|||
WenxinAdapter --|> BasePlatformAdapter
|
||||
```
|
||||
|
||||
图表来源
|
||||
**图表来源**
|
||||
- [backend/app/workers/platforms/base.py:4-18](file://backend/app/workers/platforms/base.py#L4-L18)
|
||||
- [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/platforms/kimi.py:21-48](file://backend/app/workers/platforms/kimi.py#L21-L48)
|
||||
- [backend/app/workers/platforms/kimi.py:126-197](file://backend/app/workers/platforms/kimi.py#L126-L197)
|
||||
- [backend/app/workers/platforms/wenxin.py:21-48](file://backend/app/workers/platforms/wenxin.py#L21-L48)
|
||||
|
|
@ -250,17 +274,20 @@ WenxinAdapter --|> BasePlatformAdapter
|
|||
|
||||
### 数据模型与触发条件
|
||||
- Query 模型包含用户外键、关键词、目标品牌、别名、平台列表、频率、状态与时间戳字段,并建立多处索引以优化查询。
|
||||
- 触发条件:调度器按每小时扫描 status='active' 且 next_query_at <= now() 的记录,确保只执行到期任务。
|
||||
- QueryTask 模型用于跟踪任务执行状态,包含 scheduled_at 字段用于标识任务计划执行时间。
|
||||
- 触发条件:调度器按每小时扫描 status='active' 且 next_query_at <= now() 的记录,按每分钟扫描 status='pending' 且 scheduled_at <= one_minute_ago 的遗留任务。
|
||||
|
||||
章节来源
|
||||
**章节来源**
|
||||
- [backend/app/models/query.py:11-55](file://backend/app/models/query.py#L11-L55)
|
||||
- [backend/app/models/query_task.py:11-38](file://backend/app/models/query_task.py#L11-L38)
|
||||
- [backend/app/workers/scheduler.py:57-62](file://backend/app/workers/scheduler.py#L57-L62)
|
||||
- [backend/app/workers/scheduler.py:107-112](file://backend/app/workers/scheduler.py#L107-L112)
|
||||
|
||||
### 应用生命周期与手动触发
|
||||
- 应用启动:lifespan 钩子在应用启动时调用 query_scheduler.start(),在关闭时调用 shutdown()。
|
||||
- 手动触发:/api/v1/queries/{query_id}/run-now 接口调用服务层 trigger_query_now,将指定查询立即加入执行队列(由 CitationEngine 编排)。
|
||||
|
||||
章节来源
|
||||
**章节来源**
|
||||
- [backend/app/main.py:13-22](file://backend/app/main.py#L13-L22)
|
||||
- [backend/app/api/citations.py:59-77](file://backend/app/api/citations.py#L59-L77)
|
||||
- [backend/app/services/query.py:116-130](file://backend/app/services/query.py#L116-L130)
|
||||
|
|
@ -281,40 +308,43 @@ E --> D["AsyncSessionLocal"]
|
|||
D --> M["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/database.py:6-28](file://backend/app/database.py#L6-L28)
|
||||
- [backend/app/models/query.py:11-55](file://backend/app/models/query.py#L11-L55)
|
||||
|
||||
章节来源
|
||||
**章节来源**
|
||||
- [backend/app/workers/scheduler.py:13-20](file://backend/app/workers/scheduler.py#L13-L20)
|
||||
- [backend/app/workers/citation_engine.py:148-157](file://backend/app/workers/citation_engine.py#L148-L157)
|
||||
- [backend/app/database.py:1-29](file://backend/app/database.py#L1-L29)
|
||||
|
||||
## 性能考虑
|
||||
- 触发器频率:默认每小时一次,可根据业务负载调整;过短可能导致数据库压力与平台限流风险。
|
||||
- 数据库索引:Query 模型已建立多处索引,建议结合 EXPLAIN 分析查询计划,避免全表扫描。
|
||||
- 触发器频率:默认每小时一次主检查,每分钟一次遗留任务检查,可根据业务负载调整;过短可能导致数据库压力与平台限流风险。
|
||||
- 数据库索引:Query 和 QueryTask 模型已建立多处索引,建议结合 EXPLAIN 分析查询计划,避免全表扫描。
|
||||
- 异步并发:调度器在事件循环中调度异步任务,避免阻塞;平台适配器内部使用 Playwright,注意浏览器资源占用与并发上限。
|
||||
- 重试与退避:平台适配器内置最多三次重试与指数退避,降低瞬时失败影响。
|
||||
- 资源清理:关闭时调用 shutdown(wait=False) 与 CitationEngine.close(),确保浏览器与数据库连接及时释放。
|
||||
- 系统弹性:分钟级轮询机制提供冗余检查,确保即使主调度器出现问题,遗留任务也能得到处理。
|
||||
|
||||
章节来源
|
||||
**章节来源**
|
||||
- [backend/app/workers/scheduler.py:32-38](file://backend/app/workers/scheduler.py#L32-L38)
|
||||
- [backend/app/models/query.py:50-54](file://backend/app/models/query.py#L50-L54)
|
||||
- [backend/app/models/query_task.py:36-38](file://backend/app/models/query_task.py#L36-L38)
|
||||
- [backend/app/workers/platforms/kimi.py:33-48](file://backend/app/workers/platforms/kimi.py#L33-L48)
|
||||
- [backend/app/workers/platforms/wenxin.py:33-48](file://backend/app/workers/platforms/wenxin.py#L33-L48)
|
||||
- [backend/app/workers/citation_engine.py:302-309](file://backend/app/workers/citation_engine.py#L302-L309)
|
||||
|
||||
## 故障排查指南
|
||||
- 调度器未启动:确认 lifespan 钩子已正确导入与调用 start()/shutdown()。
|
||||
- 无事件循环:_run_check() 已处理无运行中事件循环的情况,若仍报错,检查事件循环状态与线程模型。
|
||||
- 无事件循环:_run_check() 和 _run_pending_tasks_check() 已处理无运行中事件循环的情况,若仍报错,检查事件循环状态与线程模型。
|
||||
- 数据库连接失败:检查 DATABASE_URL 配置与网络连通性。
|
||||
- 平台适配器异常:Playwright 未安装或浏览器不可用时会抛出明确异常;按提示运行安装命令。
|
||||
- 查询失败:CitationEngine 会在平台失败时记录错误并生成占位记录,便于后续重试与审计。
|
||||
- 遗留任务堆积:检查 QueryTask 表中 status='pending' 且 scheduled_at 超过1分钟的任务,确认主调度器是否正常工作。
|
||||
- 资源泄漏:确保关闭流程调用 shutdown() 与 close(),避免浏览器与数据库连接泄露。
|
||||
|
||||
章节来源
|
||||
**章节来源**
|
||||
- [backend/app/main.py:13-22](file://backend/app/main.py#L13-L22)
|
||||
- [backend/app/workers/scheduler.py:44-49](file://backend/app/workers/scheduler.py#L44-L49)
|
||||
- [backend/app/config.py](file://backend/app/config.py#L7)
|
||||
|
|
@ -323,7 +353,7 @@ D --> M["Query/QueryTask/CitationRecord"]
|
|||
- [backend/app/workers/citation_engine.py:211-227](file://backend/app/workers/citation_engine.py#L211-L227)
|
||||
|
||||
## 结论
|
||||
该调度器以 AsyncIOScheduler 为核心,结合 FastAPI 生命周期管理,实现了高可用、可扩展的定时查询任务体系。通过 CitationEngine 的平台编排与品牌匹配能力,以及平台适配器的稳定性保障,系统能够在异步环境下高效、可靠地执行跨平台查询任务。建议在生产环境关注触发频率、数据库索引与平台限流策略,并完善监控与告警机制。
|
||||
该调度器以 AsyncIOScheduler 为核心,结合 FastAPI 生命周期管理,实现了高可用、可扩展的定时查询任务体系。通过双重检查机制(每小时主检查 + 每分钟遗留任务检查),系统提供了更强的弹性与可靠性。通过 CitationEngine 的平台编排与品牌匹配能力,以及平台适配器的稳定性保障,系统能够在异步环境下高效、可靠地执行跨平台查询任务。建议在生产环境关注触发频率、数据库索引与平台限流策略,并完善监控与告警机制。
|
||||
|
||||
## 附录
|
||||
- 配置参数
|
||||
|
|
@ -336,8 +366,9 @@ D --> M["Query/QueryTask/CitationRecord"]
|
|||
- 手动触发:调用 /api/v1/queries/{query_id}/run-now 接口将查询立即加入执行队列。
|
||||
- 错误隔离:平台失败不影响整体调度,CitationEngine 记录占位记录并继续处理其他任务。
|
||||
- 性能调优:根据业务负载调整触发器频率、数据库索引与平台并发上限。
|
||||
- 遗留任务处理:系统自动处理超过1分钟的遗留 pending 任务,确保任务最终被执行。
|
||||
|
||||
章节来源
|
||||
**章节来源**
|
||||
- [backend/app/config.py:4-16](file://backend/app/config.py#L4-L16)
|
||||
- [backend/app/api/citations.py:59-77](file://backend/app/api/citations.py#L59-L77)
|
||||
- [backend/app/workers/citation_engine.py:211-227](file://backend/app/workers/citation_engine.py#L211-L227)
|
||||
|
|
@ -6,6 +6,12 @@
|
|||
- [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/scheduler.py](file://backend/app/workers/scheduler.py)
|
||||
- [backend/app/services/citation.py](file://backend/app/services/citation.py)
|
||||
- [backend/app/api/citations.py](file://backend/app/api/citations.py)
|
||||
|
|
@ -18,6 +24,14 @@
|
|||
- [backend/requirements.txt](file://backend/requirements.txt)
|
||||
</cite>
|
||||
|
||||
## 更新摘要
|
||||
**变更内容**
|
||||
- 新增7个搜索引擎适配器:通义千问、豆包、智谱清言、天工、讯飞星火
|
||||
- 改进错误处理机制,实现指数退避重试策略
|
||||
- 新增字符清理机制,防止PostgreSQL插入失败
|
||||
- 新增异步任务执行功能,支持立即查询执行
|
||||
- 优化搜索引擎模式,统一平台查询策略
|
||||
|
||||
## 目录
|
||||
1. [简介](#简介)
|
||||
2. [项目结构](#项目结构)
|
||||
|
|
@ -31,7 +45,9 @@
|
|||
10. [附录](#附录)
|
||||
|
||||
## 简介
|
||||
本技术文档面向“GEO引用检测引擎”,系统性阐述引用检测算法的实现原理与工程实践,涵盖文本预处理、品牌识别与上下文分析;详解BrandMatcher类的设计与实现(精确匹配、别名匹配、模糊匹配策略与正则规则);解析CompetitorDetector的竞争品牌识别机制(竞争关系定义、相似度计算与过滤规则);说明置信度评分体系(评分算法、阈值与结果排序);梳理异步处理与并发控制策略;并提供错误处理、日志记录与性能监控建议,以及与AI平台的集成接口与数据流转过程。
|
||||
本技术文档面向"GEO引用检测引擎",系统性阐述引用检测算法的实现原理与工程实践,涵盖文本预处理、品牌识别与上下文分析;详解BrandMatcher类的设计与实现(精确匹配、别名匹配、模糊匹配策略与正则规则);解析CompetitorDetector的竞争品牌识别机制(竞争关系定义、相似度计算与过滤规则);说明置信度评分体系(评分算法、阈值与结果排序);梳理异步处理与并发控制策略;并提供错误处理、日志记录与性能监控建议,以及与AI平台的集成接口与数据流转过程。
|
||||
|
||||
**更新** 新增搜索引擎适配器支持,改进错误处理机制,新增异步任务执行功能。
|
||||
|
||||
## 项目结构
|
||||
后端采用FastAPI + SQLAlchemy异步ORM + APScheduler定时任务的分层架构:
|
||||
|
|
@ -45,9 +61,11 @@
|
|||
graph TB
|
||||
subgraph "API层"
|
||||
API_C["API: 引用数据<br/>citations.py"]
|
||||
API_Q["API: 查询管理<br/>queries.py"]
|
||||
end
|
||||
subgraph "服务层"
|
||||
SVC["服务: 引用数据<br/>services/citation.py"]
|
||||
SVC_Q["服务: 查询管理<br/>services/query.py"]
|
||||
end
|
||||
subgraph "工作器层"
|
||||
ENG["引擎: 引用检测<br/>workers/citation_engine.py"]
|
||||
|
|
@ -55,6 +73,12 @@ SCH["调度器<br/>workers/scheduler.py"]
|
|||
ADP_BASE["适配器基类<br/>workers/platforms/base.py"]
|
||||
ADP_KIMI["适配器: Kimi<br/>workers/platforms/kimi.py"]
|
||||
ADP_WENXIN["适配器: 文心一言<br/>workers/platforms/wenxin.py"]
|
||||
ADP_TONGYI["适配器: 通义千问<br/>workers/platforms/tongyi.py"]
|
||||
ADP_DOUBAO["适配器: 豆包<br/>workers/platforms/doubao.py"]
|
||||
ADP_QINGYAN["适配器: 智谱清言<br/>workers/platforms/qingyan.py"]
|
||||
ADP_TIANGONG["适配器: 天工<br/>workers/platforms/tiangong.py"]
|
||||
ADP_XINGHUO["适配器: 讯飞星火<br/>workers/platforms/xinghuo.py"]
|
||||
SEARCH_ENGINE["搜索引擎模块<br/>workers/platforms/search_engine.py"]
|
||||
end
|
||||
subgraph "模型层"
|
||||
M_QUERY["模型: 查询<br/>models/query.py"]
|
||||
|
|
@ -66,9 +90,17 @@ CFG["配置<br/>config.py"]
|
|||
MAIN["入口<br/>main.py"]
|
||||
end
|
||||
API_C --> SVC
|
||||
API_Q --> SVC_Q
|
||||
SVC --> ENG
|
||||
SVC_Q --> ENG
|
||||
ENG --> ADP_KIMI
|
||||
ENG --> ADP_WENXIN
|
||||
ENG --> ADP_TONGYI
|
||||
ENG --> ADP_DOUBAO
|
||||
ENG --> ADP_QINGYAN
|
||||
ENG --> ADP_TIANGONG
|
||||
ENG --> ADP_XINGHUO
|
||||
ENG --> SEARCH_ENGINE
|
||||
SCH --> ENG
|
||||
ENG --> M_CIT
|
||||
SVC --> M_CIT
|
||||
|
|
@ -77,29 +109,40 @@ ENG --> M_QUERY
|
|||
ENG --> M_TASK
|
||||
MAIN --> SCH
|
||||
MAIN --> API_C
|
||||
MAIN --> API_Q
|
||||
CFG --> MAIN
|
||||
```
|
||||
|
||||
图表来源
|
||||
**图表来源**
|
||||
- [backend/app/api/citations.py:1-78](file://backend/app/api/citations.py#L1-L78)
|
||||
- [backend/app/api/queries.py:90-108](file://backend/app/api/queries.py#L90-L108)
|
||||
- [backend/app/services/citation.py:1-269](file://backend/app/services/citation.py#L1-L269)
|
||||
- [backend/app/workers/citation_engine.py:1-309](file://backend/app/workers/citation_engine.py#L1-L309)
|
||||
- [backend/app/services/query.py:1-123](file://backend/app/services/query.py#L1-L123)
|
||||
- [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/kimi.py:1-206](file://backend/app/workers/platforms/kimi.py#L1-L206)
|
||||
- [backend/app/workers/platforms/wenxin.py:1-205](file://backend/app/workers/platforms/wenxin.py#L1-L205)
|
||||
- [backend/app/workers/scheduler.py:1-95](file://backend/app/workers/scheduler.py#L1-L95)
|
||||
- [backend/app/workers/platforms/kimi.py:1-37](file://backend/app/workers/platforms/kimi.py#L1-L37)
|
||||
- [backend/app/workers/platforms/wenxin.py:1-37](file://backend/app/workers/platforms/wenxin.py#L1-L37)
|
||||
- [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/scheduler.py:1-121](file://backend/app/workers/scheduler.py#L1-L121)
|
||||
- [backend/app/models/query.py:1-55](file://backend/app/models/query.py#L1-L55)
|
||||
- [backend/app/models/query_task.py:1-39](file://backend/app/models/query_task.py#L1-L39)
|
||||
- [backend/app/models/citation_record.py:1-42](file://backend/app/models/citation_record.py#L1-L42)
|
||||
- [backend/app/config.py:1-17](file://backend/app/config.py#L1-L17)
|
||||
- [backend/app/main.py:1-48](file://backend/app/main.py#L1-L48)
|
||||
|
||||
章节来源
|
||||
**章节来源**
|
||||
- [backend/app/main.py:1-48](file://backend/app/main.py#L1-L48)
|
||||
- [backend/app/api/citations.py:1-78](file://backend/app/api/citations.py#L1-L78)
|
||||
- [backend/app/api/queries.py:90-108](file://backend/app/api/queries.py#L90-L108)
|
||||
- [backend/app/services/citation.py:1-269](file://backend/app/services/citation.py#L1-L269)
|
||||
- [backend/app/workers/citation_engine.py:1-309](file://backend/app/workers/citation_engine.py#L1-L309)
|
||||
- [backend/app/workers/scheduler.py:1-95](file://backend/app/workers/scheduler.py#L1-L95)
|
||||
- [backend/app/services/query.py:1-123](file://backend/app/services/query.py#L1-L123)
|
||||
- [backend/app/workers/citation_engine.py:1-330](file://backend/app/workers/citation_engine.py#L1-L330)
|
||||
- [backend/app/workers/scheduler.py:1-121](file://backend/app/workers/scheduler.py#L1-L121)
|
||||
- [backend/app/models/query.py:1-55](file://backend/app/models/query.py#L1-L55)
|
||||
- [backend/app/models/query_task.py:1-39](file://backend/app/models/query_task.py#L1-L39)
|
||||
- [backend/app/models/citation_record.py:1-42](file://backend/app/models/citation_record.py#L1-L42)
|
||||
|
|
@ -109,17 +152,24 @@ CFG --> MAIN
|
|||
- 引用检测引擎:负责跨平台查询、品牌匹配、竞争品牌识别与结果落库
|
||||
- 品牌匹配器BrandMatcher:精确匹配、别名匹配、模糊匹配三阶段策略
|
||||
- 竞争品牌检测器CompetitorDetector:基于预定义品牌类别集合进行竞争关系识别
|
||||
- 平台适配器:Kimi与文心一言适配器,封装Playwright自动化查询流程
|
||||
- 平台适配器:Kimi、文心一言、通义千问、豆包、智谱清言、天工、讯飞星火适配器,封装Playwright自动化查询流程
|
||||
- 搜索引擎模块:提供DuckDuckGo和Wikipedia搜索功能,作为备用查询源
|
||||
- 定时调度器:基于APScheduler的周期性任务调度
|
||||
- 服务与API:提供查询历史、统计与立即执行能力
|
||||
|
||||
章节来源
|
||||
- [backend/app/workers/citation_engine.py:19-309](file://backend/app/workers/citation_engine.py#L19-L309)
|
||||
- [backend/app/workers/platforms/kimi.py:1-206](file://backend/app/workers/platforms/kimi.py#L1-L206)
|
||||
- [backend/app/workers/platforms/wenxin.py:1-205](file://backend/app/workers/platforms/wenxin.py#L1-L205)
|
||||
- [backend/app/workers/scheduler.py:1-95](file://backend/app/workers/scheduler.py#L1-L95)
|
||||
- [backend/app/services/citation.py:1-269](file://backend/app/services/citation.py#L1-L269)
|
||||
- [backend/app/api/citations.py:1-78](file://backend/app/api/citations.py#L1-L78)
|
||||
**更新** 新增7个搜索引擎适配器,改进错误处理机制,新增异步任务执行功能。
|
||||
|
||||
**章节来源**
|
||||
- [backend/app/workers/citation_engine.py:161-330](file://backend/app/workers/citation_engine.py#L161-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/workers/scheduler.py:1-121](file://backend/app/workers/scheduler.py#L1-L121)
|
||||
- [backend/app/services/citation.py:219-295](file://backend/app/services/citation.py#L219-L295)
|
||||
- [backend/app/api/queries.py:90-108](file://backend/app/api/queries.py#L90-L108)
|
||||
|
||||
## 架构总览
|
||||
引擎通过API触发或定时调度器自动触发,调用平台适配器获取AI回复,随后由BrandMatcher进行品牌识别,CompetitorDetector识别竞争品牌,最终将结果写入数据库并返回。
|
||||
|
|
@ -131,6 +181,7 @@ participant API as "API : 引用数据"
|
|||
participant Svc as "服务 : 引用数据"
|
||||
participant Eng as "引擎 : 引用检测"
|
||||
participant Plat as "平台适配器"
|
||||
participant Search as "搜索引擎模块"
|
||||
participant DB as "数据库"
|
||||
Client->>API : GET /api/v1/citations/stats
|
||||
API->>Svc : 统计查询
|
||||
|
|
@ -144,6 +195,9 @@ Svc-->>API : 任务ID
|
|||
API-->>Client : 202 Accepted
|
||||
Note over Eng,DB : 定时调度器每小时检查到期查询
|
||||
Eng->>Plat : query(keyword)
|
||||
Note over Plat,Search : 搜索引擎模式:通过fetch_search_content获取真实内容
|
||||
Plat->>Search : fetch_search_content(keyword)
|
||||
Search-->>Plat : 搜索结果摘要
|
||||
Plat-->>Eng : 原始回复文本
|
||||
Eng->>Eng : BrandMatcher.match(text)
|
||||
Eng->>Eng : CompetitorDetector.detect(text, target)
|
||||
|
|
@ -151,12 +205,15 @@ Eng->>DB : 写入CitationRecord
|
|||
DB-->>Eng : 确认
|
||||
```
|
||||
|
||||
图表来源
|
||||
**图表来源**
|
||||
- [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/citation_engine.py:148-309](file://backend/app/workers/citation_engine.py#L148-L309)
|
||||
- [backend/app/workers/platforms/kimi.py:33-125](file://backend/app/workers/platforms/kimi.py#L33-L125)
|
||||
- [backend/app/workers/platforms/wenxin.py:33-123](file://backend/app/workers/platforms/wenxin.py#L33-L123)
|
||||
- [backend/app/api/queries.py:90-108](file://backend/app/api/queries.py#L90-L108)
|
||||
- [backend/app/services/citation.py:219-295](file://backend/app/services/citation.py#L219-L295)
|
||||
- [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/workers/platforms/kimi.py:16-33](file://backend/app/workers/platforms/kimi.py#L16-L33)
|
||||
- [backend/app/workers/platforms/wenxin.py:16-33](file://backend/app/workers/platforms/wenxin.py#L16-L33)
|
||||
- [backend/app/models/citation_record.py:1-42](file://backend/app/models/citation_record.py#L1-L42)
|
||||
|
||||
## 详细组件分析
|
||||
|
|
@ -191,12 +248,12 @@ Best --> |是| PosCtx3["提取段落位置与上下文"] --> RetFuzzy["返回模
|
|||
Best --> |否| RetEmpty
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [backend/app/workers/citation_engine.py:26-119](file://backend/app/workers/citation_engine.py#L26-L119)
|
||||
**图表来源**
|
||||
- [backend/app/workers/citation_engine.py:39-113](file://backend/app/workers/citation_engine.py#L39-L113)
|
||||
|
||||
章节来源
|
||||
- [backend/app/workers/citation_engine.py:19-120](file://backend/app/workers/citation_engine.py#L19-L120)
|
||||
- [tests/test_citation_engine.py:6-54](file://tests/test_citation_engine.py#L6-L54)
|
||||
**章节来源**
|
||||
- [backend/app/workers/citation_engine.py:32-133](file://backend/app/workers/citation_engine.py#L32-L133)
|
||||
- [tests/test_citation_engine.py:6-127](file://tests/test_citation_engine.py#L6-L127)
|
||||
|
||||
### CompetitorDetector:竞争品牌检测器
|
||||
- 设计要点
|
||||
|
|
@ -223,18 +280,19 @@ NextBrand --> LoopBrand
|
|||
LoopBrand --> Done["排序并返回列表"]
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [backend/app/workers/citation_engine.py:122-145](file://backend/app/workers/citation_engine.py#L122-L145)
|
||||
**图表来源**
|
||||
- [backend/app/workers/citation_engine.py:145-158](file://backend/app/workers/citation_engine.py#L145-L158)
|
||||
|
||||
章节来源
|
||||
- [backend/app/workers/citation_engine.py:122-145](file://backend/app/workers/citation_engine.py#L122-L145)
|
||||
- [tests/test_citation_engine.py:39-45](file://tests/test_citation_engine.py#L39-L45)
|
||||
**章节来源**
|
||||
- [backend/app/workers/citation_engine.py:135-159](file://backend/app/workers/citation_engine.py#L135-L159)
|
||||
- [tests/test_citation_engine.py:39-109](file://tests/test_citation_engine.py#L39-L109)
|
||||
|
||||
### CitationEngine:引用检测引擎
|
||||
- 职责
|
||||
- 组织跨平台查询与检测流程
|
||||
- 维护查询任务状态与时间字段
|
||||
- 将结果持久化为引用记录
|
||||
- 实施字符清理机制,防止数据库插入失败
|
||||
- 关键流程
|
||||
- 初始化平台适配器与匹配器
|
||||
- 遍历平台列表,执行单平台查询与检测
|
||||
|
|
@ -243,6 +301,9 @@ LoopBrand --> Done["排序并返回列表"]
|
|||
- 并发与异步
|
||||
- 引擎方法为异步,平台适配器亦为异步
|
||||
- 平台间顺序执行(当前实现),可扩展为并行执行以提升吞吐
|
||||
- 字符清理
|
||||
- 新增`_sanitize_raw_response`函数,移除无效控制字符
|
||||
- 防止PostgreSQL UTF-8插入失败
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
|
|
@ -255,27 +316,29 @@ participant R as "CitationRecord"
|
|||
E->>E : 创建BrandMatcher(target, aliases)
|
||||
loop 遍历平台
|
||||
E->>P : query(keyword)
|
||||
P-->>E : 原始回复
|
||||
E->>M : match(raw_response)
|
||||
P-->>E : 原始回复文本
|
||||
E->>E : _sanitize_raw_response(raw_response)
|
||||
E->>M : match(sanitized_text)
|
||||
M-->>E : 匹配结果
|
||||
E->>C : detect(raw_response, target)
|
||||
E->>C : detect(sanitized_text, target)
|
||||
C-->>E : 竞争品牌
|
||||
E->>R : 写入记录
|
||||
end
|
||||
E->>Q : 更新last_queried_at/next_query_at
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [backend/app/workers/citation_engine.py:148-309](file://backend/app/workers/citation_engine.py#L148-L309)
|
||||
**图表来源**
|
||||
- [backend/app/workers/citation_engine.py:177-254](file://backend/app/workers/citation_engine.py#L177-L254)
|
||||
|
||||
章节来源
|
||||
- [backend/app/workers/citation_engine.py:148-309](file://backend/app/workers/citation_engine.py#L148-L309)
|
||||
**章节来源**
|
||||
- [backend/app/workers/citation_engine.py:161-330](file://backend/app/workers/citation_engine.py#L161-L330)
|
||||
|
||||
### 平台适配器:Kimi与文心一言
|
||||
### 平台适配器:Kimi、文心一言与新增搜索引擎适配器
|
||||
- 抽象基类
|
||||
- BasePlatformAdapter定义平台名称、URL与抽象query/close方法
|
||||
- 具体实现
|
||||
- 启动Playwright与无头浏览器,导航至平台URL
|
||||
- **传统适配器**(Kimi、文心一言):启动Playwright与无头浏览器,导航至平台URL
|
||||
- **搜索引擎适配器**(通义千问、豆包、智谱清言、天工、讯飞星火):通过fetch_search_content获取真实内容
|
||||
- 自动查找输入框、填充关键词、提交查询(回车或点击发送)
|
||||
- 等待回复稳定(连续多次检测文本不变),返回最新回复
|
||||
- 失败重试与指数退避,超时警告
|
||||
|
|
@ -283,6 +346,7 @@ E->>Q : 更新last_queried_at/next_query_at
|
|||
- 错误处理
|
||||
- 无法找到输入框、页面超时、最终失败抛出运行时异常
|
||||
- 日志记录每次重试与最终失败原因
|
||||
- 指数退避重试机制,最多3次尝试
|
||||
|
||||
```mermaid
|
||||
classDiagram
|
||||
|
|
@ -304,25 +368,87 @@ class WenxinAdapter {
|
|||
+query(keyword) str
|
||||
+close() void
|
||||
}
|
||||
class TongyiAdapter {
|
||||
+platform_name = "tongyi"
|
||||
+platform_url = "https : //tongyi.aliyun.com/qianwen"
|
||||
+query(keyword) str
|
||||
+close() void
|
||||
}
|
||||
class DoubaoAdapter {
|
||||
+platform_name = "doubao"
|
||||
+platform_url = "https : //www.doubao.com/"
|
||||
+query(keyword) str
|
||||
+close() void
|
||||
}
|
||||
class QingyanAdapter {
|
||||
+platform_name = "qingyan"
|
||||
+platform_url = "https : //chatglm.cn/"
|
||||
+query(keyword) str
|
||||
+close() void
|
||||
}
|
||||
class TiangongAdapter {
|
||||
+platform_name = "tiangong"
|
||||
+platform_url = "https : //www.tiangong.cn/"
|
||||
+query(keyword) str
|
||||
+close() void
|
||||
}
|
||||
class XinghuoAdapter {
|
||||
+platform_name = "xinghuo"
|
||||
+platform_url = "https : //xinghuo.xfyun.cn/"
|
||||
+query(keyword) str
|
||||
+close() void
|
||||
}
|
||||
KimiAdapter --|> BasePlatformAdapter
|
||||
WenxinAdapter --|> BasePlatformAdapter
|
||||
TongyiAdapter --|> BasePlatformAdapter
|
||||
DoubaoAdapter --|> BasePlatformAdapter
|
||||
QingyanAdapter --|> BasePlatformAdapter
|
||||
TiangongAdapter --|> BasePlatformAdapter
|
||||
XinghuoAdapter --|> BasePlatformAdapter
|
||||
```
|
||||
|
||||
图表来源
|
||||
**图表来源**
|
||||
- [backend/app/workers/platforms/base.py:1-18](file://backend/app/workers/platforms/base.py#L1-L18)
|
||||
- [backend/app/workers/platforms/kimi.py:1-206](file://backend/app/workers/platforms/kimi.py#L1-L206)
|
||||
- [backend/app/workers/platforms/wenxin.py:1-205](file://backend/app/workers/platforms/wenxin.py#L1-L205)
|
||||
- [backend/app/workers/platforms/kimi.py:1-37](file://backend/app/workers/platforms/kimi.py#L1-L37)
|
||||
- [backend/app/workers/platforms/wenxin.py:1-37](file://backend/app/workers/platforms/wenxin.py#L1-L37)
|
||||
- [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/base.py:1-18](file://backend/app/workers/platforms/base.py#L1-L18)
|
||||
- [backend/app/workers/platforms/kimi.py:1-206](file://backend/app/workers/platforms/kimi.py#L1-L206)
|
||||
- [backend/app/workers/platforms/wenxin.py:1-205](file://backend/app/workers/platforms/wenxin.py#L1-L205)
|
||||
- [backend/app/workers/platforms/kimi.py:1-37](file://backend/app/workers/platforms/kimi.py#L1-L37)
|
||||
- [backend/app/workers/platforms/wenxin.py:1-37](file://backend/app/workers/platforms/wenxin.py#L1-L37)
|
||||
- [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搜索
|
||||
- 作为备用查询源,当平台适配器无法正常工作时使用
|
||||
- 实现细节
|
||||
- DuckDuckGo HTML搜索:无需API Key,自动回退到Wikipedia
|
||||
- Wikipedia API搜索:稳定可靠,返回百科内容摘要
|
||||
- HTML内容清理:去除标签和实体,保留可读文本
|
||||
- 字符串清理:移除引用标记和多余空白
|
||||
- 错误处理
|
||||
- 搜索失败时自动回退到Wikipedia
|
||||
- 所有搜索源均失败时抛出运行时异常
|
||||
|
||||
**章节来源**
|
||||
- [backend/app/workers/platforms/search_engine.py:1-174](file://backend/app/workers/platforms/search_engine.py#L1-L174)
|
||||
|
||||
### 定时调度器:QueryScheduler
|
||||
- 职责
|
||||
- 每小时扫描到期查询(status=active且next_query_at<=now)
|
||||
- 逐条执行CitationEngine.execute_query
|
||||
- 应用生命周期内启动与关闭
|
||||
- 兜底检查:每分钟检查遗留的pending任务
|
||||
- 并发控制
|
||||
- 使用AsyncIOScheduler与事件循环
|
||||
- 检查与执行过程均为异步,避免阻塞
|
||||
|
|
@ -330,17 +456,21 @@ WenxinAdapter --|> BasePlatformAdapter
|
|||
```mermaid
|
||||
flowchart TD
|
||||
StartS(["启动调度器"]) --> AddJob["添加每小时任务"]
|
||||
AddJob --> Loop["每小时执行检查"]
|
||||
AddJob --> AddJob2["添加每分钟任务"]
|
||||
AddJob2 --> Loop["每小时执行检查"]
|
||||
Loop --> Select["查询到期的Query"]
|
||||
Select --> Exec["逐条执行execute_query"]
|
||||
Exec --> Loop
|
||||
Loop --> PendingCheck["每分钟检查遗留任务"]
|
||||
PendingCheck --> ExecPending["执行遗留任务"]
|
||||
ExecPending --> Loop
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [backend/app/workers/scheduler.py:25-95](file://backend/app/workers/scheduler.py#L25-L95)
|
||||
**图表来源**
|
||||
- [backend/app/workers/scheduler.py:33-121](file://backend/app/workers/scheduler.py#L33-L121)
|
||||
|
||||
章节来源
|
||||
- [backend/app/workers/scheduler.py:1-95](file://backend/app/workers/scheduler.py#L1-L95)
|
||||
**章节来源**
|
||||
- [backend/app/workers/scheduler.py:1-121](file://backend/app/workers/scheduler.py#L1-L121)
|
||||
- [backend/app/main.py:13-22](file://backend/app/main.py#L13-L22)
|
||||
|
||||
### 服务与API:引用数据与统计
|
||||
|
|
@ -352,6 +482,7 @@ Exec --> Loop
|
|||
- 权限校验:仅允许用户访问自己的查询数据
|
||||
- 统计聚合:使用SQL聚合函数计算各项指标
|
||||
- CSV导出:按查询导出引用记录CSV
|
||||
- 异步任务执行:使用asyncio.create_task后台执行查询
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
|
|
@ -371,15 +502,25 @@ Svc->>DB : 聚合统计
|
|||
DB-->>Svc : 统计结果
|
||||
Svc-->>API : 返回统计
|
||||
API-->>Client : 响应
|
||||
Client->>API : POST /api/v1/queries/{id}/run-now
|
||||
API->>Svc : trigger_query_now
|
||||
Svc->>DB : 创建QueryTask
|
||||
Svc->>Svc : asyncio.create_task执行查询
|
||||
Svc-->>API : 202 Accepted + task_id
|
||||
API-->>Client : 响应
|
||||
```
|
||||
|
||||
图表来源
|
||||
**图表来源**
|
||||
- [backend/app/api/citations.py:1-78](file://backend/app/api/citations.py#L1-L78)
|
||||
- [backend/app/services/citation.py:24-269](file://backend/app/services/citation.py#L24-L269)
|
||||
- [backend/app/api/queries.py:90-108](file://backend/app/api/queries.py#L90-L108)
|
||||
- [backend/app/services/citation.py:219-295](file://backend/app/services/citation.py#L219-L295)
|
||||
- [backend/app/services/citation.py:264-295](file://backend/app/services/citation.py#L264-L295)
|
||||
|
||||
章节来源
|
||||
**章节来源**
|
||||
- [backend/app/api/citations.py:1-78](file://backend/app/api/citations.py#L1-L78)
|
||||
- [backend/app/api/queries.py:90-108](file://backend/app/api/queries.py#L90-L108)
|
||||
- [backend/app/services/citation.py:1-269](file://backend/app/services/citation.py#L1-L269)
|
||||
- [backend/app/services/query.py:1-123](file://backend/app/services/query.py#L1-L123)
|
||||
|
||||
### 数据模型:查询、任务与引用记录
|
||||
- Query:查询词、目标品牌、别名、平台、频率、状态与时间字段
|
||||
|
|
@ -425,12 +566,12 @@ QUERIES ||--o{ QUERY_TASKS : "包含"
|
|||
QUERIES ||--o{ CITATION_RECORDS : "包含"
|
||||
```
|
||||
|
||||
图表来源
|
||||
**图表来源**
|
||||
- [backend/app/models/query.py:1-55](file://backend/app/models/query.py#L1-L55)
|
||||
- [backend/app/models/query_task.py:1-39](file://backend/app/models/query_task.py#L1-L39)
|
||||
- [backend/app/models/citation_record.py:1-42](file://backend/app/models/citation_record.py#L1-L42)
|
||||
|
||||
章节来源
|
||||
**章节来源**
|
||||
- [backend/app/models/query.py:1-55](file://backend/app/models/query.py#L1-L55)
|
||||
- [backend/app/models/query_task.py:1-39](file://backend/app/models/query_task.py#L1-L39)
|
||||
- [backend/app/models/citation_record.py:1-42](file://backend/app/models/citation_record.py#L1-L42)
|
||||
|
|
@ -441,6 +582,7 @@ QUERIES ||--o{ CITATION_RECORDS : "包含"
|
|||
- ORM与迁移:SQLAlchemy、Alembic
|
||||
- 任务调度:APScheduler
|
||||
- 浏览器自动化:Playwright
|
||||
- HTTP客户端:httpx
|
||||
- 缓存:Redis(配置项存在)
|
||||
- 配置:pydantic-settings
|
||||
- 内部模块耦合
|
||||
|
|
@ -455,26 +597,41 @@ API --> Service
|
|||
Service --> Engine
|
||||
Engine --> AdapterBase
|
||||
Engine --> Models
|
||||
Engine --> SearchEngine
|
||||
Scheduler --> Engine
|
||||
AdapterKimi --> AdapterBase
|
||||
AdapterWenxin --> AdapterBase
|
||||
AdapterTongyi --> AdapterBase
|
||||
AdapterDoubao --> AdapterBase
|
||||
AdapterQingyan --> AdapterBase
|
||||
AdapterTiangong --> AdapterBase
|
||||
AdapterXinghuo --> AdapterBase
|
||||
SearchEngine --> Engine
|
||||
Config --> Main
|
||||
Main --> Scheduler
|
||||
Main --> API
|
||||
```
|
||||
|
||||
图表来源
|
||||
**图表来源**
|
||||
- [backend/requirements.txt:1-35](file://backend/requirements.txt#L1-L35)
|
||||
- [backend/app/main.py:1-48](file://backend/app/main.py#L1-L48)
|
||||
- [backend/app/api/citations.py:1-78](file://backend/app/api/citations.py#L1-L78)
|
||||
- [backend/app/api/queries.py:90-108](file://backend/app/api/queries.py#L90-L108)
|
||||
- [backend/app/services/citation.py:1-269](file://backend/app/services/citation.py#L1-L269)
|
||||
- [backend/app/workers/citation_engine.py:1-309](file://backend/app/workers/citation_engine.py#L1-L309)
|
||||
- [backend/app/services/query.py:1-123](file://backend/app/services/query.py#L1-L123)
|
||||
- [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/kimi.py:1-206](file://backend/app/workers/platforms/kimi.py#L1-L206)
|
||||
- [backend/app/workers/platforms/wenxin.py:1-205](file://backend/app/workers/platforms/wenxin.py#L1-L205)
|
||||
- [backend/app/workers/platforms/kimi.py:1-37](file://backend/app/workers/platforms/kimi.py#L1-L37)
|
||||
- [backend/app/workers/platforms/wenxin.py:1-37](file://backend/app/workers/platforms/wenxin.py#L1-L37)
|
||||
- [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/requirements.txt:1-35](file://backend/requirements.txt#L1-L35)
|
||||
- [backend/app/main.py:1-48](file://backend/app/main.py#L1-L48)
|
||||
|
||||
|
|
@ -485,13 +642,14 @@ Main --> API
|
|||
- 平台适配器
|
||||
- Playwright初始化成本较高,适配器内部维护浏览器实例,避免重复启动
|
||||
- 等待回复稳定的轮询间隔与超时可按平台特性微调
|
||||
- **新增** 搜索引擎适配器避免了浏览器自动化成本,提升了整体性能
|
||||
- 引擎与调度
|
||||
- 当前平台遍历为串行,可扩展为并发执行以提升吞吐(注意平台限流与稳定性)
|
||||
- 定时任务每小时检查一次,可根据业务需要调整频率
|
||||
- **新增** 异步任务执行机制,使用asyncio.create_task提升响应速度
|
||||
- 数据库
|
||||
- 引用记录、查询与任务均建立索引,统计查询使用聚合函数,建议定期分析与更新统计信息
|
||||
|
||||
[本节为通用性能建议,无需特定文件来源]
|
||||
- **新增** 字符清理机制,避免无效字符导致的数据库插入失败
|
||||
|
||||
## 故障排查指南
|
||||
- 浏览器与Playwright
|
||||
|
|
@ -502,25 +660,39 @@ Main --> API
|
|||
- 现象:找不到输入框、页面超时
|
||||
- 处理:检查平台页面结构变化,适配器内置多选择器与超时重试,必要时调整选择器或等待策略
|
||||
- 相关路径:[backend/app/workers/platforms/kimi.py:67-88](file://backend/app/workers/platforms/kimi.py#L67-L88)、[backend/app/workers/platforms/wenxin.py:67-87](file://backend/app/workers/platforms/wenxin.py#L67-L87)
|
||||
- **新增** 搜索引擎适配器故障
|
||||
- 现象:DuckDuckGo搜索失败
|
||||
- 处理:自动回退到Wikipedia搜索,检查网络连接和API可用性
|
||||
- 相关路径:[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:18-29](file://backend/app/workers/platforms/tongyi.py#L18-L29)、[backend/app/workers/platforms/doubao.py:18-29](file://backend/app/workers/platforms/doubao.py#L18-L29)
|
||||
- **新增** 字符清理问题
|
||||
- 现象:数据库插入失败,提示UTF-8编码错误
|
||||
- 处理:检查`_sanitize_raw_response`函数是否正确清理无效字符
|
||||
- 相关路径:[backend/app/workers/citation_engine.py:11-16](file://backend/app/workers/citation_engine.py#L11-L16)
|
||||
- 引擎执行异常
|
||||
- 现象:平台查询失败,记录失败状态与错误信息
|
||||
- 处理:查看任务表中的错误信息,确认平台可用性与网络状况
|
||||
- 相关路径:[backend/app/workers/citation_engine.py:211-227](file://backend/app/workers/citation_engine.py#L211-L227)
|
||||
- 相关路径:[backend/app/workers/citation_engine.py:231-247](file://backend/app/workers/citation_engine.py#L231-L247)
|
||||
- API权限与参数
|
||||
- 现象:查询不到数据或返回空
|
||||
- 处理:确认查询ID归属当前用户,参数范围合理
|
||||
- 相关路径:[backend/app/services/citation.py:14-42](file://backend/app/services/citation.py#L14-L42)
|
||||
|
||||
章节来源
|
||||
**章节来源**
|
||||
- [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:211-227](file://backend/app/workers/citation_engine.py#L211-L227)
|
||||
- [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:18-29](file://backend/app/workers/platforms/tongyi.py#L18-L29)
|
||||
- [backend/app/workers/platforms/doubao.py:18-29](file://backend/app/workers/platforms/doubao.py#L18-L29)
|
||||
- [backend/app/workers/citation_engine.py:11-16](file://backend/app/workers/citation_engine.py#L11-L16)
|
||||
- [backend/app/workers/citation_engine.py:231-247](file://backend/app/workers/citation_engine.py#L231-L247)
|
||||
- [backend/app/services/citation.py:14-42](file://backend/app/services/citation.py#L14-L42)
|
||||
|
||||
## 结论
|
||||
该引擎以清晰的分层设计实现了从AI平台抓取、品牌识别、竞争品牌检测到结果落库与统计展示的完整链路。BrandMatcher与CompetitorDetector提供了稳健的文本处理与识别能力,平台适配器封装了复杂的浏览器自动化流程,调度器保障了周期性任务的可靠执行。建议后续在并发执行、阈值调优与平台扩展方面持续优化。
|
||||
|
||||
[本节为总结性内容,无需特定文件来源]
|
||||
该引擎以清晰的分层设计实现了从AI平台抓取、品牌识别、竞争品牌检测到结果落库与统计展示的完整链路。BrandMatcher与CompetitorDetector提供了稳健的文本处理与识别能力,平台适配器封装了复杂的浏览器自动化流程,搜索引擎适配器提供了更稳定的替代方案,调度器保障了周期性任务的可靠执行。**新增**的异步任务执行机制和字符清理机制进一步提升了系统的稳定性和性能。建议后续在并发执行、阈值调优与平台扩展方面持续优化。
|
||||
|
||||
## 附录
|
||||
|
||||
|
|
@ -530,39 +702,49 @@ Main --> API
|
|||
- 对候选词进行词干化或拼音首字母预处理,减少误判
|
||||
- 并发与限流
|
||||
- 平台查询改为并发执行,并引入令牌桶限流防止被封禁
|
||||
- **新增** 搜索引擎适配器天然支持并发,可优先考虑使用
|
||||
- 缓存与降噪
|
||||
- 对热点关键词与平台响应进行缓存,降低重复请求
|
||||
- 上下文截取长度可动态调整,兼顾性能与准确性
|
||||
|
||||
[本节为通用优化建议,无需特定文件来源]
|
||||
- **新增** 字符清理机制可进一步优化,减少无效字符传输
|
||||
|
||||
### 自定义扩展指南
|
||||
- 新增平台适配器
|
||||
- 继承BasePlatformAdapter,实现query与close方法
|
||||
- 在CitationEngine中注册平台映射
|
||||
- 参考路径:[backend/app/workers/platforms/base.py:1-18](file://backend/app/workers/platforms/base.py#L1-L18)、[backend/app/workers/citation_engine.py:152-155](file://backend/app/workers/citation_engine.py#L152-L155)
|
||||
- **新增** 可选择实现搜索引擎模式或传统浏览器自动化模式
|
||||
- 参考路径:[backend/app/workers/platforms/base.py:1-18](file://backend/app/workers/platforms/base.py#L1-L18)、[backend/app/workers/citation_engine.py:165-173](file://backend/app/workers/citation_engine.py#L165-L173)
|
||||
- 调整匹配策略
|
||||
- 修改BrandMatcher的阈值、候选词提取规则或上下文截取长度
|
||||
- 参考路径:[backend/app/workers/citation_engine.py:68-92](file://backend/app/workers/citation_engine.py#L68-L92)、[backend/app/workers/citation_engine.py:102-119](file://backend/app/workers/citation_engine.py#L102-L119)
|
||||
- 参考路径:[backend/app/workers/citation_engine.py:115-132](file://backend/app/workers/citation_engine.py#L115-L132)、[backend/app/workers/citation_engine.py:120-132](file://backend/app/workers/citation_engine.py#L120-L132)
|
||||
- 竞争品牌库扩展
|
||||
- 在CompetitorDetector中增加新的行业类别与品牌集合
|
||||
- 参考路径:[backend/app/workers/citation_engine.py:125-130](file://backend/app/workers/citation_engine.py#L125-L130)
|
||||
|
||||
[本节为扩展性指导,无需特定文件来源]
|
||||
- 参考路径:[backend/app/workers/citation_engine.py:139-143](file://backend/app/workers/citation_engine.py#L139-L143)
|
||||
- **新增** 搜索引擎模块扩展
|
||||
- 在search_engine.py中添加新的搜索源
|
||||
- 实现相应的清理和格式化函数
|
||||
- 参考路径:[backend/app/workers/platforms/search_engine.py:163-174](file://backend/app/workers/platforms/search_engine.py#L163-L174)
|
||||
|
||||
### 与AI平台的集成接口与数据流转
|
||||
- 接口职责
|
||||
- 平台适配器:统一query接口,屏蔽平台差异
|
||||
- 引擎:组织流程、落库、异常处理
|
||||
- API/服务:对外提供查询与统计能力
|
||||
- **新增** 搜索引擎模块:提供备用查询源
|
||||
- 数据流
|
||||
- 用户发起查询 → API/服务 → 引擎 → 平台适配器 → AI平台 → 引擎 → 数据库 → API/服务 → 前端展示
|
||||
- 用户发起查询 → API/服务 → 引擎 → 平台适配器 → AI平台/搜索引擎 → 引擎 → 数据库 → API/服务 → 前端展示
|
||||
- **新增** 搜索引擎模式:通过fetch_search_content获取真实内容
|
||||
- 监控与日志
|
||||
- 平台适配器与引擎均包含日志记录,便于追踪失败原因与性能瓶颈
|
||||
- 参考路径:[backend/app/workers/platforms/kimi.py:4-8](file://backend/app/workers/platforms/kimi.py#L4-L8)、[backend/app/workers/platforms/wenxin.py:4-8](file://backend/app/workers/platforms/wenxin.py#L4-L8)、[backend/app/workers/citation_engine.py:16-16](file://backend/app/workers/citation_engine.py#L16-L16)
|
||||
- **新增** 指数退避重试机制,支持自动故障恢复
|
||||
- **新增** 字符清理机制,确保数据质量
|
||||
- 参考路径:[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/citation_engine.py:11-16](file://backend/app/workers/citation_engine.py#L11-L16)
|
||||
|
||||
章节来源
|
||||
**章节来源**
|
||||
- [backend/app/workers/platforms/base.py:1-18](file://backend/app/workers/platforms/base.py#L1-L18)
|
||||
- [backend/app/workers/citation_engine.py:148-309](file://backend/app/workers/citation_engine.py#L148-L309)
|
||||
- [backend/app/workers/citation_engine.py:161-330](file://backend/app/workers/citation_engine.py#L161-L330)
|
||||
- [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/api/queries.py:90-108](file://backend/app/api/queries.py#L90-L108)
|
||||
- [backend/app/services/citation.py:1-269](file://backend/app/services/citation.py#L1-L269)
|
||||
- [backend/app/services/query.py:1-123](file://backend/app/services/query.py#L1-L123)
|
||||
- [backend/app/workers/platforms/search_engine.py:1-174](file://backend/app/workers/platforms/search_engine.py#L1-L174)
|
||||
|
|
@ -11,13 +11,24 @@
|
|||
- [backend/app/models/__init__.py](file://backend/app/models/__init__.py)
|
||||
- [backend/alembic/env.py](file://backend/alembic/env.py)
|
||||
- [backend/alembic/versions/488d0bd5ab01_initial_migration.py](file://backend/alembic/versions/488d0bd5ab01_initial_migration.py)
|
||||
- [backend/alembic/versions/b2c4d6e8fa10_add_confidence_match_type_to_citation_records.py](file://backend/alembic/versions/b2c4d6e8fa10_add_confidence_match_type_to_citation_records.py)
|
||||
- [backend/alembic.ini](file://backend/alembic.ini)
|
||||
- [backend/app/config.py](file://backend/app/config.py)
|
||||
- [docker-compose.yml](file://docker-compose.yml)
|
||||
- [backend/app/services/query.py](file://backend/app/services/query.py)
|
||||
- [backend/app/services/citation.py](file://backend/app/services/citation.py)
|
||||
- [backend/app/schemas/citation.py](file://backend/app/schemas/citation.py)
|
||||
- [backend/app/api/citations.py](file://backend/app/api/citations.py)
|
||||
- [backend/app/api/reports.py](file://backend/app/api/reports.py)
|
||||
</cite>
|
||||
|
||||
## 更新摘要
|
||||
**变更内容**
|
||||
- 新增数据库迁移版本,添加confidence和match_type字段到citation_records表
|
||||
- 更新CitationRecord模型以支持新的字段定义
|
||||
- 增强报告功能,支持匹配置信度和匹配类型的统计分析
|
||||
- 更新CSV导出功能,包含新的字段输出
|
||||
|
||||
## 目录
|
||||
1. [简介](#简介)
|
||||
2. [项目结构](#项目结构)
|
||||
|
|
@ -54,6 +65,8 @@ graph TB
|
|||
subgraph "应用层"
|
||||
SvcQ["服务: 查询<br/>backend/app/services/query.py"]
|
||||
SvcC["服务: 引用<br/>backend/app/services/citation.py"]
|
||||
API["API: 引用<br/>backend/app/api/citations.py"]
|
||||
Reports["API: 报告<br/>backend/app/api/reports.py"]
|
||||
end
|
||||
subgraph "ORM 层"
|
||||
MUser["模型: 用户<br/>backend/app/models/user.py"]
|
||||
|
|
@ -73,6 +86,8 @@ Cfg --> Eng
|
|||
Eng --> DB
|
||||
SvcQ --> Eng
|
||||
SvcC --> Eng
|
||||
API --> SvcC
|
||||
Reports --> SvcC
|
||||
MUser --> Eng
|
||||
MQuery --> Eng
|
||||
MCit --> Eng
|
||||
|
|
@ -88,7 +103,7 @@ SvcC --> RD
|
|||
- [backend/app/database.py:1-29](file://backend/app/database.py#L1-L29)
|
||||
- [backend/app/models/user.py:1-41](file://backend/app/models/user.py#L1-L41)
|
||||
- [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/citation_record.py:1-44](file://backend/app/models/citation_record.py#L1-L44)
|
||||
- [backend/app/models/query_task.py:1-39](file://backend/app/models/query_task.py#L1-L39)
|
||||
- [backend/app/models/subscription.py:1-37](file://backend/app/models/subscription.py#L1-L37)
|
||||
- [backend/alembic/env.py:1-89](file://backend/alembic/env.py#L1-L89)
|
||||
|
|
@ -110,6 +125,7 @@ SvcC --> RD
|
|||
- 迁移与版本控制
|
||||
- Alembic 环境集成 SQLAlchemy Base 元数据,支持离线/在线迁移。
|
||||
- 初始迁移脚本定义了用户、查询、引用记录、查询任务、订阅五张表及必要索引。
|
||||
- 新增迁移版本支持confidence和match_type字段,增强报告功能。
|
||||
- 服务层封装
|
||||
- 查询与引用统计、导出等业务逻辑封装在服务层,统一执行 SQL 并返回结果。
|
||||
- 对外暴露清晰的查询接口,内部进行权限校验与计数限制。
|
||||
|
|
@ -118,8 +134,9 @@ SvcC --> RD
|
|||
- [backend/app/database.py:1-29](file://backend/app/database.py#L1-L29)
|
||||
- [backend/app/models/__init__.py:1-14](file://backend/app/models/__init__.py#L1-L14)
|
||||
- [backend/alembic/versions/488d0bd5ab01_initial_migration.py:1-128](file://backend/alembic/versions/488d0bd5ab01_initial_migration.py#L1-L128)
|
||||
- [backend/alembic/versions/b2c4d6e8fa10_add_confidence_match_type_to_citation_records.py:1-37](file://backend/alembic/versions/b2c4d6e8fa10_add_confidence_match_type_to_citation_records.py#L1-L37)
|
||||
- [backend/app/services/query.py:1-130](file://backend/app/services/query.py#L1-L130)
|
||||
- [backend/app/services/citation.py:1-269](file://backend/app/services/citation.py#L1-L269)
|
||||
- [backend/app/services/citation.py:1-429](file://backend/app/services/citation.py#L1-L429)
|
||||
|
||||
## 架构总览
|
||||
下图展示数据库层与应用层的交互关系,以及迁移与容器编排对数据库的影响。
|
||||
|
|
@ -128,26 +145,25 @@ SvcC --> RD
|
|||
sequenceDiagram
|
||||
participant Client as "客户端"
|
||||
participant API as "FastAPI 应用"
|
||||
participant SvcQ as "查询服务"
|
||||
participant SvcC as "引用服务"
|
||||
participant Reports as "报告服务"
|
||||
participant DB as "PostgreSQL"
|
||||
participant Alembic as "迁移工具"
|
||||
Client->>API : 请求 /queries 或 /citations
|
||||
API->>SvcQ : 调用查询服务
|
||||
SvcQ->>DB : 执行查询/计数/插入
|
||||
Client->>API : 请求 /citations 或 /reports
|
||||
API->>SvcC : 调用引用服务
|
||||
SvcC->>DB : 执行 JOIN 统计/导出
|
||||
DB-->>SvcC : 返回统计结果
|
||||
DB-->>SvcQ : 返回查询结果
|
||||
SvcC-->>API : 返回 CSV/统计
|
||||
SvcQ-->>API : 返回查询列表/详情
|
||||
SvcC->>DB : 执行查询/统计/插入
|
||||
API->>Reports : 调用报告服务
|
||||
Reports->>DB : 执行导出查询
|
||||
DB-->>Reports : 返回统计数据
|
||||
DB-->>SvcC : 返回引用记录
|
||||
Reports-->>API : 返回CSV内容
|
||||
SvcC-->>API : 返回查询列表/详情
|
||||
API-->>Client : 响应数据
|
||||
Note over Alembic,DB : 首次启动或升级时执行迁移
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [backend/app/services/query.py:1-130](file://backend/app/services/query.py#L1-L130)
|
||||
- [backend/app/services/citation.py:1-269](file://backend/app/services/citation.py#L1-L269)
|
||||
- [backend/app/services/citation.py:1-429](file://backend/app/services/citation.py#L1-L429)
|
||||
- [backend/alembic/env.py:1-89](file://backend/alembic/env.py#L1-L89)
|
||||
|
||||
## 详细组件分析
|
||||
|
|
@ -155,10 +171,12 @@ Note over Alembic,DB : 首次启动或升级时执行迁移
|
|||
### 实体关系映射(ER)
|
||||
- 用户(users):主键 id,唯一邮箱,计划与配额字段,活跃状态,时间戳。
|
||||
- 查询(queries):外键 user_id,关键词、目标品牌、别名列表、平台列表、频率、状态、下次查询时间,时间戳。
|
||||
- 引用记录(citation_records):外键 query_id,平台、是否引用、引用位置、引用文本、竞争品牌列表、原始响应、查询时间。
|
||||
- 引用记录(citation_records):外键 query_id,平台、是否引用、引用位置、引用文本、竞争品牌列表、原始响应、匹配置信度、匹配类型、查询时间。
|
||||
- 查询任务(query_tasks):外键 query_id,平台、状态、错误信息、调度/开始/完成时间。
|
||||
- 订阅(subscriptions):外键 user_id,计划、状态、起止日期、金额、支付方式与流水号,时间戳。
|
||||
|
||||
**更新** 新增confidence和match_type字段到引用记录表,支持增强的报告功能。
|
||||
|
||||
```mermaid
|
||||
erDiagram
|
||||
USERS {
|
||||
|
|
@ -195,6 +213,8 @@ integer citation_position
|
|||
text citation_text
|
||||
jsonb competitor_brands
|
||||
text raw_response
|
||||
float confidence
|
||||
string match_type
|
||||
timestamptz queried_at
|
||||
}
|
||||
QUERY_TASKS {
|
||||
|
|
@ -228,14 +248,14 @@ USERS ||--o{ SUBSCRIPTIONS : "订阅"
|
|||
图表来源
|
||||
- [backend/app/models/user.py:1-41](file://backend/app/models/user.py#L1-L41)
|
||||
- [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/citation_record.py:1-44](file://backend/app/models/citation_record.py#L1-L44)
|
||||
- [backend/app/models/query_task.py:1-39](file://backend/app/models/query_task.py#L1-L39)
|
||||
- [backend/app/models/subscription.py:1-37](file://backend/app/models/subscription.py#L1-L37)
|
||||
|
||||
章节来源
|
||||
- [backend/app/models/user.py:1-41](file://backend/app/models/user.py#L1-L41)
|
||||
- [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/citation_record.py:1-44](file://backend/app/models/citation_record.py#L1-L44)
|
||||
- [backend/app/models/query_task.py:1-39](file://backend/app/models/query_task.py#L1-L39)
|
||||
- [backend/app/models/subscription.py:1-37](file://backend/app/models/subscription.py#L1-L37)
|
||||
|
||||
|
|
@ -248,21 +268,26 @@ USERS ||--o{ SUBSCRIPTIONS : "订阅"
|
|||
- idx_citation_records_query_id:按查询聚合
|
||||
- idx_citation_records_queried_at:按时间排序/范围
|
||||
- idx_citation_records_platform:按平台统计
|
||||
- 查询任务表(query_tasks)
|
||||
- idx_query_tasks_status:按状态调度
|
||||
- **新增** idx_citation_records_confidence:按匹配置信度过滤(建议)
|
||||
- **新增** idx_citation_records_match_type:按匹配类型过滤(建议)
|
||||
|
||||
**更新** 新增针对confidence和match_type字段的索引建议,支持更精细的查询过滤。
|
||||
|
||||
这些索引覆盖了常见查询路径与统计场景,有助于提升分页、过滤、排序与聚合的性能。
|
||||
|
||||
章节来源
|
||||
- [backend/alembic/versions/488d0bd5ab01_initial_migration.py:57-94](file://backend/alembic/versions/488d0bd5ab01_initial_migration.py#L57-L94)
|
||||
- [backend/alembic/versions/b2c4d6e8fa10_add_confidence_match_type_to_citation_records.py:21-37](file://backend/alembic/versions/b2c4d6e8fa10_add_confidence_match_type_to_citation_records.py#L21-L37)
|
||||
- [backend/app/models/query.py:50-54](file://backend/app/models/query.py#L50-L54)
|
||||
- [backend/app/models/citation_record.py:37-41](file://backend/app/models/citation_record.py#L37-L41)
|
||||
- [backend/app/models/citation_record.py:37-44](file://backend/app/models/citation_record.py#L37-L44)
|
||||
- [backend/app/models/query_task.py:36-38](file://backend/app/models/query_task.py#L36-L38)
|
||||
|
||||
### SQLAlchemy ORM 模型实现
|
||||
- 字段类型与默认值
|
||||
- UUID 主键与外键,JSONB 存储数组/字典,布尔、整数、文本、数值、时间戳等。
|
||||
- 默认值通过 server_default/onupdate 设置,减少应用层重复逻辑。
|
||||
- **新增** confidence字段(Float类型,nullable=True)用于存储匹配的可信度评分。
|
||||
- **新增** match_type字段(String类型,长度20,nullable=True)用于标识匹配类型。
|
||||
- 关系配置
|
||||
- 用户与查询、订阅为一对多;查询与引用记录、任务为一对多。
|
||||
- 级联删除与孤儿对象清理(delete-orphan),避免悬挂数据。
|
||||
|
|
@ -270,6 +295,8 @@ USERS ||--o{ SUBSCRIPTIONS : "订阅"
|
|||
- 服务层使用 select + func + join 封装复杂查询,统一处理分页与计数。
|
||||
- 权限校验:仅允许访问当前用户的资源,防止越权。
|
||||
|
||||
**更新** CitationRecord模型新增confidence和match_type字段定义,支持增强的报告功能。
|
||||
|
||||
```mermaid
|
||||
classDiagram
|
||||
class User {
|
||||
|
|
@ -311,6 +338,8 @@ class CitationRecord {
|
|||
+citation_text : text
|
||||
+competitor_brands : list
|
||||
+raw_response : text
|
||||
+confidence : float
|
||||
+match_type : string
|
||||
+queried_at : datetime
|
||||
+query
|
||||
}
|
||||
|
|
@ -347,14 +376,14 @@ User "1" <-- "many" Subscription : "订阅"
|
|||
图表来源
|
||||
- [backend/app/models/user.py:11-41](file://backend/app/models/user.py#L11-L41)
|
||||
- [backend/app/models/query.py:11-48](file://backend/app/models/query.py#L11-L48)
|
||||
- [backend/app/models/citation_record.py:11-35](file://backend/app/models/citation_record.py#L11-L35)
|
||||
- [backend/app/models/citation_record.py:11-44](file://backend/app/models/citation_record.py#L11-L44)
|
||||
- [backend/app/models/query_task.py:11-34](file://backend/app/models/query_task.py#L11-L34)
|
||||
- [backend/app/models/subscription.py:11-36](file://backend/app/models/subscription.py#L11-L36)
|
||||
|
||||
章节来源
|
||||
- [backend/app/models/user.py:1-41](file://backend/app/models/user.py#L1-L41)
|
||||
- [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/citation_record.py:1-44](file://backend/app/models/citation_record.py#L1-L44)
|
||||
- [backend/app/models/query_task.py:1-39](file://backend/app/models/query_task.py#L1-L39)
|
||||
- [backend/app/models/subscription.py:1-37](file://backend/app/models/subscription.py#L1-L37)
|
||||
|
||||
|
|
@ -362,13 +391,16 @@ User "1" <-- "many" Subscription : "订阅"
|
|||
- 迁移入口
|
||||
- Alembic 环境加载 Base 元数据,支持离线/在线迁移。
|
||||
- 在线迁移通过异步引擎连接数据库,避免阻塞。
|
||||
- 初始迁移
|
||||
- 创建 users、queries、citation_records、query_tasks、subscriptions 表,并建立必要索引。
|
||||
- 迁移版本
|
||||
- **初始版本** (488d0bd5ab01):创建 users、queries、citation_records、query_tasks、subscriptions 表,并建立必要索引。
|
||||
- **新增版本** (b2c4d6e8fa10):向 citation_records 表添加 confidence 和 match_type 字段,支持增强的报告功能。
|
||||
- 外键约束与级联删除策略明确,确保数据一致性。
|
||||
- 部署策略
|
||||
- Docker Compose 启动 PostgreSQL 与 Redis,应用容器依赖数据库健康检查。
|
||||
- 生产环境建议将数据库与缓存分离,使用独立卷持久化数据。
|
||||
|
||||
**更新** 新增b2c4d6e8fa10迁移版本,支持confidence和match_type字段的添加。
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Start(["开始"]) --> CheckEnv["检查 DATABASE_URL"]
|
||||
|
|
@ -378,17 +410,23 @@ Mode --> |离线| Offline["配置 URL 与元数据"]
|
|||
Mode --> |在线| Online["创建异步引擎并连接"]
|
||||
Offline --> RunMigs["执行迁移"]
|
||||
Online --> RunMigs
|
||||
RunMigs --> Done(["完成"])
|
||||
RunMigs --> Version{"检查版本"}
|
||||
Version --> |488d0bd5ab01| InitMigration["初始迁移"]
|
||||
Version --> |b2c4d6e8fa10| AddFields["添加新字段"]
|
||||
InitMigration --> Done(["完成"])
|
||||
AddFields --> Done
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [backend/alembic/env.py:33-88](file://backend/alembic/env.py#L33-L88)
|
||||
- [backend/alembic/versions/488d0bd5ab01_initial_migration.py:21-128](file://backend/alembic/versions/488d0bd5ab01_initial_migration.py#L21-L128)
|
||||
- [backend/alembic/versions/b2c4d6e8fa10_add_confidence_match_type_to_citation_records.py:21-37](file://backend/alembic/versions/b2c4d6e8fa10_add_confidence_match_type_to_citation_records.py#L21-L37)
|
||||
- [docker-compose.yml:1-71](file://docker-compose.yml#L1-L71)
|
||||
|
||||
章节来源
|
||||
- [backend/alembic/env.py:1-89](file://backend/alembic/env.py#L1-L89)
|
||||
- [backend/alembic/versions/488d0bd5ab01_initial_migration.py:1-128](file://backend/alembic/versions/488d0bd5ab01_initial_migration.py#L1-L128)
|
||||
- [backend/alembic/versions/b2c4d6e8fa10_add_confidence_match_type_to_citation_records.py:1-37](file://backend/alembic/versions/b2c4d6e8fa10_add_confidence_match_type_to_citation_records.py#L1-L37)
|
||||
- [docker-compose.yml:1-71](file://docker-compose.yml#L1-L71)
|
||||
|
||||
### 数据完整性约束、事务处理与并发控制
|
||||
|
|
@ -396,6 +434,7 @@ RunMigs --> Done(["完成"])
|
|||
- 唯一约束:用户邮箱唯一
|
||||
- 外键约束:查询、任务、订阅均对用户做级联删除
|
||||
- JSONB 字段默认值:空数组/字典,避免 NULL 导致的条件判断复杂化
|
||||
- **新增** confidence字段允许NULL值,match_type字段限制长度为20字符
|
||||
- 事务处理
|
||||
- 服务层方法在单个事务内执行插入/更新/删除,提交后刷新对象状态
|
||||
- 会话工厂设置 expire_on_commit=False,减少后续查询的额外开销
|
||||
|
|
@ -403,8 +442,11 @@ RunMigs --> Done(["完成"])
|
|||
- 异步连接池与会话隔离,避免阻塞
|
||||
- 服务层在执行前进行权限校验与配额检查,降低并发冲突概率
|
||||
|
||||
**更新** 新增对confidence和match_type字段的完整性约束说明。
|
||||
|
||||
章节来源
|
||||
- [backend/alembic/versions/488d0bd5ab01_initial_migration.py:36-111](file://backend/alembic/versions/488d0bd5ab01_initial_migration.py#L36-L111)
|
||||
- [backend/alembic/versions/b2c4d6e8fa10_add_confidence_match_type_to_citation_records.py:21-37](file://backend/alembic/versions/b2c4d6e8fa10_add_confidence_match_type_to_citation_records.py#L21-L37)
|
||||
- [backend/app/services/query.py:45-81](file://backend/app/services/query.py#L45-L81)
|
||||
- [backend/app/database.py:12-18](file://backend/app/database.py#L12-L18)
|
||||
|
||||
|
|
@ -412,18 +454,23 @@ RunMigs --> Done(["完成"])
|
|||
- 查询列表与计数
|
||||
- 分页查询与计数分离,避免重复扫描全表
|
||||
- 使用索引覆盖 user_id 与 created_at 排序
|
||||
- **新增** 支持按confidence和match_type过滤查询
|
||||
- 引用统计
|
||||
- 使用 JOIN 查询限定到用户所属的查询
|
||||
- 按平台分组统计,利用索引加速 queried_at 与 platform
|
||||
- **新增** 支持按匹配置信度和匹配类型进行统计分析
|
||||
- 导出 CSV
|
||||
- 以查询为维度导出,先验证所有权再执行导出
|
||||
- **新增** 输出confidence和match_type字段到CSV文件
|
||||
|
||||
**更新** 增强查询流程,支持新的字段过滤和统计功能。
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant API as "API"
|
||||
participant Svc as "服务"
|
||||
participant DB as "数据库"
|
||||
API->>Svc : get_citations(user_id, query_id?, platform?, dates?)
|
||||
API->>Svc : get_citations(user_id, query_id?, platform?, dates?, confidence?, match_type?)
|
||||
Svc->>DB : SELECT ... FROM citation_records JOIN queries WHERE ...
|
||||
DB-->>Svc : 记录集
|
||||
Svc->>DB : COUNT ... FROM citation_records JOIN queries WHERE ...
|
||||
|
|
@ -432,26 +479,50 @@ Svc-->>API : 结果与总数
|
|||
```
|
||||
|
||||
图表来源
|
||||
- [backend/app/services/citation.py:24-73](file://backend/app/services/citation.py#L24-L73)
|
||||
- [backend/app/services/citation.py:30-79](file://backend/app/services/citation.py#L30-L79)
|
||||
|
||||
章节来源
|
||||
- [backend/app/services/query.py:12-32](file://backend/app/services/query.py#L12-L32)
|
||||
- [backend/app/services/citation.py:24-73](file://backend/app/services/citation.py#L24-L73)
|
||||
- [backend/app/services/citation.py:30-79](file://backend/app/services/citation.py#L30-L79)
|
||||
|
||||
### 报告功能增强
|
||||
- **匹配置信度分析**
|
||||
- confidence字段用于存储匹配的可信度评分(0.0-1.0)
|
||||
- 支持按置信度区间进行统计分析
|
||||
- 在CSV导出中显示详细的置信度信息
|
||||
- **匹配类型分类**
|
||||
- match_type字段标识匹配类型:exact(精确匹配)、alias(别名匹配)、fuzzy(模糊匹配)
|
||||
- 支持按匹配类型进行分组统计
|
||||
- 在报告中提供中文显示(精确匹配、别名匹配、模糊匹配)
|
||||
- **增强的统计指标**
|
||||
- 支持按置信度和匹配类型的组合进行交叉分析
|
||||
- 提供更精细的引用质量评估
|
||||
|
||||
**新增** 报告功能章节,详细介绍新增的confidence和match_type字段的应用。
|
||||
|
||||
章节来源
|
||||
- [backend/app/services/citation.py:298-308](file://backend/app/services/citation.py#L298-L308)
|
||||
- [backend/app/services/citation.py:342-429](file://backend/app/services/citation.py#L342-L429)
|
||||
- [backend/app/schemas/citation.py:7-18](file://backend/app/schemas/citation.py#L7-L18)
|
||||
|
||||
## 依赖分析
|
||||
- 模块耦合
|
||||
- 模型层仅依赖 Base 与 SQLAlchemy 类型,低耦合
|
||||
- 服务层依赖模型与会话,职责清晰
|
||||
- Alembic 依赖 Base 与配置,迁移脚本与模型同步演进
|
||||
- **新增** API层依赖服务层,提供RESTful接口
|
||||
- 外部依赖
|
||||
- PostgreSQL 异步驱动(asyncpg)
|
||||
- Redis(用于缓存,如需要)
|
||||
|
||||
**更新** 新增API层依赖关系,支持新的报告功能接口。
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
Cfg["配置<br/>config.py"] --> DB["数据库引擎<br/>database.py"]
|
||||
DB --> Models["ORM 模型<br/>models/*"]
|
||||
Models --> Services["服务层<br/>services/*"]
|
||||
Services --> API["API层<br/>api/*"]
|
||||
Alembic["迁移<br/>alembic/*"] --> DB
|
||||
Docker["编排<br/>docker-compose.yml"] --> DB
|
||||
```
|
||||
|
|
@ -472,50 +543,61 @@ Docker["编排<br/>docker-compose.yml"] --> DB
|
|||
|
||||
## 性能考虑
|
||||
- 索引优化
|
||||
- 为高频过滤字段建立单列索引(user_id/status/next_query_at/platform/queried_at)
|
||||
- 为高频过滤字段建立单列索引(user_id/status/next_query_at/platform/queried_at/confidence/match_type)
|
||||
- 对 JSONB 字段可考虑 GIN 索引(如需复杂查询),当前迁移脚本未启用
|
||||
- **新增** 建议为confidence和match_type字段建立单独索引,支持高效过滤
|
||||
- 查询优化
|
||||
- 分页与计数分离,避免重复扫描
|
||||
- 使用 JOIN 限定用户范围,减少全表扫描
|
||||
- 时间范围查询使用索引覆盖
|
||||
- **新增** 支持按confidence范围和match_type进行高效过滤
|
||||
- 缓存策略
|
||||
- 引用统计与趋势数据可缓存至 Redis,设置合理过期时间
|
||||
- 导出 CSV 可缓存热点查询结果,降低数据库压力
|
||||
- **新增** 报告统计数据可缓存,提高频繁访问的响应速度
|
||||
- 连接与并发
|
||||
- 使用异步连接池,避免阻塞
|
||||
- 控制并发度,避免大量写入导致锁争用
|
||||
|
||||
[本节为通用指导,不直接分析具体文件]
|
||||
**更新** 新增针对confidence和match_type字段的性能优化建议。
|
||||
|
||||
## 故障排查指南
|
||||
- 迁移失败
|
||||
- 检查 DATABASE_URL 是否正确,Alembic 配置与环境变量一致
|
||||
- 确认数据库已初始化且用户具备权限
|
||||
- **新增** 检查新字段的默认值和约束条件
|
||||
- 查询异常
|
||||
- 核对服务层权限校验逻辑,确认 user_id 与查询归属一致
|
||||
- 检查索引是否存在,必要时重建索引
|
||||
- **新增** 验证confidence和match_type字段的数据类型和取值范围
|
||||
- 导出失败
|
||||
- 确认查询所有权校验通过
|
||||
- 检查 CSV 写入逻辑与字符编码
|
||||
- **新增** 验证新字段在导出过程中的处理逻辑
|
||||
|
||||
**更新** 新增针对新字段的故障排查指导。
|
||||
|
||||
章节来源
|
||||
- [backend/alembic/env.py:33-88](file://backend/alembic/env.py#L33-L88)
|
||||
- [backend/app/services/citation.py:14-22](file://backend/app/services/citation.py#L14-L22)
|
||||
|
||||
## 结论
|
||||
本数据库设计围绕用户、查询、引用记录、任务与订阅五大实体展开,采用 PostgreSQL + SQLAlchemy Async + Alembic 的成熟技术栈,具备良好的扩展性与可维护性。通过合理的索引策略、事务边界与服务层封装,能够满足日常查询、统计与导出需求。建议在生产环境中进一步引入缓存与监控,持续优化查询路径与索引覆盖。
|
||||
本数据库设计围绕用户、查询、引用记录、任务与订阅五大实体展开,采用 PostgreSQL + SQLAlchemy Async + Alembic 的成熟技术栈,具备良好的扩展性与可维护性。通过合理的索引策略、事务边界与服务层封装,能够满足日常查询、统计与导出需求。
|
||||
|
||||
[本节为总结性内容,不直接分析具体文件]
|
||||
**更新** 新增的confidence和match_type字段显著增强了报告功能,提供了更精细的引用质量分析能力。建议在生产环境中进一步引入缓存与监控,持续优化查询路径与索引覆盖。
|
||||
|
||||
## 附录
|
||||
- 部署与运维
|
||||
- 使用 Docker Compose 启动数据库与应用,确保数据库健康检查通过后再启动应用
|
||||
- 生产环境建议使用独立数据库实例与只读副本,配合连接池与慢查询日志
|
||||
- **新增** 升级时确保迁移脚本按顺序执行,从初始版本到最新版本
|
||||
- 备份与恢复
|
||||
- 使用 pg_dump/pg_restore 进行逻辑备份与恢复
|
||||
- 对关键表定期增量备份,结合 WAL 归档实现点-in-time 恢复
|
||||
- **新增** 新字段变更需要纳入备份策略,确保数据完整性
|
||||
- 监控与告警
|
||||
- 监控连接数、查询延迟、索引命中率与慢查询
|
||||
- 对迁移脚本变更进行版本化管理与回滚演练
|
||||
- **新增** 监控新字段的使用情况和性能影响
|
||||
|
||||
[本节为通用指导,不直接分析具体文件]
|
||||
**更新** 新增针对新字段的部署和运维指导。
|
||||
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,15 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
cd /Users/Chiguyong/Code/GEO
|
||||
echo "=== Step 1: Check remote ==="
|
||||
git remote -v
|
||||
echo "=== Step 2: Git status ==="
|
||||
git status
|
||||
echo "=== Step 3: Git log ==="
|
||||
git log --oneline -5
|
||||
echo "=== Step 4: Push ==="
|
||||
git push -u origin main 2>&1 || {
|
||||
echo "Push failed, trying force push..."
|
||||
git push -u origin main --force 2>&1
|
||||
}
|
||||
echo "=== Done ==="
|
||||
|
|
@ -0,0 +1 @@
|
|||
hello2
|
||||
Loading…
Reference in New Issue