From 1a7f484a62a471ffc4409f23b119305973a5513a Mon Sep 17 00:00:00 2001
From: shaohuzhang1 <80892890+shaohuzhang1@users.noreply.github.com>
Date: Tue, 18 Mar 2025 15:50:30 +0800
Subject: [PATCH] feat: User information in the application conversation log.
(#2599)
---
.../step/chat_step/impl/base_chat_step.py | 17 ++++++---
apps/application/flow/i_step_node.py | 3 +-
.../application/migrations/0026_chat_asker.py | 20 ++++++++++
apps/application/models/application.py | 5 +++
.../serializers/chat_message_serializers.py | 25 ++++++++++---
.../application/sql/list_application_chat.sql | 2 +-
.../ai-chat/component/user-form/index.vue | 37 ++++++++++++-------
ui/src/locales/lang/en-US/views/log.ts | 1 +
ui/src/locales/lang/zh-CN/views/log.ts | 3 +-
ui/src/locales/lang/zh-Hant/views/log.ts | 3 +-
ui/src/views/log/index.vue | 15 +++-----
11 files changed, 93 insertions(+), 38 deletions(-)
create mode 100644 apps/application/migrations/0026_chat_asker.py
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 @@
+
+
+ {{ row.asker?.user_name }}
+
+
{{ datetimeFormat(row.update_time) }}
-
-