本文主要对 Dify 中的讯飞星火平台工具 spark 进行了源码分析,该工具可根据用户的输入生成图片,由讯飞星火提供图片生成 API。通过本文学习可自行实现将第三方 API 封装为 Dify 中工具的能力。
源码位置:dify-0.6.14\api\core\tools\provider\builtin\spark
一. spark.yaml(工具供应商 yaml)
这段代码是一个配置文件,用于设置一个平台工具的认证信息。这个平台工具的名称是 "Spark",由一个名为 Onelevenvy 的作者创建。下面逐行解释这段代码的每个部分:
identity:
author: Onelevenvy
name: spark
label:
en_US: Spark
zh_Hans: 讯飞星火
pt_BR: Spark
description:
en_US: Spark Platform Toolkit
zh_Hans: 讯飞星火平台工具
pt_BR: Pacote de Ferramentas da Plataforma Spark
icon: icon.svg
tags:
- image
1.identity定义平台工具的基本信息
-
author: 工具的作者是 Onelevenvy。
-
name: 工具的名称是 "spark"。
-
label: 工具的标签在不同语言中的翻译。
- en_US: 英文标签为 "Spark"。
- zh_Hans: 简体中文标签为 "讯飞星火"。
- pt_BR: 葡萄牙语标签为 "Spark"。
-
description: 工具的描述在不同语言中的翻译。
- en_US: 英文描述为 "Spark Platform Toolkit"。
- zh_Hans: 简体中文描述为 "讯飞星火平台工具"。
- pt_BR: 葡萄牙语描述为 "Pacote de Ferramentas da Plataforma Spark"。
-
icon: 图标文件的名称是 "icon.svg"。
-
tags: 标签信息,这里仅包含一个标签 "image",表明这个工具与图像相关。
credentials_for_provider:
APPID:
type: secret-input
required: true
label:
en_US: Spark APPID
zh_Hans: APPID
pt_BR: Spark APPID
help:
en_US: Please input your APPID
zh_Hans: 请输入你的 APPID
pt_BR: Please input your APPID
placeholder:
en_US: Please input your APPID
zh_Hans: 请输入你的 APPID
pt_BR: Please input your APPID
其中,credentials_for_provider定义用于认证的必要凭证。
2.credentials_for_provider - APPID
-
type: 输入类型为 "secret-input",这意味着它是一个需要保密的输入字段。
-
required: 这个字段是必填的。
-
label: 在不同语言中的标签。
- en_US: 英文标签为 "Spark APPID"。
- zh_Hans: 简体中文标签为 "APPID"。
- pt_BR: 葡萄牙语标签为 "Spark APPID"。
-
help: 提示信息,在不同语言中的翻译。
- en_US: 英文提示为 "Please input your APPID"。
- zh_Hans: 简体中文提示为 "请输入你的 APPID"。
- pt_BR: 葡萄牙语提示为 "Please input your APPID"。
-
placeholder: 占位符信息,在不同语言中的翻译。
-
en_US: 英文占位符为 "Please input your APPID"。
-
zh_Hans: 简体中文占位符为 "请输入你的 APPID"。
-
pt_BR: 葡萄牙语占位符为 "Please input your APPID"。
APISecret:
type: secret-input
required: true
label:
en_US: Spark APISecret
zh_Hans: APISecret
pt_BR: Spark APISecret
help:
en_US: Please input your Spark APISecret
zh_Hans: 请输入你的 APISecret
pt_BR: Please input your Spark APISecret
placeholder:
en_US: Please input your Spark APISecret
zh_Hans: 请输入你的 APISecret
pt_BR: Please input your Spark APISecret
-
3.credentials_for_provider - APISecret
-
type: 输入类型为 "secret-input"。
-
required: 这个字段是必填的。
-
label: 在不同语言中的标签。
- en_US: 英文标签为 "Spark APISecret"。
- zh_Hans: 简体中文标签为 "APISecret"。
- pt_BR: 葡萄牙语标签为 "Spark APISecret"。
-
help: 提示信息,在不同语言中的翻译。
- en_US: 英文提示为 "Please input your Spark APISecret"。
- zh_Hans: 简体中文提示为 "请输入你的 APISecret"。
- pt_BR: 葡萄牙语提示为 "Please input your Spark APISecret"。
-
placeholder: 占位符信息,在不同语言中的翻译。
-
en_US: 英文占位符为 "Please input your Spark APISecret"。
-
zh_Hans: 简体中文占位符为 "请输入你的 APISecret"。
-
pt_BR: 葡萄牙语占位符为 "Please input your Spark APISecret"。
APIKey:
type: secret-input
required: true
label:
en_US: Spark APIKey
zh_Hans: APIKey
pt_BR: Spark APIKey
help:
en_US: Please input your Spark APIKey
zh_Hans: 请输入你的 APIKey
pt_BR: Please input your Spark APIKey
placeholder:
en_US: Please input your Spark APIKey
zh_Hans: 请输入你的 APIKey
pt_BR: Please input Spark APIKey
url: https://console.xfyun.cn/services
-
4.credentials_for_provider - APIKey
-
type: 输入类型为 "secret-input"。
-
required: 这个字段是必填的。
-
label: 在不同语言中的标签。
- en_US: 英文标签为 "Spark APIKey"。
- zh_Hans: 简体中文标签为 "APIKey"。
- pt_BR: 葡萄牙语标签为 "Spark APIKey"。
-
help: 提示信息,在不同语言中的翻译。
- en_US: 英文提示为 "Please input your Spark APIKey"。
- zh_Hans: 简体中文提示为 "请输入你的 APIKey"。
- pt_BR: 葡萄牙语提示为 "Please input your Spark APIKey"。
-
placeholder: 占位符信息,在不同语言中的翻译。
- en_US: 英文占位符为 "Please input your Spark APIKey"。
- zh_Hans: 简体中文占位符为 "请输入你的 APIKey"。
- pt_BR: 葡萄牙语占位符为 "Please input Spark APIKey"。
-
url: 提供了一个 URL 链接,指向用于获取或管理这些凭证的控制台页面。
总结:这段配置文件定义了一个名为 Spark 的平台工具的各种信息和认证所需的凭证。
二. spark.py(工具供应商代码)
在供应商模块下创建一个供应商类,用于实现供应商的凭据验证逻辑,如果凭据验证失败,将会抛出 ToolProviderCredentialValidationError
异常。
class SparkProvider(BuiltinToolProviderController):
def _validate_credentials(self, credentials: dict) -> None:
try:
if "APPID" not in credentials or not credentials.get("APPID"):
raise ToolProviderCredentialValidationError("APPID is required.")
if "APISecret" not in credentials or not credentials.get("APISecret"):
raise ToolProviderCredentialValidationError("APISecret is required.")
if "APIKey" not in credentials or not credentials.get("APIKey"):
raise ToolProviderCredentialValidationError("APIKey is required.")
appid = credentials.get("APPID")
apisecret = credentials.get("APISecret")
apikey = credentials.get("APIKey")
prompt = "a cute black dog"
try:
response = spark_response(prompt, appid, apikey, apisecret)
data = json.loads(response)
code = data["header"]["code"]
if code == 0:
# 0 success,
pass
else:
raise ToolProviderCredentialValidationError(
"image generate error, code:{}".format(code)
)
except Exception as e:
raise ToolProviderCredentialValidationError(
"APPID APISecret APIKey is invalid. {}".format(e)
)
except Exception as e:
raise ToolProviderCredentialValidationError(str(e))
三.spark_img_generation.yaml(工具 yaml)
1.Identity 部分
这个部分定义了工具或服务的基本身份信息。
identity:
name: spark_img_generation
author: Onelevenvy
label:
en_US: Spark Image Generation
zh_Hans: 图片生成
pt_BR: Geração de imagens Spark
icon: icon.svg
description:
en_US: Spark Image Generation
zh_Hans: 图片生成
pt_BR: Geração de imagens Spark
-
name : 工具的唯一标识符,是
spark_img_generation
。 -
author : 工具的创建者或作者,是
Onelevenvy
。 -
label: 工具在不同语言中的显示名称。
- en_US : 在英语中是
Spark Image Generation
("Spark 图像生成")。 - zh_Hans : 在简体中文中是
图片生成
(意思是"图像生成")。 - pt_BR : 在葡萄牙语(巴西)中是
Geração de imagens Spark
(意思是"Spark 图像生成")。
- en_US : 在英语中是
-
icon : 工具关联的图标,指定为
icon.svg
。 -
description: 工具的简要描述,支持多种语言。
- en_US : 在英语中描述为
Spark Image Generation
(与标签相同)。 - zh_Hans : 在简体中文中是
图片生成
(与标签相同)。 - pt_BR : 在葡萄牙语(巴西)中是
Geração de imagens Spark
(与标签相同)。
- en_US : 在英语中描述为
2.Description 部分
提供有关工具的详细信息,包括对人类用户和语言模型的描述。
description:
human:
en_US: Generate images based on user input, with image generation API
provided by Spark
zh_Hans: 根据用户的输入生成图片,由讯飞星火提供图片生成api
pt_BR: Gerar imagens com base na entrada do usuário, com API de geração
de imagem fornecida pela Spark
llm: spark_img_generation is a tool used to generate images from text
-
human: 这个子部分描述了从用户的角度如何使用这个工具。
- en_US: 在英语中,描述为"根据用户输入生成图像,使用 Spark 提供的图像生成 API"。
- zh_Hans: 在简体中文中是"根据用户的输入生成图片,由讯飞星火提供图片生成 api"。
- pt_BR: 在葡萄牙语(巴西)中是"根据用户输入生成图像,使用 Spark 提供的图像生成 API"。
-
llm: 这个子部分为语言模型提供描述。
- 说明
spark_img_generation
是一个从文本生成图像的工具。
- 说明
3.Parameters 部分
parameters:
- name: prompt
type: string
required: true
label:
en_US: Prompt
zh_Hans: 提示词
pt_BR: Prompt
human_description:
en_US: Image prompt
zh_Hans: 图像提示词
pt_BR: Image prompt
llm_description: Image prompt of spark_img_generation tooll, you should
describe the image you want to generate as a list of words as possible
as detailed
form: llm
- parameters : 这个部分定义了工具接受的参数。
- name : 参数的名称,是
prompt
。 - type : 参数的类型,是
string
(字符串)。 - required : 指示该参数是否是必需的。在这里是
true
,意味着prompt
是必需的。 - label : 参数的显示标签,支持多种语言。
- en_US : 在英语中是
Prompt
("提示词")。 - zh_Hans : 在简体中文中是
提示词
(意思是"提示")。 - pt_BR : 在葡萄牙语(巴西)中是
Prompt
(与英语相同)。
- en_US : 在英语中是
- human_description : 为人类用户提供的参数描述。
- en_US: 在英语中描述为"Image prompt"(图像提示词)。
- zh_Hans : 在简体中文中是
图像提示词
(描述图像的提示)。 - pt_BR : 在葡萄牙语(巴西)中是
Image prompt
(与英语相同)。
- llm_description : 为语言模型提供的参数描述。
- 说明
prompt
是生成图像的输入。描述应尽可能详细,以便生成所需的图像。
- 说明
- form : 指定期望的输入形式,这里是
llm
(可能指语言模型的输入)。form 表单类型,目前支持 llm、form 两种类型,分别对应 Agent 自行推理和前端填写。
- name : 参数的名称,是
四.spark_img_generation.py(工具代码)
工具的整体逻辑都在 _invoke
方法中,这个方法接收两个参数:user_id
和 tool_paramters
,分别表示用户 ID 和工具参数。
1.spark_response()方法
主要是发起 requests.post 请求,返回图像内容:
def spark_response(text, appid, apikey, apisecret):
host = "http://spark-api.cn-huabei-1.xf-yun.com/v2.1/tti"
url = assemble_ws_auth_url(
host, method="POST", api_key=apikey, api_secret=apisecret
)
content = get_body(appid, text)
response = requests.post(
url, json=content, headers={"content-type": "application/json"}
).text
return response
返回图像具体内容:
2.img_generation()方法
主要是返回图像具体的内容:
def img_generation(self, prompt):
response = spark_response(
text=prompt,
appid=self.runtime.credentials.get("APPID"),
apikey=self.runtime.credentials.get("APIKey"),
apisecret=self.runtime.credentials.get("APISecret"),
)
data = json.loads(response)
code = data["header"]["code"]
if code != 0:
return self.create_text_message(f"error: {code}, {data}")
else:
text = data["payload"]["choices"]["text"]
image_content = text[0]
image_base = image_content["content"]
json_data = {"base64_image": image_base}
return [json_data]
3._invoke()方法
对图像内容 image["base64_image"]进行 b64decode 解码,创建 create_blob_message:
def _invoke(
self,
user_id: str,
tool_parameters: dict[str, Any],
) -> Union[ToolInvokeMessage, list[ToolInvokeMessage]]:
<em>"""</em>
<em> invoke tools</em>
<em> """</em>
......
prompt = tool_parameters.get("prompt", "")
if not prompt:
return self.create_text_message("Please input prompt")
res = self.img_generation(prompt)
result = []
for image in res:
result.append(
self.create_blob_message(
blob=b64decode(image["base64_image"]),
meta={"mime_type": "image/png"},
save_as=self.VARIABLE_KEY.IMAGE.value,
)
)
return result
原始图像内容进行 b64decode 解码后的图像内容:
说明:生成的图像保存在 dify-0.6.14\api\storage\tools\095756e3-1af6-435f-bafb-82c05264f64d 目录。
参考文献
[1] 快速接入工具:https://docs.dify.ai/v/zh-hans/guides/gong-ju/quick-tool-integration
[2] 高级接入工具:https://docs.dify.ai/v/zh-hans/guides/gong-ju/advanced-tool-integration
[3] 工具配置:https://docs.dify.ai/v/zh-hans/guides/gong-ju/tool-configuration
[4] Dify 中的工具:https://z0yrmerhgi8.feishu.cn/wiki/L0WWwUllrirwNvksBMjcOCmanuh
NLP工程化(星球号)