v0.1.0
This commit is contained in:
commit
35f41e10f3
11
.gitignore
vendored
Normal file
11
.gitignore
vendored
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
# Python-generated files
|
||||||
|
__pycache__/
|
||||||
|
*.py[oc]
|
||||||
|
build/
|
||||||
|
dist/
|
||||||
|
wheels/
|
||||||
|
*.egg-info
|
||||||
|
|
||||||
|
# Virtual environments
|
||||||
|
.venv
|
||||||
|
.env
|
||||||
1
.python-version
Normal file
1
.python-version
Normal file
@ -0,0 +1 @@
|
|||||||
|
3.13
|
||||||
183
README.md
Normal file
183
README.md
Normal file
@ -0,0 +1,183 @@
|
|||||||
|
# LangChain Learning Project
|
||||||
|
|
||||||
|
> 基于 LangChain 1.0.3 的 AI Agent 学习项目,展示如何使用 MCP (Model Context Protocol) 构建智能代理
|
||||||
|
|
||||||
|
## 项目概述
|
||||||
|
|
||||||
|
本项目是一个 LangChain 学习与实践项目,演示了如何构建具有外部工具调用能力的 AI Agent。通过集成 MCP 服务器,实现了对外部服务的调用,如天气查询、数学运算、学术搜索等功能。
|
||||||
|
|
||||||
|
## 技术栈
|
||||||
|
|
||||||
|
| 技术 | 版本 | 用途 |
|
||||||
|
|------|------|------|
|
||||||
|
| **LangChain** | 1.0.3 | 核心框架 |
|
||||||
|
| **LangChain-Community** | 0.4.1 | 社区组件 |
|
||||||
|
| **LangChain-MCP-Adapters** | ≥0.1.11 | MCP 客户端 |
|
||||||
|
| **FastMCP** | ≥2.13.0 | MCP 协议实现 |
|
||||||
|
| **LangChain-Ollama** | ≥1.0.0 | Ollama 本地模型 |
|
||||||
|
| **LangGraph** | - | Agent 记忆组件 |
|
||||||
|
|
||||||
|
## 项目结构
|
||||||
|
|
||||||
|
```
|
||||||
|
langchain-learning/
|
||||||
|
├── agent/
|
||||||
|
│ ├── langchain_agent.py # MCP Agent (Ollama + weather + math)
|
||||||
|
│ └── langchain_agent_tool_mcp.py # 扩展 Agent (+ arxiv + wikipedia + 自定义工具)
|
||||||
|
├── mcp/
|
||||||
|
│ ├── math_server.py # 数学运算 MCP 服务器 (stdio)
|
||||||
|
│ └── get_weather_server.py # 天气查询 MCP 服务器 (HTTP)
|
||||||
|
├── ollama/
|
||||||
|
│ └── ollama_demo.py # Ollama 本地模型调用示例
|
||||||
|
├── main.py # 程序入口
|
||||||
|
├── pyproject.toml # 项目配置
|
||||||
|
└── .env # 环境变量 (API Keys)
|
||||||
|
```
|
||||||
|
|
||||||
|
## 功能特性
|
||||||
|
|
||||||
|
### MCP 服务器
|
||||||
|
|
||||||
|
| 服务器 | 功能 | 传输方式 | 端口 |
|
||||||
|
|--------|------|----------|------|
|
||||||
|
| `math_server` | 加法、乘法运算 | stdio | - |
|
||||||
|
| `weather_server` | 城市天气查询 | HTTP/SSE | 9000 |
|
||||||
|
|
||||||
|
### 支持的 LLM
|
||||||
|
|
||||||
|
| 模型 | 类型 | 调用方式 |
|
||||||
|
|------|------|----------|
|
||||||
|
| `gemma4:e2b` / `gemma4:26b` | Ollama 本地 | `langchain_ollama` |
|
||||||
|
| `Qwen/Qwen3-14B` | SiliconFlow 云端 | OpenAI 兼容接口 |
|
||||||
|
|
||||||
|
### 工具集成
|
||||||
|
|
||||||
|
| 来源 | 工具 |
|
||||||
|
|------|------|
|
||||||
|
| **MCP Servers** | `get_weather`, `add`, `multiply` |
|
||||||
|
| **内置 (load_tools)** | `arxiv`, `wikipedia` |
|
||||||
|
| **自定义** | `greet(name)` |
|
||||||
|
|
||||||
|
## 快速开始
|
||||||
|
|
||||||
|
### 1. 安装依赖
|
||||||
|
|
||||||
|
```bash
|
||||||
|
uv sync
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 配置环境变量
|
||||||
|
|
||||||
|
编辑 `.env` 文件:
|
||||||
|
|
||||||
|
```env
|
||||||
|
# Ollama (本地)
|
||||||
|
OLLAMA_API_KEY=ollama
|
||||||
|
OLLAMA_BASE_URL=http://localhost:11434/v1
|
||||||
|
|
||||||
|
# SiliconFlow (可选云端)
|
||||||
|
SILICONFLOW_API_KEY=your_siliconflow_key
|
||||||
|
SILICONFLOW_BASE_URL=https://api.siliconflow.cn/v1
|
||||||
|
|
||||||
|
# 天气API
|
||||||
|
WEATHER_API_KEY=your_weatherapi_key
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. 启动 MCP 服务器
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 终端 1: 启动天气服务器 (HTTP)
|
||||||
|
python mcp/get_weather_server.py
|
||||||
|
|
||||||
|
# 终端 2: 启动数学服务器 (stdio)
|
||||||
|
python mcp/math_server.py
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. 运行 Agent
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Agent 1: Ollama + MCP (weather + math)
|
||||||
|
python agent/langchain_agent.py
|
||||||
|
|
||||||
|
# Agent 2: Ollama + MCP + 内置工具 + 自定义工具
|
||||||
|
python agent/langchain_agent_tool_mcp.py
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5. Ollama 直接调用示例
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python ollama/ollama_demo.py
|
||||||
|
```
|
||||||
|
|
||||||
|
## 使用示例
|
||||||
|
|
||||||
|
```
|
||||||
|
请输入你的问题(输入exit则退出) > 北京天气怎么样
|
||||||
|
|
||||||
|
计算过程:
|
||||||
|
- 调用工具: get_weather({'city': '北京'})
|
||||||
|
- get_weather 的结果是: {"location":{"name":"北京",...},"current":{"temp_c":22.0,...}}
|
||||||
|
|
||||||
|
最终答案: 北京的天气晴朗,温度约22°C。
|
||||||
|
```
|
||||||
|
|
||||||
|
## Agent 对比
|
||||||
|
|
||||||
|
| Agent | 模型 | MCP | 内置工具 | 自定义工具 |
|
||||||
|
|-------|------|-----|----------|------------|
|
||||||
|
| `langchain_agent.py` | Ollama | ✅ weather, math | ❌ | ❌ |
|
||||||
|
| `langchain_agent_tool_mcp.py` | Ollama | ✅ weather, math | ✅ arxiv, wikipedia | ✅ greet |
|
||||||
|
|
||||||
|
## 核心代码说明
|
||||||
|
|
||||||
|
### MCP 客户端配置
|
||||||
|
|
||||||
|
```python
|
||||||
|
client = MultiServerMCPClient({
|
||||||
|
"weather": {
|
||||||
|
"url": "http://localhost:9000/mcp",
|
||||||
|
"transport": "streamable_http",
|
||||||
|
},
|
||||||
|
"math": {
|
||||||
|
"command": sys.executable, # 使用当前解释器
|
||||||
|
"args": ["./mcp/math_server.py"],
|
||||||
|
"transport": "stdio"
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### Agent 创建
|
||||||
|
|
||||||
|
```python
|
||||||
|
from langchain.agents import create_agent
|
||||||
|
from langgraph.checkpoint.memory import InMemorySaver
|
||||||
|
|
||||||
|
agent = create_agent(
|
||||||
|
model=llm,
|
||||||
|
tools=tools,
|
||||||
|
checkpointer=InMemorySaver() # 会话记忆
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
## 依赖列表
|
||||||
|
|
||||||
|
核心依赖见 `pyproject.toml`:
|
||||||
|
|
||||||
|
- `langchain >= 1.0.3`
|
||||||
|
- `langchain-community >= 0.4.1`
|
||||||
|
- `langchain-mcp-adapters >= 0.1.11`
|
||||||
|
- `langchain-ollama >= 1.0.0`
|
||||||
|
- `fastmcp >= 2.13.0.2`
|
||||||
|
- `wikipedia >= 1.4.0`
|
||||||
|
- `arxiv >= 2.2.0`
|
||||||
|
|
||||||
|
## 学习资源
|
||||||
|
|
||||||
|
- [LangChain 官方文档](https://python.langchain.com/)
|
||||||
|
- [MCP 协议规范](https://modelcontextprotocol.io/)
|
||||||
|
- [LangChain GitHub](https://github.com/langchain-ai/langchain)
|
||||||
|
- [FastMCP 文档](https://github.com/jlowin/fastmcp)
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
MIT License
|
||||||
113
agent/langchain_agent.py
Normal file
113
agent/langchain_agent.py
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
import asyncio
|
||||||
|
import logging
|
||||||
|
import sys
|
||||||
|
from langchain_openai import ChatOpenAI
|
||||||
|
from langchain_mcp_adapters.client import MultiServerMCPClient
|
||||||
|
import os
|
||||||
|
import dotenv
|
||||||
|
from langgraph.checkpoint.memory import InMemorySaver
|
||||||
|
|
||||||
|
logging.basicConfig(
|
||||||
|
level=logging.DEBUG,
|
||||||
|
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s"
|
||||||
|
)
|
||||||
|
|
||||||
|
dotenv.load_dotenv()
|
||||||
|
|
||||||
|
## 设置环境变量
|
||||||
|
os.environ['OPENAI_API_KEY'] = os.getenv("OLLAMA_API_KEY")
|
||||||
|
os.environ['OPENAI_BASE_URL'] = os.getenv("OLLAMA_BASE_URL")
|
||||||
|
|
||||||
|
# 默认的 'model_name': 'deepseek-ai/DeepSeek-V3.1',
|
||||||
|
llm = ChatOpenAI(model="gemma4:e2b")
|
||||||
|
|
||||||
|
|
||||||
|
def print_optimized_result(agent_response):
|
||||||
|
"""
|
||||||
|
解析代理响应并输出优化后的结果。
|
||||||
|
:param agent_response: 代理返回的完整响应
|
||||||
|
"""
|
||||||
|
messages = agent_response.get("messages", [])
|
||||||
|
steps = [] # 用于记录计算步骤
|
||||||
|
final_answer = None # 最终答案
|
||||||
|
|
||||||
|
for message in messages:
|
||||||
|
if hasattr(message, "additional_kwargs") and "tool_calls" in message.additional_kwargs:
|
||||||
|
# 提取工具调用信息
|
||||||
|
tool_calls = message.additional_kwargs["tool_calls"]
|
||||||
|
for tool_call in tool_calls:
|
||||||
|
tool_name = tool_call["function"]["name"]
|
||||||
|
tool_args = tool_call["function"]["arguments"]
|
||||||
|
steps.append(f"调用工具: {tool_name}({tool_args})")
|
||||||
|
elif message.type == "tool":
|
||||||
|
# 提取工具执行结果
|
||||||
|
tool_name = message.name
|
||||||
|
tool_result = message.content
|
||||||
|
steps.append(f"{tool_name} 的结果是: {tool_result}")
|
||||||
|
elif message.type == "ai":
|
||||||
|
# 提取最终答案
|
||||||
|
final_answer = message.content
|
||||||
|
|
||||||
|
# 打印优化后的结果
|
||||||
|
print("\n计算过程:")
|
||||||
|
for step in steps:
|
||||||
|
print(f"- {step}")
|
||||||
|
if final_answer:
|
||||||
|
print(f"\n最终答案: {final_answer}")
|
||||||
|
|
||||||
|
|
||||||
|
async def execute():
|
||||||
|
# 1. 创建langchain中的mcp客户端 —— uv add langchain_mcp_adapters
|
||||||
|
client = MultiServerMCPClient(
|
||||||
|
# mcp.run(transport="streamable-http", host="127.0.0.1", port=9000)
|
||||||
|
{
|
||||||
|
# 这里是定义服务端信息的,可以有多个服务端
|
||||||
|
"weather": {
|
||||||
|
"url": "http://localhost:9000/mcp",
|
||||||
|
"transport": "streamable_http",
|
||||||
|
},
|
||||||
|
"math": {
|
||||||
|
# "command": "python", # npx uvx
|
||||||
|
"command": sys.executable,
|
||||||
|
"args": ["./mcp/math_server.py"],
|
||||||
|
"transport": "stdio"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
try:
|
||||||
|
# 2. 通过客户端获取工具列表
|
||||||
|
## 这里是通过服务端获取,所以可能会有异常(比如服务端没有启动,或者网络连接有问题
|
||||||
|
tools = await client.get_tools()
|
||||||
|
|
||||||
|
# 3. 创建一个智能代理,能够完成 思考--> 行动 --> 观察 --> 思考 --> 行动 --> ... --> 最终答案
|
||||||
|
|
||||||
|
from langchain.agents import create_agent
|
||||||
|
## 创建一个带记忆和工具的agent
|
||||||
|
agent = create_agent(
|
||||||
|
model=llm,
|
||||||
|
tools=tools,
|
||||||
|
# 配置记忆后,必须增加thread_id, checkpoint_ns, checkpoint_id参数之一,用于区分会话
|
||||||
|
checkpointer=InMemorySaver()
|
||||||
|
)
|
||||||
|
|
||||||
|
while True:
|
||||||
|
user_input = input("请输入你的问题(输入exit则退出) > ")
|
||||||
|
if user_input == "exit":
|
||||||
|
print("感谢使用,再见👋🏻")
|
||||||
|
break
|
||||||
|
agent_response = await agent.ainvoke(
|
||||||
|
{"messages": [{"role": "user", "content": user_input}]},
|
||||||
|
{"configurable": {"thread_id": "1"}},
|
||||||
|
)
|
||||||
|
## agent会自己去调用 tools ,不需要我们去进行调用
|
||||||
|
print_optimized_result(agent_response)
|
||||||
|
|
||||||
|
finally:
|
||||||
|
# 资源回收
|
||||||
|
if hasattr(client, 'close'):
|
||||||
|
client.close()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
asyncio.run(execute())
|
||||||
136
agent/langchain_agent_tool_mcp.py
Normal file
136
agent/langchain_agent_tool_mcp.py
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
import asyncio
|
||||||
|
import logging
|
||||||
|
import sys
|
||||||
|
from docutils.nodes import description
|
||||||
|
from langchain_community.agent_toolkits.load_tools import load_tools
|
||||||
|
from langchain_core.tools import tool
|
||||||
|
from langchain_openai import ChatOpenAI
|
||||||
|
from langchain_mcp_adapters.client import MultiServerMCPClient
|
||||||
|
import os
|
||||||
|
import dotenv
|
||||||
|
from langgraph.checkpoint.memory import InMemorySaver
|
||||||
|
from pydantic import BaseModel, Field
|
||||||
|
|
||||||
|
logging.basicConfig(
|
||||||
|
level=logging.DEBUG,
|
||||||
|
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s"
|
||||||
|
)
|
||||||
|
|
||||||
|
dotenv.load_dotenv()
|
||||||
|
|
||||||
|
## 设置环境变量
|
||||||
|
os.environ['OPENAI_API_KEY'] = os.getenv("OLLAMA_API_KEY")
|
||||||
|
os.environ['OPENAI_BASE_URL'] = os.getenv("OLLAMA_BASE_URL")
|
||||||
|
|
||||||
|
# 默认的 'model_name': 'deepseek-ai/DeepSeek-V3.1',
|
||||||
|
llm = ChatOpenAI(model="gemma4:e2b")
|
||||||
|
|
||||||
|
|
||||||
|
def print_optimized_result(agent_response):
|
||||||
|
"""
|
||||||
|
解析代理响应并输出优化后的结果。
|
||||||
|
:param agent_response: 代理返回的完整响应
|
||||||
|
"""
|
||||||
|
messages = agent_response.get("messages", [])
|
||||||
|
steps = [] # 用于记录计算步骤
|
||||||
|
final_answer = None # 最终答案
|
||||||
|
|
||||||
|
for message in messages:
|
||||||
|
if hasattr(message, "additional_kwargs") and "tool_calls" in message.additional_kwargs:
|
||||||
|
# 提取工具调用信息
|
||||||
|
tool_calls = message.additional_kwargs["tool_calls"]
|
||||||
|
for tool_call in tool_calls:
|
||||||
|
tool_name = tool_call["function"]["name"]
|
||||||
|
tool_args = tool_call["function"]["arguments"]
|
||||||
|
steps.append(f"调用工具: {tool_name}({tool_args})")
|
||||||
|
elif message.type == "tool":
|
||||||
|
# 提取工具执行结果
|
||||||
|
tool_name = message.name
|
||||||
|
tool_result = message.content
|
||||||
|
steps.append(f"{tool_name} 的结果是: {tool_result}")
|
||||||
|
elif message.type == "ai":
|
||||||
|
# 提取最终答案
|
||||||
|
final_answer = message.content
|
||||||
|
|
||||||
|
# 打印优化后的结果
|
||||||
|
print("\n计算过程:")
|
||||||
|
for step in steps:
|
||||||
|
print(f"- {step}")
|
||||||
|
if final_answer:
|
||||||
|
print(f"\n最终答案: {final_answer}")
|
||||||
|
|
||||||
|
|
||||||
|
def greet(name: str) -> str:
|
||||||
|
"""用于打招呼的函数"""
|
||||||
|
return f"你好呀,{name}"
|
||||||
|
|
||||||
|
|
||||||
|
class greetInput(BaseModel):
|
||||||
|
name: str = Field(description="打招呼的对象")
|
||||||
|
|
||||||
|
|
||||||
|
async def execute():
|
||||||
|
# 1. 创建langchain中的mcp客户端 —— uv add langchain_mcp_adapters
|
||||||
|
client = MultiServerMCPClient(
|
||||||
|
# mcp.run(transport="streamable-http", host="127.0.0.1", port=9000)
|
||||||
|
{
|
||||||
|
# 这里是定义服务端信息的,可以有多个服务端
|
||||||
|
# 这里是定义服务端信息的,可以有多个服务端
|
||||||
|
"weather": {
|
||||||
|
"url": "http://localhost:9000/mcp",
|
||||||
|
"transport": "streamable_http",
|
||||||
|
},
|
||||||
|
"math": {
|
||||||
|
# "command": "python", # npx uvx
|
||||||
|
"command": sys.executable,
|
||||||
|
"args": ["./mcp/math_server.py"],
|
||||||
|
"transport": "stdio"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
try:
|
||||||
|
# 2. 通过客户端获取工具列表
|
||||||
|
## 这里是通过服务端获取,所以可能会有异常(比如服务端没有启动,或者网络连接有问题
|
||||||
|
tools_mcp = await client.get_tools()
|
||||||
|
|
||||||
|
tools = tools_mcp + tools_internal + [tools_custom]
|
||||||
|
# 3. 创建一个智能代理,能够完成 思考--> 行动 --> 观察 --> 思考 --> 行动 --> ... --> 最终答案
|
||||||
|
|
||||||
|
from langchain.agents import create_agent
|
||||||
|
## 创建一个带记忆和工具的agent
|
||||||
|
agent = create_agent(
|
||||||
|
model=llm,
|
||||||
|
tools=tools,
|
||||||
|
# 配置记忆后,必须增加thread_id, checkpoint_ns, checkpoint_id参数之一,用于区分会话
|
||||||
|
checkpointer=InMemorySaver()
|
||||||
|
)
|
||||||
|
|
||||||
|
while True:
|
||||||
|
user_input = input("请输入你的问题(输入exit则退出) > ")
|
||||||
|
if user_input == "exit":
|
||||||
|
print("感谢使用,再见👋🏻")
|
||||||
|
break
|
||||||
|
agent_response = await agent.ainvoke(
|
||||||
|
{"messages": [{"role": "user", "content": user_input}]},
|
||||||
|
{"configurable": {"thread_id": "1"}},
|
||||||
|
)
|
||||||
|
## agent会自己去调用 tools ,不需要我们去进行调用
|
||||||
|
print_optimized_result(agent_response)
|
||||||
|
|
||||||
|
finally:
|
||||||
|
# 资源回收
|
||||||
|
if hasattr(client, 'close'):
|
||||||
|
client.close()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
|
||||||
|
tools_internal = load_tools(["arxiv", "wikipedia"], llm=llm, allow_dangerous_tools=True)
|
||||||
|
tools_custom = tool(
|
||||||
|
name_or_callable="greet",
|
||||||
|
runnable=greet,
|
||||||
|
description="用于打招呼的函数",
|
||||||
|
args_schema=greetInput
|
||||||
|
)
|
||||||
|
asyncio.run(execute())
|
||||||
6
main.py
Normal file
6
main.py
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
def main():
|
||||||
|
print("Hello from langchain-learning-new!")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
32
mcp/get_weather_server.py
Normal file
32
mcp/get_weather_server.py
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
# uv add fastmcp
|
||||||
|
import os
|
||||||
|
import logging
|
||||||
|
import requests
|
||||||
|
from fastmcp import FastMCP
|
||||||
|
|
||||||
|
mcp = FastMCP("mcp demo")
|
||||||
|
WEATHER_API_KEY = os.getenv("WEATHER_API_KEY")
|
||||||
|
|
||||||
|
# @mcp.tool()
|
||||||
|
# async def get_weather(city: str) -> str:
|
||||||
|
# """获取传入的城市的天气信息"""
|
||||||
|
# logging.info(f"调用了查询天气服务,传入的参数为{city}")
|
||||||
|
# return f"{city}的天气很好,阳光明媚,晴空万里"
|
||||||
|
|
||||||
|
|
||||||
|
@mcp.tool()
|
||||||
|
async def get_weather(city: str) -> str:
|
||||||
|
"""获取传入的城市的天气信息"""
|
||||||
|
logging.info("The get_weather method is called: city=%s", city)
|
||||||
|
api_key = os.getenv("WEATHER_API_KEY")
|
||||||
|
# url = f"https://api.weatherapi.com/v1/current.json?key=6056d3b7245449069d0152825252910&q={city}"
|
||||||
|
url = f"https://api.weatherapi.com/v1/current.json?key={WEATHER_API_KEY}&q={city}"
|
||||||
|
response = requests.get(url, timeout=10)
|
||||||
|
response.raise_for_status()
|
||||||
|
return response.text
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
logging.info("启动一个可以通过MCP调用获取天气的服务")
|
||||||
|
mcp.run(transport="streamable-http", host="127.0.0.1", port=9000)
|
||||||
|
# mcp.run(transport="stdio", host="127.0.0.1", port=9000)
|
||||||
29
mcp/math_server.py
Normal file
29
mcp/math_server.py
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
from fastmcp import FastMCP
|
||||||
|
import logging
|
||||||
|
|
||||||
|
# 配置日志记录器
|
||||||
|
logging.basicConfig(
|
||||||
|
level=logging.INFO, # 设置日志级别为 INFO
|
||||||
|
format="%(asctime)s - %(levelname)s - %(message)s" # 日志格式
|
||||||
|
)
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
# 创建 FastMCP 实例
|
||||||
|
mcp = FastMCP("Math")
|
||||||
|
|
||||||
|
@mcp.tool()
|
||||||
|
def add(a: int, b: int) -> int:
|
||||||
|
"""Add two numbers"""
|
||||||
|
logger.info("The add method is called: a=%d, b=%d", a, b) # 记录加法调用日志
|
||||||
|
return a + b
|
||||||
|
|
||||||
|
@mcp.tool()
|
||||||
|
def multiply(a: int, b: int) -> int:
|
||||||
|
"""Multiply two numbers"""
|
||||||
|
logger.info("The multiply method is called: a=%d, b=%d", a, b) # 记录乘法调用日志
|
||||||
|
return a * b
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
logger.info("Start math server through MCP") # 记录服务启动日志
|
||||||
|
# mcp.run(transport="streamable-http",port=8081,path='/mcp') # 启动服务并使用标准输入输出通信
|
||||||
|
mcp.run(transport="stdio") # 启动服务并使用标准输入输出通信(子进程)
|
||||||
26
ollama/ollama_demo.py
Normal file
26
ollama/ollama_demo.py
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
# 配置一下解释器
|
||||||
|
# uv add langchain_ollama
|
||||||
|
|
||||||
|
from langchain_core.messages import HumanMessage
|
||||||
|
from langchain_ollama import ChatOllama
|
||||||
|
|
||||||
|
#此时调用的是本地的大模型。省略base_url、api-key
|
||||||
|
llm = ChatOllama(
|
||||||
|
model = "gemma4:26b",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# llm.invoke("你好,请介绍一下你自己!")
|
||||||
|
|
||||||
|
|
||||||
|
messages = [
|
||||||
|
HumanMessage(content="你好,请介绍一下你自己!")
|
||||||
|
]
|
||||||
|
|
||||||
|
# response = llm.invoke(messages)
|
||||||
|
# print(response.content)
|
||||||
|
|
||||||
|
chunks = []
|
||||||
|
for chunk in llm.stream(messages):
|
||||||
|
# chunks.append(chunk)
|
||||||
|
print(chunk.content, end="", flush=True)
|
||||||
21
pyproject.toml
Normal file
21
pyproject.toml
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
[project]
|
||||||
|
name = "langchain-new"
|
||||||
|
version = "0.1.0"
|
||||||
|
description = "Add your description here"
|
||||||
|
requires-python = ">=3.13"
|
||||||
|
dependencies = [
|
||||||
|
"langchain>=1.1.3",
|
||||||
|
"langchain-community>=0.4.1",
|
||||||
|
"langchain-mcp-adapters>=0.1.11",
|
||||||
|
"langchain-openai>=1.0.1",
|
||||||
|
"langchain-text-splitters>=1.0.0",
|
||||||
|
"numexpr>=2.10.2",
|
||||||
|
"wikipedia>=1.4.0",
|
||||||
|
"arxiv>=2.2.0",
|
||||||
|
"httpx>=0.28.1",
|
||||||
|
"socksio>=1.0.0",
|
||||||
|
"fastmcp>=2.13.0.2",
|
||||||
|
"langchain-ollama>=1.0.0",
|
||||||
|
"langgraph-prebuilt>=1.0.9",
|
||||||
|
"uvicorn[standard]>=0.30.0",
|
||||||
|
]
|
||||||
Loading…
Reference in New Issue
Block a user