使用 Langchain 和 watsonx.ai 实现智能体分块来优化 LLM 输入。

作者

Shalini Harkar

Lead AI Advocate

什么是智能体式分块?

语言模型处理和分割文本的方式正在从传统的静态方法,转变为一种更好、更具响应性的流程。与传统的固定大小分块方法不同,传统方法在固定位置对大型文档进行分割,而智能体式分块采用基于 AI 的技术,通过动态流程分析内容,从而确定最佳的文本分割方式。

智能体式分块利用基于 AI 的文本拆分方法、递归分块和分块重叠技术,这些方法协同工作,不断提升分块效果,既保留重要观点间的联系,又实时优化上下文窗口。通过智能体式分块,每个块都丰富了元数据,以加深检索准确性和整体模型效率。这在 RAG 应用中尤为重要,因为数据的分割方式会直接影响检索质量和回复的连贯性。所有较小的分块中都保留了有意义的上下文,使得这种方法对聊天机器人、知识库以及生成式人工智能 (Gen AI) 等应用尤为重要。框架如 Langchain 或 LlamaIndex 进一步提高了检索效率,使这种方法非常有效。

智能体式分块的关键要素

1. 自适应分块策略:根据内容类型、查询背后的意图和检索需求动态选择最佳分块方法,以确保有效分割。

2. 动态分块调整:根据语义结构和上下文实时调整分块大小,而非严格遵循固定的令牌限制。

3. 保留上下文的重叠:通过智能评估块之间的重叠,保持内容连贯性,避免关键信息丢失,从而提升检索效率。

 

专家为您带来最新的 AI 趋势

获取有关最重要且最有趣的 AI 新闻的精选洞察分析。订阅我们的每周 Think 时事通讯。请参阅 IBM 隐私声明

谢谢!您已订阅。

您的订阅将以英语提供。您会在每份时事通讯中找到一个取消订阅链接。您可以在此处管理您的订阅或取消订阅。有关更多信息,请参阅我们的 IBM 隐私声明

智能体式分块相对于传统方法的优势

智能体式分块比传统分块具有以下优势:

a. 保持上下文:在不进行不必要拆分的情况下,保留关键信息。

b. 智能调整大小:根据内容的含义和重要性调整分块边界。

c. 查询优化:持续优化分块,使其更符合特定查询的需求。

d. 高效检索:通过减少不必要的文本碎片化,提升搜索和 RAG 系统的输出效果。

 

在本教程中,您将使用 IBM Granite-3.0-8B-Instruct 模型(现已在 watsonx.ai 上线),进行智能体式分块策略的实验。总体目标是执行高效的分块,以有效实现 RAG。

前提条件

您需要一个IBM Cloud 帐户来创建 watsonx.ai项目。

步骤

第 1 步:设置环境

虽然您可以选择多种工具,本教程将引导您如何设置 IBM 帐户以使用 Jupyter Notebook。

  1. 使用您的 IBM Cloud 帐户登录 watsonx.ai

  2. 创建 watsonx.ai 项目
    您可以从项目内部获取项目 ID。单击“管理”选项卡。然后,从“常规”页面中的“详细信息”部分复制项目 ID。您需要此 ID 来完成本教程。

  3. 创建一个 Jupyter Notebook

此步骤将打开一个笔记本环境,可在其中复制本教程中的代码。或者,您可以将此笔记本下载到本地系统并将其作为资产上传到您的 watsonx.ai 项目。要查看详情 Granite 教程,请访问 IBM Granite 社区。可以在 GitHub 上找到此 Jupyter Notebook 以及使用的数据集。

第 2 步:设置 watsonx.ai 运行时实例和 API 密钥

  1. 创建一个 watsonx.ai 运行时服务实例(选择适当的区域并选择精简计划,这是一个免费实例)。

  2. 生成 API 密钥

  3. 将 watsonx.ai 运行时服务实例与您在 watsonx.ai 中创建的项目关联。

第 3 步:安装并导入相关库,并设置您的凭据

