想象一下,如果你的孩子拥有一个随时待命、知识渊博的AI科学导师,能够用孩子们易于理解的语言解答关于宇宙、动物、行星和科学实验的各种问题,那会是怎样一番景象? KidSciBot,正是这样一款基于LangGraph和Gemini构建的智能Agent,旨在为儿童提供个性化的科学教育体验。 它巧妙地融合了大型语言模型(LLM)、检索增强生成(RAG)、网络搜索以及向量数据库等多种技术,让孩子们在轻松愉快的氛围中探索科学的奥秘。
1. LLM与Agent:理解AI的基石
在深入探讨KidSciBot的细节之前,我们需要区分两个关键概念:大型语言模型(LLM)和Agent。可以将LLM视为一位博学多才的讲故事大师,它接受过海量数据的训练,能够生成优美的文本、创作诗歌、解决数学难题,甚至解释复杂的科学概念。 然而,LLM本身并不具备决策能力和行动能力。举个例子,如果你对一个LLM说:“帮我给老板发邮件说我要迟到了”,它可能会为你生成一封措辞得体的邮件,例如:“您好,由于交通拥堵,我可能会迟到30分钟。” 但仅此而已,它不会帮你发送这封邮件。
而Agent则不同,它就像一个聪明的助手,能够控制和协调包括LLM、网络爬虫、搜索引擎等在内的多种工具,根据用户的查询做出决策,选择合适的工具,路由问题,验证响应,并在需要时进行循环。 在上面的例子中,Agent会使用LLM生成邮件内容,然后获取你老板的邮箱地址,登录你的邮箱账户,并最终发送邮件。 它像一个智能助理一样,端到端地编排整个流程。
正是由于Agent的这种决策和行动能力,使得我们能够构建像KidSciBot这样复杂的应用程序,它不仅仅是生成答案,而是构建一个知道要做什么、怎么做以及何时做的系统。
2. LangGraph:构建智能Agent的基石
那么,如何构建一个具备决策能力的智能Agent呢? 这就要归功于LangGraph。 当开发者想要构建一个超越简单问答的智能系统时,LangGraph便能派上大用场。 LangGraph允许将AI系统设计为一个任务图,每个任务都是一个小的函数(称为节点),例如“检查这是否是科学问题”、“从PDF中获取答案”或“验证响应”。 这些任务通过边缘连接,边缘就像道路一样,告诉Agent根据情况下一步该去哪里。
在KidSciBot中,如果问题是关于科学的,Agent会进入RAG节点;如果问题是关于当天的新闻,它会移动到网络搜索节点;如果只是一个一般性问题,它会使用LLM节点。 这种结构使得KidSciBot能够像一个聪明的决策者一样一步一步地处理问题,而不仅仅是一个聊天机器人。 LangGraph提供了将逻辑、灵活性和模块化设计相结合的工具,使得机器人既智能又适合儿童使用。 想象一下,如果我们要构建一个自动驾驶系统,LangGraph可以帮助我们将任务分解为“感知环境”、“规划路线”、“控制车辆”等节点,并根据不同的路况和交通状况选择不同的路线,从而实现安全可靠的自动驾驶。
3. KidSciBot工作流程:智能决策的幕后英雄
为了更好地理解KidSciBot的工作原理,我们来看一下它的流程图:
- 问题分类: 首先,KidSciBot会判断用户提出的问题类型,例如是科学问题、一般性问题还是关于当前事件的问题。
- 路由查询: 然后,它会将查询路由到正确的来源,例如RAG(从科学文档中检索答案)、LLM(使用大型语言模型生成答案)或网络搜索(从网络上获取最新信息)。
- 答案验证: 最后,它会对答案进行验证,确保答案的相关性、简洁性和易懂性,然后再将其呈现给用户。
这个流程图展示了KidSciBot如何利用LangGraph构建一个智能的决策流程,从而为孩子们提供准确、简洁、易懂的科学知识。
4. 环境搭建:为KidSciBot准备起飞跑道
在构建KidSciBot之前,我们需要确保开发环境已经准备就绪,并安装了所有必要的工具和配置。
-
安装必要的Python库: KidSciBot依赖于多个Python库来实现AI模型、向量存储、文档加载等功能。 可以使用以下命令一次性安装所有库:
bash
pip install langchain langgraph langchain-google-genai langchain-community \
langchain-huggingface chromadb pydantic tavily-python python-dotenv
-
设置环境变量: 为了保护API密钥和敏感凭据的安全,我们需要使用
.env
文件。 在项目目录中创建一个名为.env
的文件,并添加以下内容(将占位符替换为实际的密钥):
GOOGLE_GEMINI_API_KEY=your_google_gemini_api_key_here
TAVILY_API_KEY=your_tavily_api_key_here
注意: 永远不要公开分享.env
文件或将其提交到任何公共存储库。 -
加载环境变量: 使用
python-dotenv
库将这些变量加载到Python代码中。 在主Jupyter Notebook文件中(例如,名为kidscibot.ipynb
),编写以下代码:import os from dotenv import load_dotenv # 从.env文件加载环境变量 load_dotenv() GOOGLE_GEMINI_API_KEY = os.getenv("GOOGLE_GEMINI_API_KEY") TAVILY_API_KEY = os.getenv("TAVILY_API_KEY")
-
验证设置: 运行一个快速测试脚本来检查环境变量是否已正确加载:
python
if GOOGLE_GEMINI_API_KEY and TAVILY_API_KEY:
print("API密钥加载成功!")
else:
print("错误:缺少API密钥。请检查您的.env文件。")
-
加载模型和准备文档存储: 准备好环境并验证API密钥后,我们就可以加载AI模型,设置嵌入模型,并准备文档数据库了。
# 加载语言模型 from langchain_google_genai import ChatGoogleGenerativeAI model = ChatGoogleGenerativeAI(model='gemini-1.5-flash') output = model.invoke("Hi") output # 设置嵌入模型并加载PDF from langchain_huggingface import HuggingFaceEmbeddings from langchain_community.document_loaders import PyPDFLoader from langchain_community.vectorstores import Chroma from langchain.text_splitter import RecursiveCharacterTextSplitter # 加载嵌入模型 embeddings = HuggingFaceEmbeddings(model_name = "BAAI/bge-small-en") # 加载PDF并存储到向量数据库 FILE_PATH = "PATH OF YOUR PDF" # 替换为你的PDF文件路径 loader = PyPDFLoader(FILE_PATH) docs = loader.load() # 分块以存储到向量数据库 text_splitter=RecursiveCharacterTextSplitter(chunk_size=800,chunk_overlap=50) new_docs = text_splitter.split_documents(docs) new_docs # 存储到向量数据库(Chroma) db=Chroma.from_documents(new_docs,embeddings) retriever=db.as_retriever(search_kwargs={"k": 3})
5. 构建KidSciBot的核心节点
KidSciBot的核心在于各个节点,它们分别负责不同的任务。
- Supervisor节点: 负责对问题进行分类,判断其是否与科学相关。
- Router函数: 根据问题的分类和关键词,决定将问题路由到RAG节点、网络搜索节点还是LLM节点。
- RAG节点: 从向量数据库中检索科学信息,并使用模型生成简单的解释。
- LLM节点: 对于一般性问题,使用大型语言模型直接生成答案。
- Web Search节点: 对于关于当前事件或新闻的问题,使用Tavily API从网络上获取最新的答案。
- Validation节点: 验证答案的质量,确保其相关性、简洁性和易懂性。
这些节点协同工作,使得KidSciBot能够智能地处理各种问题,并提供高质量的答案。
6. 代码实现:将节点连接成智能流程
文章提供了各个节点的详细代码,这里不再赘述。 关键在于如何使用LangGraph将这些节点连接成一个智能的流程。
from langgraph.graph import StateGraph, END
builder = StateGraph(AgentState)
# 1. 入口点
builder.set_entry_point("Supervisor")
# 2. 添加节点
builder.add_node("Supervisor", supervisor_node)
builder.add_node("RAG Call", rag_node)
builder.add_node("LLM Call", llm_node)
builder.add_node("WEB Call", web_node)
builder.add_node("Validation", validation_with_llm)
# 3. Supervisor → Router
builder.add_conditional_edges("Supervisor", router, {
"RAG Call": "RAG Call",
"LLM Call": "LLM Call",
"WEB Call": "WEB Call",
"Final": END # 如果已经验证
})
# 4. Generation → Validation
builder.add_edge("RAG Call", "Validation")
builder.add_edge("LLM Call", "Validation")
builder.add_edge("WEB Call", "Validation")
# 5. Validation → Supervisor or END
builder.add_conditional_edges(
"Validation",
lambda state: "Final" if state["validated"] else "Supervisor",
{
"Final": END,
"Supervisor": "Supervisor"
})
# 6. 编译
science_bot_app = builder.compile()
这段代码定义了KidSciBot的整个工作流程,包括各个节点之间的连接方式以及条件跳转。 通过LangGraph,我们可以轻松地构建一个复杂的智能Agent,并对其行为进行精确的控制。
7. 运行KidSciBot:体验AI的魔力
一旦连接了完整的工作流程,运行KidSciBot就像用一个问题调用它一样简单。 根据查询的类型,它会自动选择正确的路径 – 无论是科学(RAG)、时事(网络)还是常识(LLM) – 并返回适合儿童的答案。
from IPython.display import Image, display
# 显示图表可视化
display(Image(science_bot_app.get_graph().draw_mermaid_png()))
# 准备每个节点类型的示例状态
science_question = AgentState(messages=["什么是光合作用?"], validated=False)
current_event_question = AgentState(messages=["关于火星任务的最新消息是什么?"], validated=False)
general_question = AgentState(messages=["阿尔伯特·爱因斯坦是谁?"], validated=False)
# 在每个问题上调用机器人并打印最终答案
print("🔬 测试科学问题(RAG节点):")
science_output = science_bot_app.invoke(science_question)
print("✅ 最终答案:", science_output["messages"][-1], "\n")
print("🌐 测试当前事件问题(WEB节点):")
web_output = science_bot_app.invoke(current_event_question)
print("✅ 最终答案:", web_output["messages"][-1], "\n")
print("🤖 测试一般问题(LLM节点):")
llm_output = science_bot_app.invoke(general_question)
print("✅ 最终答案:", llm_output["messages"][-1])
8. 结语:AI赋能,点亮学习之路
KidSciBot是一个有趣、智能且互动的科学导师,它使用LangGraph和Google Gemini构建。 它不仅了解孩子们提出的问题,还决定如何使用文档、网络搜索或自己的AI知识来找到最佳的、适合年龄的答案。
这个项目是构建智能Agent的激动人心的旅程 – 并且有很大的潜力使其变得更好! 当AI遇到好奇心时,学习就变得神奇起来。 这就是KidSciBot的精神。 未来,我们可以进一步扩展KidSciBot的功能,例如增加语音交互、图像识别等功能,使其成为一个更加完善的AI教育平台。 随着LLM、LangGraph等技术的不断发展,AI将在教育领域发挥越来越重要的作用,为孩子们提供个性化、智能化、趣味化的学习体验。 让我们一起拥抱AI,点亮孩子们的学习之路!