AI知识库

53AI知识库

学习大模型的前沿技术与行业应用场景


使用 Lang Chain 和 Lang Graph 构建多代理 RAG :分步指南 + Gemma 2
发布日期:2024-12-23 12:02:39 浏览次数: 1535 来源:barry的异想世界


检索代理[1] 在我们想要判断文档是否相关以决定是否从索引中检索时非常有用,或者它可以从网络搜索工具中检索。

要实现检索代理,我们只需让 LLM 访问检索工具。

智能体 RAG 是一种基于智能体的方法,用于以有序的方式对多个文档进行问答。虽然标准 RAG 在少量文档的简单查询中表现出色,但智能体 RAG 进一步提升,成为问答的强大解决方案。它通过采用 AI 智能体引入了一层智能。这些智能体作为自主决策者,分析初步发现,并战略性地选择最有效的工具进行进一步的数据检索。

智能体 RAG 采用基于智能体的方法,在多个文档中系统地进行问答。虽然传统 RAG 在有限数量的文档中对简单查询有效,但智能体 RAG 改进了这一过程,提供了一个强大的问答解决方案。它通过使用 AI 智能体引入了一定程度的智能。这些智能体独立操作,评估初步结果,并仔细选择最合适的工具进行额外的数据提取。

想象一下,这就像拥有一支专业研究团队,每个成员都具备独特的技能和能力,协同工作以满足您的信息需求。

智能体 RAG 是传统 RAG 的一种演变,集成了 AI 智能体以增强 RAG 方法。这种方法利用自主智能体分析初步发现,并战略性地选择有效的数据检索工具。这些 AI 智能体能够将复杂任务分解为多个子任务,从而变得易于处理。它们还具备记忆(如聊天记录),因此它们知道发生了什么以及接下来需要采取哪些步骤。

此外,这些 AI 智能体非常聪明,可以在需要解决任务时随时调用任何 API 或工具。这些智能体能够提出逻辑、推理并相应采取行动。这正是使智能体 RAG 方法如此突出的原因。系统将复杂查询分解为可管理的部分,为每个部分分配特定的智能体,同时保持无缝协调。

Agentic RAG的主要好处和使用案例

Agentic RAG相较于传统系统提供了众多优势。其自主代理可以独立工作,从而有效地并行处理复杂查询。该系统的适应性使其能够根据新信息或不断变化的用户需求动态调整策略。在营销中,Agentic RAG可以分析客户数据,生成个性化沟通并提供实时竞争情报。它还增强了活动管理中的决策能力,并改善了搜索引擎优化策略。

  • • 该过程从Agent节点开始。
  • • Agent然后决定是否Should Retrieve信息。
  • • 如果决定是Yes,则流程移至Tool节点,在此选择特定工具或资源。
  • • 从Tool节点,流程继续到Continue节点。
  • • 在Continue节点,决定是否继续或结束该过程。
  • • 如果决定是Yes,则流程移动到Check Relevance节点。
  • • 在Check Relevance节点,评估一个条件。如果条件满足(Yes),则流程转到Generate节点,在此生成最终的Answer
  • • 如果在Check Relevance节点的条件不满足(No),则流程转到Web search节点。
  • • 在Web search节点,进行网络搜索,并使用网络搜索中的信息生成最终的Answer

问题陈述:

我创建了一些与RAG、图形RAG与RAG以及Ollama相关的博客,如果有人想了解博客中的概念,比如“什么是图形RAG?”

解决方案

要么阅读故事的人会回答,要么你得自己阅读故事…. ??

无论你还是某个没有阅读博客的人,关于博客的问题都无法回答,想想这怎么可能 ????

“是的,我们的AI AGENTS可以做到?”

代理将配备两个代理,一个与博客相关的检索器,另一个是网络搜索代理。

如果有人问与博客相关的问题,则代理状态将使用检索工具来回答问题。

如果有人问与博客无关的问题,则代理状态将重定向到网络搜索工具并生成答案..??

呜呼,你准备好编码了吗?

是的,编码时间到!!!!!!!!!!!!!!!!!!!

请在你的Google Collab中安装以下内容

! pip install -U langchain_community tiktoken langchain-openai langchainhub chromadb langchain langgraph  langchain-google-genai langchain-groq
import os
os.environ["LANGCHAIN_TRACING_V2"] = "true"
os.environ["LANGCHAIN_ENDPOINT"] = "https://api.smith.langchain.com"
os.environ["LANGCHAIN_API_KEY"] = ""

