执行器最佳实践
1. 背景
在大模型实时互动产品中,有很多特色功能,例如Function Call。有时客户希望在这些功能中,通过HTTP请求查询业务数据,或检索知识库,并让操作的执行结果能够反馈到系统的功能模块、或者说LLM中。
2. 执行器
2.1 执行器概念
大模型实时互动产品定义了执行器概念,用于在系统的部分模块中调用预先定义的资源,目的是让系统能够与外部服务、内部知识库进行交互,查询实时数据或执行动作(例如网页搜索、数据库查询或内容处理),并在系统内部使用执行结果,从而实现高度自定义的业务能力。
2.2 执行器分类
现阶段支持RAG执行器和HTTP执行器两种类型,后续会扩展其它执行器。
2.3 执行器表达式和使用方式
系统支持在角色Prompt、Function描述中通过表达式形式,来引用环境变量或使用执行器。执行器表达式包含3个部分:
- 系统执行器类型名称,目前支持
sys_rag和sys_http。 - 执行器资源ID,由客户定义,可理解为要执行的目标方法名。
- 执行器参数,在部分类别的执行器中,支持传入执行动作所需的输入参数。
执行器表达式格式如下:
1{{系统执行器类型名称.执行器资源ID()}}
3. RAG执行器
RAG执行器,可用于在角色对话、Function Call参数提取功能中,根据用户query检索系统内置的轻量级知识库,并将知识库检索内容注入到对应prompt,用于控制角色对话效果、Function Call参数提取效果。
使用RAG执行器功能,一般需要经过如下几步:
- 在控制台创建知识库并上传文档;
- 定义RAG资源池,在资源池中声明要检索的知识库ID、检索策略等;
- 在角色Prompt,或Function描述、Function参数描述中编写执行器表达式,以及如何使用执行结果的规则。
3.1 知识库建立
目前,RAG执行器只支持系统内置的轻量级知识库,不支持第三方知识库。
需要客户在控制台提前创建好知识库并上传文档。上传文档的要求及创建知识库的流程,请参考知识库使用最佳实践中3.1.1 文档要求和3.2 控制台方式接入小节。
3.2 定义RAG资源池
定义RAG资源池后,可以在系统多个模块中使用资源池中的资源,不同模块之间也可以复用同一个资源。
3.2.1 RagCfg数据结构
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| id | String | 是 | 执行器唯一ID,prompt表达式中通过sys_rag.<id>()调用执行器 |
| kbIds | String[] | 是 | 执行器检索的知识库ID列表,支持配置多个kbId |
| recall | Object | 否 | 召回配置 |
| +type | String | 否 | 检索类型,取值hybrid表示混合检索 |
| +topK | Integer | 否 | 控制召回阶段返回得分最高的k个元素 |
| +rerank | Object | 否 | 重排序配置 |
| +enable | Boolean | 否 | 是否开启重排序 |
| +topK | Integer | 否 | 控制重排序阶段返回得分最高的k个元素,需小于recall.topK |
3.2.2 配置方式
通过服务端API的创建大模型互动实例(互动智能体)接口,在config字段中增加ragCfgs字段,即可定义RAG资源池。
config数据结构(以下仅列出RAG资源池字段):
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| ragCfgs | RagCfg[] | 否 | RAG执行器定义列表 |
配置示例如下:
1{
2 "config": "{\"ragCfgs\": [{...},{...}]}"
3}
3.2.3 RAG资源池示例
1{
2 "ragCfgs": [
3 {
4 "id": "answerRag",
5 "kbIds": ["kb1"]
6 },
7 {
8 "id": "func1Rag",
9 "kbIds": ["kb2"]
10 },
11 {
12 "id": "func2Rag",
13 "kbIds": ["kb3","kb4"],
14 "recall": {"topK": 1}
15 }
16 ]
17}
3.3 使用RAG执行器
3.3.1 RAG执行器表达式
RAG执行器名称为:sys_rag。
(1)基础用法 系统默认使用当前对话的用户query作为检索知识库的query,基础用法如下:
1{{sys_rag.执行器资源ID()}}
(2)高级用法(传入参数) 系统还支持使用固定的query检索知识库,需在表达式括号内传入参数,格式如下:
1{{sys_rag.执行器资源ID(query="参数取值")}}
3.3.2 支持模块
系统支持在如下模块中使用RAG执行器:
- 角色模块,可以在角色Prompt中使用RAG执行器表达式。
- Function Call模块,可以在Function的描述、以及参数的描述中使用RAG执行器表达式。
3.3.3 使用示例
如下是在历史老师角色Prompt中,使用RAG执行器基础用法和高级用法检索知识库的示例:
1## 角色设定
2你是一名知识渊博、耐心友善的历史老师。
3
4## 任务
5回答学生提出的历史问题,帮助学生理解历史事件、人物和时代背景。
6
7## 回答原则
81. 优先结合“相关历史知识”回答学生的问题。
92. “近代史概要”仅在与问题相关时作为背景补充。
103. 围绕学生的问题回答,不主动扩展无关内容。
114. 不机械复述知识库,应整理后用通俗易懂的方式讲解。
125. 不编造历史事实;存在争议时,客观说明不同观点。
13
14## 回答要求
15语言简洁、生动,适合学生理解。根据问题需要说明事件经过、原因、背景或影响。
16
17## 知识库检索结果
18### 相关历史知识
19{{sys_rag.answerRag()}}
20
21### 近代史概要
22{{sys_rag.answerRag(query="中国近代史概要")}}
3.3.4 使用建议
在Function Call等相对复杂的功能中,模型需要理解Function的能力并提取参数,上下文过长会影响参数提取效果。建议在Function Call中使用RAG执行器时,将recall.topK配置为1,避免引入过多上下文。
在角色对话场景中,一般无需配置recall和rerank;如果配置的话,recall.topK建议不要大于3。
3.4 知识库意图路由和RAG执行器对比
3.4.1 知识库意图路由
控制台/接口中的知识库意图路由功能,需要客户先配置意图路由,只有意图命中后,才会触发知识库检索和模型总结回答。
优点:
- 延迟低;
- 由大模型判断意图,避免召回无关知识内容而污染对话;
- 知识库总结回复规则已内置,无需客户关注。
缺点:
- 需要配置意图路由。如果意图不命中,无法检索知识库。
备注:
- 知识库意图路由,优先级高于Function Call,且不区分用户query是闲聊还是动作类。因此,当同时使用知识库意图路由和Function Call时,需要注意两者的意图路由不能有冲突。
3.4.2 RAG执行器
RAG执行器不仅可以用在角色对话功能上,还可以用在Function Call等模块;并且客户可以通过执行器表达式,自行编写知识库检索结果的使用规则。
优点:
- 高度自定义,客户可自行编写知识库结果使用规则;
- 可以用在Function Call等模块;
- 无需配置意图路由。
缺点:
- 执行器在实际使用时才会触发,延迟相对偏高;
- 默认检索可能会导致无关知识影响对话效果。
备注:
- RAG执行器只对配置了执行器表达式的模块生效。如果在角色Prompt中配置RAG执行器,则只有在闲聊时才会触发执行器检索;命中实搜、视觉等模块时,不会触发知识库检索,因此不会影响这些模块的回复效果;
- 如果产品形态较为单一、功能范围较小,对话功能集中于知识库问答,则建议通过RAG执行器实现默认检索。
4. HTTP执行器
HTTP执行器,可用于在角色对话、Function Call参数提取功能中,依据执行器和表达式配置,携带相关参数请求业务HTTP服务,并获取HTTP响应、查询业务数据,支持将响应体的字段回填到Function参数,或将响应体中的文本部分(_text)注入到响应prompt中控制角色对话效果。
使用HTTP执行器功能,一般需要经过如下几步:
- 准备可访问的业务HTTP服务,明确请求方法、URL、请求头、入参和响应字段;
- 定义HTTP资源池,在资源池中声明要调用的HTTP服务;
- 在Function描述、Function参数描述中编写HTTP执行器表达式,使用前一步定义的HTTP执行器。
4.1 业务HTTP服务
目前,HTTP执行器支持调用任意遵循RESTful规范的业务HTTP服务,用于在对话中请求业务数据,并将响应结果回填到Function Call参数或注入到Prompt中。
需要客户提前准备可访问的HTTP服务,并明确:
- 请求方法(method)和请求URL(url);
- 请求头(headers),如鉴权信息;
- 请求入参,包括常量入参和动态入参,动态入参目前仅支持引用Function Call参数取值;
- 响应字段,返回JSON格式数据。
4.2 定义HTTP资源池
定义HTTP资源池后,可以在Function Call模块中使用资源池中的资源,不同模块之间也可以复用同一个资源。
4.2.1 HttpCfg数据结构
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| id | String | 是 | 执行器唯一ID,prompt表达式中通过sys_http.<id>()调用执行器 |
| method | String | 是 | HTTP请求方法,如GET、POST |
| url | String | 是 | 请求URL,可携带参数 |
| headers | Object | 否 | 请求头,可用于携带鉴权信息 |
| presetInputs | Map | 否 | 常量入参,创建智能体时直接给定。Map的key只支持String类型,value支持String/Number/Boolean类型 |
| inputs | Input[] | 否 | 动态入参声明,在Function Call功能中,支持引用Function Call参数。 - 为空数组时,表示无动态入参; - 为null时,Function Call模块中支持复用Function的参数定义。 |
| +name | String | 是 | 入参名称 |
| +type | String | 否 | 参数类型,支持取值:String/Number/Boolean |
| +required | Boolean | 否 | 是否必填,默认false;required=true时需等待该参数就绪后才触发HTTP请求 |
4.2.2 配置方式
通过服务端API的创建大模型互动实例(互动智能体)接口,在config字段中增加httpCfgs字段,即可定义HTTP资源池。
config数据结构(以下仅列出HTTP资源池字段):
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| httpCfgs | HttpCfg[] | 否 | HTTP执行器定义列表 |
配置示例如下:
1{
2 "config": "{\"httpCfgs\": [{...},{...}]}"
3}
4.3 使用HTTP执行器
4.3.1 HTTP执行器表达式
HTTP执行器名称为:sys_http。
(1)基础用法 基础用法中,只需要配置好执行器资源ID,系统会获取对应的HttpCfg、触发http请求,并自动将Function定义中已提取的参数及其取值传递给业务HTTP服务:
1{{sys_http.执行器资源ID()}}
4.3.2 支持模块
目前,HTTP执行器仅支持在Function Call模块中使用,后续会扩展支持角色等模块。
- Function Call模块,可以在Function的描述、以及参数的描述中使用HTTP执行器表达式。
4.4 HTTP执行器规则
4.4.1 HTTP请求体组装
4.4.1.1 请求体内容
大模型互动服务向业务HTTP服务发送HTTP请求时,会按照HttpCfg中的method、url发起请求,并携带headers和请求体。其中请求体包含3部分:
- presetInputs常量入参;
- inputs动态入参,在Function Call功能中,会默认引用Function定义的所有参数;
- 系统内部自动添加的参数,用于携带必要的上下文和请求ID,均以
_开头,例如_query和_requestId。
4.4.1.2 inputs动态入参
inputs用于声明要携带的动态入参,参数取值可以引用系统中的环境变量,暂时只支持在Function Call功能中引用Function中参数。
在Function Call功能中,还为HTTP执行器内置了一个规则:
inputs为null时,可以复用Function的参数定义,并且自动引用同名参数的取值。
具体复用规则如下:
- 复用参数名称;
- 复用参数类型;
- 复用参数是否必填。
也就是说,在Function Call功能中使用HTTP执行器时,只有当HTTP执行器的必填参数和Function不一致时,才需要在inputs声明必填参数,其它时候无需声明inputs字段。
4.4.2 HTTP响应体处理
4.4.2.1 执行器表达式替换
业务HTTP服务在收到http请求后,可以在响应体中返回字符串类型的_text字段,系统会使用该字段替换HTTP执行器表达式,作为prompt的一部分,影响Function Call参数提取、角色对话效果等。
4.4.2.2 Function Call参数回填
业务HTTP服务在响应时,除了可以返回_text字段,还可以在响应体中携带其它自定义的字段。
在Function Call功能中,系统会自动将字段取值回填到Function定义的同名参数中。
4.4.3 执行器触发时机
与RAG执行器类似,功能模块会在请求大模型之前,解析prompt中的HTTP执行器表达式,并触发HTTP执行器、处理执行器执行结果,替换表达式后再继续大模型请求。
对于HTTP执行器,存在一个特殊点:解析表达式后,并不意味着一定会触发HTTP请求,还需要满足两个额外的要求:
- HTTP执行器必填参数都已就绪;
- HTTP执行器必填参数取值发生了变化。
另外,在Function Call功能中,当Function定义的所有必填参数都补齐后,系统也会额外请求一次业务HTTP服务,用于回填Function参数。
4.5 Function Call使用HTTP执行器示例
4.5.1 场景说明和Function定义
在快递查询场景中,用户希望查询快递的实时物流状态。物流信息存储在业务侧,系统无法直接从对话中获取,需要通过HTTP执行器请求业务HTTP服务,并将响应结果回填到Function Call参数。
(1)定义Function Call:expressTrack,参数如下:
trackingNo:快递单号(必填,从用户query中提取);status:物流状态(由HTTP执行器回填);location:包裹当前位置(由HTTP执行器回填);estimatedDelivery:预计送达时间(由HTTP执行器回填)。
(2)在Function描述中使用基础表达式绑定HTTP执行器:
- Function描述示例中“# 物流信息”是便于大模型理解注入内容(_text)的说明,可自行调整描述或省略。如果只使用回填参数模式,可省略该描述。
1# 功能
2查询快递的实时物流状态。
3
4# 物流信息
5{{sys_http.expressTrackHttp()}}
4.5.2 HTTP执行器定义
在config字段的httpCfgs中声明expressTrackHttp执行器:
- 在
presetInputs中,配置了userId字段,用于传递业务信息:用户ID。 - 未声明
inputs字段,意味该HTTP执行器和Function:expressTrack定义保持一致,即存在1个必填参数trackingNo。
1{
2 "httpCfgs": [
3 {
4 "id": "expressTrackHttp",
5 "method": "POST",
6 "url": "https://express.example.com/api/track",
7 "headers": {
8 "Authorization": "Bearer xxxxxx",
9 "Content-Type": "application/json"
10 },
11 "presetInputs": {
12 "userId": "u-123456"
13 }
14 }
15 ]
16}
4.5.3 请求
用户说“帮我查一下快递SF1234567890到哪了”,系统提取出trackingNo参数,取值为"SF1234567890",判断必填参数就绪后触发expressTrackHttp执行器。
请求体如下:
1POST https://express.example.com/api/track
2Authorization: Bearer ******
3Content-Type: application/json
4
5{
6 "_requestId":"xxxxxx",
7 "userId": "u-123456",
8 "trackingNo": "SF1234567890"
9}
4.5.4 响应
业务HTTP服务返回如下响应,系统将status、location、estimatedDelivery按同名规则回填到Function Call参数;若携带_text字段,则会在参数提取阶段替换执行器表达式,影响后续参数提取效果。
响应体如下:
1{
2 "_text": "您的快递已到达北京转运中心,预计明天下午送达",
3 "status": "运输中",
4 "location": "北京转运中心",
5 "estimatedDelivery": "明天下午"
6}
4.6 Function Call功能中HTTP回调和HTTP执行器对比
4.6.1 HTTP回调
控制台可以为Function配置回调方式为SDK回调、或者HTTP回调,当配置为HTTP回调时,系统会将识别出的Function名称、提取出的参数回调给HTTP服务。
功能作用:
- 调用业务HTTP服务,回调Function最终识别和参数提取结果。
特点:
- 只会在Function识别结束时,回调1次;
- 无法影响Function参数提取过程。
4.6.2 HTTP执行器
功能作用:
- 调用业务HTTP服务。
- 查询业务数据、获取响应体,影响Function参数识别的过程。
特点:
- 一次Function Call识别过程中,可以多次触发执行,只要执行器的必填参数取值变化即可;
- 可以处理HTTP响应体,响应体可以影响Function参数提取过程。
评价此篇文章
