diff --git a/apps/application/chat_pipeline/step/chat_step/impl/base_chat_step.py b/apps/application/chat_pipeline/step/chat_step/impl/base_chat_step.py index 19af59fba..8e6d37bc3 100644 --- a/apps/application/chat_pipeline/step/chat_step/impl/base_chat_step.py +++ b/apps/application/chat_pipeline/step/chat_step/impl/base_chat_step.py @@ -124,9 +124,11 @@ def event_content(response, request_token = 0 response_token = 0 write_context(step, manage, request_token, response_token, all_text) + asker = manage.context.get('form_data', {}).get('asker', None) post_response_handler.handler(chat_id, chat_record_id, paragraph_list, problem_text, all_text, manage, step, padding_problem_text, client_id, - reasoning_content=reasoning_content if reasoning_content_enable else '') + reasoning_content=reasoning_content if reasoning_content_enable else '' + , asker=asker) yield manage.get_base_to_response().to_stream_chunk_response(chat_id, str(chat_record_id), 'ai-chat-node', [], '', True, request_token, response_token, @@ -137,8 +139,10 @@ def event_content(response, logging.getLogger("max_kb_error").error(f'{str(e)}:{traceback.format_exc()}') all_text = 'Exception:' + str(e) write_context(step, manage, 0, 0, all_text) + asker = manage.context.get('asker', None) post_response_handler.handler(chat_id, chat_record_id, paragraph_list, problem_text, - all_text, manage, step, padding_problem_text, client_id) + all_text, manage, step, padding_problem_text, client_id, reasoning_content='', + asker=asker) add_access_num(client_id, client_type, manage.context.get('application_id')) yield manage.get_base_to_response().to_stream_chunk_response(chat_id, str(chat_record_id), 'ai-chat-node', [], all_text, @@ -150,7 +154,6 @@ def event_content(response, 'reasoning_content': ''}) - class BaseChatStep(IChatStep): def execute(self, message_list: List[BaseMessage], chat_id, @@ -304,9 +307,11 @@ class BaseChatStep(IChatStep): else: reasoning_content = reasoning_result.get('reasoning_content') + reasoning_result_end.get( 'reasoning_content') + asker = manage.context.get('asker', None) post_response_handler.handler(chat_id, chat_record_id, paragraph_list, problem_text, content, manage, self, padding_problem_text, client_id, - reasoning_content=reasoning_content if reasoning_content_enable else '') + reasoning_content=reasoning_content if reasoning_content_enable else '', + asker=asker) add_access_num(client_id, client_type, manage.context.get('application_id')) return manage.get_base_to_response().to_block_response(str(chat_id), str(chat_record_id), content, True, @@ -320,8 +325,10 @@ class BaseChatStep(IChatStep): except Exception as e: all_text = 'Exception:' + str(e) write_context(self, manage, 0, 0, all_text) + asker = manage.context.get('asker', None) post_response_handler.handler(chat_id, chat_record_id, paragraph_list, problem_text, - all_text, manage, self, padding_problem_text, client_id) + all_text, manage, self, padding_problem_text, client_id, reasoning_content='', + asker=asker) add_access_num(client_id, client_type, manage.context.get('application_id')) return manage.get_base_to_response().to_block_response(str(chat_id), str(chat_record_id), all_text, True, 0, 0, _status=status.HTTP_500_INTERNAL_SERVER_ERROR) diff --git a/apps/application/flow/i_step_node.py b/apps/application/flow/i_step_node.py index e1a567731..fcead7a40 100644 --- a/apps/application/flow/i_step_node.py +++ b/apps/application/flow/i_step_node.py @@ -84,7 +84,8 @@ class WorkFlowPostHandler: answer_text_list=answer_text_list, run_time=time.time() - workflow.context['start_time'], index=0) - self.chat_info.append_chat_record(chat_record, self.client_id) + asker = workflow.context.get('asker', None) + self.chat_info.append_chat_record(chat_record, self.client_id, asker) # 重新设置缓存 chat_cache.set(chat_id, self.chat_info, timeout=60 * 30) diff --git a/apps/application/migrations/0026_chat_asker.py b/apps/application/migrations/0026_chat_asker.py new file mode 100644 index 000000000..e556f8c3a --- /dev/null +++ b/apps/application/migrations/0026_chat_asker.py @@ -0,0 +1,20 @@ +# Generated by Django 4.2.18 on 2025-03-18 06:05 + +import application.models.application +import common.encoder.encoder +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('application', '0025_alter_application_prologue'), + ] + + operations = [ + migrations.AddField( + model_name='chat', + name='asker', + field=models.JSONField(default=application.models.application.default_asker, encoder=common.encoder.encoder.SystemEncoder, verbose_name='访问者'), + ), + ] diff --git a/apps/application/models/application.py b/apps/application/models/application.py index 7b5a3b51b..dfe9534e8 100644 --- a/apps/application/models/application.py +++ b/apps/application/models/application.py @@ -115,10 +115,15 @@ class ApplicationDatasetMapping(AppModelMixin): db_table = "application_dataset_mapping" +def default_asker(): + return {'user_name': '游客'} + + class Chat(AppModelMixin): id = models.UUIDField(primary_key=True, max_length=128, default=uuid.uuid1, editable=False, verbose_name="主键id") application = models.ForeignKey(Application, on_delete=models.CASCADE) abstract = models.CharField(max_length=1024, verbose_name="摘要") + asker = models.JSONField(verbose_name="访问者", default=default_asker, encoder=SystemEncoder) client_id = models.UUIDField(verbose_name="客户端id", default=None, null=True) is_deleted = models.BooleanField(verbose_name="", default=False) diff --git a/apps/application/serializers/chat_message_serializers.py b/apps/application/serializers/chat_message_serializers.py index 8c15b032a..2194028e6 100644 --- a/apps/application/serializers/chat_message_serializers.py +++ b/apps/application/serializers/chat_message_serializers.py @@ -116,13 +116,15 @@ class ChatInfo: } def to_pipeline_manage_params(self, problem_text: str, post_response_handler: PostResponseHandler, - exclude_paragraph_id_list, client_id: str, client_type, stream=True): + exclude_paragraph_id_list, client_id: str, client_type, stream=True, form_data=None): + if form_data is None: + form_data = {} params = self.to_base_pipeline_manage_params() return {**params, 'problem_text': problem_text, 'post_response_handler': post_response_handler, 'exclude_paragraph_id_list': exclude_paragraph_id_list, 'stream': stream, 'client_id': client_id, - 'client_type': client_type} + 'client_type': client_type, 'form_data': form_data} - def append_chat_record(self, chat_record: ChatRecord, client_id=None): + def append_chat_record(self, chat_record: ChatRecord, client_id=None, asker=None): chat_record.problem_text = chat_record.problem_text[0:10240] if chat_record.problem_text is not None else "" chat_record.answer_text = chat_record.answer_text[0:40960] if chat_record.problem_text is not None else "" is_save = True @@ -137,8 +139,17 @@ class ChatInfo: if self.application.id is not None: # 插入数据库 if not QuerySet(Chat).filter(id=self.chat_id).exists(): + asker_dict = {'user_name': '游客'} + if asker is not None: + if isinstance(asker, str): + asker_dict = { + 'user_name': asker + } + elif isinstance(asker, dict): + asker_dict = asker + Chat(id=self.chat_id, application_id=self.application.id, abstract=chat_record.problem_text[0:1024], - client_id=client_id, update_time=datetime.now()).save() + client_id=client_id, asker=asker_dict, update_time=datetime.now()).save() else: Chat.objects.filter(id=self.chat_id).update(update_time=datetime.now()) # 插入会话记录 @@ -171,7 +182,8 @@ def get_post_handler(chat_info: ChatInfo): answer_text_list=answer_list, run_time=manage.context['run_time'], index=len(chat_info.chat_record_list) + 1) - chat_info.append_chat_record(chat_record, client_id) + asker = kwargs.get("asker", None) + chat_info.append_chat_record(chat_record, client_id, asker=asker) # 重新设置缓存 chat_cache.set(chat_id, chat_info, timeout=60 * 30) @@ -310,6 +322,7 @@ class ChatMessageSerializer(serializers.Serializer): stream = self.data.get('stream') client_id = self.data.get('client_id') client_type = self.data.get('client_type') + form_data = self.data.get("form_data") pipeline_manage_builder = PipelineManage.builder() # 如果开启了问题优化,则添加上问题优化步骤 if chat_info.application.problem_optimization: @@ -331,7 +344,7 @@ class ChatMessageSerializer(serializers.Serializer): exclude_paragraph_id_list = list(set(paragraph_id_list)) # 构建运行参数 params = chat_info.to_pipeline_manage_params(message, get_post_handler(chat_info), exclude_paragraph_id_list, - client_id, client_type, stream) + client_id, client_type, stream, form_data) # 运行流水线作业 pipeline_message.run(params) return pipeline_message.context['chat_result'] diff --git a/apps/application/sql/list_application_chat.sql b/apps/application/sql/list_application_chat.sql index bf269d005..7f3e1680c 100644 --- a/apps/application/sql/list_application_chat.sql +++ b/apps/application/sql/list_application_chat.sql @@ -1,5 +1,5 @@ SELECT - * + *,to_json(asker) as asker FROM application_chat application_chat LEFT JOIN ( diff --git a/ui/src/components/ai-chat/component/user-form/index.vue b/ui/src/components/ai-chat/component/user-form/index.vue index b73fdfc36..617b56cf3 100644 --- a/ui/src/components/ai-chat/component/user-form/index.vue +++ b/ui/src/components/ai-chat/component/user-form/index.vue @@ -276,6 +276,25 @@ function handleInputFieldList() { : { title: t('chat.userInput') } }) } +const getRouteQueryValue = (field: string) => { + let _value = route.query[field] + if (_value != null) { + if (_value instanceof Array) { + _value = _value + .map((item) => { + if (item != null) { + return decodeQuery(item) + } + return null + }) + .filter((item) => item != null) + } else { + _value = decodeQuery(_value) + } + return _value + } + return null +} /** * 校验参数 */ @@ -294,20 +313,8 @@ const checkInputParam = () => { let msg = [] for (let f of apiInputFieldList.value) { if (!api_form_data_context.value[f.field]) { - let _value = route.query[f.field] + let _value = getRouteQueryValue(f.field) if (_value != null) { - if (_value instanceof Array) { - _value = _value - .map((item) => { - if (item != null) { - return decodeQuery(item) - } - return null - }) - .filter((item) => item != null) - } else { - _value = decodeQuery(_value) - } api_form_data_context.value[f.field] = _value } } @@ -315,6 +322,10 @@ const checkInputParam = () => { msg.push(f.field) } } + if (!api_form_data_context.value['asker']) { + api_form_data_context.value['asker'] = getRouteQueryValue('asker') + } + if (msg.length > 0) { MsgWarning( `${t('chat.tip.inputParamMessage1')} ${msg.join('、')}${t('chat.tip.inputParamMessage2')}` diff --git a/ui/src/locales/lang/en-US/views/log.ts b/ui/src/locales/lang/en-US/views/log.ts index 5c8274f88..9dfa40e00 100644 --- a/ui/src/locales/lang/en-US/views/log.ts +++ b/ui/src/locales/lang/en-US/views/log.ts @@ -13,6 +13,7 @@ export default { table: { abstract: 'Title', chat_record_count: 'Total Messages', + user: 'User', feedback: { label: 'User Feedback', star: 'Agree', diff --git a/ui/src/locales/lang/zh-CN/views/log.ts b/ui/src/locales/lang/zh-CN/views/log.ts index f55681e76..c866a9551 100644 --- a/ui/src/locales/lang/zh-CN/views/log.ts +++ b/ui/src/locales/lang/zh-CN/views/log.ts @@ -13,6 +13,7 @@ export default { table: { abstract: '摘要', chat_record_count: '对话提问数', + user: '用户', feedback: { label: '用户反馈', star: '赞同', @@ -35,6 +36,6 @@ export default { }, title: { placeholder: '请给当前内容设置一个标题,以便管理查看' - }, + } } } diff --git a/ui/src/locales/lang/zh-Hant/views/log.ts b/ui/src/locales/lang/zh-Hant/views/log.ts index 9073e4840..5e84a698d 100644 --- a/ui/src/locales/lang/zh-Hant/views/log.ts +++ b/ui/src/locales/lang/zh-Hant/views/log.ts @@ -13,6 +13,7 @@ export default { table: { abstract: '摘要', chat_record_count: '對話提問數', + user: '用戶', feedback: { label: '用戶反饋', star: '贊同', @@ -35,6 +36,6 @@ export default { }, title: { placeholder: '請給當前內容設定一個標題,以便管理查看' - }, + } } } diff --git a/ui/src/views/log/index.vue b/ui/src/views/log/index.vue index 68c332e3b..3c2930191 100644 --- a/ui/src/views/log/index.vue +++ b/ui/src/views/log/index.vue @@ -142,21 +142,16 @@ + + + - -