我如何使用 CocoIndex 构建语义搜索引擎
Source: Dev.to
介绍
在本教程中,我将向你展示如何使用 CocoIndex——一个用于创建强大搜索体验的开源 Python 库——构建语义搜索引擎。如果你曾想构建一个能够理解上下文和含义(而不仅仅是精确关键词匹配)的搜索功能,那么本文适合你!
什么是 CocoIndex?
CocoIndex 是一个轻量级的语义搜索库,能够轻松地对文档进行向量嵌入并进行搜索。与传统的基于关键词的搜索不同,语义搜索能够理解查询背后的意义,使用户即使使用不同的词语也能找到相关结果。
为什么选择 CocoIndex
我需要一个满足以下条件的搜索解决方案:
- 易于集成 – 无需复杂的设置或基础设施
- 高速 – 快速的索引和搜索性能
- 语义化 – 理解上下文,而不仅仅是关键词
- 开源 – 免费使用且可自行修改
CocoIndex 完全满足了这些要求!
入门
首先,安装 CocoIndex:
pip install cocoindex
构建搜索引擎
1. 初始化 CocoIndex
from cocoindex import CocoIndex
2. 添加文档
@cocoindex.flow_def(name="TextEmbedding")
def text_embedding_flow(flow_builder: cocoindex.FlowBuilder, data_scope: cocoindex.DataScope):
"""
Define an example flow that embeds text into a vector database.
"""
data_scope["documents"] = flow_builder.add_source(
cocoindex.sources.LocalFile(path="markdown_files")
)
doc_embeddings = data_scope.add_collector()
索引文档
处理每个文档
with data_scope["documents"].row() as doc:
doc["chunks"] = doc["content"].transform(
cocoindex.functions.SplitRecursively(),
language="markdown",
chunk_size=2000,
chunk_overlap=500,
)
嵌入
with doc["chunks"].row() as chunk:
chunk["embedding"] = chunk["text"].transform(
cocoindex.functions.SentenceTransformerEmbed(
model="sentence-transformers/all-MiniLM-L6-v2"
)
)
doc_embeddings.collect(
filename=doc["filename"],
location=chunk["location"],
text=chunk["text"],
embedding=chunk["embedding"],
)
导出
doc_embeddings.export(
"doc_embeddings",
cocoindex.storages.Postgres(),
primary_key_fields=["filename", "location"],
vector_indexes=[
cocoindex.VectorIndexDef(
field_name="embedding",
metric=cocoindex.VectorSimilarityMetric.COSINE_SIMILARITY,
)
],
)
3. 执行语义搜索
def search(pool: ConnectionPool, query: str, top_k: int = 5):
table_name = cocoindex.utils.get_target_storage_default_name(
text_embedding_flow, "doc_embeddings"
)
query_vector = text_to_embedding.eval(query)
with pool.connection() as conn:
with conn.cursor() as cur:
cur.execute(
f"""
SELECT filename, text, embedding %s::vector AS distance
FROM {table_name}
ORDER BY distance
LIMIT %s
""",
(query_vector, top_k),
)
return [
{"filename": row[0], "text": row[1], "score": 1.0 - row[2]}
for row in cur.fetchall()
]
我实现的关键特性
快速索引
CocoIndex 使用高效的向量存储,使得对成千上万的文档进行索引既快速又轻松。
语义理解
搜索能够理解“teaching computers”与“machine learning”之间的关联,即使没有完全匹配的关键词。
可定制的嵌入模型
你可以根据具体需求和精度要求选择不同的嵌入模型。
实际案例
我为自己的项目构建了一个包含 500 多个 markdown 文件的文档搜索。使用 CocoIndex:
- 索引耗时不到 30 秒
- 搜索响应时间平均 50 ms
- 用户即使使用模糊查询也能找到相关文档
性能优化技巧
- 批量索引 – 一次添加多个文档以提升性能
- 选择合适的嵌入模型 – 在精度和速度之间取得平衡
- 缓存常用结果 – 将常见查询的结果存储起来,实现即时响应
我遇到的挑战
挑战 1:选择嵌入维度
维度越高精度越好,但性能会下降。我最终选择了 384 维作为折中方案。
挑战 2:处理大规模文档集合
对于超过 1 万篇文档的集合,我实现了分页和惰性加载。
结果
使用 CocoIndex 后:
- 用户满意度显著提升
- 实现时间仅 2 天,而其他方案需要数周
结论
CocoIndex 让构建语义搜索引擎变得异常简单。无论你是在构建文档站点、博客搜索还是产品目录,它都是一个轻量却功能强大的工具。该库维护活跃、文档完善,社区也很热心。强烈推荐在你的下一个搜索实现中尝试它!
资源
- GitHub: CocoIndex Repository
- 文档: Official Docs
- 演示项目: Simple Vector Index Demo