全文检索
什么是全文检索
向量检索能够捕捉文本间的语义关系,即使检索关键词不完全匹配,也能返回相关结果,对模糊表达或描述性问题具有较强的容错能力。同时向量检索可以在多模态数据(如文本、图像、音频)中使用,适配更复杂的检索需求,这些特性使向量检索在RAG、推荐系统和智能搜索中表现优异。
然而向量检索依赖于模型的语义理解能力,但在某些情况下,模型可能无法正确捕捉到某些特定领域的细微差别,也无法实现精确匹配,比如检索一个特定ID、一个人名字等场景,向量检索表现往往不佳。同时向量都是浮点数字,其透明性及可解释性对人类有天然的障碍,检索效果不佳时,开发人员往往难以调优。而这洽洽是传统全文检索技术的优势。
全文检索通常基于倒排索引(Inverted Index),能够实现对关键词的精确匹配。当用户查询包含特定的词或短语时,全文检索可以迅速定位并返回包含这些词的文档,确保结果的准确性和相关性,这在法律文件、医学文献等需要精确匹配的场景中尤为重要。
全文检索的优势
百度VectorDB从2.0内核版本开始,也引入了对全文检索的支持,其具备以下几个关键特性:
- 全新自研的倒排索引结构,基于高性能KV引擎而构建
- 业界少有的全实时方案,文档写入成功后只要符合检索条件就一定可以检索到,而ES类系统只能称为近实时检索系统
- 基于百度搜索自研分词器,分词器基于百度NLP内部自主研发的DeepCRF模型,该模型凝聚了百度在中文搜索领域十几年的技术积累,其模型性能与准确率均处于业界领先地位
全文检索使用示例
接下来,通过一个例子展示如何使用百度VectorDB的全文检索功能。
1、创建带倒排索引的表
import time
import json
import random
import pymochow
import logging
from pymochow.configuration import Configuration
from pymochow.auth.bce_credentials import BceCredentials
from pymochow.exception import ClientError, ServerError
from pymochow.model.schema import (
Schema,
Field,
SecondaryIndex,
FilteringIndex,
VectorIndex,
InvertedIndex,
InvertedIndexParams
)
from pymochow.model.enum import (
FieldType, ElementType, IndexType, InvertedIndexAnalyzer, InvertedIndexParseMode, MetricType, ServerErrCode,
InvertedIndexFieldAttribute
)
from pymochow.model.enum import TableState, IndexState
from pymochow.model.table import (
Partition,
Row,
FloatVector,
BM25SearchRequest,
HybridSearchRequest
)
logging.basicConfig(filename='demo.log', level=logging.DEBUG,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
if __name__ == "__main__":
account = 'root'
api_key = 'xxxxxxxx'
endpoint = 'http://xx.xx.xx.xx:5287' #endpoint from VectorDB console
config = Configuration(credentials=BceCredentials(account, api_key),
endpoint=endpoint)
client = pymochow.MochowClient(config)
"""create database"""
database = 'test_db'
table_name = 'test_table_with_bm25_search'
db = client.create_database(database)
"""create table"""
fields = []
fields.append(Field("docID", FieldType.STRING, primary_key=True,
partition_key=True, auto_increment=False, not_null=True))
fields.append(Field("chunkID", FieldType.STRING, primary_key=True, not_null=True))
fields.append(Field("title", FieldType.TEXT, not_null=True))
fields.append(Field("content", FieldType.TEXT, not_null=True))
fields.append(Field("size", FieldType.UINT64, not_null=True))
fields.append(Field("meta", FieldType.STRING, not_null=True))
indexes = []
indexes.append(InvertedIndex(index_name="title_content_inverted_index",
fields=["title", "content"],
field_attributes=[InvertedIndexFieldAttribute.NOT_ANALYZED, InvertedIndexFieldAttribute.ANALYZED],
params=InvertedIndexParams(analyzer=InvertedIndexAnalyzer.CHINESE_ANALYZER,
parse_mode=InvertedIndexParseMode.COARSE_MODE)))
db.create_table(
table_name=table_name,
replication=3,
partition=Partition(partition_num=3),
schema=Schema(fields=fields, indexes=indexes)
)
while True:
time.sleep(2)
table = db.describe_table(table_name)
if table.state == TableState.NORMAL:
break
table = db.table(table_name)
上述代码在test_db中新建了一张test_table_with_bm25_search表,并新建了名为title_content_inverted_index的倒排索引,该索引将为表每行数据的title、content列构建倒排索引结构,其中title列内容不分词(类似于ES的keyword),而content列内容需要分词。
2、灌入数据
"""insert some rows into table"""
rows = [
Row(docID='doc_589412-897452-536331',
chunkID='chunk_0000',
title='科比.布莱恩特',
content='科比·布莱恩特(Kobe Bryant),绰号“黑曼巴”,是NBA历史上最伟大的球员之一。他于1978年出生于美国宾夕法尼亚州,1996年直接从高中进入NBA,
加入洛杉矶湖人队,开启了传奇的20年职业生涯',
size=100,
meta='{"createAt" : "2024-12-25"}'),
Row(docID='doc_589412-897452-536331',
chunkID='chunk_0001',
title='科比.布莱恩特',
content='科比以极强的得分能力和坚韧的意志著称,职业生涯五次夺得NBA总冠军,两次荣膺总决赛MVP,并18次入选全明星赛。他职业生涯总得分超过33000分>,位列历史前列',
size=100,
meta='{"createAt" : "2024-12-25"}'),
Row(docID='doc_589412-897452-536331',
chunkID='chunk_0002',
title='科比.布莱恩特',
content='科比的“曼巴精神”象征着永不放弃和持续精进,不仅影响着篮球界,也激励着全球无数人。2016年退役后,他在商业和文化领域继续创造价值',
size=80,
meta='{"createAt" : "2024-12-25"}'),
Row(docID='doc_589412-897452-536331',
chunkID='chunk_0003',
title='科比.布莱恩特',
content='2020年,科比在直升机事故中不幸去世,震惊世界。他的精神与影响力仍在延续,激励着新一代球员和球迷',
size=70,
meta='{"createAt" : "2024-12-25"}'),
Row(docID='doc_589412-897452-536332',
chunkID='chunk_0000',
title='洛杉矶.湖人队',
content='洛杉矶湖人队(Los Angeles Lakers)是NBA最具传奇色彩的球队之一,成立于1947年,总部位于加利福尼亚州洛杉矶。湖人队历史悠久,共赢得17次NBA总冠军,与波士顿凯尔特人并列联盟第一',
size=120,
meta='{"createAt" : "2024-12-26"}'),
Row(docID='doc_589412-897452-536332',
chunkID='chunk_0001',
title='洛杉矶.湖人队',
content='湖人队以明星球员云集著称,埃尔文·约翰逊(魔术师)、卡里姆·阿卜杜尔-贾巴尔、科比·布莱恩特和勒布朗·詹姆斯等都是队史代表人物。湖人队的“Showtime”时代凭借快速攻防和华丽球风席卷联盟,而科比时代的五冠成就进一步巩固了球队的地位',
size=200,
meta='{"createAt" : "2024-12-26"}'),
Row(docID='doc_589412-897452-536332',
chunkID='chunk_0002',
title='洛杉矶.湖人队',
content='作为NBA最受欢迎的球队之一,湖人队不仅在竞技层面表现出色,也在全球拥有庞大的粉丝群体。湖人队象征着辉煌和荣耀,持续书写着属于自己的篮>球传奇。',
size=160,
meta='{"createAt" : "2024-12-26"}')
]
table.upsert(rows=rows)
3、执行全文检索
3.1 不带Filter条件的全文检索
request = BM25SearchRequest(index_name="title_content_inverted_index",
search_text="title:科比.布莱恩特",
limit=10)
res = table.bm25_search(request=request)
logger.debug("BM25 search res: {}".format(res))
这里例子在表中检索title为'科比.布莱恩特'的数据,并返回匹配Row的全部标量列,检索结果如下:
{metadata:{content__length:u'1581',content__type:u'application/json',request_id:u'796dc5d6-e206-40b1-b53a-6aef03d07545'},
rows:[
{'row': {'docID': 'doc_589412-897452-536331', 'chunkID': 'chunk_0003', 'title': '科比.布莱恩特', 'content': '2020年,科比在直升机事故中不幸去世,震惊世界。他的精神与影响力仍在延续,激励着新一代球员和球迷', 'size': 70, 'meta': '{"createAt" : "2024-12-25"}'}, 'score': 0.7985076904296875},
{'row': {'docID': 'doc_589412-897452-536331', 'chunkID': 'chunk_0001', 'title': '科比.布莱恩特', 'content': '科比以极强的得分能力和坚韧的意志著称,职业生涯五次夺得NBA总冠军,两次荣膺总决赛MVP,并18次入选全明星赛。他职业生涯总得分超过33000分,位列历史前列', 'size': 100, 'meta': '{"createAt" : "2024-12-25"}'}, 'score': 0.7985076904296875},
{'row': {'docID': 'doc_589412-897452-536331', 'chunkID': 'chunk_0002', 'title': '科比.布莱恩特', 'content': '科比的“曼巴精神”象征着永不放弃和持续精进,不仅影响着篮球界,也激励着全球无数人。2016年退役后,他在商业和文化领域继续创造价值', 'size': 80, 'meta': '{"createAt" : "2024-12-25"}'}, 'score': 0.7985076904296875},
{'row': {'docID': 'doc_589412-897452-536331', 'chunkID': 'chunk_0000', 'title': '科比.布莱恩特', 'content': '科比·布莱恩特(Kobe Bryant),绰号“黑曼巴”,是NBA历史上最伟大的球员之一。他于1978年出生于美国宾夕法尼亚州,1996年直接从高中进入NBA,加入洛杉矶湖人队,开启了传奇的20年职业生涯', 'size': 100, 'meta': '{"createAt" : "2024-12-25"}'}, 'score': 0.7985076904296875}
],
code:0, msg:u'Success'}
3.2 带Filter的全文检索
request = BM25SearchRequest(index_name="title_content_inverted_index",
search_text="title:科比.布莱恩特 AND content:总冠军",
filter="size >= 80",
limit=10)
res = table.bm25_search(request=request)
logger.debug("BM25 search res: {}".format(res))
这个例子在表中检索title列为'科比.布莱恩特'且content列包含'总冠军'的数据,同时要求匹配Row的size列 >= 80,以下为例子检索结果输出:
{metadata: {content__length:u'436',content__type:u'application/json',request_id:u'fc4f94e1-0471-4724-b5e0-7113fd93ee90'},
rows:[
{'row': {'docID': 'doc_589412-897452-536331', 'chunkID': 'chunk_0001', 'title': '科比.布莱恩特', 'content': '科比以极强的得分能力和坚韧的意志著称,职业生涯五次夺得NBA总冠军,两次荣膺总决赛MVP,并18次入选全明星赛。他职业生涯总得分超过33000分,位列历史前列', 'size': 100, 'meta': '{"createAt" : "2024-12-25"}'}, 'score': 1.6523597240447998}
],
code:0,msg:u'Success'}
更多全文检索用法,请参考百度VectorDB全文检索API。