首页 > 教程攻略 > ai资讯 >LlamaEdge 支持 tool call!调用外部工具

LlamaEdge 支持 tool call!调用外部工具

来源:互联网 时间:2026-08-24 14:16:06

工具调用,可以说是真正第一个“LLM原生”的交互模式。它给会“思考”的大语言模型装上了一双能“动手”的手——既能获取新知识,也能执行现实世界的操作。这对于任何 agentic app 来说,都是不可或缺的核心能力。

LlamaEdge 支持 tool call!调用外部工具

好消息是,开源LLM在工具调用方面越来越给力。比如 Llama 3 8B,已经让开发者在自己的笔记本上就能实现靠谱的工具调用!也就是说,你在 Mac 上用自然语言就能指挥它干活——社区月会上的 demo 就是活生生的例子。


本文就来演示一个简单的 Python 程序,让本地 LLM 在本地计算机上运行代码、操作数据。

先决条件

按照本教程[1]先启动一个 LlamaEdge API 服务器。

第一步:装 WasmEdge[2],跑下面这行命令。

curl -sSf https://raw.githubusercontent.com/WasmEdge/WasmEdge/master/utils/install_v2.sh | bash -s -- -v 0.13.5 --ggmlbn=b3259

第二步:下载 API server 应用——一个跨平台、能跑在各种 CPU 和 GPU 上的 Wasm 程序。

curl -LO https://github.com/LlamaEdge/LlamaEdge/releases/latest/download/llama-api-server.wasm

第三步:需要一个能调用工具的开源模型。Groq 微调过的 Llama 3 8B 是个不错的选择。下载模型文件。

curl -LO https://huggingface.co/second-state/Llama-3-Groq-8B-Tool-Use-GGUF/resolve/main/Llama-3-Groq-8B-Tool-Use-Q5_K_M.gguf

然后按下面方式启动 LlamaEdge API 服务器。

wasmedge --dir .:. \
    --nn-preload default:GGML:AUTO:Llama-3-Groq-8B-Tool-Use-Q5_K_M.gguf \
    --nn-preload embedding:GGML:AUTO:nomic-embed-text-v1.5.f16.gguf \
    llama-api-server.wasm \
    --model-alias default,embedding \
    --model-name llama-3-groq-8b,nomic-embed \
    --prompt-template groq-llama3-tool,embedding \
    --batch-size 128,8192 \
    --ctx-size 8192,8192

注意哈,这里的 groq-llama3-tool 提示词模板很关键——它把用户查询和 LLM 响应(包括工具调用的 JSON 消息)整理成模型微调时要求的正确格式。

运行 demo agent

Agent app[3] 用 Python 实现,演示了 LLM 如何借助工具操作 SQL 数据库。具体来说,它启动一个内存中的 SQLite 数据库,用来存待办事项列表。

下载代码,安装依赖:

git clone https://github.com/second-state/llm_todo
cd llm_todo
pip install -r requirements.txt

设置环境变量,指向刚才启动的 API 服务器和模型名。

export OPENAI_MODEL_NAME="llama-3-groq-8b"
export OPENAI_BASE_URL="http://127.0.0.1:8080/v1"

main.py,调出命令行聊天界面。

python main.py

使用 agent

现在你可以让 LLM 执行任务了。比如,说一句:

User: 
Help me to write down it I'm going to fix a bug

LLM 能理解你需要在数据库里插入一条记录,然后以 JSON 格式返回工具调用响应。

Assistant:

{"id": 0, "name": "create_task", "arguments": {"task": "going to fix a bug"}}

Agent app(也就是 main.py)在收到 JSON 响应后,自动执行 create_task,并把结果以 Tool 角色发回。不需要你手动操作——一切自动发生在 main.py 里。执行完工具调用,SQLite 数据库就更新了。

Tool:
[{'result': 'ok'}]

LLM 拿到执行结果,然后回答:

Assistant:
I've added "going to fix a bug" to your task list. Is there anything else you'd like to do?

你可以继续对话。关于工具调用的工作原理,更多细节可以参考这篇文章[4]

代码拆解

main.py 脚本是个很好的示例,展示了工具调用应用的结构。

