【wow-rag系列】 task03 制作初步的问答引擎(关于金庸小说)

最近拖更了,两个原因,第一个加班干活,第二个才是最主要原因,遇到一点小小问题,就开始纠结其背后是什么玩意,what,why,how都做了一遍,太耗费时间了,收效甚微。也没有从工程角度把这个wow-rag项目去做完。

构建初步的问答引擎,大概有四种方法

四种方法构建问答引擎

方法1:直接从Documents构建向量索引

LlamaIndex 框架中提供了对构造向量存储索引对象的最高层封装,即可以用 Document 对象直接构造向量存储索引对象。使用一个方法 from_documents 就可以快速地用文档构造向量存储索引对象。

# ---------------------
# step 1.设定key、模型url、推理模型名称以及embedding模型名称
# ---------------------
BASE_IP = "http://localhost:11434"
BASE_URL = BASE_IP+"/api/chat"
MODEL_NAME = "deepseek-r1"

# ---------------------
# step 2.使用SimpleDirectoryReader函数完成数据加载和数据分割
# ---------------------
from llama_index.core import SimpleDirectoryReader,Document
# documents = SimpleDirectoryReader(input_files=['./docs/天龙八部.txt']).load_data()
documents = SimpleDirectoryReader(input_files=['./docs/越女剑1.txt']).load_data()
# print(documents)

# ---------------------
# step 3.设置本地embedding模型
# ---------------------
from llama_index.embeddings.ollama import OllamaEmbedding
embedding = OllamaEmbedding(base_url=BASE_IP, model_name=MODEL_NAME)

# ---------------------
# step 4.构造向量存储索引
# ---------------------
from llama_index.core import VectorStoreIndex
index = VectorStoreIndex.from_documents(documents,embed_model=embedding,show_progress= True)
# print(index)

# ---------------------
# step 5.构造本地模型的查询引擎
# ---------------------
from llama_index.llms.ollama import Ollama
llm = Ollama(base_url=BASE_IP, model=MODEL_NAME)
query_engine = index.as_query_engine(llm=llm)

# ---------------------
# step 6.对查询引擎提问
# ---------------------
response = query_engine.query("阿青为什么武功这么厉害?")
print(response)

测试结果:

Parsing nodes: 100%|██████████| 1/1 [00:00<00:00, 48.24it/s]
Generating embeddings: 100%|██████████| 30/30 [00:08<00:00,  3.61it/s]
<think>
嗯,用户问的是阿青为什么武功这么厉害。根据提供的文本,我需要仔细分析上下文来找出原因。

首先,范蠡和阿青的关系很重要。范蠡一开始觉得阿青的剑术是白公公教的,而白公公可能有特殊传授方式。范蠡认为她年轻天真,被用竹棒玩耍,后来才学到真正的剑术。这说明阿青的学习方法不同寻常。

接着,阿青在与白猿的对战中使用了不同的招式,虽然没有提到具体的招数名称,但她表现出极高的灵活性和技巧。她的竹棒挥舞起来非常迅速,给人一种难以招架的感觉,甚至让白猿连退三步,说明她的攻击手段高效且精准。

此外,范蠡观察到阿青在面对越国剑士时,所有对手要么被手腕戳中,要么直接失去平衡摔地,这显示她使用竹棒的攻击方式非常有效,几乎能击溃任何对手。她的战斗风格独特,可能不是传统的长剑或镋钯术,而是有自己独特的技巧。

综合来看,阿青武功厉害的原因包括白公公的教学方法、她自身的特殊武术风格以及她在战斗中的出色表现。这些都是导致她成为 formidable warrior的原因。
</think>

根据提供的上下文,阿青的武功之所以这么厉害,是因为她的竹棒剑法非常独特且高效。范蠡观察到阿青在与白猿对战时,使用了看似普通的竹棒,却使得白猿接连后退,并且她的攻击方式让白猿几乎无法招架。此外,她面对越国的剑士时,所有对手要么被刺中手腕,要么失去平衡而倒地,显示出她在战斗中的极快节奏和精准打击能力。这些都表明阿青拥有独特的武术风格和高超的技术。

也就是说,在使用 from_documents 方法构造向量存储索引对象的过程中,框架已经自动完成了文档分割向量构造向量存储。但是向量索引仅在内存中,程序停止后,向量索引也就被内存回收了,只适合检索少量文档。

