Skip to content

Commit a4005c3

Browse files
feat: The prompt template for the Intent Recognition is configurable
1 parent 983a7c7 commit a4005c3

File tree

10 files changed

+97
-10
lines changed

10 files changed

+97
-10
lines changed

apps/application/flow/step_node/intent_node/i_intent_node.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ class IntentBranchSerializer(serializers.Serializer):
1717

1818
class IntentNodeSerializer(serializers.Serializer):
1919
model_id = serializers.CharField(required=True, label=_("Model id"))
20+
prompt_template = serializers.CharField(required=False, allow_blank=True, allow_null=True, label=_("Prompt template"))
2021
content_list = serializers.ListField(required=True, label=_("Text content"))
2122
dialogue_number = serializers.IntegerField(required=True, label=
2223
_("Number of multi-round conversations"))

apps/application/flow/step_node/intent_node/impl/base_intent_node.py

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
from application.flow.step_node.intent_node.i_intent_node import IIntentNode
1313
from models_provider.models import Model
1414
from models_provider.tools import get_model_instance_by_model_workspace_id, get_model_credential
15-
from .prompt_template import PROMPT_TEMPLATE
15+
from .prompt_template import DEFAULT_PROMPT_TEMPLATE
1616

1717

1818
def get_default_model_params_setting(model_id):
@@ -52,7 +52,7 @@ def save_context(self, details, workflow_manage):
5252
self.context['branch_id'] = details.get('branch_id')
5353
self.context['category'] = details.get('category')
5454