使用Gemini Pro生成嵌入,你可以选择任何你喜欢的嵌入模型。

我已经选择了3篇中等的博客文章。

文本 -> 拆分 -> 嵌入 -> chroma db -> 检索器

from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_community.document_loaders import WebBaseLoader
from langchain_community.vectorstores import Chroma
from langchain_google_genai import GoogleGenerativeAIEmbeddings
GOOGLE_API_KEY = ""
GROQ_API_KEY=""
embeddings = GoogleGenerativeAIEmbeddings(model="models/embedding-001", google_api_key=GOOGLE_API_KEY)
urls = [
    "https://medium.com/@sridevi.gogusetty/rag-vs-graph-rag-llama-3-1-8f2717c554e6",
    "https://medium.com/@sridevi.gogusetty/retrieval-augmented-generation-rag-gemini-pro-pinecone-1a0a1bfc0534",
    "https://medium.com/@sridevi.gogusetty/introduction-to-ollama-run-llm-locally-data-privacy-f7e4e58b37a0",
]
docs = [WebBaseLoader(url).load() for url in urls]
docs_list = [item for sublist in docs for item in sublist]
text_splitter = RecursiveCharacterTextSplitter.from_tiktoken_encoder(
    chunk_size=250, chunk_overlap=0
)
doc_splits = text_splitter.split_documents(docs_list)
## 添加到vectorDB
vectorstore = Chroma.from_documents(
    documents=doc_splits,
    collection_name="rag-chroma",
    embedding=embeddings,
)
retriever = vectorstore.as_retriever()

使用检索器创建retriever_tool

from langchain.tools.retriever import create_retriever_tool
retriever_tool = create_retriever_tool(
    retriever,
    "retrieve_blog_posts",
    "搜索并返回关于sridevi gogusetty在RAG、RAG与图形RAG、Ollama上的博客文章的信息。",
)
tools = [retriever_tool]

Agent State用于存储和表示代理图的状态,因为我们遍历各个节点。它将存储并跟踪用户查询、一个标志变量(指示是否需要进行网络搜索)、一组上下文文档(从向量数据库和/或网络搜索中检索)以及LLM生成的响应。

from typing import Annotated, Sequence, TypedDict
from langchain_core.messages import BaseMessage
from langgraph.graph.message import add_messages
class AgentState(TypedDict):
    # add_messages函数定义了如何处理更新
    # 默认是替换。add_messages表示“追加”
    messages: Annotated[Sequence[BaseMessage], add_messages]

如果你想为自己创建一个,请传递TAVILY_API_KEY,从这个链接获取 https://app.tavily.com/

import getpass
import os
os.environ["TAVILY_API_KEY"] = getpass.getpass()

这里,web_search_tool我们将使用Tavily API进行网络搜索,因此我们加载与此API的连接。对于我们的搜索,我们将使用前3个搜索结果作为额外的上下文信息;不过,你可以自由加载更多的搜索结果。

#### 搜索
from langchain_community.tools.tavily_search import TavilySearchResults
from langchain.utilities.tavily_search import TavilySearchAPIWrapper
from langchain.tools.tavily_search import TavilySearchResults
## tavily_tool = TavilySearchResults(k=3)
search = TavilySearchAPIWrapper()
web_search_tool = TavilySearchResults(api_wrapper=search, max_results=5,
    include_answer=True,
    include_raw_content=True,
    include_images=True,)

定义节点 = > “web_search_agent, retrieve_agent, generate”

web_search_agent=> 这将用于使用网络搜索工具搜索给定查询并从网络中检索一些信息

retrieve_agent=> 它将决定使用检索工具检索,或简单地结束

generate=> 这是在RAG系统中从查询和上下文文档生成标准LLM响应的功能。

定义边缘/关系 => “grade_documents

grade_documents=> 这将用于使用LLM Grader确定检索到的文档是否与问题相关。它返回 generate 如果文档相关,否则返回 web_search

