diff --git a/apps/application/chat_pipeline/step/generate_human_message_step/i_generate_human_message_step.py b/apps/application/chat_pipeline/step/generate_human_message_step/i_generate_human_message_step.py index ca2d00e0b59..fe6be7d2ebe 100644 --- a/apps/application/chat_pipeline/step/generate_human_message_step/i_generate_human_message_step.py +++ b/apps/application/chat_pipeline/step/generate_human_message_step/i_generate_human_message_step.py @@ -37,6 +37,8 @@ class InstanceSerializer(serializers.Serializer): "最大携带知识库段落长度")) # 模板 prompt = serializers.CharField(required=True, error_messages=ErrMessage.char("提示词")) + system = serializers.CharField(required=False, allow_null=True, allow_blank=True, + error_messages=ErrMessage.char("系统提示词(角色)")) # 补齐问题 padding_problem_text = serializers.CharField(required=False, error_messages=ErrMessage.char("补齐问题")) # 未查询到引用分段 @@ -59,6 +61,7 @@ def execute(self, prompt: str, padding_problem_text: str = None, no_references_setting=None, + system=None, **kwargs) -> List[BaseMessage]: """ @@ -71,6 +74,7 @@ def execute(self, :param padding_problem_text 用户修改文本 :param kwargs: 其他参数 :param no_references_setting: 无引用分段设置 + :param system 系统提示称 :return: """ pass diff --git a/apps/application/chat_pipeline/step/generate_human_message_step/impl/base_generate_human_message_step.py b/apps/application/chat_pipeline/step/generate_human_message_step/impl/base_generate_human_message_step.py index 8b769c77002..68cfbbcb95d 100644 --- a/apps/application/chat_pipeline/step/generate_human_message_step/impl/base_generate_human_message_step.py +++ b/apps/application/chat_pipeline/step/generate_human_message_step/impl/base_generate_human_message_step.py @@ -9,6 +9,7 @@ from typing import List, Dict from langchain.schema import BaseMessage, HumanMessage +from langchain_core.messages import SystemMessage from application.chat_pipeline.I_base_chat_pipeline import ParagraphPipelineModel from application.chat_pipeline.step.generate_human_message_step.i_generate_human_message_step import \ @@ -27,6 +28,7 @@ def execute(self, problem_text: str, prompt: str, padding_problem_text: str = None, no_references_setting=None, + system=None, **kwargs) -> List[BaseMessage]: prompt = prompt if (paragraph_list is not None and len(paragraph_list) > 0) else no_references_setting.get( 'value') @@ -35,6 +37,11 @@ def execute(self, problem_text: str, history_message = [[history_chat_record[index].get_human_message(), history_chat_record[index].get_ai_message()] for index in range(start_index if start_index > 0 else 0, len(history_chat_record))] + if system is not None and len(system) > 0: + return [SystemMessage(system), *flat_map(history_message), + self.to_human_message(prompt, exec_problem_text, max_paragraph_char_number, paragraph_list, + no_references_setting)] + return [*flat_map(history_message), self.to_human_message(prompt, exec_problem_text, max_paragraph_char_number, paragraph_list, no_references_setting)] diff --git a/apps/application/chat_pipeline/step/reset_problem_step/i_reset_problem_step.py b/apps/application/chat_pipeline/step/reset_problem_step/i_reset_problem_step.py index ce30d96af3a..fe806811901 100644 --- a/apps/application/chat_pipeline/step/reset_problem_step/i_reset_problem_step.py +++ b/apps/application/chat_pipeline/step/reset_problem_step/i_reset_problem_step.py @@ -29,6 +29,8 @@ class InstanceSerializer(serializers.Serializer): error_messages=ErrMessage.list("历史对答")) # 大语言模型 chat_model = ModelField(required=False, allow_null=True, error_messages=ErrMessage.base("大语言模型")) + problem_optimization_prompt = serializers.CharField(required=False, max_length=102400, + error_messages=ErrMessage.char("问题补全提示词")) def get_step_serializer(self, manage: PipelineManage) -> Type[serializers.Serializer]: return self.InstanceSerializer @@ -47,5 +49,6 @@ def _run(self, manage: PipelineManage): @abstractmethod def execute(self, problem_text: str, history_chat_record: List[ChatRecord] = None, chat_model: BaseChatModel = None, + problem_optimization_prompt=None, **kwargs): pass diff --git a/apps/application/chat_pipeline/step/reset_problem_step/impl/base_reset_problem_step.py b/apps/application/chat_pipeline/step/reset_problem_step/impl/base_reset_problem_step.py index c0595d590fb..3a32bbf0211 100644 --- a/apps/application/chat_pipeline/step/reset_problem_step/impl/base_reset_problem_step.py +++ b/apps/application/chat_pipeline/step/reset_problem_step/impl/base_reset_problem_step.py @@ -21,6 +21,7 @@ class BaseResetProblemStep(IResetProblemStep): def execute(self, problem_text: str, history_chat_record: List[ChatRecord] = None, chat_model: BaseChatModel = None, + problem_optimization_prompt=None, **kwargs) -> str: if chat_model is None: self.context['message_tokens'] = 0 @@ -30,8 +31,9 @@ def execute(self, problem_text: str, history_chat_record: List[ChatRecord] = Non history_message = [[history_chat_record[index].get_human_message(), history_chat_record[index].get_ai_message()] for index in range(start_index if start_index > 0 else 0, len(history_chat_record))] + reset_prompt = problem_optimization_prompt if problem_optimization_prompt else prompt message_list = [*flat_map(history_message), - HumanMessage(content=prompt.format(**{'question': problem_text}))] + HumanMessage(content=reset_prompt.replace('{question}', problem_text))] response = chat_model.invoke(message_list) padding_problem = problem_text if response.content.__contains__("") and response.content.__contains__(''): @@ -39,6 +41,9 @@ def execute(self, problem_text: str, history_chat_record: List[ChatRecord] = Non response.content.index('') + 6:response.content.index('')] if padding_problem_data is not None and len(padding_problem_data.strip()) > 0: padding_problem = padding_problem_data + elif len(response.content) > 0: + padding_problem = response.content + try: request_token = chat_model.get_num_tokens_from_messages(message_list) response_token = chat_model.get_num_tokens(padding_problem) diff --git a/apps/application/migrations/0014_application_problem_optimization_prompt.py b/apps/application/migrations/0014_application_problem_optimization_prompt.py new file mode 100644 index 00000000000..e2efc1097ce --- /dev/null +++ b/apps/application/migrations/0014_application_problem_optimization_prompt.py @@ -0,0 +1,18 @@ +# Generated by Django 4.2.15 on 2024-09-13 18:57 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('application', '0013_application_tts_type'), + ] + + operations = [ + migrations.AddField( + model_name='application', + name='problem_optimization_prompt', + field=models.CharField(blank=True, default='()里面是用户问题,根据上下文回答揣测用户问题({question}) 要求: 输出一个补全问题,并且放在标签中', max_length=102400, null=True, verbose_name='问题优化提示词'), + ), + ] diff --git a/apps/application/models/application.py b/apps/application/models/application.py index c03bec1eb74..13bf3b6aa90 100644 --- a/apps/application/models/application.py +++ b/apps/application/models/application.py @@ -35,7 +35,7 @@ def get_dataset_setting_dict(): def get_model_setting_dict(): - return {'prompt': Application.get_default_model_prompt()} + return {'prompt': Application.get_default_model_prompt(), 'no_references_prompt': '{question}'} class Application(AppModelMixin): @@ -54,8 +54,13 @@ class Application(AppModelMixin): work_flow = models.JSONField(verbose_name="工作流数据", default=dict) type = models.CharField(verbose_name="应用类型", choices=ApplicationTypeChoices.choices, default=ApplicationTypeChoices.SIMPLE, max_length=256) - tts_model = models.ForeignKey(Model, related_name='tts_model_id', on_delete=models.SET_NULL, db_constraint=False, blank=True, null=True) - stt_model = models.ForeignKey(Model, related_name='stt_model_id', on_delete=models.SET_NULL, db_constraint=False, blank=True, null=True) + problem_optimization_prompt = models.CharField(verbose_name="问题优化提示词", max_length=102400, blank=True, + null=True, + default="()里面是用户问题,根据上下文回答揣测用户问题({question}) 要求: 输出一个补全问题,并且放在标签中") + tts_model = models.ForeignKey(Model, related_name='tts_model_id', on_delete=models.SET_NULL, db_constraint=False, + blank=True, null=True) + stt_model = models.ForeignKey(Model, related_name='stt_model_id', on_delete=models.SET_NULL, db_constraint=False, + blank=True, null=True) tts_model_enable = models.BooleanField(verbose_name="语音合成模型是否启用", default=False) stt_model_enable = models.BooleanField(verbose_name="语音识别模型是否启用", default=False) tts_type = models.CharField(verbose_name="语音播放类型", max_length=20, default="BROWSER") diff --git a/apps/application/serializers/application_serializers.py b/apps/application/serializers/application_serializers.py index a04af8999e4..884b14e7066 100644 --- a/apps/application/serializers/application_serializers.py +++ b/apps/application/serializers/application_serializers.py @@ -120,7 +120,12 @@ class DatasetSettingSerializer(serializers.Serializer): class ModelSettingSerializer(serializers.Serializer): - prompt = serializers.CharField(required=True, max_length=2048, error_messages=ErrMessage.char("提示词")) + prompt = serializers.CharField(required=False, allow_null=True, allow_blank=True, max_length=102400, + error_messages=ErrMessage.char("提示词")) + system = serializers.CharField(required=False, allow_null=True, allow_blank=True, max_length=102400, + error_messages=ErrMessage.char("角色提示词")) + no_references_prompt = serializers.CharField(required=True, max_length=102400, allow_null=True, allow_blank=True, + error_messages=ErrMessage.char("无引用分段提示词")) class ApplicationWorkflowSerializer(serializers.Serializer): @@ -174,7 +179,7 @@ class ApplicationSerializer(serializers.Serializer): error_messages=ErrMessage.char("应用描述")) model_id = serializers.CharField(required=False, allow_null=True, allow_blank=True, error_messages=ErrMessage.char("模型")) - multiple_rounds_dialogue = serializers.BooleanField(required=True, error_messages=ErrMessage.char("多轮对话")) + dialogue_number = serializers.BooleanField(required=True, error_messages=ErrMessage.char("会话次数")) prologue = serializers.CharField(required=False, allow_null=True, allow_blank=True, max_length=4096, error_messages=ErrMessage.char("开场白")) dataset_id_list = serializers.ListSerializer(required=False, child=serializers.UUIDField(required=True), @@ -185,6 +190,8 @@ class ApplicationSerializer(serializers.Serializer): model_setting = ModelSettingSerializer(required=True) # 问题补全 problem_optimization = serializers.BooleanField(required=True, error_messages=ErrMessage.boolean("问题补全")) + problem_optimization_prompt = serializers.CharField(required=False, max_length=102400, + error_messages=ErrMessage.char("问题补全提示词")) # 应用类型 type = serializers.CharField(required=True, error_messages=ErrMessage.char("应用类型"), validators=[ @@ -364,8 +371,8 @@ class Edit(serializers.Serializer): error_messages=ErrMessage.char("应用描述")) model_id = serializers.CharField(required=False, allow_blank=True, allow_null=True, error_messages=ErrMessage.char("模型")) - multiple_rounds_dialogue = serializers.BooleanField(required=False, - error_messages=ErrMessage.boolean("多轮会话")) + dialogue_number = serializers.IntegerField(required=False, + error_messages=ErrMessage.boolean("多轮会话")) prologue = serializers.CharField(required=False, allow_null=True, allow_blank=True, max_length=4096, error_messages=ErrMessage.char("开场白")) dataset_id_list = serializers.ListSerializer(required=False, child=serializers.UUIDField(required=True), @@ -430,13 +437,14 @@ def insert_simple(self, application: Dict): def to_application_model(user_id: str, application: Dict): return Application(id=uuid.uuid1(), name=application.get('name'), desc=application.get('desc'), prologue=application.get('prologue'), - dialogue_number=3 if application.get('multiple_rounds_dialogue') else 0, + dialogue_number=application.get('dialogue_number', 0), user_id=user_id, model_id=application.get('model_id'), dataset_setting=application.get('dataset_setting'), model_setting=application.get('model_setting'), problem_optimization=application.get('problem_optimization'), type=ApplicationTypeChoices.SIMPLE, model_params_setting=application.get('model_params_setting', {}), + problem_optimization_prompt=application.get('problem_optimization_prompt', None), work_flow={} ) diff --git a/apps/application/serializers/chat_message_serializers.py b/apps/application/serializers/chat_message_serializers.py index 8fbf0dbbc65..44f31759c9f 100644 --- a/apps/application/serializers/chat_message_serializers.py +++ b/apps/application/serializers/chat_message_serializers.py @@ -60,6 +60,17 @@ def __init__(self, self.chat_record_list: List[ChatRecord] = [] self.work_flow_version = work_flow_version + @staticmethod + def get_no_references_setting(dataset_setting, model_setting): + no_references_setting = dataset_setting.get( + 'no_references_setting', { + 'status': 'ai_questioning', + 'value': '{question}'}) + if no_references_setting.get('status') == 'ai_questioning': + no_references_prompt = model_setting.get('no_references_prompt', '{question}') + no_references_setting['value'] = no_references_prompt if len(no_references_prompt) > 0 else "{question}" + return no_references_setting + def to_base_pipeline_manage_params(self): dataset_setting = self.application.dataset_setting model_setting = self.application.model_setting @@ -80,8 +91,13 @@ def to_base_pipeline_manage_params(self): 'history_chat_record': self.chat_record_list, 'chat_id': self.chat_id, 'dialogue_number': self.application.dialogue_number, + 'problem_optimization_prompt': self.application.problem_optimization_prompt if self.application.problem_optimization_prompt is not None and len( + self.application.problem_optimization_prompt) > 0 else '()里面是用户问题,根据上下文回答揣测用户问题({question}) 要求: 输出一个补全问题,并且放在标签中', 'prompt': model_setting.get( - 'prompt') if 'prompt' in model_setting else Application.get_default_model_prompt(), + 'prompt') if 'prompt' in model_setting and len(model_setting.get( + 'prompt')) > 0 else Application.get_default_model_prompt(), + 'system': model_setting.get( + 'system', None), 'model_id': model_id, 'problem_optimization': self.application.problem_optimization, 'stream': True, @@ -89,11 +105,7 @@ def to_base_pipeline_manage_params(self): self.application.model_params_setting.keys()) == 0 else self.application.model_params_setting, 'search_mode': self.application.dataset_setting.get( 'search_mode') if 'search_mode' in self.application.dataset_setting else 'embedding', - 'no_references_setting': self.application.dataset_setting.get( - 'no_references_setting') if 'no_references_setting' in self.application.dataset_setting else { - 'status': 'ai_questioning', - 'value': '{question}', - }, + 'no_references_setting': self.get_no_references_setting(self.application.dataset_setting, model_setting), 'user_id': self.application.user_id } diff --git a/apps/application/swagger_api/application_api.py b/apps/application/swagger_api/application_api.py index e153f6279af..d05fbb04780 100644 --- a/apps/application/swagger_api/application_api.py +++ b/apps/application/swagger_api/application_api.py @@ -40,15 +40,15 @@ def get_request_body_api(): def get_response_body_api(): return openapi.Schema( type=openapi.TYPE_OBJECT, - required=['id', 'name', 'desc', 'model_id', 'multiple_rounds_dialogue', 'user_id', 'status', 'create_time', + required=['id', 'name', 'desc', 'model_id', 'dialogue_number', 'user_id', 'status', 'create_time', 'update_time'], properties={ 'id': openapi.Schema(type=openapi.TYPE_STRING, title="", description="主键id"), 'name': openapi.Schema(type=openapi.TYPE_STRING, title="应用名称", description="应用名称"), 'desc': openapi.Schema(type=openapi.TYPE_STRING, title="应用描述", description="应用描述"), 'model_id': openapi.Schema(type=openapi.TYPE_STRING, title="模型id", description="模型id"), - "multiple_rounds_dialogue": openapi.Schema(type=openapi.TYPE_BOOLEAN, title="是否开启多轮对话", - description="是否开启多轮对话"), + "dialogue_number": openapi.Schema(type=openapi.TYPE_NUMBER, title="多轮对话次数", + description="多轮对话次数"), 'prologue': openapi.Schema(type=openapi.TYPE_STRING, title="开场白", description="开场白"), 'example': openapi.Schema(type=openapi.TYPE_ARRAY, items=openapi.Schema(type=openapi.TYPE_STRING), title="示例列表", description="示例列表"), @@ -164,8 +164,8 @@ def get_request_body_api(): 'name': openapi.Schema(type=openapi.TYPE_STRING, title="应用名称", description="应用名称"), 'desc': openapi.Schema(type=openapi.TYPE_STRING, title="应用描述", description="应用描述"), 'model_id': openapi.Schema(type=openapi.TYPE_STRING, title="模型id", description="模型id"), - "multiple_rounds_dialogue": openapi.Schema(type=openapi.TYPE_BOOLEAN, title="是否开启多轮对话", - description="是否开启多轮对话"), + "dialogue_number": openapi.Schema(type=openapi.TYPE_NUMBER, title="多轮对话次数", + description="多轮对话次数"), 'prologue': openapi.Schema(type=openapi.TYPE_STRING, title="开场白", description="开场白"), 'dataset_id_list': openapi.Schema(type=openapi.TYPE_ARRAY, items=openapi.Schema(type=openapi.TYPE_STRING), @@ -176,7 +176,22 @@ def get_request_body_api(): description="是否开启问题优化", default=True), 'icon': openapi.Schema(type=openapi.TYPE_STRING, title="icon", description="icon", default="/ui/favicon.ico"), - 'work_flow': ApplicationApi.WorkFlow.get_request_body_api() + 'type': openapi.Schema(type=openapi.TYPE_STRING, title="应用类型", + description="应用类型 简易:SIMPLE|工作流:WORK_FLOW"), + 'work_flow': ApplicationApi.WorkFlow.get_request_body_api(), + 'problem_optimization_prompt': openapi.Schema(type=openapi.TYPE_STRING, title='问题优化提示词', + description="问题优化提示词", + default="()里面是用户问题,根据上下文回答揣测用户问题({question}) 要求: 输出一个补全问题,并且放在标签中"), + 'tts_model_id': openapi.Schema(type=openapi.TYPE_STRING, title="文字转语音模型ID", + description="文字转语音模型ID"), + 'stt_model_id': openapi.Schema(type=openapi.TYPE_STRING, title="语音转文字模型id", + description="语音转文字模型id"), + 'stt_model_enable': openapi.Schema(type=openapi.TYPE_STRING, title="语音转文字是否开启", + description="语音转文字是否开启"), + 'tts_model_enable': openapi.Schema(type=openapi.TYPE_STRING, title="语音转文字是否开启", + description="语音转文字是否开启"), + 'tts_type': openapi.Schema(type=openapi.TYPE_STRING, title="文字转语音类型", + description="文字转语音类型") } ) @@ -248,6 +263,11 @@ def get_request_body_api(): '\n问题:' '\n{question}')), + 'system': openapi.Schema(type=openapi.TYPE_STRING, title="系统提示词(角色)", + description="系统提示词(角色)"), + 'no_references_prompt': openapi.Schema(type=openapi.TYPE_STRING, title="无引用分段提示词", + default="{question}", description="无引用分段提示词") + } ) @@ -267,14 +287,14 @@ class Create(ApiMixin): def get_request_body_api(): return openapi.Schema( type=openapi.TYPE_OBJECT, - required=['name', 'desc', 'model_id', 'multiple_rounds_dialogue', 'dataset_setting', 'model_setting', - 'problem_optimization'], + required=['name', 'desc', 'model_id', 'dialogue_number', 'dataset_setting', 'model_setting', + 'problem_optimization', 'stt_model_enable', 'stt_model_enable', 'tts_type'], properties={ 'name': openapi.Schema(type=openapi.TYPE_STRING, title="应用名称", description="应用名称"), 'desc': openapi.Schema(type=openapi.TYPE_STRING, title="应用描述", description="应用描述"), 'model_id': openapi.Schema(type=openapi.TYPE_STRING, title="模型id", description="模型id"), - "multiple_rounds_dialogue": openapi.Schema(type=openapi.TYPE_BOOLEAN, title="是否开启多轮对话", - description="是否开启多轮对话"), + "dialogue_number": openapi.Schema(type=openapi.TYPE_NUMBER, title="多轮对话次数", + description="多轮对话次数"), 'prologue': openapi.Schema(type=openapi.TYPE_STRING, title="开场白", description="开场白"), 'dataset_id_list': openapi.Schema(type=openapi.TYPE_ARRAY, items=openapi.Schema(type=openapi.TYPE_STRING), @@ -284,8 +304,20 @@ def get_request_body_api(): 'problem_optimization': openapi.Schema(type=openapi.TYPE_BOOLEAN, title="问题优化", description="是否开启问题优化", default=True), 'type': openapi.Schema(type=openapi.TYPE_STRING, title="应用类型", - description="应用类型 简易:SIMPLE|工作流:WORK_FLOW") - + description="应用类型 简易:SIMPLE|工作流:WORK_FLOW"), + 'problem_optimization_prompt': openapi.Schema(type=openapi.TYPE_STRING, title='问题优化提示词', + description="问题优化提示词", + default="()里面是用户问题,根据上下文回答揣测用户问题({question}) 要求: 输出一个补全问题,并且放在标签中"), + 'tts_model_id': openapi.Schema(type=openapi.TYPE_STRING, title="文字转语音模型ID", + description="文字转语音模型ID"), + 'stt_model_id': openapi.Schema(type=openapi.TYPE_STRING, title="语音转文字模型id", + description="语音转文字模型id"), + 'stt_model_enable': openapi.Schema(type=openapi.TYPE_STRING, title="语音转文字是否开启", + description="语音转文字是否开启"), + 'tts_model_enable': openapi.Schema(type=openapi.TYPE_STRING, title="语音转文字是否开启", + description="语音转文字是否开启"), + 'tts_type': openapi.Schema(type=openapi.TYPE_STRING, title="文字转语音类型", + description="文字转语音类型") } ) diff --git a/ui/src/api/type/application.ts b/ui/src/api/type/application.ts index 24215a5fbbe..97be3b25794 100644 --- a/ui/src/api/type/application.ts +++ b/ui/src/api/type/application.ts @@ -4,12 +4,13 @@ interface ApplicationFormType { name?: string desc?: string model_id?: string - multiple_rounds_dialogue?: boolean + dialogue_number?: number prologue?: string dataset_id_list?: string[] dataset_setting?: any model_setting?: any problem_optimization?: boolean + problem_optimization_prompt?: string icon?: string | undefined type?: string work_flow?: any diff --git a/ui/src/locales/lang/zh_CN/views/application.ts b/ui/src/locales/lang/zh_CN/views/application.ts index 8d0888a157d..5554943278f 100644 --- a/ui/src/locales/lang/zh_CN/views/application.ts +++ b/ui/src/locales/lang/zh_CN/views/application.ts @@ -104,8 +104,10 @@ export default { } }, prompt: { - defaultPrompt: - '已知信息:\n{data}\n回答要求:\n- 请使用简洁且专业的语言来回答用户的问题。\n- 如果你不知道答案,请回答“没有在知识库中查找到相关信息,建议咨询相关技术支持或参考官方文档进行操作”。\n- 避免提及你是从已知信息中获得的知识。\n- 请保证答案与已知信息中描述的一致。\n- 请使用 Markdown 语法优化答案的格式。\n- 已知信息中的图片、链接地址和脚本语言请直接返回。\n- 请使用与问题相同的语言来回答。\n问题:\n{question}', + defaultPrompt: `已知信息:{data} +用户问题:{question} +回答要求: + - 请使用中文回答用户问题`, defaultPrologue: '您好,我是 MaxKB 小助手,您可以向我提出 MaxKB 使用问题。\n- MaxKB 主要功能有什么?\n- MaxKB 支持哪些大语言模型?\n- MaxKB 支持哪些文档类型?' } diff --git a/ui/src/views/application/ApplicationSetting.vue b/ui/src/views/application/ApplicationSetting.vue index 9ef5cef2cb6..9a491854420 100644 --- a/ui/src/views/application/ApplicationSetting.vue +++ b/ui/src/views/application/ApplicationSetting.vue @@ -61,10 +61,7 @@ /> - + + + + - - + + + + + + - - - - + - 浏览器播放(免费) - TTS模型 + 浏览器播放(免费) + TTS模型 ({ name: '', desc: '', model_id: '', - multiple_rounds_dialogue: false, + dialogue_number: 1, prologue: t('views.application.prompt.defaultPrologue'), dataset_id_list: [], dataset_setting: { @@ -555,10 +566,14 @@ const applicationForm = ref({ } }, model_setting: { - prompt: defaultPrompt + prompt: defaultPrompt, + system: '你是 xxx 小助手', + no_references_prompt: '{question}' }, model_params_setting: {}, problem_optimization: false, + problem_optimization_prompt: + '()里面是用户问题,根据上下文回答揣测用户问题({question}) 要求: 输出一个补全问题,并且放在标签中', stt_model_id: '', tts_model_id: '', stt_model_enable: false, @@ -574,20 +589,6 @@ const rules = reactive>({ message: t('views.application.applicationForm.form.appName.placeholder'), trigger: 'blur' } - ], - model_id: [ - { - required: false, - message: t('views.application.applicationForm.form.aiModel.placeholder'), - trigger: 'change' - } - ], - 'model_setting.prompt': [ - { - required: true, - message: t('views.application.applicationForm.form.prompt.placeholder'), - trigger: 'blur' - } ] }) const modelOptions = ref(null) @@ -623,11 +624,11 @@ const openAIParamSettingDialog = () => { } const openParamSettingDialog = () => { - ParamSettingDialogRef.value?.open(applicationForm.value.dataset_setting) + ParamSettingDialogRef.value?.open(applicationForm.value) } function refreshParam(data: any) { - applicationForm.value.dataset_setting = data + applicationForm.value = { ...applicationForm.value, ...data } } function refreshForm(data: any) { @@ -666,6 +667,8 @@ function getDetail() { applicationForm.value.stt_model_id = res.data.stt_model applicationForm.value.tts_model_id = res.data.tts_model applicationForm.value.tts_type = res.data.tts_type + applicationForm.value.model_setting.no_references_prompt = + res.data.model_setting.no_references_prompt || '' }) } diff --git a/ui/src/views/application/component/CreateApplicationDialog.vue b/ui/src/views/application/component/CreateApplicationDialog.vue index 0e04346a563..8e78b9a325e 100644 --- a/ui/src/views/application/component/CreateApplicationDialog.vue +++ b/ui/src/views/application/component/CreateApplicationDialog.vue @@ -104,7 +104,7 @@ const applicationForm = ref({ name: '', desc: '', model_id: '', - multiple_rounds_dialogue: false, + dialogue_number: 1, prologue: t('views.application.prompt.defaultPrologue'), dataset_id_list: [], dataset_setting: { @@ -118,9 +118,19 @@ const applicationForm = ref({ } }, model_setting: { - prompt: defaultPrompt + prompt: defaultPrompt, + system: '你是 xxx 小助手', + no_references_prompt: '{question}' }, + model_params_setting: {}, problem_optimization: false, + problem_optimization_prompt: + '()里面是用户问题,根据上下文回答揣测用户问题({question}) 要求: 输出一个补全问题,并且放在标签中', + stt_model_id: '', + tts_model_id: '', + stt_model_enable: false, + tts_model_enable: false, + tts_type: 'BROWSER', type: 'SIMPLE' }) @@ -147,7 +157,7 @@ watch(dialogVisible, (bool) => { name: '', desc: '', model_id: '', - multiple_rounds_dialogue: false, + dialogue_number: 1, prologue: t('views.application.prompt.defaultPrologue'), dataset_id_list: [], dataset_setting: { @@ -161,9 +171,18 @@ watch(dialogVisible, (bool) => { } }, model_setting: { - prompt: defaultPrompt + prompt: defaultPrompt, + system: '你是 xxx 小助手', + no_references_prompt: '{question}' }, + model_params_setting: {}, problem_optimization: false, + problem_optimization_prompt: '', + stt_model_id: '', + tts_model_id: '', + stt_model_enable: false, + tts_model_enable: false, + tts_type: 'BROWSER', type: 'SIMPLE' } applicationFormRef.value?.clearValidate() diff --git a/ui/src/views/application/component/ParamSettingDialog.vue b/ui/src/views/application/component/ParamSettingDialog.vue index 9b81a9858f4..7b953ceaee4 100644 --- a/ui/src/views/application/component/ParamSettingDialog.vue +++ b/ui/src/views/application/component/ParamSettingDialog.vue @@ -14,7 +14,11 @@ - +

