From d1add538d448a15e15738d5350c8b9347a323af4 Mon Sep 17 00:00:00 2001 From: wxg0103 <727495428@qq.com> Date: Wed, 29 Jul 2026 11:12:08 +0800 Subject: [PATCH 1/2] feat: add knowledge_ids field to ApplicationVersion and populate from ResourceMapping --- .../0014_applicationversion_knowledge_ids.py | 61 +++++++++++++++++++ apps/application/models/application.py | 1 + apps/application/serializers/application.py | 28 +++++---- apps/chat/serializers/chat.py | 28 ++++++--- 4 files changed, 98 insertions(+), 20 deletions(-) create mode 100644 apps/application/migrations/0014_applicationversion_knowledge_ids.py diff --git a/apps/application/migrations/0014_applicationversion_knowledge_ids.py b/apps/application/migrations/0014_applicationversion_knowledge_ids.py new file mode 100644 index 00000000000..676b0cb0d58 --- /dev/null +++ b/apps/application/migrations/0014_applicationversion_knowledge_ids.py @@ -0,0 +1,61 @@ +# Generated by Django 5.2.15 on 2026-07-29 02:42 + +from django.db import migrations, models + + +def forwards(apps, schema_editor): + Application = apps.get_model("application", "Application") + ResourceMapping = apps.get_model("system_manage", "ResourceMapping") + ApplicationVersion = apps.get_model("application", "ApplicationVersion") + + APPLICATION = "APPLICATION" + KNOWLEDGE = "KNOWLEDGE" + SIMPLE = "SIMPLE" + db_alias = schema_editor.connection.alias + simple_application_ids = { + str(app_id) + for app_id in Application.objects.using(db_alias) + .filter(type=SIMPLE) + .values_list("id", flat=True) + } + mapping = {} + qs = ( + ResourceMapping.objects.using(db_alias) + .filter(source_type=APPLICATION, target_type=KNOWLEDGE) + .values_list("source_id", "target_id") + ) + for source_id, target_id in qs.iterator(): + if source_id in simple_application_ids: + mapping.setdefault(source_id, []).append(target_id) + mapping = {k: list(dict.fromkeys(v)) for k, v in mapping.items()} + + updates = [] + for obj in ApplicationVersion.objects.using(db_alias).iterator(): + app_id = str(obj.application_id) + if app_id not in simple_application_ids: + continue + knowledge_ids = mapping.get(app_id) + if knowledge_ids: + obj.knowledge_ids = knowledge_ids + updates.append(obj) + if updates: + ApplicationVersion.objects.using(db_alias).bulk_update( + updates, ["knowledge_ids"], batch_size=500 + ) + + +class Migration(migrations.Migration): + + dependencies = [ + ('application', '0013_application_long_term_enable_and_more'), + ('system_manage', '0005_resourcemapping'), + ] + + operations = [ + migrations.AddField( + model_name='applicationversion', + name='knowledge_ids', + field=models.JSONField(default=list, verbose_name='数据集id列表'), + ), + migrations.RunPython(forwards, migrations.RunPython.noop), + ] diff --git a/apps/application/models/application.py b/apps/application/models/application.py index 34824b29eee..71d345164cc 100644 --- a/apps/application/models/application.py +++ b/apps/application/models/application.py @@ -192,6 +192,7 @@ class ApplicationVersion(AppModelMixin): long_term_model_params_setting = models.JSONField(verbose_name="长期记忆模型参数相关设置", default=dict) long_term_trigger_type = models.CharField(verbose_name='长期记忆触发类型', default='ROUND') long_term_trigger_setting = models.JSONField(verbose_name='长期记忆触发配置', default=dict) + knowledge_ids = models.JSONField(verbose_name="数据集id列表", default=list) class Meta: db_table = "application_version" diff --git a/apps/application/serializers/application.py b/apps/application/serializers/application.py index d5c6f9a8261..c3a74a9c8a1 100644 --- a/apps/application/serializers/application.py +++ b/apps/application/serializers/application.py @@ -86,7 +86,7 @@ def get_bound_tool_ids(instance: Dict) -> List[str]: """ tool_ids = set() for key in ("tool_ids", "skill_tool_ids", "mcp_tool_ids"): - for tool_id in (instance.get(key) or []): + for tool_id in instance.get(key) or []: tool_ids.add(str(tool_id)) if instance.get("mcp_tool_id"): tool_ids.add(str(instance.get("mcp_tool_id"))) @@ -96,7 +96,7 @@ def collect(node_data): if node_data.get(key): tool_ids.add(str(node_data.get(key))) for key in ("mcp_tool_ids", "tool_ids", "skill_tool_ids"): - for tool_id in (node_data.get(key) or []): + for tool_id in node_data.get(key) or []: tool_ids.add(str(tool_id)) _walk_workflow_nodes(instance.get("work_flow"), collect) @@ -109,11 +109,11 @@ def get_bound_application_ids(instance: Dict) -> List[str]: ai-chat-node 的 node_data 包含 application_ids 列表。 """ application_ids = set() - for app_id in (instance.get("application_ids") or []): + for app_id in instance.get("application_ids") or []: application_ids.add(str(app_id)) def collect(node_data): - for app_id in (node_data.get("application_ids") or []): + for app_id in node_data.get("application_ids") or []: application_ids.add(str(app_id)) _walk_workflow_nodes(instance.get("work_flow"), collect) @@ -186,7 +186,9 @@ def validate_bound_tool_permissions(user_id: str, workspace_id: str, instance: D application_ids = get_bound_application_ids(instance) if application_ids: authorized_application_ids = set(get_authorized_application_ids(user_id, workspace_id, application_ids)) - unauthorized_application_ids = [app_id for app_id in application_ids if app_id not in authorized_application_ids] + unauthorized_application_ids = [ + app_id for app_id in application_ids if app_id not in authorized_application_ids + ] if unauthorized_application_ids: message = lazy_format( _("No permission to use application(s): {application_ids}"), @@ -1268,6 +1270,14 @@ def publish(self, instance, with_valid=True): workspace_id=workspace_id, ) self.reset_application_version(work_flow_version, application) + # 如果是简易应用 需要存入 knowledge_ids + if application.type == ApplicationTypeChoices.SIMPLE: + work_flow_version.knowledge_ids = [ + str(row.target_id) + for row in QuerySet(ResourceMapping).filter( + source_id=str(application.id), source_type="APPLICATION", target_type="KNOWLEDGE" + ) + ] work_flow_version.save() access_token = hashlib.md5(str(uuid.uuid7()).encode()).hexdigest()[8:24] application_access_token = QuerySet(ApplicationAccessToken).filter(application_id=application.id).first() @@ -1781,9 +1791,7 @@ def batch_delete(self, instance: Dict, with_valid=True): id_list = instance.get("id_list") workspace_id = self.data.get("workspace_id") id_list = list( - QuerySet(Application) - .filter(id__in=id_list, workspace_id=workspace_id) - .values_list("id", flat=True) + QuerySet(Application).filter(id__in=id_list, workspace_id=workspace_id).values_list("id", flat=True) ) QuerySet(ApplicationVersion).filter(application_id__in=id_list).delete() @@ -1842,9 +1850,7 @@ def batch_clean_time(self, instance: Dict, with_valid=True): class BatchCleanTimeSerializer(BatchSerializer): clean_time = serializers.IntegerField(required=True, min_value=1, max_value=100000, label=_("Clean time")) - file_clean_time = serializers.IntegerField( - required=True, min_value=1, max_value=100000, label=_("File clean time") - ) + file_clean_time = serializers.IntegerField(required=True, min_value=1, max_value=100000, label=_("File clean time")) def is_valid(self, *, model=None, raise_exception=False): super().is_valid(model=model, raise_exception=True) diff --git a/apps/chat/serializers/chat.py b/apps/chat/serializers/chat.py index 4514dc457bc..7044f290f17 100644 --- a/apps/chat/serializers/chat.py +++ b/apps/chat/serializers/chat.py @@ -495,11 +495,16 @@ def re_open_chat(self, chat_id: str): return self.re_open_chat_work_flow(chat_id, application) def re_open_chat_simple(self, chat_id, application): - # 数据集id列表 - knowledge_id_list = [str(row.target_id) for row in - QuerySet(ResourceMapping).filter(source_id=str(application.id), - source_type='APPLICATION', - target_type='KNOWLEDGE')] + if self.debug: + # 数据集id列表 + knowledge_id_list = [str(row.target_id) for row in + QuerySet(ResourceMapping).filter(source_id=str(application.id), + source_type='APPLICATION', + target_type='KNOWLEDGE')] + else: + application_version = QuerySet(ApplicationVersion).filter(application_id=application.id).order_by( + '-create_time')[0:1].first() + knowledge_id_list = application_version.knowledge_ids # 需要排除的文档 exclude_document_id_list = [str(document.id) for document in @@ -584,10 +589,15 @@ def open_simple(self, application): ip_address = self.data.get("ip_address") source = self.data.get("source") debug = self.data.get("debug") - knowledge_id_list = [str(row.target_id) for row in - QuerySet(ResourceMapping).filter(source_id=str(application_id), - source_type='APPLICATION', - target_type='KNOWLEDGE')] + if debug: + knowledge_id_list = [str(row.target_id) for row in + QuerySet(ResourceMapping).filter(source_id=str(application_id), + source_type='APPLICATION', + target_type='KNOWLEDGE')] + else: + application_version = QuerySet(ApplicationVersion).filter(application_id=application_id).order_by( + '-create_time')[0:1].first() + knowledge_id_list = application_version.knowledge_ids chat_id = str(uuid.uuid7()) ChatInfo(chat_id, chat_user_id, chat_user_type, ip_address, source, knowledge_id_list, From 9154742bc2e7dce78ef896658751d95f8eb312b0 Mon Sep 17 00:00:00 2001 From: wxg <727495428@qq.com> Date: Wed, 29 Jul 2026 11:27:15 +0800 Subject: [PATCH 2/2] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- apps/chat/serializers/chat.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/chat/serializers/chat.py b/apps/chat/serializers/chat.py index 7044f290f17..5990ee85683 100644 --- a/apps/chat/serializers/chat.py +++ b/apps/chat/serializers/chat.py @@ -495,7 +495,7 @@ def re_open_chat(self, chat_id: str): return self.re_open_chat_work_flow(chat_id, application) def re_open_chat_simple(self, chat_id, application): - if self.debug: + if self.data.get('debug'): # 数据集id列表 knowledge_id_list = [str(row.target_id) for row in QuerySet(ResourceMapping).filter(source_id=str(application.id),