from typing import Annotated, LiteralSequence
from typing_extensions import TypedDict
from langchain import hub
from langchain_core.messages import BaseMessage, HumanMessage
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import PromptTemplate
from langchain_openai import ChatOpenAI
from pydantic import BaseModel, Field
from langchain_core.documents import Document
from langgraph.prebuilt import tools_condition
from langchain_groq import ChatGroq
#### 边缘
def grade_documents(state) -> Literal["generate""web_search"]:
    """
    确定检索到的文档是否与问题相关。
    参数:
        state (messages): 当前状态
    返回:
        str: 一个决定,表示文档是否相关
    """
    print("---检查相关性---")
    # 数据模型
    class grade(BaseModel):
        """相关性检查的二进制评分。"""
        binary_score: str = Field(description="相关性评分 'yes' 或 'no'")
    # LLM
    model =  ChatGroq(temperature=0, model_name="gemma2-9b-it", groq_api_key=GROQ_API_KEY)
    # 带工具和验证的LLM
    llm_with_tool = model.with_structured_output(grade)
    # 提示
    prompt = PromptTemplate(
        template="""你是一个评估检索文档与用户问题相关性的评分员。 \n
        这是检索到的文档: \n\n {context} \n\n
        这是用户问题: {question} \n
        如果文档包含与用户问题相关的关键字或语义含义,请将其评为相关。 \n
        给出一个二进制评分 'yes' 或 'no' 来指示文档是否与问题相关。"""
,
        input_variables=["context""question"],
    )
    # 链
    chain = prompt | llm_with_tool
    messages = state["messages"]
    last_message = messages[-1]
    question = messages[0].content
    docs = last_message.content
    scored_result = chain.invoke({"question": question, "context": docs})
    score = scored_result.binary_score
    if score == "yes":
        print("---决策: 文档相关---")
        return "generate"
    else:
        print("---决策: 文档不相关---")
        print(score)
        return "web_search"
#### 节点
def web_search_agent(state):
    """
    基于重新表述的问题进行网络搜索。
    Args:
        state (dict): 当前图的状态
    Returns:
        state (dict): 用追加的网络结果更新文档键
    """
    print("---网络搜索---")
    question = state["messages"]
    query = question[0].content
    print(question)
    # 网络搜索
    docs = web_search_tool.invoke({"query": query})
    web_results = "\n".join([d["content"for d in docs])
    web = Document(page_content=web_results)
    # 我们返回一个列表,因为这将被添加到现有列表中
    return {"messages": [web_results]}
def retrieve_agent(state):
    """
    调用代理模型,根据当前状态生成响应。给定问题,它将决定使用检索工具进行检索,或者简单地结束。
    Args:
        state (messages): 当前状态
    Returns:
        dict: 更新后的状态,代理响应附加到消息中
    """
    print("---调用代理---")
    messages = state["messages"]
    model =  ChatGroq(temperature=0, model_name="gemma2-9b-it", groq_api_key=GROQ_API_KEY)
    model = model.bind_tools(tools)
    response = model.invoke(messages)
    # 我们返回一个列表,因为这将被添加到现有列表中
    return {"messages": [response]}
def rewrite(state):
    """
    转换查询以生成更好的问题。
    Args:
        state (messages): 当前状态
    Returns:
        dict: 更新后的状态,包含重新表述的问题
    """
    print("---转换查询---")
    messages = state["messages"]
    question = messages[0].content
    msg = [
        HumanMessage(
            content=f""" \n
    查看输入并尝试推理潜在的语义意图/含义。 \n
    这里是初始问题:
    \n ------- \n
    {question}
    \n ------- \n
    制定一个改进的问题: """
,
        )
    ]
    llm =  ChatGroq(temperature=0, model_name="gemma2-9b-it", groq_api_key=GROQ_API_KEY)
    response = llm.invoke(msg)
    return {"messages": [response]}
def generate(state):
    """
    生成答案
    Args:
        state (messages): 当前状态
    Returns:
         dict: 更新后的状态,包含重新表述的问题
    """
    print("---生成---")
    messages = state["messages"]
    question = messages[0].content
    last_message = messages[-1]
    docs = last_message.content
    # 提示
    prompt = hub.pull("rlm/rag-prompt")
    # LLM
    llm =  ChatGroq(temperature=0, model_name="gemma2-9b-it", groq_api_key=GROQ_API_KEY)
    # 后处理
    def format_docs(docs):
        return "\n\n".join(doc.page_content for doc in docs)
    # 链
    rag_chain = prompt | llm | StrOutputParser()
    # 运行
    response = rag_chain.invoke({"context": docs, "question": question})
    return {"messages": [response]}
print("*" * 20 + "提示[rlm/rag-prompt]" + "*" * 20)
prompt = hub.pull("rlm/rag-prompt").pretty_print()  # 显示提示的样子

定义图“工作流”,添加节点和边/关系并编译

from langgraph.graph import END, StateGraph, START
from langgraph.prebuilt import ToolNode
## 定义一个新图
workflow = StateGraph(AgentState)
## 定义我们将循环的节点
workflow.add_node("web_search", web_search_agent)  # 网络搜索
workflow.add_node("agent", retrieve_agent)  # 代理
retrieve = ToolNode([retriever_tool])
workflow.add_node("retrieve", retrieve)
workflow.add_node(
    "generate", generate
)  # 在我们知道文档相关后生成响应
## 调用代理节点以决定是否检索
workflow.add_edge(START, "agent")
workflow.add_edge("web_search", "generate")
## 决定是否检索
workflow.add_conditional_edges(
    "agent",
    # 评估代理决策
    tools_condition,
    {
        # 将条件输出转换为我们图中的节点
        "tools""retrieve",
        END: END,
    },
)
## 在调用`action`节点后采取的边。
workflow.add_conditional_edges(
    "retrieve",
    # 评估代理决策
    grade_documents,
)
workflow.add_edge("generate", END)
## 编译
graph = workflow.compile()
import pprint
inputs = {
    "messages": [
        ("user""你如何玩板球?"),
    ]
}
for output in graph.stream(inputs):
    for key, value in output.items():
        pprint.pprint(f"来自节点 '{key}' 的输出:")
        pprint.pprint("---")
        pprint.pprint(value, indent=2, width=80, depth=None)
    pprint.pprint("\n---\n")

上述问题“你如何玩板球?”的输出如下

该问题与文档无关,因此代理将使用网络搜索工具生成答案

---调用代理---
"来自节点 'agent' 的输出:"
'---'
'messages': [ AIMessage(content='', additional_kwargs={'tool_calls': [{'id''call_a0e8''function': {'arguments''{"query":"如何玩板球"}''name''retrieve_blog_posts'}, 'type''function'}]}, response_metadata={'token_usage': {'completion_tokens'87'prompt_tokens'978'total_tokens'1065'completion_time'0.158181818'prompt_time'0.031489045'queue_time'0.0030664820000000023'total_time'0.189670863}, 'model_name''gemma2-9b-it''system_fingerprint''fp_10c08bf97d''finish_reason''tool_calls''logprobs'None}, id='run-93d87331-d092-43dc-875e-04095a50d423-0', tool_calls=[{'name''retrieve_blog_posts''args': {'query''如何玩板球'}, 'id''call_a0e8''type''tool_call'}], usage_metadata={'input_tokens'978'output_tokens'87'total_tokens'1065})]}
'\n---\n'
---检查相关性---
---决策:文档不相关---