方法2:分割节点,构建向量索引,采用faiss作向量存储库

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2025/3/25 5:11
# @Author  : jqfu
# @File    : engine.py
# @Description :
import os

# ---------------------
# step 1.设定key、模型url、推理模型名称以及embedding模型名称
# ---------------------
BASE_IP = "http://localhost:11434"
BASE_URL = BASE_IP+"/api/chat"
MODEL_NAME = "deepseek-r1"

# ---------------------
# step 2.设置本地embedding模型
# ---------------------
from llama_index.embeddings.ollama import OllamaEmbedding
embedding = OllamaEmbedding(base_url=BASE_IP, model_name=MODEL_NAME)

# ---------------------
# step 3.使用SimpleDirectoryReader函数完成Document加载
# ---------------------
from llama_index.core import SimpleDirectoryReader,Document
# documents = SimpleDirectoryReader(input_files=['./docs/天龙八部.txt']).load_data()
documents = SimpleDirectoryReader(input_files=['./docs/越女剑1.txt']).load_data()
print('Document加载完成')

# ---------------------
# step 4.构建节点
# ---------------------
# 加载数据分割器到数据转换器(transformations)
from llama_index.core.node_parser import SentenceSplitter
transformations = [SentenceSplitter(chunk_size = 1024)]
# 运行数据转换器做数据摄取(包含数据加载与数据分割),生成要处理的 Node 对象
from llama_index.core.ingestion.pipeline import run_transformations
nodes = run_transformations(documents, transformations=transformations)
print('数据切割成node环节完成')
# ---------------------
# step 5.根据节点构建索引
# ---------------------
# 构建索引
from llama_index.vector_stores.faiss import FaissVectorStore
import faiss
from llama_index.core import StorageContext, VectorStoreIndex

# 从上一节得知,deepseek的embedding维度是3584
dimensions = 3584
# 构造基于向量存储的向量存储索引
vector_store = FaissVectorStore(faiss_index=faiss.IndexFlatL2(dimensions))
storage_context = StorageContext.from_defaults(vector_store=vector_store)
index = VectorStoreIndex(
    nodes = nodes,
    storage_context=storage_context,
    embed_model = embedding,
)
print('nodes向量化完成')
# ---------------------
# step 6.把向量索引持久化到硬盘,再从硬盘读取出来
# ---------------------
persist_dir = "./storage"
index.storage_context.persist(persist_dir)
print('nodes向量存储到本地硬盘完成')
# load index from disk
from llama_index.vector_stores.faiss import FaissVectorStore
import faiss
from llama_index.core import StorageContext, load_index_from_storage
vector_store = FaissVectorStore.from_persist_dir(persist_dir)
storage_context = StorageContext.from_defaults(
    vector_store=vector_store, persist_dir=persist_dir
)
index = load_index_from_storage(storage_context=storage_context,embed_model = embedding)
print('nodes向量从本地加载完成')
# ---------------------
# step 7.构造本地模型的查询引擎
# ---------------------
from llama_index.llms.ollama import Ollama
llm = Ollama(base_url=BASE_IP, model=MODEL_NAME)
query_engine = index.as_query_engine(llm=llm)

# ---------------------
# step 8.对查询引擎提问
# ---------------------
response = query_engine.query("阿青为什么武功这么厉害?")
print(response)

测试结果:

Document加载完成
数据切割成node环节完成
nodes向量化完成
nodes向量存储到本地硬盘完成
nodes向量从本地加载完成
<think>
嗯,用户问的是阿青为什么武功这么厉害。好的,我得从提供的上下文中找到相关信息。

首先,阿青在范蠡那里学习了白公公的剑术,所以她的武功应该是受到白公公传授的影响。接着,在与吴越剑士的对决中,她表现出了极高的技巧和速度,这说明她学到了某种特殊的招式或秘籍。

另外,文中提到她使用竹棒时动作迅速,招数精奇,甚至比吴越剑士还要快,显示她的训练方法独特。还有她教范蠡的时候,用一根短竹棒就能让对手腕折臂断,这说明她的力量和技巧都很强。

