🔧 第9期:工具调用Tool --- 让AI学会操作高炉仪表盘
专栏 :《LangChain框架在高炉炼铁智能化领域的应用》
前情回顾 :上期我们构建了高炉Agent,有了"自主决策大脑"
本期重点:Tool ------ Agent的"双手",让AI真正"动手操作"
👐 引言:大脑再好,也得有手
上期我们把 Agent 比作"有自主意识的 AI 员工"。但你想过没有------
一个员工光有大脑,没有手,能干啥?🤷
🤖 Agent (大脑)
↓ 思考:"我需要查一下当前风压数据"
↓ 决策:"还需要查一下历史趋势对比"
↓ 结论:"炉况有异常,需要报警"
↓ 但......手呢?谁来点鼠标?谁来按按钮?
😱 卡住了!
这就是 Tool(工具) 的作用------它们是 Agent 的"双手",让 AI 能真正操作外部系统!
人 = 大脑(思考) + 双手(操作)
Agent = LLM(决策) + Tool(执行)
🛠️ LangChain 中的 Tool 体系
工具的分类
Tool 类型树:
│
├── 📡 数据获取类 ------ 查参数、查数据库、查知识库
├── 🔢 计算分析类 ------ 数值计算、统计分析、公式推导
├── ✉️ 通知通讯类 ------ 发飞书、发邮件、发短信
├── 🎮 控制操作类 ------ 调整参数、下发指令
└── 🔌 外部API类 ------ 调用第三方服务
高炉场景的工具清单
| 工具 | 类型 | 作用 | Agent调用场景 |
|---|---|---|---|
get_furnace_params |
数据获取 | 查实时参数 | "看看当前炉况" |
get_param_history |
数据获取 | 查历史趋势 | "铁温最近在下降吗" |
search_kb |
数据获取 | 搜知识库 | "上次悬料怎么处理的" |
calculate_ti |
计算分析 | 算透气性指数 | "帮我算下透气性" |
send_alert |
通知通讯 | 发飞书告警 | "发现异常,通知值班" |
write_report |
数据输出 | 生成日报 | "帮我生成今天的日报" |
💻 进阶篇:从基础工具到高阶技巧
技巧1️⃣ 带参数校验的工具
python
from langchain.tools import tool
from pydantic import BaseModel, Field
# 📌 定义工具的参数模型,自动做校验
class FurnaceQueryInput(BaseModel):
"""高炉参数查询的输入校验"""
furnace_name: str = Field(
description="高炉名称,如'5号高炉'、'6号高炉'",
min_length=2, max_length=20
)
param_type: str = Field(
description="参数类别:'temperature'(温度) / 'pressure'(压力) / 'all'(全部)",
pattern="^(temperature|pressure|all)$"
)
@tool(args_schema=FurnaceQueryInput)
def query_furnace_with_filter(furnace_name: str, param_type: str) -> str:
"""按类别筛选查询高炉参数"""
all_params = {
"5号高炉": {
"temperature": {"风温": "1205°C", "铁水温度": "1490°C"},
"pressure": {"风压": "0.392MPa", "顶压": "0.22MPa"}
}
}
furnace_data = all_params.get(furnace_name, {})
if param_type == "all":
result = {}
for v in furnace_data.values():
result.update(v)
return str(result)
return str(furnace_data.get(param_type, {}))
# ✅ Agent调用时,如果参数不对会自动报错提示
技巧2️⃣ "组合式"工具
python
@tool
def comprehensive_furnace_analysis(furnace_name: str) -> str:
"""
综合高炉炉况分析:一次调用完成参数查询+关键指标计算+初步诊断
furnace_name: 高炉名称
"""
# 1. 获取参数
params = get_furnace_params_data(furnace_name) # 抽取公共逻辑
# 2. 计算复合指标
wind_volume = float(params["风量"].replace("m³/min", ""))
wind_pressure = float(params["风压"].replace("MPa", ""))
permeability = wind_volume / (wind_pressure * 10000) # 透气性指数
# 3. 初步诊断
iron_temp = float(params["铁水温度"].replace("°C", ""))
if iron_temp < 1480:
temp_status = "⚠️ 偏低"
elif iron_temp > 1520:
temp_status = "⚠️ 偏高"
else:
temp_status = "✅ 正常"
return f"""
【{furnace_name} 综合诊断】
📊 关键参数:{params}
🔢 透气性指数:{permeability:.1f}
🌡️ 铁温状态:{temp_status}
"""
技巧3️⃣ 带状态的上下文感知工具
python
from datetime import datetime
# 全局上下文(模拟)
_global_context = {
"current_shift": "甲班",
"operator": "张工",
"last_alert_time": None
}
@tool
def send_shift_alert(message: str, level: str = "info") -> str:
"""
发送班次告警/通知
message: 告警内容
level: 告警级别 (info/warning/critical)
"""
now = datetime.now()
_global_context["last_alert_time"] = now
urgency = {"info": "📋", "warning": "⚠️", "critical": "🚨"}
icon = urgency.get(level, "📋")
alert = f"""
{icon} 【{level.upper()}】{now.strftime('%H:%M:%S')}
👤 值班: {_global_context['current_shift']} - {_global_context['operator']}
📝 {message}
"""
# 真实场景这里会调用飞书/短信API
print(f"🔔 告警已发送: {alert}")
return f"告警已发送:{message}"
🏭 实战:高炉智能体完整工具集
把前面所有技巧整合,打造高炉Agent的完整工具箱 🔧
python
# 📁 bf_toolkit.py
# 高炉Agent完整工具集
from langchain.tools import tool
from langchain.agents.middleware import wrap_tool_call
from langchain.messages import ToolMessage
from typing import Optional, List
from pydantic import BaseModel, Field
import json
# ─────────── 1. 数据获取类工具 ───────────
@tool
def get_real_time_params(furnace_name: str) -> str:
"""
【高炉必用】获取高炉实时运行参数
furnace_name: 高炉名称编号,如"5号高炉"
"""
# 模拟连接SCADA系统
params = {
"5号高炉": {
"timestamp": "2025-06-05 14:30:00",
"风温": "1205°C", "风压": "0.392MPa",
"风量": "4920m³/min", "铁水温度": "1490°C",
"硅含量": "0.42%", "炉渣碱度": "1.18",
"透气性指数": "33.8", "料速": "6.3批/h",
"顶温": "185°C", "顶压": "0.22MPa"
}
}
data = params.get(furnace_name)
if not data:
return f"❌ 未找到{furnace_name}的实时数据"
return json.dumps(data, ensure_ascii=False, indent=2)
@tool
def get_historical_data(
furnace_name: str,
param_name: str,
hours: int = 24,
interval: str = "1h"
) -> str:
"""
【趋势分析】查询参数的历史变化趋势
furnace_name: 高炉名称
param_name: 参数名称
hours: 回溯小时数,默认24
interval: 数据间隔,默认1h
"""
# 模拟历史数据
import random
base_value = {
"铁水温度": 1500, "硅含量": 0.45,
"风温": 1200, "风压": 0.39
}
base = base_value.get(param_name, 100)
trend = base - hours * 0.5 # 模拟下降趋势
points = []
for i in range(min(hours, 24)):
val = trend + i * 0.3 + random.uniform(-0.5, 0.5)
points.append({"time": f"{i:02d}:00", "value": round(val, 2)})
return json.dumps({
"furnace": furnace_name,
"param": param_name,
"trend": "下降" if points[-1]["value"] < points[0]["value"] else "上升",
"data": points
}, ensure_ascii=False)
# ─────────── 2. 计算分析类工具 ───────────
@tool
def calculate_comprehensive_index(
wind_volume: float,
wind_pressure: float,
iron_temp: float,
si_content: float
) -> str:
"""
【专业计算】计算高炉综合评价指标
wind_volume: 风量 (m³/min)
wind_pressure: 风压 (MPa)
iron_temp: 铁水温度 (°C)
si_content: 硅含量 (%)
"""
# 透气性指数
ti = wind_volume / (wind_pressure * 10000) if wind_pressure > 0 else 0
# 炉热指数
heat_index = iron_temp * 0.7 + si_content * 100 * 0.3
# 综合评价
score = 0
score += 30 if 1100 <= iron_temp <= 1250 else 10
score += 30 if 0.35 <= si_content <= 0.55 else 10
score += 20 if 30 <= ti <= 38 else 5
score += 20 if 1480 <= iron_temp <= 1520 else 5
return json.dumps({
"透气性指数": round(ti, 1),
"炉热指数": round(heat_index, 1),
"综合评分": score,
"评价": "优秀" if score >= 80 else "良好" if score >= 60 else "需关注",
"计算时间": "2025-06-05 14:30:00"
}, ensure_ascii=False)
# ─────────── 3. 告警通知类工具 ───────────
@tool
def send_production_alert(
furnace_name: str,
alert_type: str,
message: str,
severity: str = "warning"
) -> str:
"""
【告警通知】发送生产告警通知到中控室
furnace_name: 高炉名称
alert_type: 告警类型 (temperature/pressure/status)
message: 告警内容
severity: 严重级别 (info/warning/critical)
"""
alert_record = {
"timestamp": "2025-06-05 14:30:00",
"furnace": furnace_name,
"type": alert_type,
"severity": severity,
"message": message,
"status": "已发送"
}
# 模拟发送通知
icons = {"info": "📋", "warning": "⚠️", "critical": "🚨"}
print(f"{icons.get(severity, '📋')} 已向{furnace_name}中控室发送告警")
return json.dumps(alert_record, ensure_ascii=False)
# ─────────── 4. 工具错误处理 ───────────
@wrap_tool_call
def bf_tool_middleware(request, handler):
"""高炉工具的全局错误处理中间件"""
try:
result = handler(request)
return result
except ValueError as e:
return ToolMessage(
content=f"参数错误: {str(e)},请检查输入参数格式",
tool_call_id=request.tool_call["id"]
)
except Exception as e:
return ToolMessage(
content=f"工具执行异常: {str(e)},请稍后重试或联系系统管理员",
tool_call_id=request.tool_call["id"]
)
# ─────────── 5. 构建带完整工具集的Agent ───────────
def build_full_agent():
"""构建带完整工具集的高炉Agent"""
from langchain.agents import create_agent
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(
model="doubao-seed-2-0-lite-260215",
temperature=0.2,
timeout=600
)
all_tools = [
get_real_time_params,
get_historical_data,
calculate_comprehensive_index,
send_production_alert
]
agent = create_agent(
model=llm,
system_prompt="""🏭 你是高炉炼铁智能体,拥有完整的高炉操作工具集。
【可用工具及使用场景】
1. get_real_time_params - 查实时参数(任何时候先查数据)
2. get_historical_data - 查历史趋势(分析问题时使用)
3. calculate_comprehensive_index - 计算综合评价指标
4. send_production_alert - 发送告警通知(发现异常时使用)
【工作流程】
1️⃣ 先获取实时数据
2️⃣ 如有需要查询历史趋势
3️⃣ 计算综合评价指标
4️⃣ 给出分析结论和建议
5️⃣ 如有异常及时发送告警
【安全规则】
- 告警需确认数据准确性后再发送
- critical级别告警必须附带数据依据""",
tools=all_tools,
middleware=[bf_tool_middleware]
)
return agent
# ─────────── 运行测试 ───────────
if __name__ == "__main__":
agent = build_full_agent()
# 测试:完整的炉况分析+告警
result = agent.invoke({
"messages": [{
"role": "user",
"content": "检查一下5号高炉炉况,铁水温度1490°C,硅含量0.38%,"
"风温1205°C,风压0.392MPa,风量4920m³/min。"
"帮我分析并给出建议,如果异常就发告警。"
}]
})
print(result["messages"][-1].content)
⚡ Tool 开发黄金法则
法则1:单一职责
python
# ❌ 错误:一个工具干所有事
@tool
def do_everything(data: str) -> str: ...
# ✅ 正确:每个工具只干一件事
@tool
def get_temperature(furnace: str) -> str: ... # 只查温度
@tool
def get_pressure(furnace: str) -> str: ... # 只查压力
法则2:详细的工具描述
python
# ❌ 抽象描述
@tool
def get_data(name: str) -> str:
"""获取数据"""
...
# ✅ 具体描述(模型需要靠描述决定是否调用!)
@tool
def get_furnace_params(name: str) -> str:
"""
当用户需要查询高炉的实时运行参数时使用此工具。
参数包括:风温、风压、风量、铁水温度、硅含量等。
适用于:判断炉况、查看指标、日常巡检。
name参数为高炉编号,如"5号高炉"。
"""
...
法则3:防呆设计
python
@tool
def query_furnace(furnace_name: str) -> str:
"""查询高炉参数"""
# 自动容错
valid_names = {"5号高炉", "5#高炉", "BF-5", "5号炉"}
if furnace_name in valid_names:
furnace_name = "5号高炉" # 统一名称
# ...
📊 本期小结
| 知识点 | 一句话总结 |
|---|---|
| Tool是什么 | Agent的"双手",让AI能操作外部系统 |
| 参数校验 | 用 Pydantic 做输入校验,防止"乱传参" |
| 组合工具 | 一次调用完成多步操作 |
| 错误处理 | 用中间件统一处理工具异常 |
| 开发法则 | 单一职责、详细描述、防呆设计 |
核心心法:
Tool 是 Agent 能力的边界------Agent 再聪明,也只能做 Tool 允许它做的事。把工具设计得"好用、可靠、安全",Agent 才能发挥最大价值!🎯
📌 下期预告
第10期:《多模态应用:看图识炉,视频监控高炉状态》 👁️
到目前为止,我们的AI只处理"文字"------你问它答,全是文本。
但高炉现场有大量的图像和视频数据:
- 🏭 炉顶红外热像图
- 🔥 风口摄像头画面
- 📷 铁口出铁监控
- 🖼️ 炉壳表面温度扫描
如果用文字描述要写1000字,一张图只需要1秒钟!
下一期,我们进入 多模态世界------让AI不仅能"读文字",还能"看图像"!从此你的高炉AI长了一双"火眼金睛"!👀🔥
🌟 距离完结还有6期!收藏追更不迷路~
作者:高炉炼铁智能化技术研究者,专注钢铁冶金与人工智能 交叉领域。
👍 如果觉得有帮助,请点赞、收藏、转发!
版权归作者所有,未经许可请勿抄袭,套用,商用(或其它具有利益性行为) 。
🔔 关注专栏,不错过后续精彩内容!