memory
This commit is contained in:
kennethcheng 2026-04-14 01:33:51 +08:00
parent 10a6a7051a
commit 434172755d
8 changed files with 322 additions and 2 deletions

View File

@ -1,6 +1,6 @@
# LangChain Learning
[![](https://img.shields.io/badge/version-0.0.4-blue.svg)](https://github.com/your-repo/langchain-learning)
[![](https://img.shields.io/badge/version-0.0.5-blue.svg)](https://github.com/your-repo/langchain-learning)
[![](https://img.shields.io/badge/python-3.11+-green.svg)](https://www.python.org/)
[![](https://img.shields.io/badge/LangChain-v1.2-orange.svg)](https://www.langchain.com/)
@ -13,6 +13,7 @@
- **Prompt 工程**:多种 Prompt 模板构建方式
- **输出解析**:支持 JSON 等格式解析
- **Token 用量追踪**:轻松监控 API 调用消耗
- **内存管理**实现对话历史持久化ConversationBufferMemory, SummaryMemory
- **实战示例**:从基础到进阶的使用模式
## 快速开始
@ -23,6 +24,8 @@
pip install langchain>=1.2.15 langchain-community>=0.4.1 langchain-siliconflow>=1.0.0 requests>=2.33.1
```
***注意:*** *如果需要完整的记忆功能和更高级的模型,你可能需要安装额外的库。*
### 2. 配置环境变量
在项目根目录创建 `.env` 文件:
@ -63,6 +66,13 @@ SILICONFLOW_BASE_URL=https://api.siliconflow.cn/v1
|------|------|------|
| Token 追踪 | `python token/token_demo.py` | 使用 get_openai_callback 追踪 token 消耗 |
**内存管理示例**
| 示例 | 命令 | 说明 |
|------|------|------|
| 基础记忆 | `python memory/memory_desc.py` | 演示不同类型的 Memory 对象。|
| 带内存聊天 | `python memory/with_memory_demo.py` | 在对话链中管理和利用聊天历史记录。 |
## 项目结构
```
@ -81,6 +91,9 @@ langchain-learning/
│ └── json_parser_demo.py # JSON 输出解析示例
├── token/
│ └── token_demo.py # Token 用量追踪示例
├── memory/ # 记忆管理模块
│ ├── memory_desc.py # 演示 Memory 对象类型
│ └── with_memory_do.py # 演示使用带内存的聊天循环
├── main.py # 入口文件
├── pyproject.toml # 项目配置
└── README.md

37
memory/memory_demo.py Normal file
View File

@ -0,0 +1,37 @@
import logging
import os
import dotenv
from langchain.chains.llm import LLMChain
from langchain.memory import ConversationBufferMemory
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_openai import ChatOpenAI
logging.basicConfig(
level=logging.DEBUG,
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s"
)
dotenv.load_dotenv()
## 设置环境变量
os.environ['OPENAI_API_KEY'] = os.getenv("SILICONFLOW_API_KEY")
os.environ['OPENAI_BASE_URL'] = os.getenv("SILICONFLOW_BASE_URL")
# 默认的 'model_name': 'deepseek-ai/DeepSeek-V3.1',
llm = ChatOpenAI(model="Qwen/Qwen3-8B")
prompt = ChatPromptTemplate.from_messages([
("system", "你是一个万能的人工智能AI"),
MessagesPlaceholder(variable_name="history"),
("human", "问题:{question}")
])
## 创建 Memory 对象
memory = ConversationBufferMemory(return_messages=True)
chain = LLMChain(prompt=prompt, memory=memory, llm=llm)
res1 = chain.invoke({"question":"我是小明"})
print(res1)
print()
res2 = chain.invoke({"question":"我是谁?"})
print(res2)

43
memory/memory_desc.py Normal file
View File

@ -0,0 +1,43 @@
import os
import dotenv
from langchain.memory import ConversationBufferMemory, ConversationTokenBufferMemory, ConversationSummaryMemory
from langchain_openai import ChatOpenAI
memory = ConversationBufferMemory()
memory.chat_memory.add_user_message("我叫小明")
memory.chat_memory.add_ai_message("噢,好的,你叫小明")
print(memory)
print(memory.memory_key)
print(memory.load_memory_variables({}))
print('---------')
memory2 = ConversationBufferMemory(memory_key="memory2")
memory2.chat_memory.add_user_message("我叫小明")
memory2.chat_memory.add_ai_message("噢,好的,你叫小明")
print(memory2)
print(memory2.memory_key)
print(memory2.load_memory_variables({}))
print('---------')
memory3 = ConversationBufferMemory(return_messages=True)
memory3.chat_memory.add_user_message("我叫小明")
memory3.chat_memory.add_ai_message("噢,好的,你叫小明")
print(memory3)
print(memory3.memory_key)
print(memory3.load_memory_variables({}))
print('---------')
dotenv.load_dotenv()
## 设置环境变量
os.environ['OPENAI_API_KEY'] = os.getenv("SILICONFLOW_API_KEY")
os.environ['OPENAI_BASE_URL'] = os.getenv("SILICONFLOW_BASE_URL")
# 默认的 'model_name': 'deepseek-ai/DeepSeek-V3.1',
llm = ChatOpenAI(model="moonshotai/Kimi-Dev-72B")
memory_test = ConversationSummaryMemory(llm=llm)
memory_test.save_context({"input": "我叫小明"}, {"output": "噢,好的,你叫小明"})
memory_test.save_context({"input": "那么你是谁呢"}, {"output": "我是一个无所不能的AI聊天助手可以帮你解答任何问题。"})
print(memory_test.load_memory_variables({}))
# {'history': '\n\nThe human introduces themselves as xiaoming. The AI confirms the name and responds. The human then asks who the AI is. The AI introduces itself as an all-powerful AI chat assistant who can answer any questions.'}

View File

@ -0,0 +1,43 @@
import logging
from langchain_core.messages import AIMessage, HumanMessage
from langchain_core.output_parsers import JsonOutputParser
from langchain_core.prompts import PromptTemplate, ChatPromptTemplate
from langchain_openai import ChatOpenAI
import os
import dotenv
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s"
)
dotenv.load_dotenv()
## 设置环境变量
os.environ['OPENAI_API_KEY'] = os.getenv("SILICONFLOW_API_KEY")
os.environ['OPENAI_BASE_URL'] = os.getenv("SILICONFLOW_BASE_URL")
# 默认的 'model_name': 'deepseek-ai/DeepSeek-V3.1',
llm = ChatOpenAI(model="Qwen/Qwen3-8B")
def chat_with_llm():
prompt_template = ChatPromptTemplate.from_messages([
("system", "你是一个人工智能助手,你是万能的"),
("human", "{question}")
])
while True:
chain = prompt_template | llm
user_input = input("请继续你的问题,如果没有问题了,输入 [quit] 结束会话:")
if user_input == "quit":
break
response = chain.invoke({"question": user_input})
print(f"AI:{response.content}")
## 将当前轮次的聊天内容ai的回答和下一轮的问题保存到prompt中带入下一次聊天。
## 这是非标准做法。
prompt_template.messages.append(AIMessage(content=response.content))
prompt_template.messages.append(HumanMessage(content=user_input))
chat_with_llm()

View File

@ -0,0 +1,56 @@
import logging
from rich.console import Console
from rich.panel import Panel
from rich.markdown import Markdown
from langchain_core.output_parsers import JsonOutputParser
from langchain_core.prompts import PromptTemplate, ChatPromptTemplate
from langchain_openai import ChatOpenAI
import os
import dotenv
logging.basicConfig(
level=logging.WARNING,
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s"
)
dotenv.load_dotenv()
## 设置环境变量
os.environ['OPENAI_API_KEY'] = os.getenv("SILICONFLOW_API_KEY")
os.environ['OPENAI_BASE_URL'] = os.getenv("SILICONFLOW_BASE_URL")
# 默认的 'model_name': 'deepseek-ai/DeepSeek-V3.1',
llm = ChatOpenAI(model="deepseek-ai/DeepSeek-R1-0528-Qwen3-8B")
system_prompt = """
你是一个由 方仔仔 开发的先进人工智能助手 木鸡鸡
你使用的模型是Pro 100.0 ProMaxUltra
你拥有128G上下文
基本原则
- 优先提供真实准确可靠的信息
- 如果信息不确定请明确说明而不是猜测或编造
- 对复杂问题进行结构化拆解逐步解释
交互风格
- 使用自然专业友好的语气
- 优先使用分点分段来提升可读性
安全与限制
- 不提供违法危险或有害行为的指导
- 不泄露或推测个人隐私与敏感信息
"""
def chat_with_llm():
prompt_template = ChatPromptTemplate.from_messages([
("system",system_prompt),
("human","{question}")
])
while True:
chain = prompt_template | llm
user_input = input()
if user_input == "quit":
break
response = chain.invoke({"question":user_input})
print(f"AI:{response.content} + /n + '-----------------'")
chat_with_llm()

View File

@ -0,0 +1,82 @@
import logging
import os
import dotenv
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
# 引入 rich 相关的库
from rich.console import Console
from rich.panel import Panel
from rich.markdown import Markdown
# 1. 消除 httpx 的烦人日志
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s"
)
logging.getLogger("httpx").setLevel(logging.WARNING)
dotenv.load_dotenv()
os.environ['OPENAI_API_KEY'] = os.getenv("SILICONFLOW_API_KEY")
os.environ['OPENAI_BASE_URL'] = os.getenv("SILICONFLOW_BASE_URL")
llm = ChatOpenAI(model="deepseek-ai/DeepSeek-R1-0528-Qwen3-8B")
system_prompt = """
你是一个由 方仔仔 开发的先进人工智能助手 木鸡鸡
你使用的模型是Pro 100.0 ProMaxUltra
你拥有128G上下文
基本原则
- 优先提供真实准确可靠的信息
- 如果信息不确定请明确说明而不是猜测或编造
- 对复杂问题进行结构化拆解逐步解释
交互风格
- 使用自然专业友好的语气
- 优先使用分点分段来提升可读性
安全与限制
- 不提供违法危险或有害行为的指导
- 不泄露或推测个人隐私与敏感信息
"""
# 初始化 rich 的控制台
console = Console()
def chat_with_llm():
prompt_template = ChatPromptTemplate.from_messages([
("system", system_prompt),
("human", "{question}")
])
# 【工程优化】:把 chain 的组装放在循环外面。
# 就像你不需要每次问问题前都重新组装一次大脑一样。
chain = prompt_template | llm
# 打印一个欢迎面板
console.print(Panel("✨ 欢迎使用 木鸡鸡 AI 助手!输入 'quit' 退出。", border_style="green"))
while True:
# 加点提示符,让输入更明显
user_input = input("\n👤 你: ")
if user_input.strip().lower() == "quit":
console.print("[dim]👋 再见![/dim]")
break
# 调用模型获取回复
response = chain.invoke({"question": user_input})
# 【核心魔法】:使用 rich 的 Panel 和 Markdown 渲染模型输出
# border_style 可以换颜色,比如 "cyan" (青色), "magenta" (洋红), "green" (绿色)
console.print(
Panel(
Markdown(response.content),
title="🤖",
border_style="cyan"
)
)
if __name__ == "__main__":
chat_with_llm()

View File

@ -9,4 +9,5 @@ dependencies = [
"langchain-community>=0.4.1",
"langchain-siliconflow>=1.0.0",
"requests>=2.33.1",
"rich>=15.0.0",
]

45
uv.lock
View File

@ -691,6 +691,7 @@ dependencies = [
{ name = "langchain-community" },
{ name = "langchain-siliconflow" },
{ name = "requests" },
{ name = "rich" },
]
[package.metadata]
@ -699,6 +700,7 @@ requires-dist = [
{ name = "langchain-community", specifier = ">=0.4.1" },
{ name = "langchain-siliconflow", specifier = ">=1.0.0" },
{ name = "requests", specifier = ">=2.33.1" },
{ name = "rich", specifier = ">=15.0.0" },
]
[[package]]
@ -817,6 +819,18 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/37/19/96250cf58070c5563446651b03bb76c2eb5afbf08e754840ab639532d8c6/langsmith-0.7.30-py3-none-any.whl", hash = "sha256:43dd9f8d290e4d406606d6cc0bd62f5d1050963f05fe0ab6ffe50acf41f2f55a", size = 372682, upload-time = "2026-04-09T21:12:00.481Z" },
]
[[package]]
name = "markdown-it-py"
version = "4.0.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "mdurl" },
]
sdist = { url = "https://files.pythonhosted.org/packages/5b/f5/4ec618ed16cc4f8fb3b701563655a69816155e79e24a17b651541804721d/markdown_it_py-4.0.0.tar.gz", hash = "sha256:cb0a2b4aa34f932c007117b194e945bd74e0ec24133ceb5bac59009cda1cb9f3", size = 73070, upload-time = "2025-08-11T12:57:52.854Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/94/54/e7d793b573f298e1c9013b8c4dade17d481164aa517d1d7148619c2cedbf/markdown_it_py-4.0.0-py3-none-any.whl", hash = "sha256:87327c59b172c5011896038353a81343b6754500a08cd7a4973bb48c6d578147", size = 87321, upload-time = "2025-08-11T12:57:51.923Z" },
]
[[package]]
name = "marshmallow"
version = "3.26.2"
@ -829,6 +843,15 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/be/2f/5108cb3ee4ba6501748c4908b908e55f42a5b66245b4cfe0c99326e1ef6e/marshmallow-3.26.2-py3-none-any.whl", hash = "sha256:013fa8a3c4c276c24d26d84ce934dc964e2aa794345a0f8c7e5a7191482c8a73", size = 50964, upload-time = "2025-12-22T06:53:51.801Z" },
]
[[package]]
name = "mdurl"
version = "0.1.2"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729, upload-time = "2022-08-14T12:40:10.846Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979, upload-time = "2022-08-14T12:40:09.779Z" },
]
[[package]]
name = "multidict"
version = "6.7.1"
@ -1403,6 +1426,15 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/00/4b/ccc026168948fec4f7555b9164c724cf4125eac006e176541483d2c959be/pydantic_settings-2.13.1-py3-none-any.whl", hash = "sha256:d56fd801823dbeae7f0975e1f8c8e25c258eb75d278ea7abb5d9cebb01b56237", size = 58929, upload-time = "2026-02-19T13:45:06.034Z" },
]
[[package]]
name = "pygments"
version = "2.20.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/c3/b2/bc9c9196916376152d655522fdcebac55e66de6603a76a02bca1b6414f6c/pygments-2.20.0.tar.gz", hash = "sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f", size = 4955991, upload-time = "2026-03-29T13:29:33.898Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl", hash = "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176", size = 1231151, upload-time = "2026-03-29T13:29:30.038Z" },
]
[[package]]
name = "python-dotenv"
version = "1.2.2"
@ -1598,6 +1630,19 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/3f/51/d4db610ef29373b879047326cbf6fa98b6c1969d6f6dc423279de2b1be2c/requests_toolbelt-1.0.0-py2.py3-none-any.whl", hash = "sha256:cccfdd665f0a24fcf4726e690f65639d272bb0637b9b92dfd91a5568ccf6bd06", size = 54481, upload-time = "2023-05-01T04:11:28.427Z" },
]
[[package]]
name = "rich"
version = "15.0.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "markdown-it-py" },
{ name = "pygments" },
]
sdist = { url = "https://files.pythonhosted.org/packages/c0/8f/0722ca900cc807c13a6a0c696dacf35430f72e0ec571c4275d2371fca3e9/rich-15.0.0.tar.gz", hash = "sha256:edd07a4824c6b40189fb7ac9bc4c52536e9780fbbfbddf6f1e2502c31b068c36", size = 230680, upload-time = "2026-04-12T08:24:00.75Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/82/3b/64d4899d73f91ba49a8c18a8ff3f0ea8f1c1d75481760df8c68ef5235bf5/rich-15.0.0-py3-none-any.whl", hash = "sha256:33bd4ef74232fb73fe9279a257718407f169c09b78a87ad3d296f548e27de0bb", size = 310654, upload-time = "2026-04-12T08:24:02.83Z" },
]
[[package]]
name = "sniffio"
version = "1.3.1"