综合来看,阿青武功厉害的原因应该是学习了白公公的剑术,并且有特殊的训练方法,使得她的招式快速、有力。
</think>

根据提供的上下文信息,阿青的武功之所以这么厉害,可能是因为她从白公公那里学会了某种特殊的剑术。此外,在与吴越剑士的对决中,她的竹棒招数非常精奇且速度快,甚至比吴越剑士还快。而且,她教范蠡的时候,用一根短竹棒就能让对手腕折臂断,显示出她的力量和技巧都很强。

这些信息说明阿青很可能有某种独特的训练方法或者掌握了某种特殊的剑术招式,使得她的武功异常高超。

方法3:构建索引器、合成器再组装问答引擎


# ---------------------
# step 1.设定key、模型url、推理模型名称以及embedding模型名称
# ---------------------
BASE_IP = "http://localhost:11434"
BASE_URL = BASE_IP+"/api/chat"
MODEL_NAME = "deepseek-r1"

# ---------------------
# step 2.设置本地embedding模型与本地大模型
# ---------------------
from llama_index.embeddings.ollama import OllamaEmbedding
embedding = OllamaEmbedding(base_url=BASE_IP, model_name=MODEL_NAME)
from llama_index.llms.ollama import Ollama
llm = Ollama(base_url=BASE_IP, model=MODEL_NAME)

# ---------------------
# step 3.使用SimpleDirectoryReader函数完成Document加载
# ---------------------
from llama_index.core import SimpleDirectoryReader,Document
# documents = SimpleDirectoryReader(input_files=['./docs/天龙八部.txt']).load_data()
documents = SimpleDirectoryReader(input_files=['./docs/越女剑1.txt']).load_data()
print('Document加载完成')

# ---------------------
# step 4.构建节点
# ---------------------
# 加载数据分割器到数据转换器(transformations)
from llama_index.core.node_parser import SentenceSplitter
transformations = [SentenceSplitter(chunk_size = 1024)]
# 运行数据转换器做数据摄取(包含数据加载与数据分割),生成要处理的 Node 对象
from llama_index.core.ingestion.pipeline import run_transformations
nodes = run_transformations(documents, transformations=transformations)
print('数据切割成node环节完成')
# ---------------------
# step 5.根据节点构建索引
# ---------------------
# 构建索引
from llama_index.vector_stores.faiss import FaissVectorStore
import faiss
from llama_index.core import StorageContext, VectorStoreIndex

# 从上一节得知,deepseek的embedding维度是3584
dimensions = 3584
# 构造基于向量存储的向量存储索引
vector_store = FaissVectorStore(faiss_index=faiss.IndexFlatL2(dimensions))
storage_context = StorageContext.from_defaults(vector_store=vector_store)
index = VectorStoreIndex(
    nodes = nodes,
    storage_context=storage_context,
    embed_model = embedding,
)
print('nodes向量化完成')
# ---------------------
# step 6.构建索引器与合成器,再组装问答引擎
# ---------------------
# 构建检索器
from llama_index.core.retrievers import VectorIndexRetriever
# 想要自定义参数,可以构造参数字典
kwargs = {'similarity_top_k': 5, 'index': index, 'dimensions': dimensions} # 必要参数
retriever = VectorIndexRetriever(**kwargs)
print('构建检索器完成')
# 构建合成器
from llama_index.core.response_synthesizers  import get_response_synthesizer
response_synthesizer = get_response_synthesizer(llm=llm)
print('构建合成器完成')
# 构建问答引擎
from llama_index.core.query_engine import RetrieverQueryEngine
engine = RetrieverQueryEngine(
      retriever=retriever,
      response_synthesizer=response_synthesizer
        )
print('构建问答引擎完成')
# 提问
question = "阿青为什么武功这么厉害??"
answer = engine.query(question)
print(answer.response)

测试结果:

Document加载完成
数据切割成node环节完成
nodes向量化完成
构建检索器完成
构建合成器完成
构建问答引擎完成
<think>
阿青的武功之所以这么厉害,可以从以下几个方面来分析:

1. **精准快速的攻击**:文中提到阿青使用竹棒时动作迅捷,如“电光急闪”逼退白猿,显示出她的攻击速度快且精准。

2. **优雅高效的招式**:阿青的招式轻柔却有效,如“拍两声轻响”将白猿的竹棒击落,这种以柔克刚的方式令人难以招架。

