feat: Application chat (#3494)
This commit is contained in:
parent
50e93e490a
commit
6effb8f0fb
@ -307,10 +307,9 @@ class BaseChatStep(IChatStep):
|
|||||||
else:
|
else:
|
||||||
reasoning_content = reasoning_result.get('reasoning_content') + reasoning_result_end.get(
|
reasoning_content = reasoning_result.get('reasoning_content') + reasoning_result_end.get(
|
||||||
'reasoning_content')
|
'reasoning_content')
|
||||||
asker = manage.context.get('form_data', {}).get('asker', None)
|
|
||||||
post_response_handler.handler(chat_id, chat_record_id, paragraph_list, problem_text,
|
post_response_handler.handler(chat_id, chat_record_id, paragraph_list, problem_text,
|
||||||
chat_id, manage, self, padding_problem_text,
|
content, manage, self, padding_problem_text,
|
||||||
reasoning_content=reasoning_content if reasoning_content_enable else '')
|
reasoning_content=reasoning_content)
|
||||||
add_access_num(client_id, client_type, manage.context.get('application_id'))
|
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),
|
return manage.get_base_to_response().to_block_response(str(chat_id), str(chat_record_id),
|
||||||
content, True,
|
content, True,
|
||||||
@ -324,10 +323,8 @@ class BaseChatStep(IChatStep):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
all_text = 'Exception:' + str(e)
|
all_text = 'Exception:' + str(e)
|
||||||
write_context(self, manage, 0, 0, all_text)
|
write_context(self, manage, 0, 0, all_text)
|
||||||
asker = manage.context.get('form_data', {}).get('asker', None)
|
|
||||||
post_response_handler.handler(chat_id, chat_record_id, paragraph_list, problem_text,
|
post_response_handler.handler(chat_id, chat_record_id, paragraph_list, problem_text,
|
||||||
chat_id, manage, self, padding_problem_text,
|
all_text, manage, self, padding_problem_text, reasoning_content='')
|
||||||
reasoning_content='')
|
|
||||||
add_access_num(client_id, client_type, manage.context.get('application_id'))
|
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,
|
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)
|
0, _status=status.HTTP_500_INTERNAL_SERVER_ERROR)
|
||||||
|
|||||||
@ -61,7 +61,7 @@ def file_id_to_base64(file_id: str):
|
|||||||
file = QuerySet(File).filter(id=file_id).first()
|
file = QuerySet(File).filter(id=file_id).first()
|
||||||
file_bytes = file.get_bytes()
|
file_bytes = file.get_bytes()
|
||||||
base64_image = base64.b64encode(file_bytes).decode("utf-8")
|
base64_image = base64.b64encode(file_bytes).decode("utf-8")
|
||||||
return [base64_image, what(None, file_bytes.tobytes())]
|
return [base64_image, what(None, file_bytes)]
|
||||||
|
|
||||||
|
|
||||||
class BaseImageUnderstandNode(IImageUnderstandNode):
|
class BaseImageUnderstandNode(IImageUnderstandNode):
|
||||||
@ -173,7 +173,7 @@ class BaseImageUnderstandNode(IImageUnderstandNode):
|
|||||||
file = QuerySet(File).filter(id=file_id).first()
|
file = QuerySet(File).filter(id=file_id).first()
|
||||||
image_bytes = file.get_bytes()
|
image_bytes = file.get_bytes()
|
||||||
base64_image = base64.b64encode(image_bytes).decode("utf-8")
|
base64_image = base64.b64encode(image_bytes).decode("utf-8")
|
||||||
image_format = what(None, image_bytes.tobytes())
|
image_format = what(None, image_bytes)
|
||||||
images.append(
|
images.append(
|
||||||
{'type': 'image_url', 'image_url': {'url': f'data:image/{image_format};base64,{base64_image}'}})
|
{'type': 'image_url', 'image_url': {'url': f'data:image/{image_format};base64,{base64_image}'}})
|
||||||
messages = [HumanMessage(
|
messages = [HumanMessage(
|
||||||
|
|||||||
@ -22,12 +22,16 @@ def get_default_global_variable(input_field_list: List):
|
|||||||
|
|
||||||
|
|
||||||
def get_global_variable(node):
|
def get_global_variable(node):
|
||||||
|
body = node.workflow_manage.get_body()
|
||||||
history_chat_record = node.flow_params_serializer.data.get('history_chat_record', [])
|
history_chat_record = node.flow_params_serializer.data.get('history_chat_record', [])
|
||||||
history_context = [{'question': chat_record.problem_text, 'answer': chat_record.answer_text} for chat_record in
|
history_context = [{'question': chat_record.problem_text, 'answer': chat_record.answer_text} for chat_record in
|
||||||
history_chat_record]
|
history_chat_record]
|
||||||
chat_id = node.flow_params_serializer.data.get('chat_id')
|
chat_id = node.flow_params_serializer.data.get('chat_id')
|
||||||
return {'time': datetime.now().strftime('%Y-%m-%d %H:%M:%S'), 'start_time': time.time(),
|
return {'time': datetime.now().strftime('%Y-%m-%d %H:%M:%S'), 'start_time': time.time(),
|
||||||
'history_context': history_context, 'chat_id': str(chat_id), **node.workflow_manage.form_data}
|
'history_context': history_context, 'chat_id': str(chat_id), **node.workflow_manage.form_data,
|
||||||
|
'chat_user_id': body.get('chat_user_id'),
|
||||||
|
'chat_user_type': body.get('chat_user_type'),
|
||||||
|
'chat_user': body.get('chat_user')}
|
||||||
|
|
||||||
|
|
||||||
class BaseStartStepNode(IStarNode):
|
class BaseStartStepNode(IStarNode):
|
||||||
@ -64,6 +68,7 @@ class BaseStartStepNode(IStarNode):
|
|||||||
'document': self.workflow_manage.document_list,
|
'document': self.workflow_manage.document_list,
|
||||||
'audio': self.workflow_manage.audio_list,
|
'audio': self.workflow_manage.audio_list,
|
||||||
'other': self.workflow_manage.other_list,
|
'other': self.workflow_manage.other_list,
|
||||||
|
|
||||||
}
|
}
|
||||||
return NodeResult(node_variable, workflow_variable)
|
return NodeResult(node_variable, workflow_variable)
|
||||||
|
|
||||||
|
|||||||
@ -154,8 +154,8 @@ class WorkflowManage:
|
|||||||
if global_fields is not None:
|
if global_fields is not None:
|
||||||
for global_field in global_fields:
|
for global_field in global_fields:
|
||||||
global_field_list.append({**global_field, 'node_id': node_id, 'node_name': node_name})
|
global_field_list.append({**global_field, 'node_id': node_id, 'node_name': node_name})
|
||||||
field_list.sort(key=lambda f: len(f.get('node_name')), reverse=True)
|
field_list.sort(key=lambda f: len(f.get('node_name') + f.get('value')), reverse=True)
|
||||||
global_field_list.sort(key=lambda f: len(f.get('node_name')), reverse=True)
|
global_field_list.sort(key=lambda f: len(f.get('node_name') + f.get('value')), reverse=True)
|
||||||
self.field_list = field_list
|
self.field_list = field_list
|
||||||
self.global_field_list = global_field_list
|
self.global_field_list = global_field_list
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,33 @@
|
|||||||
|
# Generated by Django 5.2.3 on 2025-07-07 02:59
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('application', '0004_application_publish_time_applicationversion_and_more'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='chat',
|
||||||
|
name='chat_record_count',
|
||||||
|
field=models.IntegerField(default=0, verbose_name='对话次数'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='chat',
|
||||||
|
name='mark_sum',
|
||||||
|
field=models.IntegerField(default=0, verbose_name='标记数量'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='chat',
|
||||||
|
name='star_num',
|
||||||
|
field=models.IntegerField(default=0, verbose_name='点赞数量'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='chat',
|
||||||
|
name='trample_num',
|
||||||
|
field=models.IntegerField(default=0, verbose_name='点踩数量'),
|
||||||
|
),
|
||||||
|
]
|
||||||
@ -39,6 +39,10 @@ class Chat(AppModelMixin):
|
|||||||
is_deleted = models.BooleanField(verbose_name="逻辑删除", default=False)
|
is_deleted = models.BooleanField(verbose_name="逻辑删除", default=False)
|
||||||
asker = models.JSONField(verbose_name="访问者", default=default_asker, encoder=SystemEncoder)
|
asker = models.JSONField(verbose_name="访问者", default=default_asker, encoder=SystemEncoder)
|
||||||
meta = models.JSONField(verbose_name="元数据", default=dict)
|
meta = models.JSONField(verbose_name="元数据", default=dict)
|
||||||
|
star_num = models.IntegerField(verbose_name="点赞数量", default=0)
|
||||||
|
trample_num = models.IntegerField(verbose_name="点踩数量", default=0)
|
||||||
|
chat_record_count = models.IntegerField(verbose_name="对话次数", default=0)
|
||||||
|
mark_sum = models.IntegerField(verbose_name="标记数量", default=0)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
db_table = "application_chat"
|
db_table = "application_chat"
|
||||||
|
|||||||
@ -22,12 +22,12 @@ from django.utils.translation import gettext_lazy as _, gettext
|
|||||||
from openpyxl.cell.cell import ILLEGAL_CHARACTERS_RE
|
from openpyxl.cell.cell import ILLEGAL_CHARACTERS_RE
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
|
|
||||||
from application.models import Chat, Application
|
from application.models import Chat, Application, ChatRecord
|
||||||
from common.db.search import get_dynamics_model, native_search, native_page_search
|
from common.db.search import get_dynamics_model, native_search, native_page_search
|
||||||
from common.exception.app_exception import AppApiException
|
from common.exception.app_exception import AppApiException
|
||||||
from common.utils.common import get_file_content
|
from common.utils.common import get_file_content
|
||||||
from maxkb.conf import PROJECT_DIR
|
from maxkb.conf import PROJECT_DIR
|
||||||
from maxkb.settings import TIME_ZONE
|
from maxkb.settings import TIME_ZONE, edition
|
||||||
|
|
||||||
|
|
||||||
class ApplicationChatResponseSerializers(serializers.Serializer):
|
class ApplicationChatResponseSerializers(serializers.Serializer):
|
||||||
@ -120,12 +120,8 @@ class ApplicationChatQuerySerializers(serializers.Serializer):
|
|||||||
condition = base_condition & min_trample_query
|
condition = base_condition & min_trample_query
|
||||||
else:
|
else:
|
||||||
condition = base_condition
|
condition = base_condition
|
||||||
inner_queryset = QuerySet(Chat).filter(application_id=self.data.get("application_id"))
|
|
||||||
if 'abstract' in self.data and self.data.get('abstract') is not None:
|
|
||||||
inner_queryset = inner_queryset.filter(abstract__icontains=self.data.get('abstract'))
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
'inner_queryset': inner_queryset,
|
|
||||||
'default_queryset': query_set.filter(condition).order_by("-application_chat.update_time")
|
'default_queryset': query_set.filter(condition).order_by("-application_chat.update_time")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -133,7 +129,8 @@ class ApplicationChatQuerySerializers(serializers.Serializer):
|
|||||||
if with_valid:
|
if with_valid:
|
||||||
self.is_valid(raise_exception=True)
|
self.is_valid(raise_exception=True)
|
||||||
return native_search(self.get_query_set(), select_string=get_file_content(
|
return native_search(self.get_query_set(), select_string=get_file_content(
|
||||||
os.path.join(PROJECT_DIR, "apps", "application", 'sql', 'list_application_chat.sql')),
|
os.path.join(PROJECT_DIR, "apps", "application", 'sql', ('list_application_chat_ee.sql' if ['PE', 'EE'].__contains__(
|
||||||
|
edition) else 'list_application_chat.sql'))),
|
||||||
with_table_name=False)
|
with_table_name=False)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@ -144,7 +141,7 @@ class ApplicationChatQuerySerializers(serializers.Serializer):
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def to_row(row: Dict):
|
def to_row(row: Dict):
|
||||||
details = row.get('details')
|
details = row.get('details') or {}
|
||||||
padding_problem_text = ' '.join(node.get("answer", "") for key, node in details.items() if
|
padding_problem_text = ' '.join(node.get("answer", "") for key, node in details.items() if
|
||||||
node.get("type") == 'question-node')
|
node.get("type") == 'question-node')
|
||||||
search_dataset_node_list = [(key, node) for key, node in details.items() if
|
search_dataset_node_list = [(key, node) for key, node in details.items() if
|
||||||
@ -161,7 +158,7 @@ class ApplicationChatQuerySerializers(serializers.Serializer):
|
|||||||
'name') + ':\n' + ApplicationChatQuerySerializers.paragraph_list_to_string(node.get('paragraph_list',
|
'name') + ':\n' + ApplicationChatQuerySerializers.paragraph_list_to_string(node.get('paragraph_list',
|
||||||
[])) for
|
[])) for
|
||||||
key, node in search_dataset_node_list])
|
key, node in search_dataset_node_list])
|
||||||
improve_paragraph_list = row.get('improve_paragraph_list')
|
improve_paragraph_list = row.get('improve_paragraph_list') or []
|
||||||
vote_status_map = {'-1': '未投票', '0': '赞同', '1': '反对'}
|
vote_status_map = {'-1': '未投票', '0': '赞同', '1': '反对'}
|
||||||
return [str(row.get('chat_id')), row.get('abstract'), row.get('problem_text'), padding_problem_text,
|
return [str(row.get('chat_id')), row.get('abstract'), row.get('problem_text'), padding_problem_text,
|
||||||
row.get('answer_text'), vote_status_map.get(row.get('vote_status')), reference_paragraph_len,
|
row.get('answer_text'), vote_status_map.get(row.get('vote_status')), reference_paragraph_len,
|
||||||
@ -169,18 +166,20 @@ class ApplicationChatQuerySerializers(serializers.Serializer):
|
|||||||
"\n".join([
|
"\n".join([
|
||||||
f"{improve_paragraph_list[index].get('title')}\n{improve_paragraph_list[index].get('content')}"
|
f"{improve_paragraph_list[index].get('title')}\n{improve_paragraph_list[index].get('content')}"
|
||||||
for index in range(len(improve_paragraph_list))]),
|
for index in range(len(improve_paragraph_list))]),
|
||||||
row.get('message_tokens') + row.get('answer_tokens'), row.get('run_time'),
|
(row.get('message_tokens') or 0) + (row.get('answer_tokens') or 0), row.get('run_time'),
|
||||||
str(row.get('create_time').astimezone(pytz.timezone(TIME_ZONE)).strftime('%Y-%m-%d %H:%M:%S')
|
str(row.get('create_time').astimezone(pytz.timezone(TIME_ZONE)).strftime('%Y-%m-%d %H:%M:%S')
|
||||||
)]
|
if row.get('create_time') is not None else None)]
|
||||||
|
|
||||||
def export(self, data, with_valid=True):
|
def export(self, data, with_valid=True):
|
||||||
if with_valid:
|
if with_valid:
|
||||||
self.is_valid(raise_exception=True)
|
self.is_valid(raise_exception=True)
|
||||||
ApplicationChatRecordExportRequest(data=data).is_valid(raise_exception=True)
|
ApplicationChatRecordExportRequest(data=data).is_valid(raise_exception=True)
|
||||||
|
|
||||||
data_list = native_search(self.get_query_set(data.get('select_ids')),
|
data_list = native_search(self.get_query_set(data.get('select_ids')),
|
||||||
select_string=get_file_content(
|
select_string=get_file_content(
|
||||||
os.path.join(PROJECT_DIR, "apps", "application", 'sql',
|
os.path.join(PROJECT_DIR, "apps", "application", 'sql',
|
||||||
'export_application_chat.sql')),
|
('export_application_chat_ee.sql' if ['PE', 'EE'].__contains__(
|
||||||
|
edition) else 'export_application_chat.sql'))),
|
||||||
with_table_name=False)
|
with_table_name=False)
|
||||||
|
|
||||||
batch_size = 500
|
batch_size = 500
|
||||||
@ -232,5 +231,26 @@ class ApplicationChatQuerySerializers(serializers.Serializer):
|
|||||||
if with_valid:
|
if with_valid:
|
||||||
self.is_valid(raise_exception=True)
|
self.is_valid(raise_exception=True)
|
||||||
return native_page_search(current_page, page_size, self.get_query_set(), select_string=get_file_content(
|
return native_page_search(current_page, page_size, self.get_query_set(), select_string=get_file_content(
|
||||||
os.path.join(PROJECT_DIR, "apps", "application", 'sql', 'list_application_chat.sql')),
|
os.path.join(PROJECT_DIR, "apps", "application", 'sql',
|
||||||
|
('list_application_chat_ee.sql' if ['PE', 'EE'].__contains__(
|
||||||
|
edition) else 'list_application_chat.sql'))),
|
||||||
with_table_name=False)
|
with_table_name=False)
|
||||||
|
|
||||||
|
|
||||||
|
class ChatCountSerializer(serializers.Serializer):
|
||||||
|
chat_id = serializers.UUIDField(required=True, label=_("Conversation ID"))
|
||||||
|
|
||||||
|
def get_query_set(self):
|
||||||
|
return QuerySet(ChatRecord).filter(chat_id=self.data.get('chat_id'))
|
||||||
|
|
||||||
|
def update_chat(self):
|
||||||
|
self.is_valid(raise_exception=True)
|
||||||
|
count_chat_record = native_search(self.get_query_set(), get_file_content(
|
||||||
|
os.path.join(PROJECT_DIR, "apps", "application", 'sql', 'count_chat_record.sql')), with_search_one=True)
|
||||||
|
QuerySet(Chat).filter(id=self.data.get('chat_id')).update(star_num=count_chat_record.get('star_num', 0) or 0,
|
||||||
|
trample_num=count_chat_record.get('trample_num',
|
||||||
|
0) or 0,
|
||||||
|
chat_record_count=count_chat_record.get(
|
||||||
|
'chat_record_count', 0) or 0,
|
||||||
|
mark_sum=count_chat_record.get('mark_sum', 0) or 0)
|
||||||
|
return True
|
||||||
|
|||||||
@ -18,6 +18,7 @@ from rest_framework import serializers
|
|||||||
from rest_framework.utils.formatting import lazy_format
|
from rest_framework.utils.formatting import lazy_format
|
||||||
|
|
||||||
from application.models import ChatRecord, ApplicationAccessToken, Application
|
from application.models import ChatRecord, ApplicationAccessToken, Application
|
||||||
|
from application.serializers.application_chat import ChatCountSerializer
|
||||||
from application.serializers.common import ChatInfo
|
from application.serializers.common import ChatInfo
|
||||||
from common.db.search import page_search
|
from common.db.search import page_search
|
||||||
from common.exception.app_exception import AppApiException
|
from common.exception.app_exception import AppApiException
|
||||||
@ -359,6 +360,7 @@ class ApplicationChatRecordImproveSerializer(serializers.Serializer):
|
|||||||
update_document_char_length(document_id)
|
update_document_char_length(document_id)
|
||||||
# 添加标注
|
# 添加标注
|
||||||
chat_record.save()
|
chat_record.save()
|
||||||
|
ChatCountSerializer(data={'chat_id': chat_id}).update_chat()
|
||||||
return ChatRecordSerializerModel(chat_record).data, paragraph.id, knowledge_id
|
return ChatRecordSerializerModel(chat_record).data, paragraph.id, knowledge_id
|
||||||
|
|
||||||
class Operate(serializers.Serializer):
|
class Operate(serializers.Serializer):
|
||||||
|
|||||||
@ -14,8 +14,9 @@ from django.db.models import QuerySet
|
|||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
from application.chat_pipeline.step.chat_step.i_chat_step import PostResponseHandler
|
from application.chat_pipeline.step.chat_step.i_chat_step import PostResponseHandler
|
||||||
from application.models import Application, ChatRecord, Chat, ApplicationVersion
|
from application.models import Application, ChatRecord, Chat, ApplicationVersion, ChatUserType
|
||||||
from common.constants.cache_version import Cache_Version
|
from common.constants.cache_version import Cache_Version
|
||||||
|
from common.database_model_manage.database_model_manage import DatabaseModelManage
|
||||||
from common.exception.app_exception import ChatException
|
from common.exception.app_exception import ChatException
|
||||||
from models_provider.models import Model
|
from models_provider.models import Model
|
||||||
from models_provider.tools import get_model_credential
|
from models_provider.tools import get_model_credential
|
||||||
@ -47,6 +48,7 @@ class ChatInfo:
|
|||||||
self.application_id = application_id
|
self.application_id = application_id
|
||||||
self.chat_record_list: List[ChatRecord] = []
|
self.chat_record_list: List[ChatRecord] = []
|
||||||
self.application = None
|
self.application = None
|
||||||
|
self.chat_user = None
|
||||||
self.debug = debug
|
self.debug = debug
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@ -73,8 +75,30 @@ class ChatInfo:
|
|||||||
self.application = application
|
self.application = application
|
||||||
return application
|
return application
|
||||||
|
|
||||||
|
def get_chat_user(self, asker=None):
|
||||||
|
if self.chat_user:
|
||||||
|
return self.chat_user
|
||||||
|
if self.chat_user_type == ChatUserType.CHAT_USER.value:
|
||||||
|
chat_user_model = DatabaseModelManage.get_model("chat_user")
|
||||||
|
chat_user = QuerySet(chat_user_model).filter(id=self.chat_user_id).first()
|
||||||
|
return {
|
||||||
|
'id': chat_user.id,
|
||||||
|
'email': chat_user.email,
|
||||||
|
'phone': chat_user.phone,
|
||||||
|
'nick_name': chat_user.nick_name,
|
||||||
|
'username': chat_user.username,
|
||||||
|
'source': chat_user.source
|
||||||
|
}
|
||||||
|
else:
|
||||||
|
if asker:
|
||||||
|
self.chat_user = asker
|
||||||
|
else:
|
||||||
|
self.chat_user = {'username': '游客'}
|
||||||
|
return self.chat_user
|
||||||
|
|
||||||
def to_base_pipeline_manage_params(self):
|
def to_base_pipeline_manage_params(self):
|
||||||
self.get_application()
|
self.get_application()
|
||||||
|
self.get_chat_user()
|
||||||
knowledge_setting = self.application.knowledge_setting
|
knowledge_setting = self.application.knowledge_setting
|
||||||
model_setting = self.application.model_setting
|
model_setting = self.application.model_setting
|
||||||
model_id = self.application.model_id
|
model_id = self.application.model_id
|
||||||
@ -139,7 +163,8 @@ class ChatInfo:
|
|||||||
if not self.debug:
|
if not self.debug:
|
||||||
if not QuerySet(Chat).filter(id=self.chat_id).exists():
|
if not QuerySet(Chat).filter(id=self.chat_id).exists():
|
||||||
Chat(id=self.chat_id, application_id=self.application_id, abstract=chat_record.problem_text[0:1024],
|
Chat(id=self.chat_id, application_id=self.application_id, abstract=chat_record.problem_text[0:1024],
|
||||||
chat_user_id=self.chat_user_id, chat_user_type=self.chat_user_type).save()
|
chat_user_id=self.chat_user_id, chat_user_type=self.chat_user_type,
|
||||||
|
asker=self.get_chat_user()).save()
|
||||||
else:
|
else:
|
||||||
QuerySet(Chat).filter(id=self.chat_id).update(update_time=datetime.now())
|
QuerySet(Chat).filter(id=self.chat_id).update(update_time=datetime.now())
|
||||||
# 插入会话记录
|
# 插入会话记录
|
||||||
|
|||||||
7
apps/application/sql/count_chat_record.sql
Normal file
7
apps/application/sql/count_chat_record.sql
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
SELECT COUNT
|
||||||
|
( "id" ) AS chat_record_count,
|
||||||
|
SUM ( CASE WHEN "vote_status" = '0' THEN 1 ELSE 0 END ) AS star_num,
|
||||||
|
SUM ( CASE WHEN "vote_status" = '1' THEN 1 ELSE 0 END ) AS trample_num,
|
||||||
|
SUM ( CASE WHEN array_length( application_chat_record.improve_paragraph_id_list, 1 ) IS NULL THEN 0 ELSE array_length( application_chat_record.improve_paragraph_id_list, 1 ) END ) AS mark_sum
|
||||||
|
FROM
|
||||||
|
application_chat_record
|
||||||
@ -10,24 +10,11 @@ SELECT
|
|||||||
application_chat_record_temp."index" as "index",
|
application_chat_record_temp."index" as "index",
|
||||||
application_chat_record_temp.improve_paragraph_list as improve_paragraph_list,
|
application_chat_record_temp.improve_paragraph_list as improve_paragraph_list,
|
||||||
application_chat_record_temp.vote_status as vote_status,
|
application_chat_record_temp.vote_status as vote_status,
|
||||||
application_chat_record_temp.create_time as create_time
|
application_chat_record_temp.create_time as create_time,
|
||||||
|
application_chat.asker::json AS asker
|
||||||
FROM
|
FROM
|
||||||
application_chat application_chat
|
application_chat application_chat
|
||||||
LEFT JOIN (
|
LEFT JOIN (
|
||||||
SELECT COUNT
|
|
||||||
( "id" ) AS chat_record_count,
|
|
||||||
SUM ( CASE WHEN "vote_status" = '0' THEN 1 ELSE 0 END ) AS star_num,
|
|
||||||
SUM ( CASE WHEN "vote_status" = '1' THEN 1 ELSE 0 END ) AS trample_num,
|
|
||||||
SUM ( CASE WHEN array_length( application_chat_record.improve_paragraph_id_list, 1 ) IS NULL THEN 0 ELSE array_length( application_chat_record.improve_paragraph_id_list, 1 ) END ) AS mark_sum,
|
|
||||||
chat_id
|
|
||||||
FROM
|
|
||||||
application_chat_record
|
|
||||||
WHERE chat_id IN (
|
|
||||||
SELECT id FROM application_chat ${inner_queryset})
|
|
||||||
GROUP BY
|
|
||||||
application_chat_record.chat_id
|
|
||||||
) chat_record_temp ON application_chat."id" = chat_record_temp.chat_id
|
|
||||||
LEFT JOIN (
|
|
||||||
SELECT
|
SELECT
|
||||||
*,
|
*,
|
||||||
CASE
|
CASE
|
||||||
|
|||||||
28
apps/application/sql/export_application_chat_ee.sql
Normal file
28
apps/application/sql/export_application_chat_ee.sql
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
SELECT
|
||||||
|
application_chat."id" as chat_id,
|
||||||
|
application_chat.abstract as abstract,
|
||||||
|
application_chat_record_temp.problem_text as problem_text,
|
||||||
|
application_chat_record_temp.answer_text as answer_text,
|
||||||
|
application_chat_record_temp.message_tokens as message_tokens,
|
||||||
|
application_chat_record_temp.answer_tokens as answer_tokens,
|
||||||
|
application_chat_record_temp.run_time as run_time,
|
||||||
|
application_chat_record_temp.details::JSON as details,
|
||||||
|
application_chat_record_temp."index" as "index",
|
||||||
|
application_chat_record_temp.improve_paragraph_list as improve_paragraph_list,
|
||||||
|
application_chat_record_temp.vote_status as vote_status,
|
||||||
|
application_chat_record_temp.create_time as create_time,
|
||||||
|
(CASE WHEN "chat_user".id is NULL THEN application_chat.asker ELSE jsonb_build_object('id',chat_user.id,'user_name',chat_user.username) END)::json AS asker
|
||||||
|
FROM
|
||||||
|
application_chat application_chat
|
||||||
|
left join chat_user chat_user on chat_user.id::varchar = application_chat.chat_user_id
|
||||||
|
LEFT JOIN (
|
||||||
|
SELECT
|
||||||
|
*,
|
||||||
|
CASE
|
||||||
|
WHEN array_length( application_chat_record.improve_paragraph_id_list, 1 ) IS NULL THEN
|
||||||
|
'{}' ELSE ( SELECT ARRAY_AGG ( row_to_json ( paragraph ) ) FROM paragraph WHERE "id" = ANY ( application_chat_record.improve_paragraph_id_list ) )
|
||||||
|
END as improve_paragraph_list
|
||||||
|
FROM
|
||||||
|
application_chat_record application_chat_record
|
||||||
|
) application_chat_record_temp ON application_chat_record_temp.chat_id = application_chat."id"
|
||||||
|
${default_queryset}
|
||||||
@ -1,19 +1,3 @@
|
|||||||
SELECT
|
select application_chat.*,application_chat.asker::json AS asker
|
||||||
*
|
from application_chat application_chat
|
||||||
FROM
|
|
||||||
application_chat application_chat
|
|
||||||
LEFT JOIN (
|
|
||||||
SELECT COUNT
|
|
||||||
( "id" ) AS chat_record_count,
|
|
||||||
SUM ( CASE WHEN "vote_status" = '0' THEN 1 ELSE 0 END ) AS star_num,
|
|
||||||
SUM ( CASE WHEN "vote_status" = '1' THEN 1 ELSE 0 END ) AS trample_num,
|
|
||||||
SUM ( CASE WHEN array_length( application_chat_record.improve_paragraph_id_list, 1 ) IS NULL THEN 0 ELSE array_length( application_chat_record.improve_paragraph_id_list, 1 ) END ) AS mark_sum,
|
|
||||||
chat_id
|
|
||||||
FROM
|
|
||||||
application_chat_record
|
|
||||||
WHERE chat_id IN (
|
|
||||||
SELECT id FROM application_chat ${inner_queryset})
|
|
||||||
GROUP BY
|
|
||||||
application_chat_record.chat_id
|
|
||||||
) chat_record_temp ON application_chat."id" = chat_record_temp.chat_id
|
|
||||||
${default_queryset}
|
${default_queryset}
|
||||||
4
apps/application/sql/list_application_chat_ee.sql
Normal file
4
apps/application/sql/list_application_chat_ee.sql
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
select application_chat.*,(CASE WHEN "chat_user".id is NULL THEN application_chat.asker ELSE jsonb_build_object('id',chat_user.id,'user_name',chat_user.username) END)::json AS asker
|
||||||
|
from application_chat application_chat
|
||||||
|
left join chat_user chat_user on chat_user.id::varchar = application_chat.chat_user_id
|
||||||
|
${default_queryset}
|
||||||
@ -236,7 +236,8 @@ class ChatSerializers(serializers.Serializer):
|
|||||||
'chat_user_id': chat_user_id,
|
'chat_user_id': chat_user_id,
|
||||||
'chat_user_type': chat_user_type,
|
'chat_user_type': chat_user_type,
|
||||||
'workspace_id': workspace_id,
|
'workspace_id': workspace_id,
|
||||||
'debug': debug},
|
'debug': debug,
|
||||||
|
'chat_user': chat_info.get_chat_user()},
|
||||||
WorkFlowPostHandler(chat_info),
|
WorkFlowPostHandler(chat_info),
|
||||||
base_to_response, form_data, image_list, document_list, audio_list,
|
base_to_response, form_data, image_list, document_list, audio_list,
|
||||||
other_list,
|
other_list,
|
||||||
@ -250,6 +251,7 @@ class ChatSerializers(serializers.Serializer):
|
|||||||
ChatMessageSerializers(data=instance).is_valid(raise_exception=True)
|
ChatMessageSerializers(data=instance).is_valid(raise_exception=True)
|
||||||
chat_info = self.get_chat_info()
|
chat_info = self.get_chat_info()
|
||||||
chat_info.get_application()
|
chat_info.get_application()
|
||||||
|
chat_info.get_chat_user()
|
||||||
self.is_valid_chat_id(chat_info)
|
self.is_valid_chat_id(chat_info)
|
||||||
if chat_info.application.type == ApplicationTypeChoices.SIMPLE:
|
if chat_info.application.type == ApplicationTypeChoices.SIMPLE:
|
||||||
self.is_valid_application_simple(raise_exception=True, chat_info=chat_info)
|
self.is_valid_application_simple(raise_exception=True, chat_info=chat_info)
|
||||||
|
|||||||
@ -14,6 +14,7 @@ from django.utils.translation import gettext_lazy as _, gettext
|
|||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
|
|
||||||
from application.models import VoteChoices, ChatRecord, Chat
|
from application.models import VoteChoices, ChatRecord, Chat
|
||||||
|
from application.serializers.application_chat import ChatCountSerializer
|
||||||
from application.serializers.application_chat_record import ChatRecordSerializerModel
|
from application.serializers.application_chat_record import ChatRecordSerializerModel
|
||||||
from common.db.search import page_search
|
from common.db.search import page_search
|
||||||
from common.exception.app_exception import AppApiException
|
from common.exception.app_exception import AppApiException
|
||||||
@ -74,6 +75,7 @@ class VoteSerializer(serializers.Serializer):
|
|||||||
raise AppApiException(500, gettext("Already voted, please cancel first and then vote again"))
|
raise AppApiException(500, gettext("Already voted, please cancel first and then vote again"))
|
||||||
finally:
|
finally:
|
||||||
un_lock(self.data.get('chat_record_id'))
|
un_lock(self.data.get('chat_record_id'))
|
||||||
|
ChatCountSerializer(data={'chat_id': self.data.get('chat_id')}).update_chat()
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,23 @@
|
|||||||
|
# Generated by Django 5.2.3 on 2025-07-07 02:59
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('knowledge', '0002_alter_document_status_and_more'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='file',
|
||||||
|
name='source_id',
|
||||||
|
field=models.CharField(default='TEMPORARY_120_MINUTE', verbose_name='资源id'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='file',
|
||||||
|
name='source_type',
|
||||||
|
field=models.CharField(choices=[('KNOWLEDGE', 'Knowledge'), ('APPLICATION', 'Application'), ('TOOL', 'Tool'), ('DOCUMENT', 'Document'), ('CHAT', 'Chat'), ('TEMPORARY_30_MINUTE', 'Temporary 30 Minute'), ('TEMPORARY_120_MINUTE', 'Temporary 120 Minute'), ('TEMPORARY_1_DAY', 'Temporary 1 Day')], default='TEMPORARY_120_MINUTE', verbose_name='资源类型'),
|
||||||
|
),
|
||||||
|
]
|
||||||
@ -9,6 +9,9 @@ export default {
|
|||||||
question_count: '条提问',
|
question_count: '条提问',
|
||||||
exportRecords: '导出聊天记录',
|
exportRecords: '导出聊天记录',
|
||||||
chatId: '对话 ID',
|
chatId: '对话 ID',
|
||||||
|
chatUserId: '对话用户 ID',
|
||||||
|
chatUserType: '对话用户类型',
|
||||||
|
chatUser: '对话用户',
|
||||||
userInput: '用户输入',
|
userInput: '用户输入',
|
||||||
quote: '引用',
|
quote: '引用',
|
||||||
download: '点击下载文件',
|
download: '点击下载文件',
|
||||||
@ -16,7 +19,7 @@ export default {
|
|||||||
passwordValidator: {
|
passwordValidator: {
|
||||||
title: '请输入密码打开链接',
|
title: '请输入密码打开链接',
|
||||||
errorMessage1: '密码不能为空',
|
errorMessage1: '密码不能为空',
|
||||||
errorMessage2: '密码错误'
|
errorMessage2: '密码错误',
|
||||||
},
|
},
|
||||||
operation: {
|
operation: {
|
||||||
play: '点击播放',
|
play: '点击播放',
|
||||||
@ -28,7 +31,7 @@ export default {
|
|||||||
cancelOppose: '取消反对',
|
cancelOppose: '取消反对',
|
||||||
continue: '继续',
|
continue: '继续',
|
||||||
stopChat: '停止回答',
|
stopChat: '停止回答',
|
||||||
startChat: '开始对话'
|
startChat: '开始对话',
|
||||||
},
|
},
|
||||||
tip: {
|
tip: {
|
||||||
error500Message: '抱歉,当前正在维护,无法提供服务,请稍后再试!',
|
error500Message: '抱歉,当前正在维护,无法提供服务,请稍后再试!',
|
||||||
@ -47,12 +50,12 @@ export default {
|
|||||||
requiredMessage: '请填写所有必填字段',
|
requiredMessage: '请填写所有必填字段',
|
||||||
inputParamMessage1: '请在URL中填写参数',
|
inputParamMessage1: '请在URL中填写参数',
|
||||||
inputParamMessage2: '的值',
|
inputParamMessage2: '的值',
|
||||||
prologueMessage: '抱歉,当前正在维护,无法提供服务,请稍后再试!'
|
prologueMessage: '抱歉,当前正在维护,无法提供服务,请稍后再试!',
|
||||||
},
|
},
|
||||||
inputPlaceholder: {
|
inputPlaceholder: {
|
||||||
speaking: '说话中',
|
speaking: '说话中',
|
||||||
recorderLoading: '转文字中',
|
recorderLoading: '转文字中',
|
||||||
default: '请输入问题'
|
default: '请输入问题',
|
||||||
},
|
},
|
||||||
uploadFile: {
|
uploadFile: {
|
||||||
label: '上传文件',
|
label: '上传文件',
|
||||||
@ -64,7 +67,7 @@ export default {
|
|||||||
limitMessage2: '个文件',
|
limitMessage2: '个文件',
|
||||||
sizeLimit: '单个文件大小不能超过',
|
sizeLimit: '单个文件大小不能超过',
|
||||||
imageMessage: '请解析图片内容',
|
imageMessage: '请解析图片内容',
|
||||||
errorMessage: '上传失败'
|
errorMessage: '上传失败',
|
||||||
},
|
},
|
||||||
executionDetails: {
|
executionDetails: {
|
||||||
title: '执行详情',
|
title: '执行详情',
|
||||||
@ -83,18 +86,18 @@ export default {
|
|||||||
rerankerResult: '重排结果',
|
rerankerResult: '重排结果',
|
||||||
paragraph: '分段',
|
paragraph: '分段',
|
||||||
noSubmit: '用户未提交',
|
noSubmit: '用户未提交',
|
||||||
errMessage: '错误日志'
|
errMessage: '错误日志',
|
||||||
},
|
},
|
||||||
KnowledgeSource: {
|
KnowledgeSource: {
|
||||||
title: '知识来源',
|
title: '知识来源',
|
||||||
referenceParagraph: '引用分段',
|
referenceParagraph: '引用分段',
|
||||||
consume: '消耗tokens',
|
consume: '消耗tokens',
|
||||||
consumeTime: '耗时'
|
consumeTime: '耗时',
|
||||||
},
|
},
|
||||||
paragraphSource: {
|
paragraphSource: {
|
||||||
title: '知识库引用',
|
title: '知识库引用',
|
||||||
question: '用户问题',
|
question: '用户问题',
|
||||||
optimizationQuestion: '优化后问题'
|
optimizationQuestion: '优化后问题',
|
||||||
},
|
},
|
||||||
editTitle: '编辑标题'
|
editTitle: '编辑标题',
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,27 +13,27 @@ export const startNode = {
|
|||||||
fields: [
|
fields: [
|
||||||
{
|
{
|
||||||
label: t('views.applicationWorkflow.nodes.startNode.question'),
|
label: t('views.applicationWorkflow.nodes.startNode.question'),
|
||||||
value: 'question'
|
value: 'question',
|
||||||
}
|
},
|
||||||
],
|
],
|
||||||
globalFields: [
|
globalFields: [
|
||||||
{ label: t('views.applicationWorkflow.nodes.startNode.currentTime'), value: 'time' },
|
{ label: t('views.applicationWorkflow.nodes.startNode.currentTime'), value: 'time' },
|
||||||
{
|
{
|
||||||
label: t('views.application.form.historyRecord.label'),
|
label: t('views.application.form.historyRecord.label'),
|
||||||
value: 'history_context'
|
value: 'history_context',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('chat.chatId'),
|
label: t('chat.chatId'),
|
||||||
value: 'chat_id'
|
value: 'chat_id',
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
},
|
},
|
||||||
fields: [{ label: t('views.applicationWorkflow.nodes.startNode.question'), value: 'question' }],
|
fields: [{ label: t('views.applicationWorkflow.nodes.startNode.question'), value: 'question' }],
|
||||||
globalFields: [
|
globalFields: [
|
||||||
{ label: t('views.applicationWorkflow.nodes.startNode.currentTime'), value: 'time' }
|
{ label: t('views.applicationWorkflow.nodes.startNode.currentTime'), value: 'time' },
|
||||||
],
|
],
|
||||||
showNode: true
|
showNode: true,
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
export const baseNode = {
|
export const baseNode = {
|
||||||
id: WorkflowType.Base,
|
id: WorkflowType.Base,
|
||||||
@ -50,13 +50,13 @@ export const baseNode = {
|
|||||||
desc: '',
|
desc: '',
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
prologue: t('views.application.form.defaultPrologue'),
|
prologue: t('views.application.form.defaultPrologue'),
|
||||||
tts_type: 'BROWSER'
|
tts_type: 'BROWSER',
|
||||||
},
|
},
|
||||||
config: {},
|
config: {},
|
||||||
showNode: true,
|
showNode: true,
|
||||||
user_input_config: { title: t('chat.userInput') },
|
user_input_config: { title: t('chat.userInput') },
|
||||||
user_input_field_list: []
|
user_input_field_list: [],
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* 说明
|
* 说明
|
||||||
@ -77,15 +77,15 @@ export const aiChatNode = {
|
|||||||
fields: [
|
fields: [
|
||||||
{
|
{
|
||||||
label: t('views.applicationWorkflow.nodes.aiChatNode.answer'),
|
label: t('views.applicationWorkflow.nodes.aiChatNode.answer'),
|
||||||
value: 'answer'
|
value: 'answer',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('views.applicationWorkflow.nodes.aiChatNode.think'),
|
label: t('views.applicationWorkflow.nodes.aiChatNode.think'),
|
||||||
value: 'reasoning_content'
|
value: 'reasoning_content',
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* 知识库检索配置数据
|
* 知识库检索配置数据
|
||||||
@ -101,23 +101,25 @@ export const searchKnowledgeNode = {
|
|||||||
fields: [
|
fields: [
|
||||||
{
|
{
|
||||||
label: t('views.applicationWorkflow.nodes.searchKnowledgeNode.paragraph_list'),
|
label: t('views.applicationWorkflow.nodes.searchKnowledgeNode.paragraph_list'),
|
||||||
value: 'paragraph_list'
|
value: 'paragraph_list',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('views.applicationWorkflow.nodes.searchKnowledgeNode.is_hit_handling_method_list'),
|
label: t(
|
||||||
value: 'is_hit_handling_method_list'
|
'views.applicationWorkflow.nodes.searchKnowledgeNode.is_hit_handling_method_list',
|
||||||
|
),
|
||||||
|
value: 'is_hit_handling_method_list',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('views.applicationWorkflow.nodes.searchKnowledgeNode.result'),
|
label: t('views.applicationWorkflow.nodes.searchKnowledgeNode.result'),
|
||||||
value: 'data'
|
value: 'data',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('views.applicationWorkflow.nodes.searchKnowledgeNode.directly_return'),
|
label: t('views.applicationWorkflow.nodes.searchKnowledgeNode.directly_return'),
|
||||||
value: 'directly_return'
|
value: 'directly_return',
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
export const questionNode = {
|
export const questionNode = {
|
||||||
type: WorkflowType.Question,
|
type: WorkflowType.Question,
|
||||||
@ -130,11 +132,11 @@ export const questionNode = {
|
|||||||
fields: [
|
fields: [
|
||||||
{
|
{
|
||||||
label: t('views.applicationWorkflow.nodes.questionNode.result'),
|
label: t('views.applicationWorkflow.nodes.questionNode.result'),
|
||||||
value: 'answer'
|
value: 'answer',
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
export const conditionNode = {
|
export const conditionNode = {
|
||||||
type: WorkflowType.Condition,
|
type: WorkflowType.Condition,
|
||||||
@ -148,11 +150,11 @@ export const conditionNode = {
|
|||||||
fields: [
|
fields: [
|
||||||
{
|
{
|
||||||
label: t('views.applicationWorkflow.nodes.conditionNode.branch_name'),
|
label: t('views.applicationWorkflow.nodes.conditionNode.branch_name'),
|
||||||
value: 'branch_name'
|
value: 'branch_name',
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
export const replyNode = {
|
export const replyNode = {
|
||||||
type: WorkflowType.Reply,
|
type: WorkflowType.Reply,
|
||||||
@ -165,11 +167,11 @@ export const replyNode = {
|
|||||||
fields: [
|
fields: [
|
||||||
{
|
{
|
||||||
label: t('views.applicationWorkflow.nodes.replyNode.content'),
|
label: t('views.applicationWorkflow.nodes.replyNode.content'),
|
||||||
value: 'answer'
|
value: 'answer',
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
export const rerankerNode = {
|
export const rerankerNode = {
|
||||||
type: WorkflowType.RrerankerNode,
|
type: WorkflowType.RrerankerNode,
|
||||||
@ -182,15 +184,15 @@ export const rerankerNode = {
|
|||||||
fields: [
|
fields: [
|
||||||
{
|
{
|
||||||
label: t('views.applicationWorkflow.nodes.rerankerNode.result_list'),
|
label: t('views.applicationWorkflow.nodes.rerankerNode.result_list'),
|
||||||
value: 'result_list'
|
value: 'result_list',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('views.applicationWorkflow.nodes.rerankerNode.result'),
|
label: t('views.applicationWorkflow.nodes.rerankerNode.result'),
|
||||||
value: 'result'
|
value: 'result',
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
export const formNode = {
|
export const formNode = {
|
||||||
type: WorkflowType.FormNode,
|
type: WorkflowType.FormNode,
|
||||||
@ -205,17 +207,17 @@ export const formNode = {
|
|||||||
form_field_list: [],
|
form_field_list: [],
|
||||||
form_content_format: `${t('views.applicationWorkflow.nodes.formNode.form_content_format1')}
|
form_content_format: `${t('views.applicationWorkflow.nodes.formNode.form_content_format1')}
|
||||||
{{form}}
|
{{form}}
|
||||||
${t('views.applicationWorkflow.nodes.formNode.form_content_format2')}`
|
${t('views.applicationWorkflow.nodes.formNode.form_content_format2')}`,
|
||||||
},
|
},
|
||||||
config: {
|
config: {
|
||||||
fields: [
|
fields: [
|
||||||
{
|
{
|
||||||
label: t('views.applicationWorkflow.nodes.formNode.form_data'),
|
label: t('views.applicationWorkflow.nodes.formNode.form_data'),
|
||||||
value: 'form_data'
|
value: 'form_data',
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
export const documentExtractNode = {
|
export const documentExtractNode = {
|
||||||
type: WorkflowType.DocumentExtractNode,
|
type: WorkflowType.DocumentExtractNode,
|
||||||
@ -228,11 +230,11 @@ export const documentExtractNode = {
|
|||||||
fields: [
|
fields: [
|
||||||
{
|
{
|
||||||
label: t('views.applicationWorkflow.nodes.documentExtractNode.content'),
|
label: t('views.applicationWorkflow.nodes.documentExtractNode.content'),
|
||||||
value: 'content'
|
value: 'content',
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
export const imageUnderstandNode = {
|
export const imageUnderstandNode = {
|
||||||
type: WorkflowType.ImageUnderstandNode,
|
type: WorkflowType.ImageUnderstandNode,
|
||||||
@ -245,11 +247,11 @@ export const imageUnderstandNode = {
|
|||||||
fields: [
|
fields: [
|
||||||
{
|
{
|
||||||
label: t('views.applicationWorkflow.nodes.imageUnderstandNode.answer'),
|
label: t('views.applicationWorkflow.nodes.imageUnderstandNode.answer'),
|
||||||
value: 'answer'
|
value: 'answer',
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export const variableAssignNode = {
|
export const variableAssignNode = {
|
||||||
@ -259,8 +261,8 @@ export const variableAssignNode = {
|
|||||||
height: 252,
|
height: 252,
|
||||||
properties: {
|
properties: {
|
||||||
stepName: t('views.applicationWorkflow.nodes.variableAssignNode.label'),
|
stepName: t('views.applicationWorkflow.nodes.variableAssignNode.label'),
|
||||||
config: {}
|
config: {},
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export const mcpNode = {
|
export const mcpNode = {
|
||||||
@ -274,11 +276,11 @@ export const mcpNode = {
|
|||||||
fields: [
|
fields: [
|
||||||
{
|
{
|
||||||
label: t('common.result'),
|
label: t('common.result'),
|
||||||
value: 'result'
|
value: 'result',
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export const imageGenerateNode = {
|
export const imageGenerateNode = {
|
||||||
@ -292,15 +294,15 @@ export const imageGenerateNode = {
|
|||||||
fields: [
|
fields: [
|
||||||
{
|
{
|
||||||
label: t('views.applicationWorkflow.nodes.imageGenerateNode.answer'),
|
label: t('views.applicationWorkflow.nodes.imageGenerateNode.answer'),
|
||||||
value: 'answer'
|
value: 'answer',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('common.fileUpload.image'),
|
label: t('common.fileUpload.image'),
|
||||||
value: 'image'
|
value: 'image',
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export const speechToTextNode = {
|
export const speechToTextNode = {
|
||||||
@ -314,11 +316,11 @@ export const speechToTextNode = {
|
|||||||
fields: [
|
fields: [
|
||||||
{
|
{
|
||||||
label: t('common.result'),
|
label: t('common.result'),
|
||||||
value: 'result'
|
value: 'result',
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
export const textToSpeechNode = {
|
export const textToSpeechNode = {
|
||||||
type: WorkflowType.TextToSpeechNode,
|
type: WorkflowType.TextToSpeechNode,
|
||||||
@ -331,17 +333,33 @@ export const textToSpeechNode = {
|
|||||||
fields: [
|
fields: [
|
||||||
{
|
{
|
||||||
label: t('common.result'),
|
label: t('common.result'),
|
||||||
value: 'result'
|
value: 'result',
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
export const menuNodes = [
|
export const menuNodes = [
|
||||||
{ label: t('views.applicationWorkflow.nodes.classify.aiCapability'), list: [aiChatNode, questionNode, imageGenerateNode, imageUnderstandNode, textToSpeechNode, speechToTextNode] },
|
{
|
||||||
|
label: t('views.applicationWorkflow.nodes.classify.aiCapability'),
|
||||||
|
list: [
|
||||||
|
aiChatNode,
|
||||||
|
questionNode,
|
||||||
|
imageGenerateNode,
|
||||||
|
imageUnderstandNode,
|
||||||
|
textToSpeechNode,
|
||||||
|
speechToTextNode,
|
||||||
|
],
|
||||||
|
},
|
||||||
{ label: t('views.knowledge.title'), list: [searchKnowledgeNode, rerankerNode] },
|
{ label: t('views.knowledge.title'), list: [searchKnowledgeNode, rerankerNode] },
|
||||||
{ label: t('views.applicationWorkflow.nodes.classify.businessLogic'), list: [conditionNode, formNode, variableAssignNode, replyNode] },
|
{
|
||||||
{ label: t('views.applicationWorkflow.nodes.classify.other'), list: [mcpNode, documentExtractNode] },
|
label: t('views.applicationWorkflow.nodes.classify.businessLogic'),
|
||||||
|
list: [conditionNode, formNode, variableAssignNode, replyNode],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: t('views.applicationWorkflow.nodes.classify.other'),
|
||||||
|
list: [mcpNode, documentExtractNode],
|
||||||
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -358,11 +376,11 @@ export const toolNode = {
|
|||||||
fields: [
|
fields: [
|
||||||
{
|
{
|
||||||
label: t('common.result'),
|
label: t('common.result'),
|
||||||
value: 'result'
|
value: 'result',
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
export const toolLibNode = {
|
export const toolLibNode = {
|
||||||
type: WorkflowType.ToolLib,
|
type: WorkflowType.ToolLib,
|
||||||
@ -375,11 +393,11 @@ export const toolLibNode = {
|
|||||||
fields: [
|
fields: [
|
||||||
{
|
{
|
||||||
label: t('common.result'),
|
label: t('common.result'),
|
||||||
value: 'result'
|
value: 'result',
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export const applicationNode = {
|
export const applicationNode = {
|
||||||
@ -393,11 +411,11 @@ export const applicationNode = {
|
|||||||
fields: [
|
fields: [
|
||||||
{
|
{
|
||||||
label: t('common.result'),
|
label: t('common.result'),
|
||||||
value: 'result'
|
value: 'result',
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export const compareList = [
|
export const compareList = [
|
||||||
@ -416,7 +434,7 @@ export const compareList = [
|
|||||||
{ value: 'len_le', label: t('views.applicationWorkflow.compare.len_le') },
|
{ value: 'len_le', label: t('views.applicationWorkflow.compare.len_le') },
|
||||||
{ value: 'len_lt', label: t('views.applicationWorkflow.compare.len_lt') },
|
{ value: 'len_lt', label: t('views.applicationWorkflow.compare.len_lt') },
|
||||||
{ value: 'is_true', label: t('views.applicationWorkflow.compare.is_true') },
|
{ value: 'is_true', label: t('views.applicationWorkflow.compare.is_true') },
|
||||||
{ value: 'is_not_true', label: t('views.applicationWorkflow.compare.is_not_true') }
|
{ value: 'is_not_true', label: t('views.applicationWorkflow.compare.is_not_true') },
|
||||||
]
|
]
|
||||||
|
|
||||||
export const nodeDict: any = {
|
export const nodeDict: any = {
|
||||||
@ -438,7 +456,7 @@ export const nodeDict: any = {
|
|||||||
[WorkflowType.SpeechToTextNode]: speechToTextNode,
|
[WorkflowType.SpeechToTextNode]: speechToTextNode,
|
||||||
[WorkflowType.ImageGenerateNode]: imageGenerateNode,
|
[WorkflowType.ImageGenerateNode]: imageGenerateNode,
|
||||||
[WorkflowType.VariableAssignNode]: variableAssignNode,
|
[WorkflowType.VariableAssignNode]: variableAssignNode,
|
||||||
[WorkflowType.McpNode]: mcpNode
|
[WorkflowType.McpNode]: mcpNode,
|
||||||
}
|
}
|
||||||
export function isWorkFlow(type: string | undefined) {
|
export function isWorkFlow(type: string | undefined) {
|
||||||
return type === 'WORK_FLOW'
|
return type === 'WORK_FLOW'
|
||||||
|
|||||||
@ -26,7 +26,7 @@
|
|||||||
import { cloneDeep, set } from 'lodash'
|
import { cloneDeep, set } from 'lodash'
|
||||||
import NodeContainer from '@/workflow/common/NodeContainer.vue'
|
import NodeContainer from '@/workflow/common/NodeContainer.vue'
|
||||||
import { copyClick } from '@/utils/clipboard'
|
import { copyClick } from '@/utils/clipboard'
|
||||||
import { ref, computed, onMounted } from 'vue'
|
import { ref, onMounted } from 'vue'
|
||||||
import { t } from '@/locales'
|
import { t } from '@/locales'
|
||||||
const props = defineProps<{ nodeModel: any }>()
|
const props = defineProps<{ nodeModel: any }>()
|
||||||
|
|
||||||
@ -35,9 +35,21 @@ const globalFields = [
|
|||||||
{ label: t('views.applicationWorkflow.nodes.startNode.currentTime'), value: 'time' },
|
{ label: t('views.applicationWorkflow.nodes.startNode.currentTime'), value: 'time' },
|
||||||
{
|
{
|
||||||
label: t('views.application.form.historyRecord.label'),
|
label: t('views.application.form.historyRecord.label'),
|
||||||
value: 'history_context'
|
value: 'history_context',
|
||||||
|
},
|
||||||
|
{ label: t('chat.chatId'), value: 'chat_id' },
|
||||||
|
{
|
||||||
|
label: t('chat.chatUserId'),
|
||||||
|
value: 'chat_user_id',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: t('chat.chatUserType'),
|
||||||
|
value: 'chat_user_type',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: t('chat.chatUser'),
|
||||||
|
value: 'chat_user',
|
||||||
},
|
},
|
||||||
{ label: t('chat.chatId'), value: 'chat_id' }
|
|
||||||
]
|
]
|
||||||
|
|
||||||
const getRefreshFieldList = () => {
|
const getRefreshFieldList = () => {
|
||||||
@ -79,7 +91,7 @@ const refreshFileUploadConfig = () => {
|
|||||||
item.value !== 'document' &&
|
item.value !== 'document' &&
|
||||||
item.value !== 'audio' &&
|
item.value !== 'audio' &&
|
||||||
item.value !== 'video' &&
|
item.value !== 'video' &&
|
||||||
item.value !== 'other'
|
item.value !== 'other',
|
||||||
)
|
)
|
||||||
|
|
||||||
if (form_data.length === 0) {
|
if (form_data.length === 0) {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user