txtai RAG 管线实战:用 Embeddings 检索与 LLM 生成构建检索增强生成
【免费下载链接】txtai💡 All-in-one AI framework for semantic search, LLM orchestration and language model workflows项目地址: https://gitcode.com/GitHub_Trending/tx/txtai
本指南深入讲解 txtai 中的 RAG(Retrieval Augmented Generation,检索增强生成)管线:如何将提示词、上下文数据存储与生成式模型三者结合,从自有数据中抽取知识并生成可引用答案。读完本文,你将掌握 RAG 管线的 Python 与配置驱动两种用法、底层检索与生成流程,以及输出格式、系统提示、流式响应等进阶参数的完整配置方案。
RAG 管线是什么
txtai 的 RAG 管线把三个组件拼接在一起,构成一条完整的"检索 → 增强 → 生成"链路(见 RAG 官方文档):
- 上下文数据存储(context data store):可以是带原文内容的 embeddings 数据库,也可以是带关联输入文本的 similarity(相似度)实例;
- 生成式模型(generative model):可以是提示词驱动的大语言模型(LLM)、抽取式问答模型(extractive question-answering)或自定义管线;
- 提示词(prompt):把检索到的上下文与用户问题组织成模型可执行的指令模板。
从源码实现看,RAG 类继承自Pipeline(rag.py),其类注释明确说明:"通过将提示词、上下文数据存储和生成式模型结合在一起,从内容中抽取知识"。这意味着 RAG 不只是"向量检索 + 聊天",它还能复用 txtai 的问答、相似度等基础能力,灵活性很高。
快速上手:Python 示例
下面的例子完整复现官方文档的入门场景:先构建一个带原文内容的 embeddings 索引,再创建 RAG 管线,最后提问。
from txtai import Embeddings, RAG # Input data data = [ "US tops 5 million confirmed virus cases", "Canada's last fully intact ice shelf has suddenly collapsed, " + "forming a Manhattan-sized iceberg", "Beijing mobilises invasion craft along coast as Taiwan tensions escalate", "The National Park Service warns against sacrificing slower friends " + "in a bear attack", "Maine man wins $1M from $25 lottery ticket", "Make huge profits without work, earn up to $100,000 a day" ] # Build embeddings index embeddings = Embeddings(content=True) embeddings.index(data) # Create the RAG pipeline rag = RAG(embeddings, "Qwen/Qwen3-0.6B", template=""" Answer the following question using the provided context. Question: {question} Context: {context} """) # Run RAG pipeline rag("What was won?")要点说明:
Embeddings(content=True)表示索引时保存原文内容,这是 RAG 能"抽取知识"的前提——生成阶段需要把命中片段的原文作为上下文喂给模型;RAG的第一个参数传入 embeddings 实例,第二个参数是生成模型路径;- 模板中必须包含
{question}和{context}两个占位符,分别会被替换为输入问题和检索到的上下文。
直接传入 Chat 模板
许多指令微调模型遵循固定的 chat 模板,你可以把整段模板(含系统、用户、助手角色标记)直接传给template。模板格式随模型而异:
# Prompts with chat templating can be directly passed # The template format varies by model rag = RAG(embeddings, "Qwen/Qwen3-0.6B", template=""" <|im_start|>system You are a friendly assistant.<|im_end|> <|im_start|>user Answer the following question using the provided context. Question: {question} Context: {context} <|im_start|>assistant """ ) rag("What was won?")通过 system 参数自动构建对话消息
当提供system参数时,输入会自动转换为 chat 消息。从源码看(rag.py),prompts方法会在检测到self.system时,把提示词包装成[{"role": "system", ...}, {"role": "user", ...}]两条消息,交由底层生成器处理。
rag = RAG( embeddings, "openai/gpt-oss-20b", system="You are a friendly assistant", template=""" Answer the following question using the provided context. Question: {question} Context: {context} """) rag("What was won?")额外的 LLM 选项
__call__时可以把 LLM 参数作为附加参数传入:
stream=True:以流式方式返回 RAG 响应;defaultrole="user":字符串输入始终转换为用户消息(LLM 管线的defaultrole还支持"auto"自动推断与"prompt"保持原始提示词,见 LLM 管线文档);stripThink=True:移除模型输出的思考文本(thinking text)。
rag("What was won?", stream=True, defaultrole="user", stripThink=True)从 LLM 实现 可以看到,stripthink的默认行为是:流式输出时为False,非流式时为True;思考文本的清理通过正则移除<think>...</think>等标记(见 generation.py)。
RAG 管线内部工作原理
从源码结构看,RAG 的__call__主要经历四个阶段(rag.py):
- 输入规范化:字符串问题转换为
(name, query, question, snippet)元组,字典输入按["name", "query", "question", "snippet"]字段抽取; - 上下文检索:对每个 query 执行相似度打分(
score),排序后取前context条(默认 3 条)拼接为上下文; - 提示词构建:用模板格式化
{question}与{context},必要时附加 system 消息(prompts方法); - 生成与格式化:调用底层模型得到答案,再按
output格式输出(apply方法)。
检索阶段:query → score → 过滤
query方法(rag.py)实现了一套细粒度的过滤逻辑:
- 支持必需/禁止关键词:query 中以
+开头的词(如+Giants)要求上下文必须包含,以-开头的词要求不能包含; score >= minscore才纳入匹配(minscore默认0.0);- 命中片段 token 数必须达到
mintokens(默认0.0)。
score方法(rag.py)根据相似度实例类型选择打分路径:
- 相似度实例为
Similarity管线时,调用self.similarity(queries, texts); - 传入
texts时,调用embeddings.batchsimilarity做批量相似度; - 未传
texts时,调用embeddings.batchsearch直接对索引做语义搜索(需要 embeddings 开启content=True)。
生成阶段:三种模型形态
load方法(rag.py)根据路径与任务类型决定加载哪种模型:
task == "question-answering":加载Questions抽取式问答管线,直接以"问题 + 上下文"为输入返回原文片段;- 否则走
LLM管线(llm.py),内部由GenerationFactory根据模型路径自动推断后端(factory.py):Hugging Face Transformers、llama.cpp(GGUF 路径)、LiteLLM(如ollama/...)、LiteRT-LM 与 OpenCode; - 传入非字符串路径时,直接返回该对象作为自定义管线使用。
answers方法(rag.py)据此分派:Questions模型直接调用self.model(questions, contexts),生成式模型则先经prompts构建提示词再调用self.model(prompts, **kwargs)。
输出格式化:default / flatten / reference
apply方法(rag.py)控制返回结构:
| output 取值 | 返回格式 | 说明 |
|---|---|---|
default(默认) | (name, answer) | 每行包含名称与答案 |
flatten | 答案列表 | 仅返回答案字符串序列 |
reference | (name, answer, reference) | 额外返回与该答案最匹配的上下文元素 id,便于做引用标注 |
reference模式通过terms提取查询关键词、再对答案与 top-n 上下文重新打分来确定引用来源(rag.py)。此外,若输入元组的snippet标志为真,snippets方法会把答案替换为包含它的完整上下文原文(rag.py)。官方测试 testrag.py 验证了这三种输出模式。
构造参数详解
RAG.__init__的完整签名与默认值(rag.py):
| 参数 | 默认值 | 说明 |
|---|---|---|
similarity | 必填 | 相似度实例(embeddings 或 similarity 管线) |
path | 必填 | 模型路径,支持 LLM、Questions 或自定义管线 |
quantize | False | 推理前是否量化模型 |
gpu | True | 是否使用 GPU 推理(仅在有 GPU 时生效) |
model | None | 可选的已有管线模型对象(外部加载模型时使用) |
tokenizer | None | Tokenizer 类;未设置时若相似度实例为加权稀疏模型则默认使用Tokenizer |
minscore | None→0.0 | 纳入上下文匹配的最低分数 |
mintokens | None→0.0 | 纳入上下文匹配的最低 token 数 |
context | None→3 | 纳入上下文的最匹配片段数(top-n) |
task | 自动检测 | 模型任务:language-generation、sequence-sequence或question-answering |
output | "default" | 输出格式:default/flatten/reference |
template | "{question} {context}" | 提示词模板,必须含{question}与{context} |
separator | " " | 上下文片段拼接分隔符 |
system | None | 系统提示词,提供后自动转为 chat 消息 |
kwargs | — | 透传给底层管线模型的额外关键字参数 |
需要特别说明:template的默认值是"{question} {context}",即不写模板时 RAG 也能工作(直接拼接问题与上下文);task未指定时,GenerationFactory.method先解析路径归属的生成框架,再交由Models.task推断具体任务类型。
配置驱动示例:YAML + Workflows + API
除了 Python 直接调用,RAG 管线也能用配置声明。管线在配置中使用小写类名实例化,并通过工作流或 API 运行。
config.yml
# Allow documents to be indexed writable: True # Content is required for extractor pipeline embeddings: content: True rag: path: Qwen/Qwen3-0.6B template: | Answer the following question using the provided context. Question: {question} Context: {context} workflow: search: tasks: - action: rag注意writable: True允许向索引写入文档,embeddings.content: True保存原文——这两项是 RAG 能检索并输出原文上下文的前提。
通过 Workflows 运行
from txtai import Application # Create and run pipeline with workflow app = Application("config.yml") app.add([ "US tops 5 million confirmed virus cases", "Canada's last fully intact ice shelf has suddenly collapsed, " + "forming a Manhattan-sized iceberg", "Beijing mobilises invasion craft along coast as Taiwan tensions escalate", "The National Park Service warns against sacrificing slower friends " + "in a bear attack", "Maine man wins $1M from $25 lottery ticket", "Make huge profits without work, earn up to $100,000 a day" ]) app.index() list(app.workflow("search", ["What was won?"]))app.add写入文档、app.index()建立索引,workflow("search", ...)触发配置中名为search的工作流,其任务action: rag指向 RAG 管线。
通过 API 运行
CONFIG=config.yml uvicorn "txtai.api:app" & curl \ -X POST "http://localhost:8000/workflow" \ -H "Content-Type: application/json" \ -d '{"name": "search", "elements": ["What was won"]}'此外,API 还内置了专门的 RAG 路由(rag.py):GET /rag?query=...运行单条 RAG 查询,POST /batchrag批量处理查询列表,两者均支持maxlength、stream、stripthink参数;stream=True时以StreamingResponse流式返回。
实战案例:从本地文件到 RAG 问答
仓库自带的 rag_quickstart.py 展示了一条完整的数据落地链路:收集本地文件 → 文本抽取与分块 → 建立 embeddings 索引 → 构建 RAG 管线。核心代码如下:
from txtai import Embeddings, RAG from txtai.pipeline import Textractor # Step 1: Collect files from local directory (defaults to "data") path = "data" files = [os.path.join(path, f) for f in os.listdir(path) if os.path.isfile(os.path.join(path, f))] # Step 2: Text Extraction / Chunking textractor = Textractor(backend="docling", sections=True) chunks = [] for f in files: for chunk in textractor(f): chunks.append((f, chunk)) # Step 3: Build an embeddings database embeddings = Embeddings(content=True, path="Qwen/Qwen3-Embedding-0.6B", maxlength=2048) embeddings.index(chunks) # Step 4: Create RAG pipeline template = """ Answer the following question using the provided context. Question: {question} Context: {context} """ rag = RAG( embeddings, "Qwen/Qwen3-0.6B", system="You are a friendly assistant", template=template, output="flatten", ) question = "Summarize the main advancements made by BERT" print(rag(question, maxlength=2048, stripthink=True))该示例展示了几个值得在生产中采用的实践:
- 先分块再索引:用
Textractor按章节(sections=True)切分长文档,使检索粒度更精细; - 检索模型与生成模型分离:向量模型
Qwen/Qwen3-Embedding-0.6B负责召回,生成模型Qwen/Qwen3-0.6B负责作答; - 输出扁平化:
output="flatten"直接得到答案字符串,便于下游处理; - 思考文本剥离:
stripthink=True让推理模型的思维链过程不污染最终答案。
数据存储与相似度实例的多种组合
RAG 的上下文来源不局限于 embeddings 索引。官方测试 testrag.py 覆盖了三种典型组合:
- embeddings 索引 + 搜索(
testSearch):建立content=True的索引后,rag(question)直接对索引做语义检索取上下文; - 外部文本列表(
testAnswer):rag(question, texts)传入文本列表,RAG 先对文本做相似度打分再取 top-n; - Similarity 管线 + Questions 模型(
testSimilarity):RAG(Similarity("prajjwal1/bert-medium-mnli"), Questions("distilbert-base-cased-distilled-squad"))——左侧用相似度管线做召回,右侧用抽取式问答模型做生成,完全绕开 LLM。
最后一种组合印证了"生成式模型可以是抽取式问答模型"的设计:RAG 并不强制要求大语言模型,轻量级 QA 模型同样可以驱动。
方法参考
RAG 管线对外暴露的核心方法:
RAG.__init__(similarity, path, quantize=False, gpu=True, model=None, tokenizer=None, minscore=None, mintokens=None, context=None, task=None, output="default", template=None, separator=" ", system=None, **kwargs):构建管线,参数含义见上文表格;RAG.__call__(queue, texts=None, **kwargs):输入可以是单个字符串、元组/字典或它们的列表;返回格式与output参数一致。queue元素支持(name, query, question, snippet)四元组,其中query用于检索、question用于生成、snippet控制是否返回原文片段。
延伸学习
更多主题请参考 Embeddings 配置文档 与 LLM 管线文档(后者介绍了 Transformers、llama.cpp、LiteLLM、LiteRT-LM、OpenCode 等全部生成后端)。仓库中的 notebook 示例按难度递进覆盖了 RAG 的各个进阶方向:
- 42_Prompt_driven_search_with_LLMs.ipynb:LLM 提示驱动搜索
- 52_Build_RAG_pipelines_with_txtai.ipynb:RAG 管线构建与引用生成
- 53_Integrate_LLM_Frameworks.ipynb:集成 llama.cpp、LiteLLM 与自定义生成框架
- 55_Generate_knowledge_with_Semantic_Graphs_and_RAG.ipynb:语义图 + RAG 的知识生成
- 58_Advanced_RAG_with_graph_path_traversal.ipynb:图路径遍历的高级 RAG
- 62_RAG_with_llama_cpp_and_external_API_services.ipynb:llama.cpp 与外部 API 服务
- 63_How_RAG_with_txtai_works.ipynb:RAG 流程、API 服务与 Docker 实例
- 65_Speech_to_Speech_RAG.ipynb:语音到语音的完整 RAG 工作流
- 73_Chunking_your_data_for_RAG.ipynb:面向 RAG 的数据抽取、分块与索引
- 75_Medical_RAG_Research_with_txtai.ipynb:PubMed 医学文献分析
- 77_GraphRAG_with_Wikipedia_and_GPT_OSS.ipynb:深度图搜索驱动的 RAG
- 79_RAG_is_more_than_Vector_Search.ipynb:Web、SQL 等非向量来源的上下文检索
【免费下载链接】txtai💡 All-in-one AI framework for semantic search, LLM orchestration and language model workflows项目地址: https://gitcode.com/GitHub_Trending/tx/txtai
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考