"来自节点 'retrieve' 的输出:"
'---'
'messages': [ ToolMessage(content='by Sreedevi Gogusetty9 FollowersFollowHelpStatusAboutCareersPressBlogPrivacyTermsText to speechTeams\n\nby Sreedevi Gogusetty9 FollowersFollowHelpStatusAboutCareersPressBlogPrivacyTermsText to speechTeams\n\ngive suggestions or comments for better teaching..RagGraphragLlmLlama3 1----FollowWritten by Sreedevi Gogusetty9 FollowersFollowHelpStatusAboutCareersPressBlogPrivacyTermsText to speechTeams\n\ngive suggestions or comments for better teaching..RagGraphragLlmLlama3 1----FollowWritten by Sreedevi Gogusetty9 FollowersFollowHelpStatusAboutCareersPressBlogPrivacyTermsText to speechTeams', name='retrieve_blog_posts'id='3b812678-1118-442f-9fd4-dbc89585c449', tool_call_id='call_a0e8')]}
'\n---\n'
---网络搜索---
[HumanMessage(content='你如何玩板球?', additional_kwargs={}, response_metadata={}, id='821c3254-52a0-47de-b973-2c393845b916'), AIMessage(content='', additional_kwargs={'tool_calls': [{'id''call_a0e8''function': {'arguments''{"query":"如何玩板球"}''name''retrieve_blog_posts'}, 'type''function'}]}, response_metadata={'token_usage': {'completion_tokens'87'prompt_tokens'978'total_tokens'1065'completion_time'0.158181818'prompt_time'0.031489045'queue_time'0.0030664820000000023'total_time'0.189670863}, 'model_name''gemma2-9b-it''system_fingerprint''fp_10c08bf97d''finish_reason''tool_calls''logprobs'None}, id='run-93d87331-d092-43dc-875e-04095a50d423-0', tool_calls=[{'name''retrieve_blog_posts''args': {'query''如何玩板球'}, 'id''call_a0e8''type''tool_call'}], usage_metadata={'input_tokens'978'output_tokens'87'total_tokens'1065}), ToolMessage(content='by Sreedevi Gogusetty9 FollowersFollowHelpStatusAboutCareersPressBlogPrivacyTermsText to speechTeams\n\nby Sreedevi Gogusetty9 FollowersFollowHelpStatusAboutCareersPressBlogPrivacyTermsText to speechTeams\n\ngive suggestions or comments for better teaching..RagGraphragLlmLlama3 1----FollowWritten by Sreedevi Gogusetty9 FollowersFollowHelpStatusAboutCareersPressBlogPrivacyTermsText to speechTeams\n\ngive suggestions or comments for better teaching..RagGraphragLlmLlama3 1----FollowWritten by Sreedevi Gogusetty9 FollowersFollowHelpStatusAboutCareersPressBlogPrivacyTermsText to speechTeams', name='retrieve_blog_posts'id='3b812678-1118-442f-9fd4-dbc89585c449', tool_call_id='call_a0e8')]
"来自节点 'web_search' 的输出:"
'---'
'messages': [ 'wikiHow 是一个“维基”,类似于维基百科,这意味着我们的许多文章由多个作者共同撰写。\n'
                '投球队有专门的投球手,而其他球员则分布在场地上,试图防止击球手得分,并试图接住球以将击球手出局。由于板球是由成对的击球手进行的,当击球队的 10 名球员被判出局时,他们的局就结束了,他们所得分的总和为投球队设定了目标分数。出局:出局发生在接球队在击球手试图得分并在他们能够到达场地另一侧之前将球投向门柱时。\n'
                '得分也可以通过投球手投出宽球(离门柱太远的球)、无球(投球手越过门柱前线)和腿球(没有人触球,但两个击球手仍然跑动)来获得,场地大小在板球中差异很大,但通常是在周长约 200 米的圆形草地上进行的。场地边缘被称为边界边,基本上是比赛进行和停止之间的界线。\n'
                ' 投球手将从一端投出板球,而击球手将试图从另一端击打球。\n'
                ' 得分\n'
                '当击球手用球棒击打球并且两个击球手成功跑到另一端时,就会发生得分。击球队将尝试在规定时间内尽可能多地得分,而投球队将试图通过接球来限制他们。']}
