AI 大模型企业应用实战(13)-Lostinthemiddle长上下文精度处理

109 阅读3分钟

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 组件处理长文本和检索相关信息。

  1. 导入所需的库
  2. 使用指定的预训练模型(MiniLM-L6-v2)创建嵌入对象
  3. 定义一系列与用户兴趣相关的文本
  4. 使用 Chroma 类从文本和嵌入中创建一个检索器,并设置搜索参数为返回前10个最相关的文档
  5. 定义一个查询语句,用于从检索到的文档中筛选相关信息
  6. 使用检索器根据查询语句获取相关文档
  7. 打印检索到的相关文档
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应用开发

目前主攻降低软件复杂性设计、构建高可用系统方向。

参考: