兄弟们,我又来了。前两天发了个帖子《 MCP 到底是个什么鬼?》,没想到对大家有点小帮助,非常开心。
用 LLM 的时候,工具调用确实是一个很烦的事情(它不难,就是很繁琐),要么你在某个框架里面,把你的工具封装成 MCP 服务,要么你在某个框架里面用它的机制包装(比如加一个装饰器 @tool ),五花八门。
有没有简单一点的办法呢?有的,比如最近的 lang 家的 deepagents 里面的方式就已经接近优雅了,它可以让你直接使用自己写的函数,函数(工具)本身你想怎么写怎么写,但是,他又搞了个 middleware 的 tool ,看着又很反直觉了,又得学怎么搞,本来挺清爽的,又搞复杂了。
好麻烦,不就是给 LLM 传工具么?为什么来来回回搞得这么复杂呢?有必要么?
于是,我前两天更新了一下我的库 👉👉👉:chak ( https://github.com/zhixiangxue/chak-ai ),就干一件事情:让你自己写的函数、对象,都能传给 LLM ,让它当工具用,而你不需要写任何额外的东西,连 @tool 这样的装饰器都不需要,就像这样:
# 🚩🚩🚩 这个函数你该怎么写就怎么写,不需要很麻烦的封装成什么 MCP Server ,不需要加装饰器,不需要任何植入
def get_weather(city: str) -> str:
"""查询城市天气"""
return requests.get(f'xxxx.com?city={city}').text
conv = chak.Conversation("openai/gpt-4o", tools=[get_weather]) # ⬅️ 直接把函数传进来就行了
response = conv.send("北京天气怎么样?")
或者这样:
from pydantic import BaseModel, Field
class UserInput(BaseModel):
name: str = Field(description="User's full name")
email: str = Field(description="User's email address")
age: int = Field(description="User's age")
class UserOutput(BaseModel):
id: int
name: str
status: str = "active"
# 🚩🚩🚩 你的工具的输入输出只要是可以序列化的就行,不必是简单类型,也不需要装饰任何东西
def create_user(user: UserInput) -> UserOutput:
"""Create a new user"""
return UserOutput(id=123, name=user.name, status="active")
conv = chak.Conversation(
"openai/gpt-4o",
tools=[create_user] # ⬅️ 直接传进来
)
response = await conv.asend("Create a user: John Doe, [email protected], 30 years old")
如果你喜欢把工具封装到一个类里面(这很常见对吧),你传给 LLM 一个对象也是可以的,Chak 会帮你保持对象的状态,调用完成后,你的对象甚至是带有状态更新的,相当于你可以喂给 LLM 一个你的工作流,而这个工作流就是一个普通的对象,像这样:
# 定义一个购物车
class ShoppingCart:
def __init__(self):
self.items = []
self.discount = 0
def add_item(self, name: str, price: float, quantity: int = 1):
"""Add item to cart"""
self.items.append({"name": name, "price": price, "quantity": quantity})
def apply_discount(self, percent: float):
"""Apply discount percentage"""
self.discount = percent
def get_total(self) -> float:
"""Calculate total price"""
subtotal = sum(item["price"] * item["quantity"] for item in self.items)
return subtotal * (1 - self.discount / 100)
cart = ShoppingCart()
conv = chak.Conversation(
"openai/gpt-4o",
tools=[cart] # ⬅️ 直接把这个对象作为工具
)
# 让 LLM 帮你在这个购物车里面做一些操作
response = await conv.asend(
"Add 2 iPhones at $999 each, then apply 10% discount and tell me the total"
)
# 🚩🚩🚩 LLM 折腾完了之后,你的购物车里面的数据就更新了,你都不需要解析什么 LLM 的输入(因为很多时候 LLM 输出的 Json 未必准确,有各种乌七八糟的问题),chak 自动帮你把这事情干完了
print(cart.items) # [{'name': 'iPhone', 'price': 999, 'quantity': 2}]
print(cart.discount) # 10
print(cart.get_total()) # 1798.2
所以,“工具调用非得用 MCP 、学 MCP 吗?” —— 其实大可不必(当然 Chak 也是支持 MCP 的,用起来也非常简单)
让 LLM 可以调用工具,就应该这么简单才丝滑,对吧...
工具调用本应该是助力 LLM 变得更强的,现在很多时候成了开发者的负担。如果你也烦透了这事,真心可以试试 chak:它把这些破事都打包了,你只管写业务代码,非常轻量级,依赖非常少。
项目地址👉👉👉: https://github.com/zhixiangxue/chak-ai
各位帮忙使用一下,好用的话帮我点个⭐啊,随时提 bug 、issue ,感谢~