55-
def execute(self, model_id, dialogue_number, history_chat_record, user_input, branch, output_reason,
55+
def execute(self, model_id, prompt_template, dialogue_number, history_chat_record, user_input, branch, output_reason,
5656
model_params_setting=None, **kwargs) -> NodeResult:
5757

5858
# 设置默认模型参数
@@ -73,7 +73,8 @@ def execute(self, model_id, dialogue_number, history_chat_record, user_input, br
7373
self.context['user_input'] = user_input
7474

7575
# 构建分类提示词
76-
prompt = self.build_classification_prompt(user_input, branch, output_reason)
76+
prompt_template = self.workflow_manage.generate_prompt(prompt_template)
77+
prompt = self.build_classification_prompt(prompt_template, user_input, branch, output_reason)
7778
self.context['system'] = prompt
7879

7980
# 生成消息列表
@@ -130,7 +131,7 @@ def build_system_prompt(self) -> str:
130131
"""构建系统提示词"""
131132
return "你是一个专业的意图识别助手,请根据用户输入和意图选项,准确识别用户的真实意图。"
132133

133-
def build_classification_prompt(self, user_input: str, branch: List[Dict], output_reason: bool) -> str:
134+
def build_classification_prompt(self, prompt_template: str, user_input: str, branch: List[Dict], output_reason: bool) -> str:
134135
"""构建分类提示词"""
135136

136137
classification_list = []
@@ -152,10 +153,14 @@ def build_classification_prompt(self, user_input: str, branch: List[Dict], outpu
152153
})
153154
classification_id += 1
154155

155-
return PROMPT_TEMPLATE.format(
156+
# 构建输出JSON结构
157+
output_reason = ', "reason": ""' if output_reason is True else ''
158+
output_json = f'{{"classificationId": 0{output_reason}}}'
159+
160+
return (prompt_template or DEFAULT_PROMPT_TEMPLATE).format(
156161
classification_list=classification_list,
157162
user_input=user_input,
158-
output_reason=',\n"reason": ""' if output_reason is True else ''
163+
output_json=output_json
159164
)
160165

161166
def generate_message_list(self, system: str, prompt: str, history_message):

apps/application/flow/step_node/intent_node/impl/prompt_template.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11

22

3-
PROMPT_TEMPLATE = """# Role
3+
DEFAULT_PROMPT_TEMPLATE = """# Role
44
You are an intention classification expert, good at being able to judge which classification the user's input belongs to.
55
66
## Skills
@@ -20,9 +20,7 @@
2020
- Strictly ensure that the output is in a valid JSON format.
2121
- Do not add prefix ```json or suffix ```
2222
- The answer needs to include the following fields such as:
23-
{{
24-
"classificationId": 0{output_reason}
25-
}}
23+
{output_json}
2624
2725
## Limit
2826
- Please do not reply in text."""

ui/src/locales/lang/en-US/views/application.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,11 @@ export default {
8787
- Please use concise and professional language to answer the user's question.
8888
`,
8989
},
90+
prompt_template: {
91+
label: 'Prompt Template',
92+
requiredMessage: 'Please enter Prompt template',
93+
tooltip: 'Please pay attention to the placeholders `{xxx}` in the template',
94+
},
9095
historyRecord: {
9196
label: 'Chat History',
9297
},

ui/src/locales/lang/en-US/workflow.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -542,6 +542,7 @@ You are a master of problem optimization, adept at accurately inferring user int
542542
},
543543
SystemPromptPlaceholder: 'System Prompt, can reference variables in the system, such as',
544544
UserPromptPlaceholder: 'User Prompt, can reference variables in the system, such as',
545+
PromptTemplatePlaceholder: 'Prompt Template, can reference variables in the system, such as',
545546
initiator: 'Iniiator',
546547
abnormalInformation: 'Abnormal Information',
547548
}

ui/src/locales/lang/zh-CN/views/application.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,11 @@ export default {
8080
回答要求:
8181
- 请使用中文回答用户问题`,
8282
},
83+
prompt_template: {
84+
label: '提示词模板',
85+
requiredMessage: '请输入提示词模板',
86+
tooltip: '请注意模板中的占位符 `{xxx}`',
87+
},
8388
historyRecord: {
8489
label: '历史聊天记录',
8590
},

ui/src/locales/lang/zh-CN/workflow.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -533,6 +533,7 @@ export default {
533533
},
534534
SystemPromptPlaceholder: '系统提示词,可以引用系统中的变量:如',
535535
UserPromptPlaceholder: '用户提示词,可以引用系统中的变量:如',
536+
PromptTemplatePlaceholder: '提示词模板,可以引用系统中的变量:如',
536537
initiator: '发起人',
537538
abnormalInformation: '异常信息'
538539

ui/src/locales/lang/zh-Hant/views/application.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,11 @@ export default {
8080
回答要求:
8181
- 請使用中文回答用戶問題`,
8282
},
83+
prompt_template: {
84+
label: '提示詞模板',
85+
requiredMessage: '請輸入提示詞模板',
86+
tooltip: '請注意模板中的佔位符 `{xxx}`',
87+
},
8388
historyRecord: {
8489
label: '歷史對話紀錄',
8590
},

ui/src/locales/lang/zh-Hant/workflow.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -527,6 +527,7 @@ export default {
527527
},
528528
SystemPromptPlaceholder: '系統提示詞,可以引用系統中的變量:如',
529529
UserPromptPlaceholder: '用戶提示詞,可以引用系統中的變量:如',
530+
PromptTemplatePlaceholder: '提示詞模板,可以引用系統中的變量:如',
530531
initiator: '發起人',
531532
abnormalInformation: '異常信息',
532533
}

ui/src/workflow/nodes/intent-classify-node/index.vue

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,38 @@
5151
:model-type="'LLM'"
5252
></ModelSelect>
5353
</el-form-item>
54+
<el-form-item
55+
:label="$t('views.application.form.prompt_template.label')"
56+
prop="prompt_template"
57+
:rules="{
58+
required: true,
59+
message: $t('views.application.form.prompt_template.requiredMessage'),
60+
trigger: 'blur',
61+
}"
62+
>
63+
<template #label>
64+
<div class="flex align-center">
65+
<div class="mr-4">
66+
<span
67+
>{{ $t('views.application.form.prompt_template.label')
68+
}}<span class="color-danger">*</span></span
69+
>
70+
</div>
71+
<el-tooltip effect="dark" placement="right" popper-class="max-w-200">
72+
<template #content>{{ $t('views.application.form.prompt_template.tooltip') }} </template>
73+
<AppIcon iconName="app-warning" class="app-warning-icon"></AppIcon>
74+
</el-tooltip>
75+
</div>
76+
</template>
77+
<MdEditorMagnify
78+
@wheel="wheel"
79+
:title="$t('views.application.form.prompt_template.label')"
80+
v-model="form_data.prompt_template"
81+
style="height: 100px"
82+
@submitDialog="submitTemplateDialog"
83+
:placeholder="`${t('workflow.PromptTemplatePlaceholder')}{{${t('workflow.nodes.startNode.label')}.question}}`"
84+
/>
85+
</el-form-item>
5486
<el-form-item
5587
prop="content_list"
5688
:label="$t('workflow.nodes.intentNode.input.label')"
@@ -292,8 +324,34 @@ const model_change = (model_id?: string) => {
292324
}
293325
}
294326
327+
const defaultPromptTemplate = `# Role
328+
You are an intention classification expert, good at being able to judge which classification the user's input belongs to.
329+
330+
## Skills
331+
Skill 1: Clearly determine which of the following intention classifications the user's input belongs to.
332+
Intention classification list:
333+
{classification_list}
334+
335+
Note:
336+
- Please determine the match between the user's input content and the Intention classification list content, without judging or categorizing the match with the classification ID.
337+
- **When classifying, you must give higher weight to the context and intent continuity shown in the historical conversation. Do not rely solely on the literal meaning of the current input; instead, prioritize the most consistent classification with the previous dialogue flow.**
338+
339+
## User Input
340+
{user_input}
341+
342+
## Reply requirements
343+
- The answer must be returned in JSON format.
344+
- Strictly ensure that the output is in a valid JSON format.
345+
- Do not add prefix \`\`\`json or suffix \`\`\`
346+
- The answer needs to include the following fields such as:
347+
{output_json}
348+
349+
## Limit
350+
- Please do not reply in text.`
351+
295352
const form = {
296353
model_id: '',
354+
prompt_template: defaultPromptTemplate,
297355
branch: [
298356
{
299357
id: randomId(),
@@ -315,6 +373,10 @@ function refreshParam(data: any) {
315373
set(props.nodeModel.properties.node_data, 'model_params_setting', data)
316374
}
317375
376+
function submitTemplateDialog(val: string) {
377+
set(props.nodeModel.properties.node_data, 'prompt_template', val)
378+
}
379+
318380
const openAIParamSettingDialog = (modelId: string) => {
319381
if (modelId) {
320382
AIModeParamSettingDialogRef.value?.open(modelId, id, form_data.value.model_params_setting)
@@ -323,6 +385,9 @@ const openAIParamSettingDialog = (modelId: string) => {
323385
const form_data = computed({
324386
get: () => {
325387
if (props.nodeModel.properties.node_data) {
388+
if (!props.nodeModel.properties.node_data.prompt_template) {
389+
set(props.nodeModel.properties.node_data, 'prompt_template', defaultPromptTemplate)
390+
}
326391
return props.nodeModel.properties.node_data
327392
} else {
328393
set(props.nodeModel.properties, 'node_data', form)

0 commit comments

Comments
 (0)