# 剧情语义检索开发与验收

2026-10-04。已将原关键词改写实现换成 PRD 指定的向量检索：自托管 Qwen3-Embedding-0.6B、PostgreSQL pgvector、Payload 官方后台任务。代码位于短剧库项目，Web/RN共用原查询接口，App本轮无需重建。普通渠道的本站/App内10/50集规则、用户直连优先和按需转发继续沿用。

## 实际行为

“A female CEO takes revenge after her husband betrays her”可以找到中文剧情；“害羞的钢琴家回到海边故乡重建音乐学校”可以找到英文剧情。模型只计算相似度，不生成剧名、地址或可执行指令。关键词命中与语义召回合并，当前渠道权限、综合筛选和canonical身份决定最终列表。用户仍看到两列、每页10部，cursor保留排序；后续分页不重复调用模型或扣查询次数。

默认语义分数下限0.5，与授权及筛选后最高分的差值最多0.15。调试样例发现单用固定下限会让“失散兄妹团聚”带回25部无关复仇剧，因此增加相对分数范围；现在仅返回目标剧，低分跨语言宫廷剧情仍能召回。关键词命中不因向量弱而丢失。样例只评估目标首项、无关查询为空及这项候选污染，不能视为真实剧库准确率。

目录文本使用标题、简介、标签。现有Go同步已传递简介。向量与实际文本存于同一PostgreSQL；更新后旧文本向量立即排除，推理期间再次修改的记录留待下次索引。下架与渠道权限实时过滤；只按同模型检索。模型升级使用不同版本名并重建索引。

## 接入与复用

原本就使用的PostgreSQL继续负责事务和身份，[pgvector](https://github.com/pgvector/pgvector)负责精确相似度检索；首期不增加另一套向量数据库。推理通过自托管[Ollama `/api/embed`](https://docs.ollama.com/api/embed)复用成熟服务，不增加商业SDK。Qwen模型卡标注[Apache-2.0](https://huggingface.co/Qwen/Qwen3-Embedding-0.6B/raw/main/README.md)，[Ollama使用MIT](https://github.com/ollama/ollama/blob/main/LICENSE)，[pgvector使用PostgreSQL许可证](https://github.com/pgvector/pgvector/blob/master/LICENSE)。不据此承诺模型训练数据全量公开。

```js
const application = createDramivioApplication({
  ...existingConfiguration,
  semanticSearch: {
    baseURL: 'http://127.0.0.1:11434',
    model: 'qwen3-embedding:0.6b',
    guestDailyLimit: 5,
    accountDailyLimit: 30,
    globalDailyLimit: 500,
    maxConcurrent: 2,
    minSimilarity: 0.5,
    similarityWindow: 0.15,
  },
});
await application.initialize(); // 明确的安装/升级步骤；先在隔离环境验证
await application.start();
```

pgvector与模型必须预先安装。省略`semanticSearch`时继续普通搜索，不从环境隐式启用模型。`initialize()`显式执行可选向量表和Payload官方任务迁移；`start()`不迁移、不下载模型。配置同时传给当前平台与其自有后台进程。

Payload注册`semantic-index`：每5分钟安排一次、每分钟消费队列；默认每任务最多100条、每批8条、每批推理最多30秒。剩余记录进入下一任务；失败保留官方失败记录并按框架重试3次，错误不记录模型连接细节。自动任务随后台进程运行。管理员可使用官方Jobs运行入口；接口拒绝游客/编辑者，撤销管理员角色后原token也拒绝。首次索引未建立时自动回退普通搜索。

需要拆开调用时，导入`services/platform/src/search.mjs`中的`createSemanticSearch({database,...configuration})`，得到`initialize()`、`indexCatalog()`、`search()`。向量客户端和目录索引器也可从`embeddings.mjs`分别导入。生产数据库和SMTP不在本轮测试中。

## 验证结果

| 验证 | 实际结果及范围 |
| --- | --- |
| 真实模型相关度PoC | Ollama0.35.1、Qwen0.6B Q8_0/1024维、Linux arm64 CPU；12组原创测试剧情、24条查询。19条剧情首项命中，5条无关查询为空；包含英文查中文、中文查英文。最初0.55下限漏掉一条英语宫廷查询，调至0.5后用8条追加样例验证；不作为独立盲测准确率。 |
| 真实公开接口 | Go、官方Better Auth、RAM PostgreSQL/pgvector及实际Qwen联调。游客分页10/10/5、canonicalID跨页不重复、cursor额外模型尝试0；未登录多条件401；实际邮箱验证登录后筛选生效；隐藏渠道排除。25个同文本canonical仅作分页夹具，不代表内容去重验收。OTP由测试捕获，不是SMTP。Go子进程退出0，视频源请求被夹具禁止。 |
| 失败回退 | 实际模型1毫秒截止触发关键词回退，仍查到25条标题结果；查询不增加视频账本扣次。常规接口测试覆盖3秒上限、异常维度/模型/零向量/超大响应、个人及全局预算、并发槽和慢续租。 |
| 目录与权限边界 | 真实pgvector测试覆盖批次续跑、重复任务、元数据更新、推理期间编辑、下架、当前权限、相对阈值只用可访问结果，以及弱向量保留关键词命中。 |
| 后台任务 | 实际Payload迁移、调度去重、失败保留、重试、剩余批次、完成清理及角色撤销通过。索引接口的边界测试使用受控向量响应，真实模型另行联调。 |
| 1万条规模测量 | 复制同一实际文本与其真实向量为1万个canonical记录，测精确SQL、快照与分页。显式卸载模型后首次2.31秒；后4次215–241毫秒；cursor约49–69毫秒。未测真实1万种剧情、生产并发或去重质量。 |
| 全量回归 | platform271/271；Payload95/95。App356、类型检查和Web167沿用既有结果，本轮未改RN/Web页面代码。 |

[本轮验证数据](dramivio-semantic-search-validation.json) · [当前开发状态](dramivio-development-status.md)。原搜索独立复审属于此前关键词规划实现；本轮由主Agent实现并复核，没有新一轮独立子Agent结论。

## 分阶段验收

1. 安装：准备隔离PG/pgvector和开源模型，显式初始化；未配置时普通查询可用，未建索引自动回退。
2. 目录：索引有限批次；修改简介、下架、任务重试及任务期间编辑，核对文本和向量一致。
3. 查询：中英相关与无关样例、权限与筛选、关键词保留、三页稳定、限额及模型中断；核对视频账本不变。
4. 真实环境：用实际授权剧库重新评估相关度/候选数量，按真实目录与并发测延迟，再确定服务器配置。正式SMTP、安装资格、可信邀请观看证明、真机/完整iOS、剩余离线后台调度与完整设计状态继续按原任务验收。

本轮仅更新代码与CF静态文档，未部署业务服务、运行生产迁移、发布App/OTA或开启广告/收费。
