关键词搜不到?那就让 AI 懂意思:用本地向量检索笔记

举报
茉莉风铃 发表于 2026/09/23 11:03:32 2026/09/23
【摘要】 技术笔记攒多了,用关键词搜经常找不到"意思相近但措辞不同"的内容。这篇用 Ollama 本地 embedding 模型把笔记转成向量,再用余弦相似度做语义搜索,全程离线、不依赖云端。

技术笔记写多了会遇一个尴尬:想找"Docker 容器怎么清缓存",但当初记的是"清理 Docker 悬空镜像",关键词对不上就搜不到。传统搜索是"字面匹配",而语义搜索是"意思匹配"——把文字变成向量,意思近的向量也近。这篇用 Ollama 在本地跑 embedding 模型,给自己的笔记做一个离线语义搜索。

image.png

一、原理一句话

embedding 模型把一段文字映射成一个高维向量(比如 768 维)。两句话意思越近,它们的向量夹角越小(余弦相似度越接近 1)。搜索时把查询句也 embed,然后跟所有笔记向量比一遍余弦,返回最像的那几条。

二、用 Ollama 跑 embedding

Ollama 不只出文本,也提供 embedding 接口。先拉一个嵌入模型:

ollama pull nomic-embed-text

调用方式(HTTP):

curl http://localhost:11434/api/embeddings \
  -d '{"model":"nomic-embed-text","prompt":"清理 Docker 悬空镜像"}'

返回 embedding 字段,是个浮点数组。

三、Python 实现检索

import requests, numpy as np, glob, os, json, re

EMB_API = "http://localhost:11434/api/embeddings"
MODEL = "nomic-embed-text"

def embed(text: str) -> list:
    r = requests.post(EMB_API, json={"model": MODEL, "prompt": text}, timeout=60)
    return r.json()["embedding"]

def cosine(a, b) -> float:
    a, b = np.array(a), np.array(b)
    return float(np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b)))

# 1) 离线建库:把每篇笔记 embed 存好
index = []
for path in glob.glob("notes/*.md"):
    text = open(path, encoding="utf-8").read()[:2000]
    index.append({"path": path, "vec": embed(text)})
json.dump(index, open("index.json", "w"))

# 2) 在线查询
q = embed("Docker 容器怎么清缓存")
scores = [(d["path"], cosine(q, d["vec"])) for d in index]
scores.sort(key=lambda x: -x[1])
for path, s in scores[:3]:
    print(f"{s:.3f}  {path}")

第一次跑把笔记向量存成 index.json,之后查询只 embed 那一句、做一遍余弦,几百篇笔记也是毫秒级。

四、为什么用本地

  • 离线可用:不联网也能搜,适合含敏感内容的笔记。
  • 零成本:模型一次装好,后续不花钱。
  • 可控:向量库就在本地文件,想清空重来随时的事。

代价是本地 7B 级别嵌入模型精度不如云端大模型,但对"个人笔记检索"这个量级完全够用。

五、踩过的坑

  • 向量维度不一致:换 embedding 模型后维度可能不同(768 vs 1024),旧 index.json 必须重建,否则余弦算出 NaN。模型一换就重跑建库。
  • 长文截断:喂整篇 5000 字,embedding 模型和相似度都失真。截断到前 1500~2000 字,反而更聚焦主题。
  • 余弦前不归一化:直接用点积会被向量长度带偏,务必除以各自模长做归一化(上面 cosine 已做)。
  • 索引没落盘:每次查询都重新 embed 所有笔记,慢且费算力。建一次库存文件,查询只 embed 查询句。
步骤 动作 注意
建库 笔记 → embed → 存 json 模型换了要重建
查询 查询句 → embed → 余弦 只 embed 一句
排序 按相似度降序取 TopK 归一化后再算

小结

语义搜索没那么玄:把文字交给 embedding 模型变成向量,用余弦相似度比"谁跟查询句意思更近",关键词对不上的内容也能捞出来。用 Ollama 在本地跑,离线、免费、隐私不外流,几百篇笔记检索毫无压力。真正的工程要点就两个——模型换了重建索引、查询时只 embed 那一句话。想再进阶,可以加个前端页面或接进笔记软件,不过核心逻辑到这就齐了。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。