1 长文本切分信息丢失处理方案
- 10+检索时性能大幅下降
- 相关信息在头尾性能最高
- 检索 ->> 排序 ->使用
2 处理流程
安装依赖:
# 用于生成句子/文本的语义向量(embeddings)。基于预训练的 BERT 等模型,能将文本转换为稠密向量,常用于语义相似度计算、文本检索、聚类等任务
%pip install sentence-transformers
%pip install -q diffusers accelerate peft
diffusers:HuggingFace 的扩散模型库,主要用于图像生成(如 Stable Diffusion)accelerate:简化模型在 CPU/GPU/多卡上的训练与推理部署peft:参数高效微调库(Parameter-Efficient Fine-Tuning),支持 LoRA、Prefix Tuning 等方法,以极少参数量对大模型进行微调
开始演示使用 Langchain 组件处理长文本和检索相关信息。
- 导入所需的库
- 使用指定的预训练模型(MiniLM-L6-v2)创建嵌入对象
- 定义一系列与用户兴趣相关的文本
- 使用 Chroma 类从文本和嵌入中创建一个检索器,并设置搜索参数为返回前10个最相关的文档
- 定义一个查询语句,用于从检索到的文档中筛选相关信息
- 使用检索器根据查询语句获取相关文档
- 打印检索到的相关文档
from langchain_community.document_transformers import LongContextReorder
from langchain_community.vectorstores import Chroma
from shared.llm_utils import create_qwen_embeddings
embeddings = create_qwen_embeddings(check_embedding_ctx_length=False)
# 模拟一段长文本,这里是一系列与用户兴趣相关的句子
text = [
"篮球是一项伟大的运动。",
"带我飞往月球是我最喜欢的歌曲之一。",
"凯尔特人队是我最喜欢的球队。",
"这是一篇关于波士顿凯尔特人的文件。",
"我非常喜欢去看电影。",
"波士顿凯尔特人队以20分的优势赢得了比赛。",
"这只是一段随机的文字。",
"《艾尔登之环》是过去15年最好的游戏之一。",
"L.科内特是凯尔特人队最好的球员之一。",
"拉里.伯德是一位标志性的NBA球员。"
]
# 使用Chroma从文本和嵌入中创建一个检索器,并设置搜索参数为返回前10个最相关的文档
retrieval = Chroma.from_texts(text, embeddings).as_retriever(
search_kwargs={"k": 10}
)
# 定义查询语句
query = "关于我的喜好都知道什么?"
# 根据相关性从检索器中获取相关文档
docs = retrieval.invoke(query)
# 打印结果
docs
3 对检索结果重排序
根据论文的方案,问题相关性越低的内容块放在中间,问题相关性越高的内容块放在头尾。
reordering = LongContextReorder()
reo_docs = reordering.transform_documents(docs)
#头尾共有4个高相关性内容块
reo_docs
4 检测该方案的精度效果
from langchain_core.prompts import PromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnablePassthrough
from shared.llm_utils import create_qwen_model
llm = create_qwen_model(
temperature=1,
streaming=True,
)
stuff_prompt_override = """Given this text extracts:
----------------------------------------
{context}
----------------------------------------
Please answer the following questions:
{query}
"""
prompt = PromptTemplate(
template=stuff_prompt_override,
input_variables=["context", "query"]
)
def format_docs(docs):
return "\n\n".join(doc.page_content for doc in docs)
chain = (
{"context": lambda x: format_docs(x["input_documents"]), "query": lambda x: x["query"]}
| prompt
| llm
| StrOutputParser()
)
# 调用
chain.invoke({
"input_documents": reo_docs,
"query": "我最喜欢做什么事情?"
})
'\n\n根据提供的文本,您最喜欢做的事情是**去看电影**。'
关注我,紧跟本系列专栏文章,咱们下篇再续!
作者简介:魔都架构师,多家大厂后端一线研发经验,在分布式系统设计、数据平台架构和AI应用开发等领域都有丰富实践经验。
各大技术社区头部专家博主。具有丰富的引领团队经验,深厚业务架构和解决方案的积累。
负责:
- 中央/分销预订系统性能优化
- 活动&券等营销中台建设
- 交易平台及数据中台等架构和开发设计
- 车联网核心平台-物联网连接平台、大数据平台架构设计及优化
- LLM应用开发
目前主攻降低软件复杂性设计、构建高可用系统方向。
参考: