Skip to content

Commit 4f95572

Browse files
committed
refactor: 处理历史会话中图片的问题
1 parent b406a89 commit 4f95572

File tree

9 files changed

+89
-13
lines changed

9 files changed

+89
-13
lines changed

apps/application/flow/step_node/document_extract_node/impl/base_document_extract_node.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ def execute(self, document, **kwargs):
1515

1616
self.context['document_list'] = document
1717
content = ''
18-
spliter = '\n-----------------------------------\n'
18+
splitter = '\n-----------------------------------\n'
1919
if document is None:
2020
return NodeResult({'content': content}, {})
2121

@@ -29,7 +29,7 @@ def execute(self, document, **kwargs):
2929
# 回到文件头
3030
buffer.seek(0)
3131
file_content = split_handle.get_content(buffer)
32-
content += spliter + '## ' + doc['name'] + '\n' + file_content
32+
content += splitter + '## ' + doc['name'] + '\n' + file_content
3333
break
3434

3535
return NodeResult({'content': content}, {})

apps/application/flow/step_node/image_understand_step_node/i_image_understand_node.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ class ImageUnderstandNodeSerializer(serializers.Serializer):
1616
# 多轮对话数量
1717
dialogue_number = serializers.IntegerField(required=True, error_messages=ErrMessage.integer("多轮对话数量"))
1818

19+
dialogue_type = serializers.CharField(required=True, error_messages=ErrMessage.char("对话存储类型"))
20+
1921
is_result = serializers.BooleanField(required=False, error_messages=ErrMessage.boolean('是否返回内容'))
2022

2123
image_list = serializers.ListField(required=False, error_messages=ErrMessage.list("图片"))
@@ -32,7 +34,7 @@ def _run(self):
3234
self.node_params_serializer.data.get('image_list')[1:])
3335
return self.execute(image=res, **self.node_params_serializer.data, **self.flow_params_serializer.data)
3436

35-
def execute(self, model_id, system, prompt, dialogue_number, history_chat_record, stream, chat_id,
37+
def execute(self, model_id, system, prompt, dialogue_number, dialogue_type, history_chat_record, stream, chat_id,
3638
chat_record_id,
3739
image,
3840
**kwargs) -> NodeResult:

apps/application/flow/step_node/image_understand_step_node/impl/base_image_understand_node.py

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -63,18 +63,18 @@ def save_context(self, details, workflow_manage):
6363
self.context['question'] = details.get('question')
6464
self.answer_text = details.get('answer')
6565

66-
def execute(self, model_id, system, prompt, dialogue_number, history_chat_record, stream, chat_id, chat_record_id,
66+
def execute(self, model_id, system, prompt, dialogue_number, dialogue_type, history_chat_record, stream, chat_id, chat_record_id,
6767
image,
6868
**kwargs) -> NodeResult:
6969
image_model = get_model_instance_by_model_user_id(model_id, self.flow_params_serializer.data.get('user_id'))
7070
history_message = self.get_history_message(history_chat_record, dialogue_number)
7171
self.context['history_message'] = history_message
7272
question = self.generate_prompt_question(prompt)
7373
self.context['question'] = question.content
74-
# todo 处理上传图片
7574
message_list = self.generate_message_list(image_model, system, prompt, history_message, image)
7675
self.context['message_list'] = message_list
7776
self.context['image_list'] = image
77+
self.context['dialogue_type'] = dialogue_type
7878
if stream:
7979
r = image_model.stream(message_list)
8080
return NodeResult({'result': r, 'chat_model': image_model, 'message_list': message_list,
@@ -86,15 +86,31 @@ def execute(self, model_id, system, prompt, dialogue_number, history_chat_record
8686
'history_message': history_message, 'question': question.content}, {},
8787
_write_context=write_context)
8888

89-
@staticmethod
90-
def get_history_message(history_chat_record, dialogue_number):
89+
def get_history_message(self, history_chat_record, dialogue_number):
9190
start_index = len(history_chat_record) - dialogue_number
9291
history_message = reduce(lambda x, y: [*x, *y], [
93-
[history_chat_record[index].get_human_message(), history_chat_record[index].get_ai_message()]
92+
[self.generate_history_human_message(history_chat_record[index]), history_chat_record[index].get_ai_message()]
9493
for index in
9594
range(start_index if start_index > 0 else 0, len(history_chat_record))], [])
9695
return history_message
9796

97+
def generate_history_human_message(self, chat_record):
98+
99+
for data in chat_record.details.values():
100+
if self.node.id == data['node_id'] and 'image_list' in data:
101+
image_list = data['image_list']
102+
if len(image_list) == 0 or data['dialogue_type'] == 'WORKFLOW':
103+
return HumanMessage(content=chat_record.problem_text)
104+
file_id = image_list[0]['file_id']
105+
file = QuerySet(File).filter(id=file_id).first()
106+
base64_image = base64.b64encode(file.get_byte()).decode("utf-8")
107+
return HumanMessage(
108+
content=[
109+
{'type': 'text', 'text': data['question']},
110+
{'type': 'image_url', 'image_url': {'url': f'data:image/jpeg;base64,{base64_image}'}},
111+
])
112+
return HumanMessage(content=chat_record.problem_text)
113+
98114
def generate_prompt_question(self, prompt):
99115
return HumanMessage(self.workflow_manage.generate_prompt(prompt))
100116

@@ -148,5 +164,6 @@ def get_details(self, index: int, **kwargs):
148164
'answer_tokens': self.context.get('answer_tokens'),
149165
'status': self.status,
150166
'err_message': self.err_message,
151-
'image_list': self.context.get('image_list')
167+
'image_list': self.context.get('image_list'),
168+
'dialogue_type': self.context.get('dialogue_type')
152169
}

apps/application/views/chat_views.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -442,7 +442,8 @@ class UploadFile(APIView):
442442
def post(self, request: Request, application_id: str, chat_id: str):
443443
files = request.FILES.getlist('file')
444444
file_ids = []
445-
meta = {'application_id': application_id, 'chat_id': chat_id}
445+
debug = request.data.get("debug", "false").lower() == "true"
446+
meta = {'application_id': application_id, 'chat_id': chat_id, 'debug': debug}
446447
for file in files:
447448
file_url = FileSerializer(data={'file': file, 'meta': meta}).upload()
448449
file_ids.append({'name': file.name, 'url': file_url, 'file_id': file_url.split('/')[-1]})

apps/common/job/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,10 @@
88
"""
99
from .client_access_num_job import *
1010
from .clean_chat_job import *
11+
from .clean_debug_file_job import *
1112

1213

1314
def run():
1415
client_access_num_job.run()
1516
clean_chat_job.run()
17+
clean_debug_file_job.run()
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# coding=utf-8
2+
3+
import logging
4+
from datetime import timedelta
5+
6+
from apscheduler.schedulers.background import BackgroundScheduler
7+
from django.db.models import Q
8+
from django.utils import timezone
9+
from django_apscheduler.jobstores import DjangoJobStore
10+
11+
from common.lock.impl.file_lock import FileLock
12+
from dataset.models import File
13+
14+
scheduler = BackgroundScheduler()
15+
scheduler.add_jobstore(DjangoJobStore(), "default")
16+
lock = FileLock()
17+
18+
19+
def clean_debug_file():
20+
logging.getLogger("max_kb").info('开始清理debug文件')
21+
two_hours_ago = timezone.now() - timedelta(hours=2)
22+
# 删除对应的文件
23+
File.objects.filter(Q(create_time__lt=two_hours_ago) & Q(meta__debug=True)).delete()
24+
logging.getLogger("max_kb").info('结束清理debug文件')
25+
26+
27+
def run():
28+
if lock.try_lock('clean_debug_file', 30 * 30):
29+
try:
30+
scheduler.start()
31+
clean_debug_file_job = scheduler.get_job(job_id='clean_debug_file')
32+
if clean_debug_file_job is not None:
33+
clean_debug_file_job.remove()
34+
scheduler.add_job(clean_debug_file, 'cron', hour='2', minute='0', second='0', id='clean_debug_file')
35+
finally:
36+
lock.un_lock('clean_debug_file')

ui/src/components/ai-chat/component/chat-input-operate/index.vue

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ const props = withDefaults(
100100
appId?: string
101101
chatId: string
102102
sendMessage: (question: string, other_params_data?: any, chat?: chatType) => void
103+
openChatId: () => Promise<string>
103104
}>(),
104105
{
105106
applicationDetails: () => ({}),
@@ -165,8 +166,14 @@ const uploadFile = async (file: any, fileList: any) => {
165166
}
166167
167168
if (!chatId_context.value) {
168-
const res = await applicationApi.getChatOpen(props.applicationDetails.id as string)
169-
chatId_context.value = res.data
169+
const res = await props.openChatId()
170+
chatId_context.value = res
171+
}
172+
173+
if (props.type === 'debug-ai-chat') {
174+
formData.append('debug', 'true')
175+
} else {
176+
formData.append('debug', 'false')
170177
}
171178
172179
applicationApi

ui/src/components/ai-chat/index.vue

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
:is-mobile="isMobile"
3939
:type="type"
4040
:send-message="sendMessage"
41+
:open-chat-id="openChatId"
4142
v-model:chat-id="chartOpenId"
4243
v-model:loading="loading"
4344
v-if="type !== 'log'"

ui/src/workflow/nodes/image-understand/index.vue

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,16 @@
128128
@submitDialog="submitDialog"
129129
/>
130130
</el-form-item>
131-
<el-form-item label="历史聊天记录">
131+
<el-form-item>
132+
<template #label>
133+
<div class="flex-between">
134+
<div>历史聊天记录</div>
135+
<el-select v-model="form_data.dialogue_type" class="w-120">
136+
<el-option label="节点" value="NODE"/>
137+
<el-option label="工作流" value="WORKFLOW"/>
138+
</el-select>
139+
</div>
140+
</template>
132141
<el-input-number
133142
v-model="form_data.dialogue_number"
134143
:min="0"
@@ -213,6 +222,7 @@ const form = {
213222
system: '',
214223
prompt: defaultPrompt,
215224
dialogue_number: 0,
225+
dialogue_type: 'NODE',
216226
is_result: true,
217227
temperature: null,
218228
max_tokens: null,

0 commit comments

Comments
 (0)