跳到主要内容

为模型赋能:解析 Bella OpenAPI 的 Function Call 机制

引言:为什么需要 Function Call 能力

大型语言模型(LLM)的应用已从简单对话迈向复杂工具调用场景,Function Call 能力成为构建实用 AI 应用的关键。然而,市场上的模型在这一能力上存在显著差异:OpenAI、Claude、Qwen-max 等商业模型原生支持 Function Call,而包括 DeepSeek R1 在内的许多开源模型则不具备这一能力。这种能力鸿沟给企业构建统一 AI 平台带来了挑战。通过深入分析 Bella OpenAPI 的代码实现,我们揭示其如何通过创新的模拟机制,为不支持 Function Call 的模型扩展了这一关键能力。

DeepSeek R1 的局限与行业现状

DeepSeek R1 作为一款强大的开源大语言模型,在文本生成、知识理解等方面表现出色,但它与众多开源模型一样,面临一个共同的局限:不支持原生的 Function Call 能力。这一局限使得它在工具调用、结构化输出等企业级应用场景中难以直接应用。

当前行业现状是:

  • 大部分商业模型支持完善的 Function Call
  • 部分开源模型提供有限支持
  • DeepSeek R1 等许多模型完全不支持此功能

这种不平衡状态迫使使用者要么锁定在高成本的商业模型上,要么放弃 Function Call 带来的强大能力。

代码解析:Bella OpenAPI 的模拟机制

通过分析 Bella OpenAPI 的源代码,我们可以看到其创新的 Function Call 模拟实现方式。核心机制位于 ToolCallSimulator 类和 SimulationHepler 类中:

// ToolCallSimulator.java
@Override
public CompletionResponse completion(CompletionRequest request,
String url, T property) {
if(property.isFunctionCallSimulate()) {
CompletionRequest req =
SimulationHepler.rewrite(request);
if(req != null) {
processData.setFunctionCallSimulate(true);
CompletionResponse resp = delegator.completion(req,
url, property);
try {
// 解析为 function call,替换第一个 choice
Choice choice =
SimulationHepler.parse(resp.reasoning(), resp.content());
choice.setFinish_reason(resp.finishReason());
resp.getChoices().set(0, choice);
} catch (Exception e) {
LOGGER.info(resp.content(), e);
}
return resp;
}
}
return delegator.completion(request, url, property);
}

这段代码展示了 Bella OpenAPI 的适配器模式,通过 functionCallSimulate 开关控制是否启用模拟功能。当启用时,系统会:

  • 重写原始请求(SimulationHepler.rewrite(request))
  • 发送重写后的请求给 LLM
  • 解析模型返回内容,转换为标准的 Function Call 格式

Prompt Engineering 的奥秘

模拟机制的核心在于 function_call_template.pebble 模板文件,这是一段精心设计的提示工程:

<目标>
本 prompt 的目标是为模型引入函数调用能力,但在此过程中,必须保留模型默认的回
答行为,提供详尽、全面、自然的内容,除非用户明确要求简洁回答。
</目标>

用户在跟一个 agent 进行互动,现在需要你基于`agent 基础信息`及其与用户的`互动
过程`,按照`决策要求`分析,下一步该从`候选动作集`中采取什么动作, 按照`输出格
式要求`输出结果。

...

## 候选动作集
```python
{% for func in functions %}
{{ func }}
{% endfor %}
def directly_response(type: str, content: str):
"""直接回复用户,提供完整、详尽、自然的答案,或收集必要参数信息。
...
"""
pass

这个模板通过几个关键策略实现了 Function Call 模拟:

  1. 结构化指令:明确告诉模型(包括 DeepSeek R1)如何输出 Python 函数调用格式
  2. 角色扮演:让模型扮演具有工具使用能力的 Agent
  3. 动态注入函数定义:将原始请求中的函数定义动态转换为模型可理解的 Python 定义
  4. 统一响应格式:通过严格的输出格式要求确保一致性

解析引擎:从文本到结构化调用

当 DeepSeek R1 等模型生成文本响应后,PythonFuncCallParserPythonFuncCallListener类负责将文本解析为结构化的 Function Call:

public static CompletionResponse.Choice parse(String reasoning, 
String content) throws IOException {
PythonFuncCallListener sfc = new
PythonFuncCallListener(null);
PythonFuncCallParser parser = new PythonFuncCallParser(new
StringReader(content), sfc);
parser.parse();
return sfc.getToolcalls().isEmpty()
? CompletionResponse.assistantMessageChoice(reasoning,
sfc.getBuffer().toString())
: CompletionResponse.toolcallChoice(reasoning,
sfc.getToolcalls());
}

这种解析能力使 Bella OpenAPI 能够从 DeepSeek R1 生成的文本中提取函数调用信息,并转换为标准格式,从而实现与原生支持 Function Call 的模型相同的行为。

实际效果:DeepSeek R1 的能力扩展

通过 Bella OpenAPI 的 Function Call 模拟机制,DeepSeek R1 获得了以下能力扩展:

  • 结构化输出:生成符合标准的 JSON 响应
  • 工具调用:调用外部 API、数据库查询等工具
  • 多步推理:支持通过工具调用实现复杂推理链
  • 标准化接口:与 OpenAI 支持 Function Call 的模型保持接口一致

这种扩展使 DeepSeek R1 能够在更广泛的企业应用场景中发挥作用,特别是在需要结构化输出和工具集成的场景中。

技术细节与性能考量

性能影响

Function Call 模拟机制主要带来两方面的性能影响:

  • 请求复杂度增加:需要生成更复杂的 prompt,导致 token 数增加
  • 解析开销:需要额外的解析步骤将文本转换为结构化格式

然而,对比原生 Function Call 与模拟机制,性能差异是可接受的,特别是考虑到模拟机制带来的灵活性提升。

应用价值

Bella OpenAPI 的 Function Call 模拟机制为用户提供了几个关键价值:

  • 模型选择灵活性:用户可以根据成本、性能等因素自由选择模型,无需局限于支持 Function Call 的商业模型
  • 成本优化:可以在适当场景使用 DeepSeek R1 等开源模型,降低 API 调用成本
  • 统一开发体验:无论底层使用何种模型,开发接口保持一致
  • 功能扩展:为 DeepSeek R1 等开源模型赋予了更强的应用能力

这一机制使用户能够在保持技术灵活性的同时,充分发挥 AI 的潜力,构建更智能、更实用的应用。

结语:开源 AI 的能力扩展

Bella OpenAPI 的 Function Call 模拟机制展现了开源项目的创新价值——它不仅填补了 DeepSeek R1 等开源模型的能力空缺,还为企业提供了更大的技术选择自由度。这种设计思路值得其他 AI 平台借鉴,有助于推动开源 AI 生态的发展和应用场景的扩展。

通过技术创新,Bella OpenAPI 成功地打破了 AI 能力的"鸿沟",让各类模型都能发挥最大价值,为构建更强大的 AI 应用奠定了基础。

如果您希望深入了解 Bella OpenAPI 的 Function Call 模拟机制,或者探索其在 DeepSeek R1 等模型上的应用可能,欢迎访问 GitHub 仓库或直接体验线上版本。