为什么需要接口 Link to heading
随着项目规模不断的增加,越来越多的第三方包,库需要我们去适配,同时需要去考虑可扩展性,可替换性,可替换尤为重要因为这样才能在不同的提供商方便切换,比较典型的例子有:
- 计算机硬件驱动,同样的功能比如网络,声音,我们可以用不同的网卡,麦克风和音响
- 大模型提供商,可以在同一服务使用不同的大模型,比如
Openclaw可以切换不同的模型 - 数据库选型,都是增删改查,但是我们可以使用不同的数据库去切换
但是,不同的网卡,音响或麦克风他们的厂家都不一致,他们的内部运作方式肯定也不一样,各个大模型(Qwen, Chatgpt, Claude)他们的模型的输入输出的格式都有出入,我们该如何去兼容所有厂商呢?
答案是: 给所有外部提供商提供统一的接口,不用担心外部具体的实现,只关心出入的标准
对于大模型,程序内部我们只需要一个可以返回内容的函数
def chat(user_input: str) -> reply: str:
...
return reply
不同的大模型提供商,我们可以为他们写一个同样的 chat 函数,并且函数参数和返回值都高度保持一致(这有点像函数的重载),这样我们的业务层就只需要调用 chat 函数,不需要关注内部实现,然后在函数内部就去适配,去转换输入输出类型
# 将自定义的 LLMTool 转换成 OpenAi 可接受的格式
def _to_openai_tools(
self, tools: list[LLMTool]
) -> list[ChatCompletionToolUnionParam]:
openai_tools: list[ChatCompletionToolUnionParam] = []
for tool in tools:
function_def: FunctionDefinition = {
"name": tool.name,
"description": tool.description,
"parameters": tool.input_schema,
}
openai_tool: ChatCompletionFunctionToolParam = {
"type": "function",
"function": function_def,
}
openai_tools.append(openai_tool)
return openai_tools