@@ -43,7 +47,10 @@ }} - +

{{ $t('views.application.applicationForm.dialogues.hybridSearch') }} @@ -69,7 +76,7 @@

{{ $t('views.application.applicationForm.dialogues.continueQuestioning') }}

- - -
-
+

{{ $t('views.application.applicationForm.dialogues.provideAnswer') }}

+ + + + + + + +
@@ -195,15 +214,21 @@ const defaultValue = { designated_answer: t('views.application.applicationForm.dialogues.designated_answer') } +const defaultPrompt = `()里面是用户问题,根据上下文回答揣测用户问题({question}) 要求: 输出一个补全问题,并且放在标签中` + const form = ref({ - search_mode: 'embedding', - top_n: 3, - similarity: 0.6, - max_paragraph_char_number: 5000, - no_references_setting: { - status: 'ai_questioning', - value: '{question}' - } + dataset_setting: { + search_mode: 'embedding', + top_n: 3, + similarity: 0.6, + max_paragraph_char_number: 5000, + no_references_setting: { + status: 'ai_questioning', + value: '{question}' + } + }, + problem_optimization: false, + problem_optimization_prompt: defaultPrompt }) const noReferencesform = ref({ @@ -236,14 +261,18 @@ const isWorkflowType = ref(false) watch(dialogVisible, (bool) => { if (!bool) { form.value = { - search_mode: 'embedding', - top_n: 3, - similarity: 0.6, - max_paragraph_char_number: 5000, - no_references_setting: { - status: 'ai_questioning', - value: '' - } + dataset_setting: { + search_mode: 'embedding', + top_n: 3, + similarity: 0.6, + max_paragraph_char_number: 5000, + no_references_setting: { + status: 'ai_questioning', + value: '{question}' + } + }, + problem_optimization: false, + problem_optimization_prompt: '' } noReferencesform.value = { ai_questioning: defaultValue['ai_questioning'], @@ -255,9 +284,16 @@ watch(dialogVisible, (bool) => { const open = (data: any, type?: string) => { isWorkflowType.value = isWorkFlow(type) - form.value = { ...form.value, ...cloneDeep(data) } - noReferencesform.value[form.value.no_references_setting.status] = - form.value.no_references_setting.value + form.value = { + dataset_setting: { ...data.dataset_setting }, + problem_optimization: data.problem_optimization, + problem_optimization_prompt: data.problem_optimization_prompt + } + if (!isWorkflowType.value) { + noReferencesform.value[form.value.dataset_setting.no_references_setting.status] = + form.value.dataset_setting.no_references_setting.value + } + dialogVisible.value = true } @@ -270,8 +306,8 @@ const submit = async (formEl: FormInstance | undefined) => { if (!formEl) return await formEl.validate((valid, fields) => { if (valid) { - form.value.no_references_setting.value = - noReferencesform.value[form.value.no_references_setting.status] + form.value.dataset_setting.no_references_setting.value = + noReferencesform.value[form.value.dataset_setting.no_references_setting.status] emit('refresh', form.value) dialogVisible.value = false } @@ -281,9 +317,9 @@ const submit = async (formEl: FormInstance | undefined) => { function changeHandle(val: string) { if (val === 'keywords') { - form.value.similarity = 0 + form.value.dataset_setting.similarity = 0 } else { - form.value.similarity = 0.6 + form.value.dataset_setting.similarity = 0.6 } } diff --git a/ui/src/workflow/nodes/reranker-node/index.vue b/ui/src/workflow/nodes/reranker-node/index.vue index 08d4be5f58a..4aaaef2707c 100644 --- a/ui/src/workflow/nodes/reranker-node/index.vue +++ b/ui/src/workflow/nodes/reranker-node/index.vue @@ -22,6 +22,7 @@ :gutter="8" style="margin-bottom: 8px" v-for="(reranker_reference, index) in form_data.reranker_reference_list" + :key="index" > >([]) const modelOptions = ref(null) const openParamSettingDialog = () => { - ParamSettingDialogRef.value?.open(form_data.value.dataset_setting, 'WORK_FLOW') + ParamSettingDialogRef.value?.open(form_data.value, 'WORK_FLOW') } const deleteCondition = (index: number) => { const list = cloneDeep(props.nodeModel.properties.node_data.reranker_reference_list) @@ -242,7 +243,7 @@ const form_data = computed({ } }) function refreshParam(data: any) { - set(props.nodeModel.properties.node_data, 'reranker_setting', data) + set(props.nodeModel.properties.node_data, 'reranker_setting', data.dataset_setting) } function getModel() { if (id) { diff --git a/ui/src/workflow/nodes/search-dataset-node/index.vue b/ui/src/workflow/nodes/search-dataset-node/index.vue index c065668a4a6..78d1a4f0f20 100644 --- a/ui/src/workflow/nodes/search-dataset-node/index.vue +++ b/ui/src/workflow/nodes/search-dataset-node/index.vue @@ -159,11 +159,11 @@ const datasetList = ref([]) const datasetLoading = ref(false) function refreshParam(data: any) { - set(props.nodeModel.properties.node_data, 'dataset_setting', data) + set(props.nodeModel.properties.node_data, 'dataset_setting', data.dataset_setting) } const openParamSettingDialog = () => { - ParamSettingDialogRef.value?.open(form_data.value.dataset_setting, 'WORK_FLOW') + ParamSettingDialogRef.value?.open(form_data.value, 'WORK_FLOW') } function removeDataset(id: any) {