学习本教程时,您将需要一些库和模块。请确保导入以下库,如果未安装,可以通过快速的 pip 安装来解决。

请注意,本教程使用 Python 3.12.7 构建

!pip install -q langchain langchain-ibm langchain_experimental langchain-text-splitters langchain_chroma transformers bs4 langchain_huggingface sentence-transformers
import getpass
import requests
from bs4 import BeautifulSoup
from langchain_ibm import WatsonxLLM
from langchain_huggingface import HuggingFaceEmbeddings
from langchain_community.document_loaders import WebBaseLoader
from langchain.schema import SystemMessage, HumanMessage
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain.prompts import ChatPromptTemplate
from langchain.vectorstores import Chroma
from langchain.tools import tool
from langchain.agents import AgentExecutor
from langchain.memory import ConversationBufferMemory
from transformers import AutoTokenizer
from ibm_watsonx_ai.foundation_models.utils.enums import EmbeddingTypes
from ibm_watsonx_ai.metanames import GenTextParamsMetaNames as GenParams
from langchain.output_parsers import CommaSeparatedListOutputParser
from langchain.embeddings import HuggingFaceEmbeddings
from langchain.schema import Document
from langchain.chains.combine_documents import create_stuff_documents_chain



 

为了设置凭据,我们需要 “WATSONX_APIKEY” “WATSONX_PROJECT_ID”。我们还将设置作为 API 端点的 URL。

load_dotenv(os.getcwd()+"/.env", override=True)
credentials = {
    "url": "https://us-south.ml.cloud.ibm.com",
    "apikey": os.getenv("WATSONX_APIKEY", ""),
}
project_id = os.getenv("PROJECT_ID", "")

第 4 步:初始化语言模型。

对于本教程,我们建议使用 IBM 的 Granite-3.0-8B-Instruct模型作为 LLM 来实现类似的结果。您可以自由使用您选择的任何 AI 模型。可在此处找到可通过 watsonx 获得的基础模型。

llm = WatsonxLLM(
    model_id="ibm/granite-3-8b-instruct",
    url=credentials.get("url"),
    apikey=credentials.get("apikey"),
    project_id=project_id,
    params={
        GenParams.DECODING_METHOD: "greedy",
        GenParams.TEMPERATURE: 0,
        GenParams.MIN_NEW_TOKENS: 5,
        GenParams.MAX_NEW_TOKENS: 250,
        GenParams.STOP_SEQUENCES: ["Human:", "Observation"],
    },
)

第 5 步:加载文档

这个函数用于提取 IBM 机器学习阅读解释器页面中的文本内容。此功能会删除不需要的 HTML 元素(脚本、样式),并返回清晰、可读的文本。

def get_text_from_url(url):
    response = requests.get(url)
    if response.status_code != 200:
        raise ValueError(f"Failed to fetch the page, status code: {response.status_code}")
    soup = BeautifulSoup(response.text, "html.parser")
    for script in soup(["script", "style"]):
        script.decompose()
    return soup.get_text(separator="\n", strip=True)
url = "https://www.ibm.com/cn-zh/think/topics/machine-learning"
web_text = get_text_from_url(url)
web_text

我们没有使用固定长度的分块方法,而是使用 LLM 根据含义来拆分文本。此功能充分利用 LLM 根据主题智能地将文本拆分为具有语义意义的块。

def agentic_chunking(text):
    """
    Dynamically splits text into meaningful chunks using LLM.
    """
    system_message = SystemMessage(content="You are an AI assistant helping to split text into meaningful chunks based on topics.")
    
    human_message = HumanMessage(content=f"Please divide the following text into semantically different, separate and meaningful chunks:\n\n{text}")

    response = llm.invoke([system_message, human_message]) # LLM returns a string
    return response.split("\n\n") # Split based on meaningful sections
chunks = agentic_chunking(web_text)
chunks

让我们打印这些块,以便更好地理解它们的输出结构。

for i, chunk in enumerate(chunks,1):
    print(f"Chunk {i}:\n{chunk}\n{'-'*40}")

太棒了!输出中的智能体已成功创建块。