'\n---\n'
---生成---
"来自节点 'generate' 的输出:"
'---'
'messages': [ '板球是由两支各有 11 名球员的队伍进行的。击球队通过击打由对方队伍投出的球来得分,而接球队则试图防止得分并将击球手出局。得分是通过在门柱之间跑动或将球击打到边界来完成的。 \n'
                '\n'
                '\n']}
'\n---\n'
import pprint
inputs = {
    "messages": [
        ("user""RAG与GRAPH RAG之间的区别是什么"),
    ]
}
for output in graph.stream(inputs):
    for key, value in output.items():
        pprint.pprint(f"来自节点 '{key}' 的输出:")
        pprint.pprint("---")
        pprint.pprint(value, indent=2, width=80, depth=None)
    pprint.pprint("\n---\n")

上述问题“RAG与GRAPH RAG之间的区别是什么?”的输出如下

该问题与文档相关,因此代理将使用检索工具生成答案

---CALL AGENT---
"来自节点 'agent' 的输出:"
'---'
'messages': [ AIMessage(content='', additional_kwargs={'tool_calls': [{'id''call_zm54''function': {'arguments''{"query":"RAG VS Graph RAG"}''name''retrieve_blog_posts'}, 'type''function'}]}, response_metadata={'token_usage': {'completion_tokens'85'prompt_tokens'981'total_tokens'1066'completion_time'0.154545455'prompt_time'0.031727456'queue_time'0.0029311909999999997'total_time'0.186272911}, 'model_name''gemma2-9b-it''system_fingerprint''fp_10c08bf97d''finish_reason''tool_calls''logprobs'None}, id='run-b4ea1e95-9dea-47be-98c6-b658ffa1dac7-0', tool_calls=[{'name''retrieve_blog_posts''args': {'query''RAG VS Graph RAG'}, 'id''call_zm54''type''tool_call'}], usage_metadata={'input_tokens'981'output_tokens'85'total_tokens'1066})]}
'\n---\n'
---CHECK RELEVANCE---
---DECISION: DOCS RELEVANT---
"来自节点 'retrieve' 的输出:"
'---'
'messages': [ ToolMessage(content='它们之间的关系。当处理查询时,Graph RAG 探索知识图谱,识别与用户意图相关的实体和连接。这种方法提供了对信息中上下文和关系的更深入理解。主题相关性与上下文和关系:主题相关性关注的是主题之间的相似性。想象一下两份文档,一份关于法国大革命,另一份关于美国大革命。两者都讨论革命,使它们在关于“革命”的查询中主题相关。上下文和关系则更深入。在这里,我们不仅考虑主题,还考虑它们之间的连接。Graph RAG 中的知识图谱可能显示美国革命受到法国大革命的启发,从而提供了对上下文的更丰富理解。信息与实体:信息是一个更广泛的术语,涵盖任何类型的检索知识。在 Vector RAG 中,检索到的信息可以是完整的文档或摘要。实体是信息中的特定对象或概念。在 Graph RAG 中,检索到的信息专注于识别实体(如法国大革命)及其之间的关系(例如,有因果关系的历史事件)。选择合适的 RAG 方法选择 Vector RAG 和 Graph RAG 之间的区别取决于您的具体\n\它们之间的关系。当处理查询时,Graph RAG 探索知识图谱,识别与用户意图相关的实体和连接。这种方法提供了对信息中上下文和关系的更深入理解。主题相关性与上下文和关系:主题相关性关注的是主题之间的相似性。想象一下两份文档,一份关于法国大革命,另一份关于美国大革命。两者都讨论革命,使它们在关于“革命”的查询中主题相关。上下文和关系则更深入。在这里,我们不仅考虑主题,还考虑它们之间的连接。Graph RAG 中的知识图谱可能显示美国革命受到法国大革命的启发,从而提供了对上下文的更丰富理解。信息与实体:信息是一个更广泛的术语,涵盖任何类型的检索知识。在 Vector RAG 中,检索到的信息可以是完整的文档或摘要。实体是信息中的特定对象或概念。在 Graph RAG 中,检索到的信息专注于识别实体(如法国大革命)及其之间的关系(例如,有因果关系的历史事件)。选择合适的 RAG 方法选择 Vector RAG 和 Graph RAG 之间的区别取决于您的具体\n\nRAG 与 Vector RAG 并深入探讨每个:RAG 与 Graph RAG Vector RAG 想象一个庞大的图书馆,书籍根据主题连接进行组织。Vector RAG 使用向量数据库。这些数据库将信息(如文档或实体)表示为高维空间中的数值向量。主题相似或相关的文档在这个空间中的向量会更接近。在检索过程中,Vector RAG 在数据库中搜索与用户查询最接近的向量的文档,实质上找到最具主题相关性的信息。示例:用户查询:“法国大革命的原因是什么?”检索到的信息(向量搜索):讨论导致法国大革命的历史事件的文档,关于18世纪法国的社会和经济条件的文档。生成的响应:LLM 使用检索到的文档,可能会解释导致法国大革命的各种政治、社会和经济因素。Graph RAG 想象一张详细的地图,位置及其连接清晰定义。Graph RAG 利用知识图谱。这些是结构化数据库,表示实体(如人、地点或事件)及其之间的关系。在检索过程中,Graph RAG 根据用户查询遍历知识图谱,识别实体和', name='retrieve_blog_posts'id='6490648b-73ef-41a8-ad7f-55a9ab86730d', tool_call_id='call_zm54')]}
'\n---\n'
---GENERATE---
"来自节点 'generate' 的输出:"
'---'
'messages': [ 'Vector RAG 侧重于查找与查询主题相关的信息,而 Graph RAG 强调理解知识图谱中实体之间的关系。'
                'Vector RAG 根据相似性检索文档,而 Graph RAG 识别实体及其连接,以提供更深入的上下文理解。最佳方法取决于您的应用程序是需要主题相关性还是对关系的更丰富理解。\n']}
'\n---\n'

您需要以下密钥才能在 Google Colab 中运行此代码

Google API 密钥

TAVILY API 密钥

Groq API 密钥



53AI,企业落地应用大模型首选服务商

产品:大模型应用平台+智能体定制开发+落地咨询服务

承诺:先做场景POC验证,看到效果再签署服务协议。零风险落地应用大模型,已交付160+中大型企业

联系我们

售前咨询
186 6662 7370
预约演示
185 8882 0121

微信扫码

与创始人交个朋友

回到顶部

 
扫码咨询