From 55b59e800f81b7773d2ba7c65defb11c2bd8acd9 Mon Sep 17 00:00:00 2001 From: "2287551746@qq.com" <2287551746@example.com> Date: Thu, 30 Oct 2025 18:52:51 +0800 Subject: [PATCH] 2025.10.30 --- .../{01_Models.py => 01_models.py} | 0 .../{02_Prompt.py => 02_prompt.py} | 0 .../{03_Chain.py => 03_chain.py} | 0 .../{04_Memory.py => 04_memory.py} | 0 04_langchain_basics/README.md | 10 ++- 05_langchain_advanced/01_define_toolbox.py | 23 ++++++ 05_langchain_advanced/02_general_agent.py | 54 +++++++++++++ 05_langchain_advanced/03_sql_agent.py | 50 ++++++++++++ .../04_memory_general_agent.py | 81 +++++++++++++++++++ 05_langchain_advanced/05_caching.py | 52 ++++++++++++ 05_langchain_advanced/06_streaming.py | 78 ++++++++++++++++++ 05_langchain_advanced/README.md | 69 ++++++++++++++++ README.md | 9 ++- 13 files changed, 420 insertions(+), 6 deletions(-) rename 04_langchain_basics/{01_Models.py => 01_models.py} (100%) rename 04_langchain_basics/{02_Prompt.py => 02_prompt.py} (100%) rename 04_langchain_basics/{03_Chain.py => 03_chain.py} (100%) rename 04_langchain_basics/{04_Memory.py => 04_memory.py} (100%) create mode 100644 05_langchain_advanced/01_define_toolbox.py create mode 100644 05_langchain_advanced/02_general_agent.py create mode 100644 05_langchain_advanced/03_sql_agent.py create mode 100644 05_langchain_advanced/04_memory_general_agent.py create mode 100644 05_langchain_advanced/05_caching.py create mode 100644 05_langchain_advanced/06_streaming.py create mode 100644 05_langchain_advanced/README.md diff --git a/04_langchain_basics/01_Models.py b/04_langchain_basics/01_models.py similarity index 100% rename from 04_langchain_basics/01_Models.py rename to 04_langchain_basics/01_models.py diff --git a/04_langchain_basics/02_Prompt.py b/04_langchain_basics/02_prompt.py similarity index 100% rename from 04_langchain_basics/02_Prompt.py rename to 04_langchain_basics/02_prompt.py diff --git a/04_langchain_basics/03_Chain.py b/04_langchain_basics/03_chain.py similarity index 100% rename from 04_langchain_basics/03_Chain.py rename to 04_langchain_basics/03_chain.py diff --git a/04_langchain_basics/04_Memory.py b/04_langchain_basics/04_memory.py similarity index 100% rename from 04_langchain_basics/04_Memory.py rename to 04_langchain_basics/04_memory.py diff --git a/04_langchain_basics/README.md b/04_langchain_basics/README.md index f8ad2c8..630c77a 100644 --- a/04_langchain_basics/README.md +++ b/04_langchain_basics/README.md @@ -5,7 +5,7 @@ LLM 调用|Prompt 设计|Chain 构建|Memory 记忆|实战练习 --- -### 1. `01_Models.py`(模型调用) +### 1. `01_models.py`(模型调用) 封装 LLM 实例,实现标准调用流程。 ✅ 掌握点: @@ -14,7 +14,7 @@ LLM 调用|Prompt 设计|Chain 构建|Memory 记忆|实战练习 --- -### 2. `02_Prompt.py`(提示词构建) +### 2. `02_prompt.py`(提示词构建) 使用 `ChatPromptTemplate` 构建可复用的 Prompt 模板。 ✅ 掌握点: @@ -24,7 +24,7 @@ LLM 调用|Prompt 设计|Chain 构建|Memory 记忆|实战练习 --- -### 3. `03_Chain.py`(链式调用) +### 3. `03_chain.py`(链式调用) 将 Prompt + LLM + Parser 组合成 Chain。 ✅ 掌握点: @@ -34,7 +34,7 @@ LLM 调用|Prompt 设计|Chain 构建|Memory 记忆|实战练习 --- -### 4. `04_Memory.py`(记忆功能) +### 4. `04_memory.py`(记忆功能) 添加会话记忆,实现多轮对话。 ✅ 掌握点: @@ -52,4 +52,6 @@ LLM 调用|Prompt 设计|Chain 构建|Memory 记忆|实战练习 - 实际运行体验 - 可直接扩展为 Web 应用 +--- + 💡 建议:跑通后,试试让 AI 记住你喜欢的颜色,并在后续对话中提及。 \ No newline at end of file diff --git a/05_langchain_advanced/01_define_toolbox.py b/05_langchain_advanced/01_define_toolbox.py new file mode 100644 index 0000000..987285c --- /dev/null +++ b/05_langchain_advanced/01_define_toolbox.py @@ -0,0 +1,23 @@ +import os +from dotenv import load_dotenv + +load_dotenv() +api_key = os.getenv("OPENAI_API_KEY") + + +from langchain_core.tools import tool + +@tool +def get_weather(location): + """模拟获得天气信息""" + return f"{location}当前天气:23℃,晴,风力2级" + +@tool +def get_user_name(user): + """模拟获得用户名字""" + return f'用户名字是:{user}' + + +# 封装好我们要用的工具 +tools = [get_weather,get_user_name] +print('工具箱已封装完毕!') \ No newline at end of file diff --git a/05_langchain_advanced/02_general_agent.py b/05_langchain_advanced/02_general_agent.py new file mode 100644 index 0000000..eaaea37 --- /dev/null +++ b/05_langchain_advanced/02_general_agent.py @@ -0,0 +1,54 @@ +import os +from dotenv import load_dotenv + +load_dotenv() +api_key = os.getenv("OPENAI_API_KEY") + + +import os +from langchain_openai import ChatOpenAI +from langchain.agents import AgentExecutor, create_tool_calling_agent +from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder +from langchain_core.tools import tool # 导入 @tool + +# 配置LLM +llm = ChatOpenAI( + model="deepseek-chat", + api_key=api_key, + base_url="https://api.deepseek.com" +) + +# 配置prompt +prompt = ChatPromptTemplate.from_messages([ + ("system","你是一个聪明的智能助手。当你遇到解决不了的问题时,会调用工具来解决问题。"), + ("human","{input}"), + MessagesPlaceholder(variable_name="agent_scratchpad") # 必加,Agent的思考过程 +]) + +# 配置tool +@tool +def get_weather(location): + """模拟获得天气信息""" + return f"{location}当前天气:23℃,晴,风力2级" + +@tool +def get_user_name(user): + """模拟获得用户名字""" + return f'用户名字是:{user}' + + +tools = [get_weather,get_user_name] + +# 创建Agent(大脑) +agent = create_tool_calling_agent(llm=llm,prompt=prompt,tools=tools) +# 创建AgentExecutor(执行器)--负责运行ReAct循环 +agent_executor = AgentExecutor(agent=agent,tools=tools,verbose=True) # 开启verbose以看到ai思考链 +# 运行 +response = agent_executor.invoke({ + 'input':"今天北京的天气怎么样?" +}) + +print(response) +print() +print(response['output']) + diff --git a/05_langchain_advanced/03_sql_agent.py b/05_langchain_advanced/03_sql_agent.py new file mode 100644 index 0000000..bf9da6a --- /dev/null +++ b/05_langchain_advanced/03_sql_agent.py @@ -0,0 +1,50 @@ +import os +from dotenv import load_dotenv + +load_dotenv() +api_key = os.getenv("OPENAI_API_KEY") + +import sqlite3 +from langchain_openai import ChatOpenAI +from langchain_community.agent_toolkits import create_sql_agent +from langchain_community.utilities import SQLDatabase # 导入 SQLDatabase + +# 配置llm +llm = ChatOpenAI( + model="deepseek-chat", + api_key=api_key, + base_url="https://api.deepseek.com" +) + +# 创建一个临时的数据库--用于演示 +db_file = "test_sql.db" +if os.path.exists(db_file): + os.remove(db_file) +conn = sqlite3.connect(db_file) +cursor = conn.cursor() +cursor.execute("CREATE TABLE users (id INT,name TEXT,age INT);") +cursor.execute("INSERT INTO users (id,name,age) VALUES (1,'Alice',30);") +cursor.execute("INSERT INTO users (id,name,age) VALUES (2,'Bob',25);") +conn.commit() +conn.close() + +# 连接数据库 -- LangChain 使用 SQLAlchemy URI (连接方式) +db_uri = f'sqlite:///{db_file}' +db = SQLDatabase.from_uri(db_uri) + +# 创建sqlAgent -- 一键完成,无需定义tools,仅告诉它使用openai-tools,即Tool Calling(工具调用)模式 +agent_executor = create_sql_agent( + llm=llm, + db=db, + agent_type="openai-tools", + verbose=True +) + +# 运行 +response = agent_executor.invoke({"input":"告诉我Alice多大了?"}) +print(response['output']) + +# 清理 +db._engine.dispose() # 关闭连接池,避免文件被占用 +if os.path.exists(db_file): + os.remove(db_file) diff --git a/05_langchain_advanced/04_memory_general_agent.py b/05_langchain_advanced/04_memory_general_agent.py new file mode 100644 index 0000000..ae079c5 --- /dev/null +++ b/05_langchain_advanced/04_memory_general_agent.py @@ -0,0 +1,81 @@ +import os +from dotenv import load_dotenv + +load_dotenv() +api_key = os.getenv("OPENAI_API_KEY") + + +import os +from langchain_openai import ChatOpenAI +from langchain.agents import AgentExecutor, create_tool_calling_agent +from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder +from langchain_core.tools import tool # 导入 @tool +from langchain_community.chat_message_histories import ChatMessageHistory +from langchain_core.runnables import RunnableWithMessageHistory + + +# 配置llm +llm = ChatOpenAI( + model="deepseek-chat", + api_key=api_key, + base_url="https://api.deepseek.com" +) +# 配置prompt(新增俩占位符 一个为对话历史记录,一个为agent的思考过程) +prompt = ChatPromptTemplate.from_messages([ + ('system','你是小智,一个帮助他人的智能助手。当你无法解答当前问题时,会调用工具来解决问题。'), + MessagesPlaceholder(variable_name="history"), + ('human','{input}'), + MessagesPlaceholder(variable_name="agent_scratchpad") +]) + +# 配置tool +@tool +def get_weather(location): + """模拟获得天气信息""" + return f"{location}当前天气:23℃,晴,风力2级" + + +tools = [get_weather] +# 配置agent +agent = create_tool_calling_agent(llm=llm,prompt=prompt,tools=tools) +# 配置AgentExecutor +agent_executor = AgentExecutor(agent=agent,tools=tools) # 这里没加verbose=True,想打印日志看思考链的可以自行打印 + + +# 记忆存储--包装agent_executor +store = {} +def get_session_history(session_id:str): + if session_id not in store: + store[session_id] = ChatMessageHistory() + return store[session_id] + + +agent_with_memory = RunnableWithMessageHistory( + runnable=agent_executor, + get_session_history=get_session_history, + input_messages_key="input", + history_messages_key="history" +) +# 打印测试 +session_id = 'user123' + +if __name__ == '__main__': + while 1: + user_input = input('\n你:') + if user_input == 'quit': + print('拜拜~') + break + response = agent_with_memory.invoke( + {'input': user_input}, + config={'configurable': {'session_id': session_id}} + ) + print(f"AI:{response['output']}") + + + + + + + + + diff --git a/05_langchain_advanced/05_caching.py b/05_langchain_advanced/05_caching.py new file mode 100644 index 0000000..ef5c6b3 --- /dev/null +++ b/05_langchain_advanced/05_caching.py @@ -0,0 +1,52 @@ +import os +from dotenv import load_dotenv + +load_dotenv() +api_key = os.getenv("OPENAI_API_KEY") + + +import time +from langchain_openai import ChatOpenAI +from langchain.globals import set_llm_cache +from langchain_community.cache import InMemoryCache + +# 配置llm +llm = ChatOpenAI( + model="deepseek-chat", + api_key=api_key, + base_url="https://api.deepseek.com" +) +# 设置全局缓存 +set_llm_cache(InMemoryCache()) + +# 第一次调用llm(会远程请求) +query = "用中文写一句关于猫的五言诗。" +start_time = time.time() +response1 = llm.invoke(query).content +print(f"第一次调用结果: {response1}") +print(f"第一次运行时间: {time.time() - start_time:.4f} 秒") +print('') + +# 第二次调用llm(会命中缓存) +start_time = time.time() +response2 = llm.invoke(query).content +print(f"第二次调用结果: {response2}") +print(f"第二次运行时间 (已缓存): {time.time() - start_time:.4f} 秒") + +# 清理 +set_llm_cache(None) # 关闭缓存,以免影响后续实例 +print('缓存清理完成') + + + + + + + + + + + + + + diff --git a/05_langchain_advanced/06_streaming.py b/05_langchain_advanced/06_streaming.py new file mode 100644 index 0000000..78faaba --- /dev/null +++ b/05_langchain_advanced/06_streaming.py @@ -0,0 +1,78 @@ +import os +from dotenv import load_dotenv + +load_dotenv() +api_key = os.getenv("OPENAI_API_KEY") + + +from langchain_openai import ChatOpenAI +from langchain.agents import AgentExecutor, create_tool_calling_agent +from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder +from langchain_core.tools import tool # 导入 @tool +from langchain_community.chat_message_histories import ChatMessageHistory +from langchain_core.runnables import RunnableWithMessageHistory +from langchain.callbacks.streaming_stdout import StreamingStdOutCallbackHandler + + +# 配置llm +llm = ChatOpenAI( + model="deepseek-chat", + api_key=api_key, + base_url="https://api.deepseek.com", + streaming=True, + callbacks=[StreamingStdOutCallbackHandler()] +) +# 配置prompt(新增俩占位符 一个为对话历史记录,一个为agent的思考过程) +prompt = ChatPromptTemplate.from_messages([ + ('system','你是小智,一个帮助他人的智能助手。当你无法解答当前问题时,会调用工具来解决问题。'), + MessagesPlaceholder(variable_name="history"), + ('human','{input}'), + MessagesPlaceholder(variable_name="agent_scratchpad") +]) + +# 配置tool +@tool +def get_weather(location): + """模拟获得天气信息""" + return f"{location}当前天气:23℃,晴,风力2级" + + +tools = [get_weather] +# 配置agent +agent = create_tool_calling_agent(llm=llm,prompt=prompt,tools=tools) +# 配置AgentExecutor +agent_executor = AgentExecutor(agent=agent,tools=tools) # 这里没加verbose=True,想打印日志看思考链的可以自行打印 + + +# 记忆存储--包装agent_executor +store = {} +def get_session_history(session_id:str): + if session_id not in store: + store[session_id] = ChatMessageHistory() + return store[session_id] + + +agent_with_memory = RunnableWithMessageHistory( + runnable=agent_executor, + get_session_history=get_session_history, + input_messages_key="input", + history_messages_key="history" +) +# 打印测试 +session_id = 'user123' + +if __name__ == '__main__': + while 1: + user_input = input('\n你:') + if user_input == 'quit': + print('拜拜~') + break + # 用于标记"AI:"这个内容 + # flush=True保证"AI:"立即输出,而不是等缓存区存满再输出 + print("AI: ", end="", flush=True) + response = agent_with_memory.invoke( + {'input': user_input}, + config={'configurable': {'session_id': session_id}} + ) + print() + diff --git a/05_langchain_advanced/README.md b/05_langchain_advanced/README.md new file mode 100644 index 0000000..74a1afe --- /dev/null +++ b/05_langchain_advanced/README.md @@ -0,0 +1,69 @@ +## 🧩 模块说明:LangChain Agents 进阶核心组件 + +📌 **核心知识点**: +Function Calling|@tool 工具封装|ReAct 循环|Agent 构建|SQL Agent|记忆+流式|开发优化 + +--- + +### 1. `01_define_toolbox.py`(工具函数定义) +使用 `@tool` 装饰器将 Python 函数封装为 LangChain 可调用的工具。 + +✅ 掌握点: +- 如何用 `@tool` 定义工具 +- 必须添加三引号描述(作为提示词) +- 支持任意自定义逻辑函数 + +--- + +### 2. `02_general_agent.py`(通用 Agent 构建) +基于 `create_tool_calling_agent` 创建支持工具调用的智能体。 + +✅ 掌握点: +- ReAct 思维循环:思考 → 行动 → 观察 → 再思考 +- 使用 `MessagesPlaceholder("agent_scratchpad")` 记录推理过程 +- `AgentExecutor` 执行完整流程,支持 `verbose=True` 查看思考链 + +--- + +### 3. `03_sql_agent.py`(SQL 专用 Agent) +一键构建自然语言查询数据库的智能体。 + +✅ 掌握点: +- 使用 `create_sql_agent` 快速接入 SQLite 数据库 +- 自动分析表结构、生成 SQL 并执行 +- 无需手动定义工具,开箱即用 + +--- + +### 4. `04_memory_general_agent.py`(带记忆的 Agent) +将 Agent 与对话历史结合,实现多轮上下文感知。 + +✅ 掌握点: +- 在 Prompt 中加入 `MessagesPlaceholder("history")` +- 使用 `RunnableWithMessageHistory` 包装 AgentExecutor +- 实现“记住用户身份”、“持续追问”的真实对话体验 + +--- + +### 5. `05_caching.py`(缓存优化技巧) +在开发调试阶段避免重复调用 LLM,节省成本与时间。 + +✅ 掌握点: +- 使用 `set_llm_cache(InMemoryCache())` 启用缓存 +- 第一次调用远程请求,后续命中缓存秒出结果 +- 开发时开启,上线前关闭(仅用于测试) + +--- + +### 6. `06_streaming.py`(流式输出实战) +实现 AI 回复像打字机一样逐字输出,提升用户体验。 + +✅ 掌握点: +- 设置 `streaming=True` 启用流式模式 +- 添加 `callbacks=[StreamingStdOutCallbackHandler()]` 实时打印 token +- 使用 `print("AI: ", end="", flush=True)` 确保提示立即显示 + +--- + +💡 建议: +跑通所有示例后,尝试将 `get_weather` 和 `query_user_info` 组合进一个带记忆的 Agent,让 AI 能连续问:“你是谁?”、“北京天气怎么样?”、“你喜欢什么颜色?”,并记住你的回答。 \ No newline at end of file diff --git a/README.md b/README.md index 5a5698f..bd7775e 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ | | [02 LLM 基础调用](https://github.com/Annyfee/agent-craft/tree/main/02_llm_fundamentals) | [🏠](https://blog.csdn.net/2401_87328929/article/details/153735431) | LLM API 调用 · prompt · 上下文记忆 | ⭐ | | | [03 Function Calling 与工具调用](https://github.com/Annyfee/agent-craft/tree/main/03_function_calling_tools) | [🏠](https://blog.csdn.net/2401_87328929/article/details/153866573) | Function Call · 工具函数封装 | ⭐⭐ | | ⚙️ **框架篇** | [04 LangChain 基础篇](https://github.com/Annyfee/agent-craft/tree/main/04_langchain_basics) | [🏠](https://blog.csdn.net/2401_87328929/article/details/153978186) | LLM · Prompt · Chain · Memory | ⭐⭐ | -| | 05 LangChain 进阶篇 | 🚧撰写中 | Agents · 多链协作 · 缓存 | ⭐⭐⭐ | +| | 05 LangChain 进阶篇 | [🏠](https://blog.csdn.net/2401_87328929/article/details/154064397) | Agents · 多链协作 · 缓存 | ⭐⭐⭐ | | | 06 LangGraph 入门 | 🚧 | Flow · Node · Edge 控制 | ⭐⭐⭐ | | | 07 RAG 基础篇(Embedding & 向量) | 🚧 | 向量化 · 检索匹配 | ⭐⭐ | | | 08 RAG 进阶篇(检索 + 生成) | 🚧 | RAG Pipeline · QA 系统 | ⭐⭐⭐ | @@ -67,8 +67,13 @@ - **目标**:认识Langchain六大模块,学会用Langchain构建智能体。 - **内容**:LLM 调用|Prompt 设计|Chain 构建|Memory 记忆|实战练习 +### ✅ 模块 05 — LangChain 进阶篇 -> 📌 后续模块将陆续开放(LangChain、RAG、MCP、多智能体等) +- **目标**:掌握Langchain Agents的核心机制,构建能调用工具、持续思考、具备记忆的智能体。 +- **内容**:Function Calling|@tool 工具封装|ReAct 循环|Agent 构建|SQL Agent|记忆+流式|开发优化 + + +> 📌 后续模块将陆续开放(LangGraph、RAG、MCP、多智能体等) ---