diff --git a/apps/application/migrations/0018_application_clean_time.py b/apps/application/migrations/0018_application_clean_time.py
new file mode 100644
index 000000000..0662b5f23
--- /dev/null
+++ b/apps/application/migrations/0018_application_clean_time.py
@@ -0,0 +1,18 @@
+# Generated by Django 4.2.15 on 2024-10-16 14:51
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('application', '0017_application_tts_model_params_setting'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='application',
+ name='clean_time',
+ field=models.IntegerField(default=180, verbose_name='清理时间'),
+ ),
+ ]
diff --git a/apps/application/models/application.py b/apps/application/models/application.py
index ba4c03e26..e37dcb07e 100644
--- a/apps/application/models/application.py
+++ b/apps/application/models/application.py
@@ -65,6 +65,7 @@ class Application(AppModelMixin):
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")
+ clean_time = models.IntegerField(verbose_name="清理时间", default=180)
@staticmethod
def get_default_model_prompt():
diff --git a/apps/application/serializers/application_serializers.py b/apps/application/serializers/application_serializers.py
index bdde5859b..cca5ce170 100644
--- a/apps/application/serializers/application_serializers.py
+++ b/apps/application/serializers/application_serializers.py
@@ -743,13 +743,30 @@ class ApplicationSerializer(serializers.Serializer):
application_setting = QuerySet(application_setting_model).filter(
application_id=application_access_token.application_id).first()
if application_setting is not None:
+ custom_theme = getattr(application_setting, 'custom_theme', {})
+ float_location = getattr(application_setting, 'float_location', {})
+ if not custom_theme:
+ application_setting.custom_theme = {
+ 'theme_color': '',
+ 'header_font_color': ''
+ }
+ if not float_location:
+ application_setting.float_location = {
+ 'x': {'type': '', 'value': ''},
+ 'y': {'type': '', 'value': ''}
+ }
application_setting_dict = {'show_source': application_access_token.show_source,
'show_history': application_setting.show_history,
'draggable': application_setting.draggable,
'show_guide': application_setting.show_guide,
'avatar': application_setting.avatar,
'float_icon': application_setting.float_icon,
- 'authentication': application_setting.authentication}
+ 'authentication': application_setting.authentication,
+ 'disclaimer': application_setting.disclaimer,
+ 'disclaimer_value': application_setting.disclaimer_value,
+ 'custom_theme': application_setting.custom_theme,
+ 'user_avatar': application_setting.user_avatar,
+ 'float_location': application_setting.float_location}
return ApplicationSerializer.Query.reset_application(
{**ApplicationSerializer.ApplicationModel(application).data,
'stt_model_id': application.stt_model_id,
@@ -810,8 +827,8 @@ class ApplicationSerializer(serializers.Serializer):
update_keys = ['name', 'desc', 'model_id', 'multiple_rounds_dialogue', 'prologue', 'status',
'dataset_setting', 'model_setting', 'problem_optimization', 'dialogue_number',
'stt_model_id', 'tts_model_id', 'tts_model_enable', 'stt_model_enable', 'tts_type',
- 'api_key_is_active', 'icon', 'work_flow', 'model_params_setting','tts_model_params_setting',
- 'problem_optimization_prompt']
+ 'api_key_is_active', 'icon', 'work_flow', 'model_params_setting', 'tts_model_params_setting',
+ 'problem_optimization_prompt', 'clean_time']
for update_key in update_keys:
if update_key in instance and instance.get(update_key) is not None:
application.__setattr__(update_key, instance.get(update_key))
@@ -952,7 +969,8 @@ class ApplicationSerializer(serializers.Serializer):
application_id = self.data.get('application_id')
application = QuerySet(Application).filter(id=application_id).first()
if application.tts_model_enable:
- model = get_model_instance_by_model_user_id(application.tts_model_id, application.user_id, **application.tts_model_params_setting)
+ model = get_model_instance_by_model_user_id(application.tts_model_id, application.user_id,
+ **application.tts_model_params_setting)
return model.text_to_speech(text)
class ApplicationKeySerializerModel(serializers.ModelSerializer):
diff --git a/apps/common/job/__init__.py b/apps/common/job/__init__.py
index 895bf7f5d..2f4ef2697 100644
--- a/apps/common/job/__init__.py
+++ b/apps/common/job/__init__.py
@@ -7,7 +7,9 @@
@desc:
"""
from .client_access_num_job import *
+from .clean_chat_job import *
def run():
client_access_num_job.run()
+ clean_chat_job.run()
diff --git a/apps/common/job/clean_chat_job.py b/apps/common/job/clean_chat_job.py
new file mode 100644
index 000000000..23ff2c85a
--- /dev/null
+++ b/apps/common/job/clean_chat_job.py
@@ -0,0 +1,56 @@
+# coding=utf-8
+
+import logging
+import datetime
+
+from django.db import transaction
+from django.utils import timezone
+from apscheduler.schedulers.background import BackgroundScheduler
+from django_apscheduler.jobstores import DjangoJobStore
+from application.models import Application, Chat
+from django.db.models import Q
+from common.lock.impl.file_lock import FileLock
+
+scheduler = BackgroundScheduler()
+scheduler.add_jobstore(DjangoJobStore(), "default")
+lock = FileLock()
+
+
+def clean_chat_log_job():
+ logging.getLogger("max_kb").info('开始清理对话记录')
+ now = timezone.now()
+
+ applications = Application.objects.all().values('id', 'clean_time')
+ cutoff_dates = {
+ app['id']: now - datetime.timedelta(days=app['clean_time'] or 180)
+ for app in applications
+ }
+
+ query_conditions = Q()
+ for app_id, cutoff_date in cutoff_dates.items():
+ query_conditions |= Q(application_id=app_id, create_time__lt=cutoff_date)
+
+ batch_size = 500
+ while True:
+ with transaction.atomic():
+ logs_to_delete = Chat.objects.filter(query_conditions).values_list('id', flat=True)[:batch_size]
+ count = logs_to_delete.count()
+ if count == 0:
+ break
+ deleted_count, _ = Chat.objects.filter(id__in=logs_to_delete).delete()
+ if deleted_count < batch_size:
+ break
+
+ logging.getLogger("max_kb").info(f'结束清理对话记录')
+
+
+def run():
+ if lock.try_lock('clean_chat_log_job', 30 * 30):
+ try:
+ scheduler.start()
+ existing_job = scheduler.get_job(job_id='clean_chat_log')
+ if existing_job is not None:
+ existing_job.remove()
+ scheduler.add_job(clean_chat_log_job, 'cron', hour='0', minute='5', id='clean_chat_log')
+ finally:
+ lock.un_lock('clean_chat_log_job')
diff --git a/ui/src/views/log/index.vue b/ui/src/views/log/index.vue
index 5748be6a3..01919e543 100644
--- a/ui/src/views/log/index.vue
+++ b/ui/src/views/log/index.vue
@@ -29,7 +29,10 @@
style="margin-left: 10px"
clearable
/>
-