多工具组合应用
项目需求
构建一个"多功能助手",支持以下工具:
-
计算器:数学运算
-
天气查询:查询城市天气
-
翻译工具:文本翻译
-
文本分析:分析文本情感
架构设计

完整实现代码
python
"""
多功能助手 - 完整实现
支持:计算器、天气查询、翻译、文本分析
"""
import os
import json
from typing import Literal
from dotenv import load_dotenv
from pydantic import BaseModel, Field
from langchain_openai import ChatOpenAI
from langchain_core.tools import tool
from langchain_core.messages import HumanMessage, SystemMessage, ToolMessage
load_dotenv()
# 1.模型配置
llm = ChatOpenAI(
model=os.getenv("DASHSCOPE_MODEL_NAME"),
api_key=os.getenv("DASHSCOPE_API_KEY"),
base_url=os.getenv("DASHSCOPE_BASE_URL"),
temperature=0.3,
)
# 2.工具定义
# 工具 1: 计算器
class CalculatorInput(BaseModel):
expression: str = Field(description="数学表达式,如 '2 + 3 * 4' 或 '(10 - 5) / 2'")
@tool(args_schema=CalculatorInput)
def calculator(expression: str) -> str:
"""执行数学计算。支持加减乘除和括号运算。
Args:
expression: 要计算的数学表达式
Returns:
计算结果
"""
try:
# 安全检查
allowed = set("0123456789+-*/.() ")
if not all(c in allowed for c in expression):
return "错误:包含不允许的字符"
result = eval(expression)
return f"{expression} = {result}"
except ZeroDivisionError:
return "错误:除数不能为零"
except Exception as e:
return f"计算错误:{str(e)}"
# 工具 2: 天气查询
class WeatherInput(BaseModel):
city: str = Field(description="要查询天气的城市名称,如 '北京'、'上海'")
@tool(args_schema=WeatherInput)
def get_weather(city: str) -> str:
"""查询指定城市的当前天气状况。
Args:
city: 城市名称
Returns:
天气信息,包括天气状况、温度、湿度
"""
# 模拟天气数据
weather_db = {
"北京": {"condition": "晴天", "temp": 25, "humidity": 40},
"上海": {"condition": "多云", "temp": 28, "humidity": 65},
"广州": {"condition": "小雨", "temp": 30, "humidity": 80},
"深圳": {"condition": "阴天", "temp": 29, "humidity": 70},
"杭州": {"condition": "晴天", "temp": 27, "humidity": 55},
}
if city in weather_db:
w = weather_db[city]
return f"{city}天气:{w['condition']},温度 {w['temp']}°C,湿度 {w['humidity']}%"
return f"抱歉,暂无 {city} 的天气数据"
# 工具 3: 翻译
class TranslateInput(BaseModel):
text: str = Field(description="要翻译的文本内容")
target_lang: Literal["中文", "英文", "日文"] = Field(
description="目标语言:中文、英文、日文"
)
@tool(args_schema=TranslateInput)
def translate(text: str, target_lang: str) -> str:
"""将文本翻译成目标语言。
Args:
text: 要翻译的文本
target_lang: 目标语言(中文、英文、日文)
Returns:
翻译后的文本
"""
# 这里应该调用真实的翻译 API
# 为演示目的,使用简单的模拟
translations = {
"你好": {"英文": "Hello", "日文": "こんにちは"},
"Hello": {"中文": "你好", "日文": "こんにちは"},
"谢谢": {"英文": "Thank you", "日文": "ありがとう"},
}
if text in translations and target_lang in translations[text]:
return f"翻译结果:{translations[text][target_lang]}"
return f"[模拟翻译] 将 '{text}' 翻译为{target_lang}的结果"
# 工具 4: 文本情感分析
class SentimentInput(BaseModel):
text: str = Field(description="要分析情感的文本内容")
@tool(args_schema=SentimentInput)
def analyze_sentiment(text: str) -> str:
"""分析文本的情感倾向(积极、消极或中性)。
Args:
text: 要分析的文本
Returns:
情感分析结果
"""
# 简单的关键词情感分析
positive_words = ["好", "棒", "喜欢", "开心", "优秀", "满意", "感谢", "爱"]
negative_words = ["差", "糟", "讨厌", "失望", "难过", "生气", "烦", "坏"]
pos_count = sum(1 for w in positive_words if w in text)
neg_count = sum(1 for w in negative_words if w in text)
if pos_count > neg_count:
sentiment = "积极"
confidence = min(0.9, 0.5 + pos_count * 0.1)
elif neg_count > pos_count:
sentiment = "消极"
confidence = min(0.9, 0.5 + neg_count * 0.1)
else:
sentiment = "中性"
confidence = 0.5
return f"情感分析结果:{sentiment}(置信度:{confidence:.0%})"
# 3.助手类
class MultiToolAssistant:
"""多工具助手"""
def __init__(self):
self.tools = [calculator, get_weather, translate, analyze_sentiment]
self.tool_map = {t.name: t for t in self.tools}
self.llm_with_tools = llm.bind_tools(self.tools)
self.system_prompt = """你是一个智能助手,可以使用多种工具来帮助用户:
1. calculator - 数学计算
2. get_weather - 天气查询
3. translate - 文本翻译
4. analyze_sentiment - 情感分析
请根据用户的问题,选择合适的工具来回答。如果问题不需要使用工具,直接回答即可。
回答时请使用友好、自然的语言。"""
def chat(self, query: str, verbose: bool = True) -> str:
"""处理用户查询"""
messages = [
SystemMessage(content=self.system_prompt),
HumanMessage(content=query)
]
# 第一次调用
response = self.llm_with_tools.invoke(messages)
messages.append(response)
# 检查是否需要工具
if not response.tool_calls:
return response.content
# 执行工具调用
if verbose:
print(f"\n{'=' * 40}")
print(f"[检测到 {len(response.tool_calls)} 个工具调用]")
for tc in response.tool_calls:
name = tc["name"]
args = tc["args"]
tid = tc["id"]
if verbose:
print(f" 📌 调用: {name}")
print(f" 参数: {args}")
# 执行工具
if name in self.tool_map:
result = self.tool_map[name].invoke(args)
else:
result = f"未知工具: {name}"
if verbose:
print(f" 结果: {result}")
# 添加工具结果
messages.append(ToolMessage(content=str(result), tool_call_id=tid))
if verbose:
print(f"{'=' * 40}\n")
# 最终回答
final_response = self.llm_with_tools.invoke(messages)
return final_response.content
# 主程序
def main():
assistant = MultiToolAssistant()
print("=" * 60)
print("欢迎使用多功能助手!")
print("支持功能:数学计算、天气查询、翻译、情感分析")
print("输入 'quit' 退出")
print("=" * 60)
# 预设测试用例
test_queries = [
"帮我计算一下 (100 + 50) * 2 - 30",
"北京和上海的天气怎么样?",
"把'你好'翻译成英文",
"分析一下这句话的情感:今天真是太开心了,考试成绩非常满意!",
"Python 是什么编程语言?", # 不需要工具
]
print("\n📝 运行预设测试用例:\n")
for i, query in enumerate(test_queries, 1):
print(f"\n【测试 {i}】用户: {query}")
print("-" * 40)
response = assistant.chat(query)
print(f"助手: {response}")
print()
# 交互模式
print("\n" + "=" * 60)
print("进入交互模式,请输入您的问题:\n")
while True:
try:
user_input = input("You: ").strip()
if user_input.lower() == "quit":
print("再见!")
break
if not user_input:
continue
response = assistant.chat(user_input)
print(f"Assistant: {response}\n")
except KeyboardInterrupt:
print("\n再见!")
break
if __name__ == "__main__":
main()
运行效果示例
python
============================================================
欢迎使用多功能助手!
支持功能:数学计算、天气查询、翻译、情感分析
输入 'quit' 退出
============================================================
📝 运行预设测试用例:
【测试 1】用户: 帮我计算一下 (100 + 50) * 2 - 30
----------------------------------------
========================================
[检测到 1 个工具调用]
📌 调用: calculator
参数: {'expression': '(100 + 50) * 2 - 30'}
结果: (100 + 50) * 2 - 30 = 270
========================================
助手: 计算结果是 270。具体计算过程:先算括号内 100 + 50 = 150,然后 150 × 2 = 300,最后 300 - 30 = 270。
【测试 2】用户: 北京和上海的天气怎么样?
----------------------------------------
========================================
[检测到 2 个工具调用]
📌 调用: get_weather
参数: {'city': '北京'}
结果: 北京天气:晴天,温度 25°C,湿度 40%
📌 调用: get_weather
参数: {'city': '上海'}
结果: 上海天气:多云,温度 28°C,湿度 65%
========================================
助手: 现在的天气情况如下:
- 北京:晴天,温度 25°C,湿度 40%
- 上海:多云,温度 28°C,湿度 65%
北京天气晴朗适合户外活动,上海温度稍高但天气也不错。