自定义模型接入
介绍
供应商集成完成后,接下来为供应商下模型的接入,为了帮助理解整个接入过程,我们以Xinference
为例,逐步完成一个完整的供应商接入。
需要注意的是,对于自定义模型,每一个模型的接入都需要填写一个完整的供应商凭据。
而不同于预定义模型,自定义供应商接入时永远会拥有如下两个参数,不需要在供应商 yaml 中定义。
在前文中,我们已经知道了供应商无需实现validate_provider_credential
,Runtime会自行根据用户在此选择的模型类型和模型名称调用对应的模型层的validate_credentials
来进行验证。
编写供应商 yaml
我们首先要确定,接入的这个供应商支持哪些类型的模型。
当前支持模型类型如下:
llm
文本生成模型text_embedding
文本 Embedding 模型rerank
Rerank 模型speech2text
语音转文字tts
文字转语音moderation
审查
Xinference
支持LLM
、Text Embedding
和Rerank
,那么我们开始编写xinference.yaml
。
随后,我们需要思考在 Xinference 中定义一个模型需要哪些凭据
- 它支持三种不同的模型,因此,我们需要有
model_type
来指定这个模型的类型,它有三种类型,所以我们这么编写
- 每一个模型都有自己的名称
model_name
,因此需要在这里定义
- 填写 Xinference 本地部署的地址
- 每个模型都有唯一的 model_uid,因此需要在这里定义
现在,我们就完成了供应商的基础定义。
编写模型代码
然后我们以llm
类型为例,编写xinference.llm.llm.py
在 llm.py
中创建一个 Xinference LLM 类,我们取名为 XinferenceAILargeLanguageModel
(随意),继承 __base.large_language_model.LargeLanguageModel
基类,实现以下几个方法:
-
LLM 调用
实现 LLM 调用的核心方法,可同时支持流式和同步返回。
在实现时,需要注意使用两个函数来返回数据,分别用于处理同步返回和流式返回,因为Python会将函数中包含
yield
关键字的函数识别为生成器函数,返回的数据类型固定为Generator
,因此同步和流式返回需要分别实现,就像下面这样(注意下面例子使用了简化参数,实际实现时需要按照上面的参数列表进行实现): -
预计算输入 tokens
若模型未提供预计算 tokens 接口,可直接返回 0。
有时候,也许你不需要直接返回0,所以你可以使用
self._get_num_tokens_by_gpt2(text: str)
来获取预计算的tokens,这个方法位于AIModel
基类中,它会使用GPT2的Tokenizer进行计算,但是只能作为替代方法,并不完全准确。 -
模型凭据校验
与供应商凭据校验类似,这里针对单个模型进行校验。
-
模型参数 Schema
与自定义类型不同,由于没有在 yaml 文件中定义一个模型支持哪些参数,因此,我们需要动态时间模型参数的Schema。
如Xinference支持
max_tokens
temperature
top_p
这三个模型参数。但是有的供应商根据不同的模型支持不同的参数,如供应商
OpenLLM
支持top_k
,但是并不是这个供应商提供的所有模型都支持top_k
,我们这里举例 A 模型支持top_k
,B模型不支持top_k
,那么我们需要在这里动态生成模型参数的 Schema,如下所示: -
调用异常错误映射表
当模型调用异常时需要映射到 Runtime 指定的
InvokeError
类型,方便 Dify 针对不同错误做不同后续处理。Runtime Errors:
InvokeConnectionError
调用连接错误InvokeServerUnavailableError
调用服务方不可用InvokeRateLimitError
调用达到限额InvokeAuthorizationError
调用鉴权失败InvokeBadRequestError
调用传参有误
接口方法说明见:Interfaces,具体实现可参考:llm.py。