v0.0.10
tools
This commit is contained in:
parent
f1cdf6dd1f
commit
eb82b1a174
2
.env
2
.env
@ -3,9 +3,11 @@
|
||||
SILICONFLOW_API_KEY = "sk-sylilrjrtxlvecwhfusjkutclmppzuzhncfcfxtekxrzyjee"
|
||||
SILICONFLOW_BASE_URL = "https://api.siliconflow.cn/v1"
|
||||
|
||||
# gemma4:e2b
|
||||
OLLAMA_API_KEY = "ollama"
|
||||
OLLAMA_BASE_URL = "http://localhost:11434/v1"
|
||||
|
||||
# MiniMax-M2.7
|
||||
MINIMAX_API_KEY = "sk-cp-wWkzvRP-BiQia-6izxvqgehEsHSz8v4_PtDJAuT3OI0s8QFcEOsxIHcQoZC2cVQTK3L09EUuu5HDArYMvKXFnf91jk8LuZ0tteS7-Wd4Lk2zDm8RqrKkrd4"
|
||||
MINIMAX_BASE_URL = "https://api.minimaxi.com/v1"
|
||||
|
||||
|
||||
17
README.md
17
README.md
@ -1,6 +1,6 @@
|
||||
# LangChain Learning
|
||||
|
||||
[](https://github.com/your-repo/langchain-learning)
|
||||
[](https://github.com/your-repo/langchain-learning)
|
||||
[](https://www.python.org/)
|
||||
[](https://www.langchain.com/)
|
||||
|
||||
@ -13,6 +13,7 @@
|
||||
- **流式响应**:实时流式输出,带来更好的使用体验
|
||||
- **Prompt 工程**:多种 Prompt 模板构建方式
|
||||
- **输出解析**:支持 JSON 等格式解析
|
||||
- **工具调用 (Tool Calling)**:支持 @tool 装饰器和 StructuredTool 定义工具
|
||||
- **Token 用量追踪**:轻松监控 API 调用消耗
|
||||
- **内存管理**:实现对话历史持久化(ConversationBufferMemory, SummaryMemory)
|
||||
- **Rich 终端界面**:支持 Markdown 渲染、多行输入等高级交互
|
||||
@ -24,7 +25,7 @@
|
||||
### 1. 安装依赖
|
||||
|
||||
```bash
|
||||
pip install langchain>=1.2.15 langchain-community>=0.4.1 langchain-siliconflow>=1.0.0 requests>=2.33.1 rich openai
|
||||
pip install langchain>=1.2.15 langchain-community>=0.4.1 langchain-siliconflow>=1.0.0 requests>=2.33.1 rich openai pydantic
|
||||
```
|
||||
|
||||
### 2. 配置环境变量
|
||||
@ -72,6 +73,13 @@ OLLAMA_API_KEY=ollama
|
||||
|------|------|------|
|
||||
| 基础 RAG | `python rag/rag_demo.py` | 基于 FAISS 向量库的检索问答系统 |
|
||||
|
||||
**工具调用示例**
|
||||
|
||||
| 示例 | 命令 | 说明 |
|
||||
|------|------|------|
|
||||
| 工具定义 | `python tools/tool_definition.py` | 演示 @tool 装饰器和 StructuredTool 定义方式 |
|
||||
| 工具调用 | `python tools/tool_demo.py` | 演示模型如何调用工具并获取结果 |
|
||||
|
||||
**Token 用量示例**
|
||||
|
||||
| 示例 | 命令 | 说明 |
|
||||
@ -113,6 +121,9 @@ langchain-learning/
|
||||
│ └── json_parser_demo.py # JSON 输出解析示例
|
||||
├── rag/
|
||||
│ └── rag_demo.py # RAG 检索增强生成示例
|
||||
├── tools/
|
||||
│ ├── tool_definition.py # 工具定义方式演示
|
||||
│ └── tool_demo.py # 工具调用完整流程演示
|
||||
├── token/
|
||||
│ └── token_demo.py # Token 用量追踪示例
|
||||
├── memory/
|
||||
@ -138,6 +149,7 @@ langchain-learning/
|
||||
|
||||
**Ollama (本地)**
|
||||
- `gemma4:26b`
|
||||
- `gemma4:e2b`
|
||||
- `deepseek-v3.1:671b-cloud`
|
||||
|
||||
## 技术栈
|
||||
@ -148,6 +160,7 @@ langchain-learning/
|
||||
| LLM 提供商 | SiliconFlow, Ollama |
|
||||
| 向量库 | FAISS |
|
||||
| 终端美化 | Rich |
|
||||
| 数据验证 | Pydantic |
|
||||
| 语言 | Python 3.11+ |
|
||||
|
||||
## 许可证
|
||||
|
||||
56
tools/tool_definition.py
Normal file
56
tools/tool_definition.py
Normal file
@ -0,0 +1,56 @@
|
||||
import sys
|
||||
|
||||
from langchain_core.tools import tool, StructuredTool
|
||||
from pydantic import BaseModel, Field
|
||||
from sqlalchemy import True_
|
||||
|
||||
|
||||
# 定义函数/tool
|
||||
|
||||
## 方式1:使用注解
|
||||
@tool
|
||||
def get_weather1(city: str) -> str:
|
||||
"""查询指定城市的最新天气信息"""
|
||||
# 通过api调用天气网站的接口,得到最新的天气信息
|
||||
return f"{city}当前的温度为18°C"
|
||||
|
||||
|
||||
class FieldInfo(BaseModel):
|
||||
city: str = Field(description="要查询的城市名称")
|
||||
|
||||
## 注解中可以通过传参覆盖原有函数的描述等信息
|
||||
@tool(
|
||||
name_or_callable="get_weather1",
|
||||
args_schema=FieldInfo,
|
||||
description="查询某个城市的天气,并返回温度信息",
|
||||
return_direct=True
|
||||
)
|
||||
def get_weather2(city: str) -> str:
|
||||
"""查询指定城市的最新天气信息"""
|
||||
# 通过api调用天气网站的接口,得到最新的天气信息
|
||||
return f"{city}当前的温度为18°C"
|
||||
|
||||
|
||||
## 方式2:
|
||||
def get_weather3(city: str) -> str:
|
||||
"""查询指定城市的最新天气信息"""
|
||||
# 通过api调用天气网站的接口,得到最新的天气信息
|
||||
return f"{city}当前的温度为18°C"
|
||||
|
||||
get_weather3_tool = StructuredTool.from_function(
|
||||
func=get_weather3,
|
||||
name="get_weather3",
|
||||
args_schema=FieldInfo,
|
||||
description="第三个返回天气的函数"
|
||||
)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
# 调用函数,并打印返回结果
|
||||
print(get_weather1("北京"))
|
||||
print(get_weather1("巴黎"))
|
||||
|
||||
print(f"name={get_weather3_tool.name}")
|
||||
print(f"args={get_weather3_tool.args}")
|
||||
print(f"description={get_weather3_tool.description}")
|
||||
print(f"return_direct={get_weather3_tool.return_direct}") # 直接返回:如果为false,就是会将返回值给到大模型,让大模型进一步加工后再返回。如果是true,则直接返回给用户。
|
||||
98
tools/tool_demo.py
Normal file
98
tools/tool_demo.py
Normal file
@ -0,0 +1,98 @@
|
||||
import sys
|
||||
|
||||
from langchain_core.messages import HumanMessage, ToolMessage
|
||||
from langchain_core.tools import tool, StructuredTool
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
import logging
|
||||
|
||||
from langchain_openai import ChatOpenAI
|
||||
import os
|
||||
import dotenv
|
||||
|
||||
|
||||
# 定义函数/tool
|
||||
|
||||
## 方式1:使用注解
|
||||
class FieldInfo(BaseModel):
|
||||
city: str = Field(description="要查询的城市名称")
|
||||
|
||||
|
||||
## 注解中可以通过传参覆盖原有函数的描述等信息
|
||||
@tool(
|
||||
name_or_callable="get_weather",
|
||||
args_schema=FieldInfo,
|
||||
description="查询某个城市的天气,并返回温度信息",
|
||||
return_direct=True
|
||||
)
|
||||
def get_weather(city: str) -> str:
|
||||
"""查询指定城市的最新天气信息"""
|
||||
# 通过api调用天气网站的接口,得到最新的天气信息
|
||||
return f"{city}当前的温度为18°C"
|
||||
|
||||
@tool
|
||||
def test(city: str) -> str:
|
||||
"""这个是一个测试函数"""
|
||||
# 通过api调用天气网站的接口,得到最新的天气信息
|
||||
return f"{city}当前的温度为18°C"
|
||||
######################################################################
|
||||
|
||||
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")
|
||||
os.environ['OPENAI_API_KEY'] = os.getenv("OLLAMA_API_KEY")
|
||||
os.environ['OPENAI_BASE_URL'] = os.getenv("OLLAMA_BASE_URL")
|
||||
# os.environ['OPENAI_API_KEY'] = os.getenv("MINIMAX_API_KEY")
|
||||
# os.environ['OPENAI_BASE_URL'] = os.getenv("MINIMAX_BASE_URL")
|
||||
|
||||
# 如果要使用函数调用,需要选择支持的模型
|
||||
# 如果不支持,会报错:Error code: 400 - {'code': 20037, 'message': 'Function call is not supported for this model.', 'data': None}
|
||||
# llm = ChatOpenAI(model="Qwen/Qwen2.5-7B-Instruct")
|
||||
llm = ChatOpenAI(model="gemma4:e2b")
|
||||
# llm = ChatOpenAI(model="MiniMax-M2.7")
|
||||
|
||||
|
||||
## 将模型与工具进行绑定
|
||||
llm_with_tools = llm.bind_tools([get_weather,test],tool_choice="auto")
|
||||
|
||||
messages = [HumanMessage(content="巴黎现在的气温是多少")]
|
||||
|
||||
## 使用哪个工具,由大模型自己选择
|
||||
response = llm_with_tools.invoke(messages)
|
||||
print(response)
|
||||
|
||||
## 模型会返回:需要调用get_weather,并且识别出来传参为 Paris,但是不会进行真正的调用
|
||||
|
||||
# 如果需要调用工具,则执行并把结果回传
|
||||
for call in getattr(response, "tool_calls", []) or []:
|
||||
# print(call)
|
||||
# {'name': 'get_weather', 'args': {'city': 'Paris'}, 'id': '019a305388b40ad0d961da5696e9fd2f', 'type': 'tool_call'}
|
||||
if call["name"] == "get_weather":
|
||||
args = call["args"] # 例如 {"city": "Paris"}
|
||||
result = get_weather.invoke(args)
|
||||
messages.append(response) # 把模型消息加入对话
|
||||
messages.append(
|
||||
ToolMessage(
|
||||
content=result,
|
||||
tool_call_id=call["id"], # 必须把这次tool调用的id对上
|
||||
)
|
||||
)
|
||||
# 5) 第二轮:把工具结果交回给模型,让它产出最终回答
|
||||
final_msg = llm.invoke(messages)
|
||||
print("FINAL:", final_msg.content)
|
||||
break
|
||||
else:
|
||||
# 模型未请求调用工具,直接给出回答
|
||||
print("FINAL(no-tool):", response.content)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user