首先,定义一个 Tools JSON 结构,声明可用的工具。每个工具都用函数名和参数集合来描述,而 description 字段尤为重要——它解释了何时以及怎么用这个工具。LLM 就是靠这个描述来“理解”并决定是否要调用该工具的。一旦 LLM 认为需要,就会在工具调用响应里带上这些函数名。

Tools = [
    {
        "type": "function",
        "function": {
            "name": "create_task",
            "description": "Create a task",
            "parameters": {
                "type": "object",
                "properties": {
                    "task": {
                        "type": "string",
                        "description": "Task's content",
                    }
                },
            },
        },
    },
    ... ...
]

然后,eval_tools() 函数把 LLM JSON 响应里的工具函数名和参数,映射到实际要执行的 Python 函数。

def eval_tools(tools):
    result = []
    for tool in tools:
        fun = tool.function
        if fun.name == "create_task":
            arguments = json.loads(fun.arguments)
            result.append(create_task(arguments["task"]))
        ... ...
    if len(result) > 0:
        print("Tool:")
        print(result)
    return result

Python 函数按预期执行 CURD 数据库操作:

def create_task(task):
    try:
        conn.execute("INSERT INTO todo (task, status) VALUES (?, ?)", (task, "todo"))
        conn.commit()
        return {"result": "ok"}
    except Exception as e:
        return {"result": "error", "message": str(e)}

有了 JSON 和 Python 里定义好的工具调用函数,接下来看看 agent 是怎么管理对话的。用户查询通过 chat_completions 函数发送。

def chat_completions(messages):
    stream = Client.chat.completions.create(
        model=MODEL_NAME,
        messages=messages,
        tools=Tools,
        stream=True,
    )
    tool_result = handler_llm_response(messages, stream)
    if len(tool_result) > 0:
        for result in tool_result:
            messages.append({"role": "tool", "content": json.dumps(result)})
        return False
    else:
        return True

收到响应后,调用 handler_llm_response() 判断 LLM 响应是否需要工具调用。如果不需要,就直接把 LLM 的回复展示给用户。

但如果 LLM 响应里包含工具调用的 JSON 部分,handler_llm_response() 就会负责调用关联的 Python 函数来执行。每个工具调用的执行结果,会自动作为 Tool 角色的消息发回给 LLM,LLM 再根据这些结果生成新的回答。

def handler_llm_response(messages, stream):
    tools = []
    content = ""
    print("Assistant:")
    for chunk in stream:
        if len(chunk.choices) == 0:
            break
        delta = chunk.choices[0].delta
        print(delta.content, end="")
        content += delta.content
        if len(delta.tool_calls) == 0:
            pass
        else:
            if len(tools) == 0:
                tools = delta.tool_calls
            else:
                for i, tool_call in enumerate(delta.tool_calls):
                    if tools[i] == None:
                        tools[i] = tool_call
                    else:
                        argument_delta = tool_call["function"]["arguments"]
                        tools[i]["function"]["arguments"].extend(argument_delta)
    if len(tools) == 0:
        messages.append({"role": "assistant", "content": content})
    else:
        tools_json = [tool.json() for tool in tools]
        messages.append(
            {"role": "assistant", "content": content, "tool_call": tools_json}
        )
    print()
    return eval_tools(tools)

使其稳健

LLM 应用的关键挑战之一,就是响应经常不靠谱。比如:

LLM 生成不了正确的工具调用响应来回答用户查询。

碰到这种情况,可以调整每个工具调用函数的描述。LLM 是根据描述来选工具的,所以描述要跟常见的用户查询匹配才行。

LLM 出现幻觉,生成了不存在函数名或参数错误的工具调用。

Agent 应该捕获这个错误,并要求 LLM 重新生成。要是 LLM 怎么也生成不了有效的工具调用响应,agent 可以回答类似“对不起,Da ve,我恐怕办不到”之类的话[5]

LLM 为工具生成了格式错误的 JSON 结构。

处理方式同上:捕获错误,让 LLM 重试。

工具调用是 agentic LLM 应用领域的新特性,非常期待看到大家的创意!