3. **冷静的战术策略**:阿青在战斗中表现出冷静和机智,能够根据不同情况灵活应对,如连续三天击败三组剑士,显示了她的战略思维。

4. **强大的体力和耐力**:她能连续作战多日而不倒 collapsed,说明其体能出色且有持久力。

5. **深厚的内功和修养**:阿青对战斗的掌控力源于其深厚的知识和修养,这种素养使她在战斗中游刃有余。

综上所述,阿青武功厉害的原因在于她的精准、快速、优雅、高效的攻击方式,以及冷静的战术策略和强大的体能。这些因素共同作用下,使得她成为 formidable的对手。
</think>

阿青的武功之所以这么厉害,可以从以下几个方面来分析:

1. **精准快速的攻击**:文中提到阿青使用竹棒时动作迅捷,如“电光急闪”逼退白猿,显示出她的攻击速度快且精准。

2. **优雅高效的招式**:阿青的招式轻柔却有效,如“拍两声轻响”将白猿的竹棒击落,这种以柔克刚的方式令人难以招架。

3. **冷静的战术策略**:阿青在战斗中表现出冷静和机智,能够根据不同情况灵活应对,如连续三天击败三组剑士,显示了她的战略思维。

4. **强大的体力和耐力**:她能连续作战多日而不倒 collapsed,说明其体能出色且有持久力。

5. **深厚的内功和修养**:阿青对战斗的掌控力源于其深厚的知识和修养,这种素养使她在战斗中游刃有余。

综上所述,阿青武功厉害的原因在于她的精准、快速、优雅、高效的攻击方式,以及冷静的战术策略和强大的体能。这些因素共同作用下,使得她成为 formidable的对手。

方法4:使用Qdrant数据库

先提一下两种向量数据库的区别

向量数据库QdrantFAISS
数据动态性支持实时更新、增量写入需全量重建索引
查询复杂度支持元数据过滤、混合搜索仅支持纯向量搜索
扩展性分布式架构,适合PB级数据单机内存限制,适合中小规模数据
集成复杂度提供完整API,需独立部署数据库服务需结合其他工具实现数据存储与管理
典型场景推荐系统、语义搜索、多模态应用离线模型推理、批量相似性计算

pip install qdrant-client
pip install llama-index-vector-stores-qdrant
pip install llama-index-readers-file

# ---------------------
# step 1.设定key、模型url、推理模型名称以及embedding模型名称
# ---------------------
BASE_IP = "http://localhost:11434"
BASE_URL = BASE_IP+"/api/chat"
MODEL_NAME = "deepseek-r1"

# ---------------------
# step 2.设置本地embedding模型与本地大模型
# ---------------------
from llama_index.embeddings.ollama import OllamaEmbedding
embedding = OllamaEmbedding(base_url=BASE_IP, model_name=MODEL_NAME)
from llama_index.llms.ollama import Ollama
llm = Ollama(base_url=BASE_IP, model=MODEL_NAME)

# ---------------------
# step 3.使用SimpleDirectoryReader函数完成Document加载
# ---------------------
from llama_index.core import SimpleDirectoryReader,Document
# documents = SimpleDirectoryReader(input_files=['./docs/天龙八部.txt']).load_data()
documents = SimpleDirectoryReader(input_files=['./docs/越女剑1.txt']).load_data()
print('Document加载完成,Document ID:',documents[0].doc_id)

# ---------------------
# step 4.构建索引
# ---------------------
# Create an index over the documents
from llama_index.core import VectorStoreIndex, StorageContext
from llama_index.vector_stores.qdrant import QdrantVectorStore
from qdrant_client import qdrant_client
# 连接Qdrant,并保存在本地的qdrant文件夹中
qclient = qdrant_client.QdrantClient(path="qdrant")
vector_store = QdrantVectorStore(client=qclient, collection_name="wenda")
storage_context = StorageContext.from_defaults(vector_store=vector_store)
index = VectorStoreIndex.from_documents(
    documents,
    storage_context=storage_context,
    embed_model = embedding
)
print('构建索引环节完成')
# ---------------------
# step 5.构建检索器
# ---------------------
dimensions = 3584
from llama_index.core.retrievers import VectorIndexRetriever
# 想要自定义参数,可以构造参数字典
kwargs = {'similarity_top_k': 5, 'index': index, 'dimensions': dimensions} # 必要参数
retriever = VectorIndexRetriever(**kwargs)
print('构建检索器完成')
# ---------------------
# step 5.构建合成器
# ---------------------
from llama_index.core.response_synthesizers  import get_response_synthesizer
response_synthesizer = get_response_synthesizer(llm=llm)
print('构建合成器完成')
# ---------------------
# step 6.构建问答引擎
# ---------------------
# 构建问答引擎
from llama_index.core.query_engine import RetrieverQueryEngine
engine = RetrieverQueryEngine(
      retriever=retriever,
      response_synthesizer=response_synthesizer,
        )
