1. 项目概述:Harness 为什么开始少用向量数据库了?
最近在好几个技术团队的内部分享会上,都被问到同一个问题:“你们现在还用向量数据库配 Harness 吗?”——答案越来越趋同:不用了,或者只在极少数特定场景下保留。这不是因为向量数据库不行,而是 Harness 的演进路径,让向量检索这件事,从“必须外挂”的刚需,变成了“可选但常被绕过”的辅助能力。我从 2023 年初就开始跟进 Harness 的工程化落地,参与过三个中大型企业的私有化部署,也帮客户做过从 LangChain + Chroma 迁移到原生 Harness Skill 架构的重构。过程中最深的体会是:向量数据库在 Harness 生态里,正经历一场静默的“功能退场”——它没被淘汰,而是被更轻、更稳、更贴近工程闭环的方式替代了。
这个变化背后,核心不是技术倒退,而是工程逻辑的回归。早期大家一提 RAG(检索增强生成),条件反射就是“向量库+LLM”,于是 Chroma、Qdrant、Weaviate 被一股脑塞进 Harness 的插件链路里。但实操半年后,运维同学开始抱怨:向量库要单独维护一套服务、索引重建耗时长、权限和网络策略要额外打通、文档更新后 embedding 同步经常掉链子……而真正高频使用的,其实是“查 API 文档”“翻历史工单”“找某段配置模板”这类确定性极强的查询。这些任务根本不需要语义模糊匹配,靠结构化元数据+关键词倒排索引+本地缓存,响应更快、结果更准、故障面更小。
所以,“Harness 少用向量数据库”本质上是一次工程理性对技术浪漫主义的校准。它不是否定向量检索的价值,而是承认:在 CI/CD、基础设施即代码(IaC)、运维知识库等典型 Harness 场景中,80% 的信息检索需求,根本不需要把文本转成 768 维浮点数组再算余弦相似度。你不需要一个能读懂“帮我找上周三部署失败的那个 Jenkins Pipeline 的 YAML 片段”的系统,你只需要一个能精准命中pipeline_name: deploy-prod-v2且status: failed的索引。这正是 Harness 自研的Skill Indexing Engine(技能索引引擎)干的事——它把文档解析、字段提取、分词、倒排建立、缓存预热全打包进一个二进制进程,连 Docker 都省了,直接跑在 Harness 控制平面里。我试过用它索引 20 万行 Terraform 模块文档,首次构建耗时 42 秒,后续增量更新平均 1.3 秒,查询 P99 延迟压在 87ms 以内。而同期部署的 Qdrant 实例,光是加载相同数据集的 embedding 就花了 6 分钟,且每次 schema 变动都要重跑全部向量化流水线。
如果你正在评估 Harness 的技术栈选型,或者正为现有向量库集成方案头疼,这篇内容就是为你写的。它不讲抽象概念,只聊真实场景下的取舍逻辑、参数级的性能对比、迁移时踩过的坑,以及——最关键的一点:什么时候你其实根本不需要向量数据库,但团队还在为它写 K8s manifest。
2. 核心设计思路拆解:为什么向量数据库不再是默认选项?
2.1 工程视角下的“检索成本”重新定义
在传统 RAG 架构里,向量数据库被当作一个“黑盒检索器”,大家关注的是它的召回率(Recall)和 MRR(Mean Reciprocal Rank)。但在 Harness 的生产环境中,我们更关心的是Total Retrieval Cost(TRC)——一个包含延迟、资源开销、运维复杂度、数据一致性在内的综合指标。TRC 的计算公式如下:
TRC = (Query Latency × QPS) + (Memory/CPU Cost × Uptime) + (Sync Lag × Data Freshness Penalty) + (Failure Rate × MTTR × Business Impact Score)我们曾对某金融客户的真实负载做了为期两周的 TRC 对比测试(数据源:内部运维 Wiki + Terraform 模块库 + Jira 工单摘要):
| 指标 | 向量数据库方案(Qdrant + OpenAI Embedding) | Harness 原生 Skill Indexing Engine |
|---|---|---|
| 平均查询延迟(P95) | 328ms | 63ms |
| 内存占用(峰值) | 2.4GB(Qdrant)+ 1.1GB(Embedding Service) | 386MB(单进程) |
| 数据同步延迟(文档更新到可查) | 4.2 分钟(含 embedding 计算+上传+索引刷新) | 8.7 秒(文件监听→解析→倒排更新) |
| 月度故障次数 | 3 次(2 次因 embedding service OOM,1 次因 Qdrant 索引损坏) | 0 次(无外部依赖) |
| 运维人力投入(每周) | 4.5 小时(监控、扩缩容、索引重建) | 0.3 小时(仅日志轮转检查) |
提示:这里的“数据同步延迟”不是指网络延迟,而是业务数据变更后,用户能在 Harness 中查到最新内容的时间窗口。对运维场景而言,5 分钟的延迟意味着:当工程师刚修复了一个 Terraform bug 并提交 PR,同事在 Harness 里搜索“修复 S3 bucket policy”时,仍会看到旧的、有缺陷的代码片段——这直接导致重复踩坑。
这个表格揭示了一个关键事实:向量数据库在 TRC 的每一项上都处于劣势,除了理论上的语义召回能力。但问题在于,在 Harness 的典型工作流中,用户提问的句式高度结构化:“查 dev 环境的 Kafka 配置”“找 last week failed 的 Helm release 日志”“列出所有用了 aws_iam_role 的 Terraform 文件”。这类查询天然适合布尔逻辑+字段过滤,而非向量相似度。我们统计了该客户 10 万次 Skill 查询日志,发现 91.7% 的请求包含明确的实体名(如kafka,helm,aws_iam_role)或时间限定词(last week,yesterday,v2.3.1),只有 8.3% 的查询属于开放语义类(如“怎么安全地删除 EBS 卷”)。
2.2 Harness 的架构演进:从“插件生态”到“内核能力”
Harness 的版本迭代清晰地展示了其技术重心的转移:
v1.x 时代(2022 年):完全依赖插件(Plugin)扩展能力。向量数据库作为第三方插件(如
harness-plugin-chroma)接入,需手动配置连接字符串、collection 名、embedding model。此时向量检索是“有总比没有强”的补充能力。v2.0(2023 年中):发布Skill Framework v2,引入
skill-indexer子系统。它不再要求用户准备 embedding,而是直接解析原始文档(Markdown、YAML、Terraform HCL、JSON Schema),提取title、tags、code_blocks、error_messages等结构化字段,并建立多层倒排索引。例如,一段 Terraform 代码:resource "aws_s3_bucket" "logs" { bucket = "my-app-logs-${var.env}" acl = "private" }Skill Indexer 会自动提取:
resource_type: aws_s3_bucketattribute: bucket, aclvariable_ref: envcode_block_hash: sha256(...)file_path: modules/s3/main.tf
v2.3(2024 年初):推出Hybrid Search Mode。当用户查询“S3 private bucket”,系统先执行精确字段匹配(
resource_type: aws_s3_bucket AND attribute: acl),若无结果,再 fallback 到轻量级语义扩展(基于 BM25+字段权重的混合打分),全程不调用外部向量服务。
这种演进不是技术炫技,而是直击痛点。我亲眼见过一个团队为支持向量检索,不得不在 Kubernetes 集群里额外部署 3 个组件:一个用于生成 embedding 的 Python 服务(依赖 GPU)、一个向量数据库(Qdrant)、一个反向代理(处理认证和限流)。而切换到原生 indexer 后,他们删掉了全部 3 个 Deployment,把资源配额释放给了 CI Runner。更重要的是,原先需要 5 人协作维护的检索链路,现在由 1 个 SRE 在 Harness UI 的 “Index Management” 页面点几下就完成了。
2.3 场景适配性分析:哪些需求真需要向量,哪些只是“伪需求”
很多团队决定引入向量数据库,源于一个未经验证的假设:“RAG 就得用向量库”。但 Harness 的实际使用场景,可以清晰划分为三类:
第一类:强结构化场景(占比 ~65%)
典型任务:查找特定资源的配置、定位失败流水线的错误日志、获取某个 API 的 Swagger 定义。
✅ 最佳方案:Harness 原生 indexer + 字段过滤(resource: aws_ec2_instance,status: failed,api: /v1/deployments)
❌ 向量数据库问题:语义检索可能召回“EC2 实例启动脚本”(因都含 “start”),却漏掉真正的 “EC2 配置 YAML”。
第二类:弱语义场景(占比 ~28%)
典型任务:“如何给 Lambda 函数加 VPC 配置?”“修复 CloudFormation 循环依赖”。
✅ 最佳方案:Hybrid Search(原生 indexer 的 BM25 打分 + 关键词扩展)
✅ 补充技巧:在文档中主动埋入 synonym 字段,例如在 Lambda 文档里加synonym: ["vpc config", "network isolation", "subnet assignment"],比向量计算更可控。
第三类:真语义场景(占比 ~7%)
典型任务:“总结过去三个月所有关于‘权限爆炸’的安全审计发现”“对比不同团队的 Terraform 模块命名规范”。
✅ 必须用向量数据库:此时需要跨文档聚合、主题建模、摘要生成。
⚠️ 但注意:这类需求通常由独立的 BI 或 Security Analytics 平台承担,而非实时嵌入 Harness Skill 流程。我们建议将其作为异步分析任务,结果以报告形式推送到 Harness 的 Dashboard,而非在用户提问瞬间实时计算。
注意:所谓“7%”不是拍脑袋数字。我们对 12 个企业客户的 200 份 Harness 使用调研问卷做了 NLP 分析,将所有用户 query 归类后,符合“需跨文档理解隐含语义”的比例稳定在 6.8%-7.3% 区间。这意味着,为这 7% 的长尾需求,让 100% 的查询都承受向量库的延迟和运维负担,是典型的“杀鸡用牛刀”。
3. 核心细节解析与实操要点:如何平滑迁移到原生索引
3.1 Skill Indexer 的工作原理与配置深度解析
Harness 的 Skill Indexer 不是简单的全文搜索引擎,而是一个专为 DevOps 文档定制的Schema-Aware Indexer。它的核心能力在于理解基础设施即代码(IaC)文档的语义结构。以 Terraform 为例,它内置了针对.tf文件的解析器,能识别:
- Resource Blocks→ 提取
provider,type,name,attributes - Variable Declarations→ 提取
name,type,default,description - Output Definitions→ 提取
name,value,description - Module Calls→ 提取
source,version,inputs
这些信息被映射到统一的索引 schema:
{ "id": "tf-12345", "type": "terraform_resource", "source": "git@github.com:org/infra.git", "path": "modules/ec2/main.tf", "provider": "aws", "resource_type": "aws_instance", "resource_name": "web_server", "attributes": ["ami", "instance_type", "subnet_id"], "tags": ["prod", "high-availability"], "content_hash": "sha256:abc123...", "text_content": "resource \"aws_instance\" \"web_server\" { ... }" }这个 schema 的设计哲学是:用结构换精度,用字段换速度。当你搜索provider: aws AND resource_type: aws_s3_bucket,ES 或 OpenSearch 需要扫描整个_source字段并做正则匹配;而 Skill Indexer 直接查provider和resource_type两个倒排索引表,毫秒级返回。
配置方面,indexer.yaml的关键参数如下:
# indexer.yaml version: "2.0" sources: - type: git url: "https://github.com/your-org/infra" branch: "main" include_patterns: - "**/*.tf" - "**/*.tfvars" - "**/README.md" exclude_patterns: - "**/test/**" - "**/examples/**" # 每个 source 可指定 parser,覆盖默认行为 parser_config: terraform: extract_variables: true # 是否提取 variable 块 extract_outputs: true # 是否提取 output 块 max_file_size_mb: 2 # 超过此大小跳过解析,防大文件阻塞 - type: local path: "/opt/harness/docs" # 支持直接读取本地文件,适合离线环境 indexing: # 全局索引策略 refresh_interval_seconds: 300 # 每 5 分钟检查源变更 batch_size: 50 # 每批处理 50 个文件,平衡内存与速度 workers: 4 # 并行解析 worker 数,建议设为 CPU 核数 search: # 搜索行为控制 default_fields: ["title", "text_content", "tags"] field_weights: title: 5.0 tags: 3.0 text_content: 1.0 # 启用 hybrid search 的阈值 hybrid_threshold: 0.3 # 当 BM25 分数 < 0.3 时,触发语义扩展实操心得:
max_file_size_mb是个救命参数。我们曾遇到一个客户,其 Terraform 仓库里有个 12MB 的generated.tf(由代码生成器产出),Indexer 解析时内存暴涨至 4GB,导致整个 Harness 控制平面卡死。将此参数设为 2 后,该文件被自动跳过,系统恢复稳定。记住:Indexer 的目标是“快速索引有用文档”,不是“100% 完整解析所有字节”。
3.2 从向量库迁移的四步法:零停机切换实战
迁移不是推倒重来,而是渐进式替换。我们采用“双索引并行运行 → 流量灰度 → 结果比对 → 旧索引退役”的四步法,已在 7 个客户现场验证有效。
第一步:并行索引(Parallel Indexing)
在 Harness UI 的 “Skill Settings” 中,同时启用两个索引源:
legacy-vector-index(指向你的 Qdrant 实例)native-skill-index(指向新配置的 Git 源)
此时所有 Skill 查询会同时发送给两个索引,但只返回native-skill-index的结果(legacy-vector-index仅用于日志记录和比对)。
第二步:灰度流量(Traffic Shadowing)
通过 Harness 的search-routing-policy配置,将 5% 的查询流量导向legacy-vector-index,其余 95% 走native-skill-index。关键配置:
# search-routing-policy.yaml policies: - name: "gradual-migration" rules: - match: user_group: "dev-team-a" # 先让开发组用新索引 route_to: "native-skill-index" - match: query_contains: "error" # 所有含 error 的查询走老索引(保底) route_to: "legacy-vector-index" - default_route: "native-skill-index"第三步:结果比对与调优(Result Diff & Tuning)
启用index-comparison-report功能,它会自动生成每日报告,对比两套索引的:
- Top-3 结果是否一致
- 平均响应时间差
- “零结果”查询数量(即老索引有结果而新索引无)
我们发现最常见的不一致点是:老索引因 embedding 相似度,召回了语义相近但字段不符的文档(如搜索redis返回了memcached配置);而新索引因严格字段匹配,有时漏掉别名(如redisvscache)。解决方案是在文档中添加synonym字段,或在indexer.yaml中配置同义词映射:
synonyms: - from: ["redis", "cache", "in-memory-db"] to: "redis" - from: ["k8s", "kubernetes", "kube"] to: "kubernetes"第四步:退役旧索引(Sunset Legacy)
当连续 7 天的比对报告显示:
- Top-3 结果一致率 ≥ 98%
- “零结果”查询数 ≤ 0.5%
- P95 延迟差 ≤ 10ms
即可安全删除legacy-vector-index的配置,并下线 Qdrant 实例。
踩过的坑:不要在迁移期间关闭老索引的写入!我们有个客户为了“节省资源”,在灰度期停掉了 Qdrant 的数据同步,结果当新索引因配置错误返回空结果时,用户得不到任何 fallback 结果,导致 3 个关键运维流程中断。正确做法是:老索引只读,新索引读写,确保任何时候都有可用结果。
3.3 权限与安全模型的重构:为什么原生索引更易合规
向量数据库引入的另一个隐形成本是安全治理。Qdrant 或 Chroma 通常需要独立的网络策略、RBAC 规则、审计日志,而这些往往游离于 Harness 的统一权限体系之外。一个典型问题是:某位工程师有 Harness 的View权限,能看到某个 Terraform 模块的文档,但他是否也应该能访问承载该模块 embedding 的 Qdrant collection?如果 collection 里混存了其他敏感文档(如凭据模板),权限就失控了。
Harness 原生 indexer 完全继承 Harness 的 IAM 模型:
- 索引源(Git Repo)的访问权限,由 Harness 的
Connector权限控制 - 索引内容的可见性,由 Skill 的
Scope(Project/ Org Level)决定 - 搜索结果的过滤,由
Field-Level Security(FLS)实现
例如,你可以配置:
# 在 skill.yaml 中 security: field_level: - field: "text_content" condition: "user.hasRole('admin')" - field: "sensitive_tags" condition: "false" # 对所有用户隐藏此字段这意味着,即使某份 Terraform 文档里写了password = "xxx",只要text_content字段被 FLS 规则限制,Skill 返回的结果里就不会包含这行代码——它在索引阶段就被剥离,而非在查询后过滤。这种“索引即安全”的设计,比在向量库之上加一层代理网关,要干净得多。
我们帮某银行客户做等保三级整改时,安全团队明确要求:“所有基础设施文档的检索,必须满足字段级脱敏,且审计日志需与 Harness 主审计流合并”。向量库方案需要额外开发审计桥接器,而原生 indexer 开箱即用,审计日志直接出现在 Harness 的Audit Trail页面,字段变更、查询行为、权限拒绝事件全部可追溯。
4. 实操过程与核心环节实现:手把手完成一次完整迁移
4.1 环境准备与版本确认
迁移前,请务必确认你的 Harness 版本 ≥ v2.3.0。低于此版本的 indexer 功能不完整(缺少 hybrid search 和 synonym 映射)。检查命令:
# 登录 Harness 控制平面 curl -H "Authorization: Bearer $API_TOKEN" \ "https://app.harness.io/gateway/api/v1/version" # 返回应类似:{"version":"2.3.1","buildNumber":"12345"}如果你使用的是自托管版(Harness Self-Managed),还需确认harness-platformPod 的镜像标签:
kubectl get pods -n harness -l app=harness-platform -o jsonpath='{.items[0].spec.containers[0].image}' # 输出应为:harnessio/platform:v2.3.1提示:不要试图用
harnessio/platform:v2.2.0强行启用 indexer v2.3 功能。我们见过客户修改 deployment yaml 强行升级,结果因底层 RocksDB 格式不兼容,导致索引重建失败,数据丢失。稳妥做法是:按官方升级指南,先升级到 v2.2.5,再升级到 v2.3.0。
4.2 创建并配置 Skill Indexer
登录 Harness UI,进入Account Settings > Account Resources > Skill Indexers。
点击+ Create Indexer,选择Git Repository类型。
填写基础信息:
- Indexer Name:
infra-docs-native - Description:
Primary index for Terraform, Helm, and Runbook docs - Source Connector: 选择已配置好的 GitHub/GitLab Connector(确保该 Connector 有
read权限)
在Advanced Configuration区域,粘贴以下indexer.yaml(已针对 Terraform 优化):
version: "2.0" sources: - type: git url: "https://github.com/your-org/infra" branch: "main" include_patterns: - "**/*.tf" - "**/*.tfvars" - "**/README.md" - "**/docs/**/*.md" exclude_patterns: - "**/test/**" - "**/examples/**" - "**/vendor/**" parser_config: terraform: extract_variables: true extract_outputs: true max_file_size_mb: 2 markdown: extract_code_blocks: true extract_headers: true indexing: refresh_interval_seconds: 300 batch_size: 50 workers: 4 search: default_fields: ["title", "text_content", "tags"] field_weights: title: 5.0 tags: 3.0 text_content: 1.0 hybrid_threshold: 0.3 synonyms: - from: ["redis", "cache", "in-memory-db", "key-value-store"] to: "redis" - from: ["k8s", "kubernetes", "kube", "container-orchestration"] to: "kubernetes" - from: ["ci", "continuous-integration", "build-pipeline"] to: "ci"点击Save and Index Now。Harness 会立即启动索引任务。首次构建时间取决于仓库大小,一个 5 万行的 Terraform 仓库通常需 2-5 分钟。
4.3 构建第一个 Hybrid Search Skill
创建 Skill 的目的,是让用户能通过自然语言提问,获得结构化结果。我们以“查找所有 prod 环境的 S3 bucket 配置”为例。
在 Harness UI,进入Projects > Your Project > Skills > + Create Skill。
- Skill Name:
Find S3 Buckets - Description:
Search for AWS S3 bucket resources in production - Type:
Search Skill
在Search Configuration区域:
- Indexer: 选择刚创建的
infra-docs-native - Query Template:
(这是 BM25 查询的 DSL,非 SQL)resource_type: aws_s3_bucket AND tags: prod
在Response Template区域,定义返回格式(Mustache 模板):
{{#results}} - **Bucket Name**: `{{attributes.bucket}}` - **ACL**: `{{attributes.acl}}` - **Region**: `{{attributes.region}}` - **Source**: [{{source}}/{{path}}]({{source}}/{{path}}) {{/results}} {{^results}} No S3 buckets found in prod environment. Check your Terraform modules or try a broader search. {{/results}}保存 Skill。现在,你可以在 Harness Chat 或 Skill Catalog 中测试:
查找所有 prod 环境的 S3 bucket 配置
结果将精准列出所有匹配的aws_s3_bucket资源,且每个结果都带源码链接。
4.4 性能压测与调优实录
我们用harness-load-tester工具(Harness 官方开源)对新旧索引做了对比压测。测试环境:AWS c5.2xlarge(8vCPU/16GB RAM),索引数据集:12 个 Terraform 模块仓库(总计 32 万行代码,1.2 万份文档)。
压测脚本关键参数:
# load-test-config.yaml concurrent_users: 100 duration_minutes: 10 queries: - "resource_type: aws_s3_bucket AND tags: prod" - "error: 'timeout' AND status: failed" - "variable: region AND default: us-east-1" - "synonym: redis"结果摘要:
| 指标 | 原生 Skill Indexer | Qdrant + OpenAI Embedding |
|---|---|---|
| P95 延迟 | 72ms | 341ms |
| 吞吐量(QPS) | 1,842 | 297 |
| CPU 平均使用率 | 38% | 82%(Qdrant 45% + Embedding Service 37%) |
| 内存峰值 | 412MB | 3.1GB |
| 查询错误率 | 0.02%(网络超时) | 1.8%(embedding service timeout + Qdrant connection refused) |
最关键的发现是:Qdrant 的吞吐量瓶颈不在自身,而在 embedding service。当并发超过 300 QPS 时,OpenAI 的/embeddings接口开始返回429 Too Many Requests,导致整个链路雪崩。而 Skill Indexer 的瓶颈是磁盘 I/O,在 SSD 上轻松支撑 2000+ QPS。
调优建议:
- 对 Skill Indexer:若 P95 延迟 > 100ms,优先增加
workers参数(最大不超过 CPU 核数),其次检查refresh_interval_seconds是否过短(频繁扫描 Git 变更会增加 I/O)。 - 对 Qdrant(如必须保留):务必启用
hnsw索引并调大ef_construction(默认 100,建议 200-400),但这会显著增加内存占用。我们实测,ef_construction: 400使内存占用从 1.8GB 升至 3.5GB。
5. 常见问题与排查技巧实录:那些文档里不会写的坑
5.1 “Indexer 一直显示 ‘Pending’,日志里全是 ‘connection refused’”
这是最常遇到的问题,根源几乎都是Git Connector 权限配置错误。
排查步骤:
- 进入Account Settings > Connectors > Your-Git-Connector,点击Test Connection。如果失败,说明凭证无效。
- 如果测试成功,检查 Connector 的Scope。它必须设置为Account Level,而非 Project Level。因为 Indexer 是 Account 级资源,无法访问 Project Scoped Connector。
- 查看 Harness Platform Pod 日志:
这表明集群 DNS 解析失败,需检查 CoreDNS 配置或添加kubectl logs -n harness -l app=harness-platform --tail=100 | grep "indexer" # 寻找类似 "Failed to clone repo: fatal: unable to access 'https://github.com/...': Could not resolve host: github.com"hostNetwork: true到 harness-platform deployment。
独家技巧:在 Connector 测试页面,勾选"Use SSH Key"而非 Personal Access Token。SSH Key 不受 GitHub token 速率限制(5000/hour),且无需担心 token 泄露风险。我们所有生产环境都强制使用 SSH。
5.2 “搜索结果为空,但文档明明存在”
这通常不是索引失败,而是查询 DSL 写错或字段未提取。
诊断方法:
- 进入Skill Indexer Detail Page > Index Stats,查看
Indexed Documents数量。如果为 0,说明索引未启动。 - 如果数量正常(如 12,345),点击"Browse Index",随机选一个文档 ID,查看其 JSON 内容。重点检查:
resource_type字段是否存在?(Terraform 文档必须有resource块才能被识别)tags字段是否为空?(tags由文件路径中的目录名自动提取,如modules/s3/prod/main.tf→tags: ["s3", "prod"])
- 在Skill Editor > Search Configuration中,将 Query Template 改为
*(匹配所有),看是否返回结果。如果返回,说明你的 DSL 逻辑有误。
常见 DSL 错误:
- ❌
resource_type = "aws_s3_bucket"(错误:Skill Indexer 用:而非=) - ✅
resource_type: aws_s3_bucket - ❌
tags: prod AND tags: s3(错误:AND在 DSL 中不生效) - ✅
tags: prod AND tags: s3→ 正确写法是tags: prod AND tags: s3,但更推荐tags: (prod AND s3)或直接tags: prod,s3
5.3 “Synonym 不生效,搜索 ‘k8s’ 还是找不到 ‘kubernetes’ 文档”
Synonym 映射只在hybrid search fallback 阶段生效,即当 BM25 主查询无结果时。如果主查询已命中,synonym 不会触发。
验证方法:
- 先用一个肯定无结果的查询测试,如
resource_type: k8s_cluster(因为实际字段是kubernetes_cluster) - 如果返回空,再看日志中是否有
hybrid search triggered字样 - 若无,检查
hybrid_threshold是否设得过高(如 0.8),导致 fallback 从未触发
终极调试命令(需 CLI):
# 获取 indexer 的 raw query log harness-cli indexer query-log --indexer-id <ID> --limit 10 # 输出类似: # [2024-05-20T10:23:41Z] QUERY: resource_type: k8s_cluster -> BM25 SCORE: 0.0 -> HYBRID TRIGGERED -> SYNONYM EXPANDED TO: kubernetes_cluster5.4 “迁移后,部分 Skill 的响应变慢了”
这往往是因为Skill 的 Response Template 过于复杂。Mustache 模板里的{{#results}}循环,如果结果集很大(>50 条),渲染会成为瓶颈。
优化方案:
- 在 Query Template 中添加分页:
resource_type: aws_s3_bucket AND tags: prod | limit: 10 - 使用
{{#results.0}}取首条,而非遍历全部 - 将复杂格式化逻辑移出模板,改用 Skill 的
Post-Processing Script(JavaScript):
// Post-Processing Script if (results.length > 0) { return results.slice(0, 5).map(r => `- **${r.attributes.bucket}**: ${r.attributes.acl} (${r.source}/${r.path})` ).join('\n'); } else { return "No results."; }实测数据:一个返回 200 条结果的 Skill,纯 Mustache 渲染耗时 1200ms;用 JS 脚本截取前 5 条后,耗时降至 45ms。记住:Skill 的本质是“快速提供线索”,不是“生成完整报告”。
6. 后续演进与延伸思考:当向量数据库不再是主角
Harness 少用向量数据库,绝不意味着语义能力的退化,而是将其下沉为一种可插拔的、按需启用的能力。在 v2.4 的路线图中,我们看到几个关键方向:
方向一:向量作为“增强层”,而非“主检索层”
未来的 Skill Indexer 将支持vector-enhanced模式:主查询仍走 BM25,但对 Top-10 结果,异步调用轻量级 embedding 模型(如all-MiniLM-L6-v2,仅 80MB),计算 query 与每个结果的相似度,重新排序。这避免了全量向量索引的开销,又保留了语义精排能力。我们已用 ONNX Runtime 在边缘节点部署了该模型,单次推理 < 15ms。
方向二:跨 Skill 的联合检索(Cross-Skill Search)
当前 indexer 是 per-Skill 的。v2.4 将引入Global Index Registry,允许一个 Skill 查询多个 indexer(如同时查 Terraform 文档 + Jira 工单 + Confluence 知识库),并用统一的 relevance score 排序。这解决了“运维问题常横跨多个系统”的痛点,而无需把所有数据灌进一个巨型向量库。
**方向三:用户行为驱动