第 6 步:创建矢量存储

既然我们已经对文本进行了智能体分块实验,接下来让我们继续进行 RAG 的具体实现。

对于本教程,我们选择智能体生成的块并将其转换为矢量嵌入。我们可以使用的开源代码矢量存储是 Chroma DB。我们可以通过 langchain_ Chroma 包轻松访问 Chroma 功能。让我们初始化我们的 Chroma 矢量数据库,为其提供我们的嵌入模型并添加由智能体分块生成的文档。

embeddings_model = HuggingFaceEmbeddings(model_name="ibm-granite/granite-embedding-30m-english")
 

创建 Chroma 矢量数据库

vector_db = Chroma(
    collection_name="example_collection",
    embedding_function=embeddings_model
)

将每个文本块转换为文档对象

documents = [Document(page_content=chunk) for chunk in chunks]

将文档添加到矢量数据库。

vector_db.add_documents(documents)

第 7 步:构建提示模板

现在,我们可以为 LLM 创建一个提示模板。该模板确保我们可以提出多个问题,同时保持一致的提示结构。此外,我们可以将矢量存储作为检索器进行集成,最终完成 RAG 框架。

prompt_template = """<|start_of_role|>user<|end_of_role|>Use the following pieces of context to answer the question at the end. If you don't know the answer, just say that you don't know, don't try to make up an answer.
{context}
Question: {input}<|end_of_text|>
<|start_of_role|>assistant<|end_of_role|>"""
qa_chain_prompt = PromptTemplate.from_template(prompt_template)
combine_docs_chain = create_stuff_documents_chain(llm, qa_chain_prompt)
rag_chain = create_retrieval_chain(vector_db.as_retriever(), combine_docs_chain)

第 8 步:提示 RAG 链

在 RAG 工作流中使用这些智能体片段,让我们启动一个用户查询。首先,我们可以在没有使用之前构建的矢量存储提供的额外上下文的情况下,有策略地提示模型,以测试它是仅依赖内置知识,还是确实利用了 RAG 上下文。现在让我们使用 IBM 的机器学习阅读解释器来问这个问题。

output = llm.invoke("What is Model optimization process")
output

显然,该模型没有接受过模型优化过程相关信息的训练,如果没有外部工具或信息,它就无法为我们提供正确的信息。模型会产生幻觉。现在,让我们用之前构建的智能体片段,将同样的查询提交给 RAG 链试试。

rag_output = rag_chain.invoke({"input": "What is Model optimization process?"})
rag_output['answer']

太棒了!Granite 模型正确地使用了智能体式 RAG 块作为上下文,为我们提供了有关模型优化过程的正确信息,同时保持了语义的连贯性。

摘要

在本教程中,我们在分块过程中使用 AI 智能体生成了较小的相关信息,并构建了一个检索增强生成 (RAG) 管道。

该方法利用人工智能和自然语言处理 (NLP) 改进信息检索和上下文窗口优化。当利用 OpenAI 的 GPT 模型等大型语言模型 (LLM) 时,它可以简化数据块以提高检索效率,以获得更好的结果。

相关解决方案
IBM AI 智能体开发

借助 IBM watsonx.ai 开发平台,让开发人员能够构建、部署和监控 AI 代理。

深入了解 watsonx.ai
IBM AI 智能体和助手

借助在业界首屈一指的全面功能,帮助企业构建、定制和管理 AI 智能体和助手,从而在提高生产力方面取得突破性进展。

深入了解 AI 智能体
IBM Granite

借助专为提高开发人员效率而设计的 Granite 小型开放式模型,可实现 90% 以上的成本节约。这些企业就绪型模型可根据安全基准提供卓越的性能,且适用于多种企业任务,包括网络安全、RAG 等。

深入了解 Granite
采取后续步骤

借助在业界首屈一指的全面功能,帮助企业构建、定制和管理 AI 智能体和助手,从而实现复杂工作流自动化并在提高生产力方面取得突破性进展。

深入了解 watsonx.ai 智能体开发 探索 watsonx Orchestrate