print('构建问答引擎完成')
# 提问
question = "到底越女剑这本小说讲了一个什么样的故事?"
answer = engine.query(question)
print(answer.response)

测试结果:

Document加载完成,Document ID: 47b8cefd-91ee-477a-95fb-c401f2fb2410
D:\dev_work\datawhale03\wow-rag-main\rag-venv\lib\site-packages\llama_index\vector_stores\qdrant\base.py:644: UserWarning: Payload indexes have no effect in the local Qdrant. Please use server Qdrant if you need payload indexes.
  self._client.create_payload_index(
构建索引环节完成
构建检索器完成
构建合成器完成
构建问答引擎完成
<think>
《越女剑》是一部充满传奇色彩的小说,主要讲述了范蠡从楚国来到吴国,在结识并受教于阿青后,凭借其独特的“越女剑法”灭掉了吴国的故事。范蠡最初是吴国的臣子,后来与伍子胥、勾践等人合作对抗吴王夫差。在一次偶然的机会中,他遇到了神秘的阿青,阿青传授了她名为“越女剑法”的特殊剑术给范蠡。范蠡通过这门剑术和自己的智慧,最终帮助勾践完成了对吴国的灭门大计。故事充满了权谋、阴谋以及范蠡如何利用阿青的特殊能力来达成自己的复仇目标。
</think>

《越女剑》是一部讲述范蠡从楚国来到吴国,在与吴王夫差的盟友伍子胥和勾践共同对抗的过程中,利用自身的智慧和阿青传授的特殊剑术灭掉吴国的故事。范蠡最初是楚国的人,后来在吴国遇到了神秘的阿青,她教给了范蠡一种叫做“越女剑法”的剑术,这种剑术以女性的柔韧性著称。然而,阿青最终失踪了,而范蠡则通过自身的智慧和这门剑术帮助勾践完成了对吴国的灭门大计。整个故事充满了权谋、阴谋以及范蠡如何利用阿青的特殊能力来达成自己的复仇目标。

New Answer:

《越女剑》是一部讲述范蠡从楚国来到吴国,在与吴王夫差的盟友伍子胥和勾践共同对抗的过程中,利用自身的智慧和阿青传授的特殊剑术灭掉吴国的故事。范蠡最初是楚国的人,后来在吴国遇到了神秘的阿青,她教给了范蠡一种叫做“越女剑法”的剑术,这种剑术以女性的柔韧性著称。然而,阿青最终失踪了,而范蠡则通过自身的智慧和这门剑术帮助勾践完成了对吴国的灭门大计。整个故事充满了权谋、阴谋以及范蠡如何利用阿青的特殊能力来达成自己的复仇目标。

使用元数据过滤器的方式

元数据也即数据的XXX(数据的属性),例如文档的作者,最后修改日期,类型,文档格式等等,都属于元数据。

在这里主要展示如何用元数据来过滤数据,有什么用呢?盲猜能大幅减少搜索量和匹配计算量。

from llama_index.core import StorageContext, VectorStoreIndex
from llama_index.core.schema import TextNode
from llama_index.vector_stores.qdrant import QdrantVectorStore
from qdrant_client import qdrant_client


# ---------------------
# step 1.设定key、模型url、推理模型名称以及embedding模型名称
# ---------------------
BASE_IP = "http://localhost:11434"
BASE_URL = BASE_IP+"/api/chat"
MODEL_NAME = "deepseek-r1"

# ---------------------
# step 2.设置本地embedding模型与本地大模型
# ---------------------
from llama_index.embeddings.ollama import OllamaEmbedding
embedding = OllamaEmbedding(base_url=BASE_IP, model_name=MODEL_NAME)
from llama_index.llms.ollama import Ollama
llm = Ollama(base_url=BASE_IP, model=MODEL_NAME)


# 模拟给每个文档添加metadata
nodes = [
    TextNode(
        text="越女剑",
        metadata={
            "author": "金庸",
            "theme": "爱情",
            "year": 1945,
        },
    ),
    TextNode(
        text="天龙八部",
        metadata={
            "author": "金庸",
            "theme": "武侠",
            "year": 1972,
        },
    ),
    TextNode(
        text="楚留香",
        metadata={
            "author": "古龙",
            "theme": "偶像",
            "year": 1960,
        },
    )
]

# 连接Qdrant,并保存在本地的qdrant1文件夹中
qclient = qdrant_client.QdrantClient(path="qdrant1")

# 构建索引
vector_store = QdrantVectorStore(client=qclient, collection_name="filter")
storage_context = StorageContext.from_defaults(vector_store=vector_store)
index = VectorStoreIndex(
    nodes,
    storage_context=storage_context,
    embed_model = embedding
)



from llama_index.core.vector_stores import (
    MetadataFilter,
    MetadataFilters,
    FilterOperator,
)

# 一,构建metadata filter
filters = MetadataFilters(
    filters=[
        # 检索 theme(主题类型) 为 偶像 | 过滤程度是 FilterOperator.EQ  也即Equal(必须等于的关系)
        MetadataFilter(key="theme", operator=FilterOperator.EQ, value="偶像"),
    ]
)



retriever = index.as_retriever(filters=filters, llm=llm)
print(retriever.retrieve("What is 楚留香 about?"))


# 二,还可以用And 或者 Or来组合多个filter
from llama_index.core.vector_stores import FilterOperator, FilterCondition
filters = MetadataFilters(
   filters=[
       MetadataFilter(key="theme", value="爱情"),
       MetadataFilter(key="year", value=1940, operator=FilterOperator.GT),
   ],
   condition=FilterCondition.AND,
)

retriever = index.as_retriever(filters=filters, llm=llm)
print(retriever.retrieve("What is 楚留香 about?"))

# [NodeWithScore(node=TextNode(id_='68418f47-569b-44d0-90c8-bf5dc55b54ee', embedding=None, metadata={'author': '金庸', 'theme': '爱情', 'year': 1945}, excluded_embed_metadata_keys=[], excluded_llm_metadata_keys=[], relationships={}, metadata_template='{key}: {value}', metadata_separator='\n', text='越女剑', mimetype='text/plain', start_char_idx=None, end_char_idx=None, metadata_seperator='\n', text_template='{metadata_str}\n\n{content}'), score=-0.22448684524375884)]


# 三,也可以直接把filter的字典作为参数,构建retriever。这样可以构建一个更复杂的filter
retriever = index.as_retriever(
    vector_store_kwargs={"filter": {"theme": "武侠"}},
    llm=llm
)
print(retriever.retrieve("What is 天龙八部 about?"))
# [NodeWithScore(node=TextNode(id_='174feaf1-0410-43e6-a905-196ad41a069b', embedding=None, metadata={'director': 'Christopher Nolan', 'theme': 'Fiction', 'year': 2010}, excluded_embed_metadata_keys=[], excluded_llm_metadata_keys=[], relationships={}, metadata_template='{key}: {value}', metadata_separator='\n', text='', mimetype='text/plain', start_char_idx=None, end_char_idx=None, metadata_seperator='\n', text_template='{metadata_str}\n\n{content}'), score=0.5399519582355652)]


# 四,利用Qdrant自带的检索能力。就是Default Qdrant Filters


# 构建向量库
vector_store = QdrantVectorStore(client=qclient, collection_name="default")
storage_context = StorageContext.from_defaults(vector_store=vector_store)
index = VectorStoreIndex(
    nodes,
    storage_context=storage_context,
    embed_model = embedding
)

# 构建Qdrant自己的的filter
from qdrant_client.http.models import Filter, FieldCondition, MatchValue
filters = Filter(
    should=[
        Filter(
            must=[
                FieldCondition(
                    key="theme",
                    match=MatchValue(value="偶像"),
                )
            ]
        ),
        Filter(
            must=[
                FieldCondition(
                    key="author",
                    match=MatchValue(value="金庸"),
                )
            ]
        ),
    ]
)

# 构建retriever
retriever = index.as_retriever(
    vector_store_kwargs={"qdrant_filters": filters},
    llm=llm
)

response = retriever.retrieve("天龙八部是什么?")
for node in response:
    print("node", node.score)
    print("node", node.text)
    print("node", node.metadata)

测试结果

[NodeWithScore(node=TextNode(id_='fee07121-9a98-4432-bb04-2033297b661d', embedding=None, metadata={'author': '古龙', 'theme': '偶像', 'year': 1960}, excluded_embed_metadata_keys=[], excluded_llm_metadata_keys=[], relationships={}, metadata_template='{key}: {value}', metadata_separator='\n', text='楚留香', mimetype='text/plain', start_char_idx=None, end_char_idx=None, metadata_seperator='\n', text_template='{metadata_str}\n\n{content}'), score=-0.1659841307886109)]
[NodeWithScore(node=TextNode(id_='f87bce43-2f8e-43d6-a750-3cbef7fb3861', embedding=None, metadata={'author': '金庸', 'theme': '爱情', 'year': 1945}, excluded_embed_metadata_keys=[], excluded_llm_metadata_keys=[], relationships={}, metadata_template='{key}: {value}', metadata_separator='\n', text='越女剑', mimetype='text/plain', start_char_idx=None, end_char_idx=None, metadata_seperator='\n', text_template='{metadata_str}\n\n{content}'), score=-0.22448684524375892)]
[NodeWithScore(node=TextNode(id_='ace90ae1-3c90-4756-88cd-00bd76b56bb9', embedding=None, metadata={'author': '金庸', 'theme': '武侠', 'year': 1972}, excluded_embed_metadata_keys=[], excluded_llm_metadata_keys=[], relationships={}, metadata_template='{key}: {value}', metadata_separator='\n', text='天龙八部', mimetype='text/plain', start_char_idx=None, end_char_idx=None, metadata_seperator='\n', text_template='{metadata_str}\n\n{content}'), score=-0.126277455878843)]
node 0.7220394832623804
node 越女剑
node {'author': '金庸', 'theme': '爱情', 'year': 1945}
03-08
### Wow-RAG 技术概述 Wow-RAG (Retrieval-Augmented Generation) 是一种增强型检索生成模型,它结合了传统检索技术和现代神经网络的优势,在多个领域提供了卓越的表现。该技术不仅限于文本处理,还可以扩展到代码、音频以及视频等领域[^1]。 #### 文本应用实例 在文本处理方面,Wow-RAG 能够高效地生成高质量的自然语言摘要、构建精准的回答系统并支持流畅的人机对话交互。通过引入外部知识库作为补充信息源,使得生成的内容更加丰富和准确。 ```python from transformers import RagTokenizer, RagRetriever, RagSequenceForGeneration tokenizer = RagTokenizer.from_pretrained("facebook/wow-rag-tokenizer") retriever = RagRetriever.from_pretrained("facebook/wow-rag-retriever", index_name="exact", use_dummy_dataset=True) model = RagSequenceForGeneration.from_pretrained("facebook/wow-rag-sequence") input_dict = tokenizer.prepare_seq2seq_batch( ["What is the capital of France?"], return_tensors="pt" ) generated_ids = model.generate(input_ids=input_dict["input_ids"], retriever=retriever) print(tokenizer.batch_decode(generated_ids, skip_special_tokens=True)) ``` #### 非文本应用场景 除了文字外,Wow-RAG 还能在其他媒体形式中找到其独特价值: - **代码辅助开发**:自动完成编程任务中的复杂逻辑编写,如函数定义、类结构设计等;同时也能为现有项目添加详细的注释说明。 - **多媒体内容创作**:无论是声音还是影像资料,都可以借助此框架快速生产出符合需求的作品概要或是特定部分的合成版本。 值得注意的是,虽然上述例子主要集中在不同类型的静态资源上,但在实际操作过程中,Wow-RAG 的灵活性允许开发者针对具体业务场景定制化调整参数配置,从而达到最佳性能表现。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值