Skip to content

Commit 87257f7

Browse files
committed
refactor: add is_portal field to Application model and update related serializers and queries
1 parent 8bbf966 commit 87257f7

6 files changed

Lines changed: 95 additions & 61 deletions

File tree

‎apps/application/models/application.py‎

Lines changed: 83 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
# coding=utf-8
22
"""
3-
@project: MaxKB
4-
@Author:虎虎
5-
@file: application.py
6-
@date:2025/5/7 15:29
7-
@desc:
3+
@project: MaxKB
4+
@Author:虎虎
5+
@file: application.py
6+
@date:2025/5/7 15:29
7+
@desc:
88
"""
9+
910
import uuid_utils.compat as uuid
1011
from django.db import models
1112
from mptt.fields import TreeForeignKey
@@ -23,45 +24,50 @@ class ApplicationFolder(MPTTModel, AppModelMixin):
2324
desc = models.CharField(max_length=200, null=True, blank=True, verbose_name="描述")
2425
user = models.ForeignKey(User, on_delete=models.SET_NULL, db_constraint=False, blank=True, null=True)
2526
workspace_id = models.CharField(max_length=64, verbose_name="工作空间id", default="default", db_index=True)
26-
parent = TreeForeignKey('self', on_delete=models.DO_NOTHING, null=True, blank=True, related_name='children')
27+
parent = TreeForeignKey("self", on_delete=models.DO_NOTHING, null=True, blank=True, related_name="children")
2728

2829
class Meta:
2930
db_table = "application_folder"
3031

3132
class MPTTMeta:
32-
order_insertion_by = ['name']
33+
order_insertion_by = ["name"]
3334

3435

3536
class ApplicationTypeChoices(models.TextChoices):
3637
"""订单类型"""
37-
SIMPLE = 'SIMPLE', '简易'
38-
WORK_FLOW = 'WORK_FLOW', '工作流'
38+
39+
SIMPLE = "SIMPLE", "简易"
40+
WORK_FLOW = "WORK_FLOW", "工作流"
3941

4042

4143
def get_dataset_setting_dict():
42-
return {'top_n': 3, 'similarity': 0.6, 'max_paragraph_char_number': 5000, 'search_mode': 'embedding',
43-
'no_references_setting': {
44-
'status': 'ai_questioning',
45-
'value': '{question}'
46-
}}
44+
return {
45+
"top_n": 3,
46+
"similarity": 0.6,
47+
"max_paragraph_char_number": 5000,
48+
"search_mode": "embedding",
49+
"no_references_setting": {"status": "ai_questioning", "value": "{question}"},
50+
}
4751

4852

4953
def get_model_setting_dict():
5054
return {
51-
'prompt': Application.get_default_model_prompt(),
52-
'no_references_prompt': '{question}',
53-
'reasoning_content_start': '<think>',
54-
'reasoning_content_end': '</think>',
55-
'reasoning_content_enable': False,
55+
"prompt": Application.get_default_model_prompt(),
56+
"no_references_prompt": "{question}",
57+
"reasoning_content_start": "<think>",
58+
"reasoning_content_end": "</think>",
59+
"reasoning_content_enable": False,
5660
}
5761

5862

5963
class Application(AppModelMixin):
6064
id = models.UUIDField(primary_key=True, max_length=128, default=uuid.uuid7, editable=False, verbose_name="主键id")
6165
workspace_id = models.CharField(max_length=64, verbose_name="工作空间id", default="default", db_index=True)
62-
folder = models.ForeignKey(ApplicationFolder, on_delete=models.DO_NOTHING, verbose_name="文件夹id",
63-
default='default')
66+
folder = models.ForeignKey(
67+
ApplicationFolder, on_delete=models.DO_NOTHING, verbose_name="文件夹id", default="default"
68+
)
6469
is_publish = models.BooleanField(verbose_name="是否发布", default=False)
70+
is_portal = models.BooleanField(verbose_name="是否在门户上架", default=False)
6571
name = models.CharField(max_length=128, verbose_name="应用名称", db_index=True)
6672
desc = models.CharField(max_length=512, verbose_name="引用描述", default="")
6773
prologue = models.CharField(max_length=40960, verbose_name="开场白", default="")
@@ -76,15 +82,25 @@ class Application(AppModelMixin):
7682
problem_optimization = models.BooleanField(verbose_name="问题优化", default=False)
7783
icon = models.CharField(max_length=256, verbose_name="应用icon", default="./favicon.ico")
7884
work_flow = models.JSONField(verbose_name="工作流数据", default=dict)
79-
type = models.CharField(verbose_name="应用类型", choices=ApplicationTypeChoices.choices,
80-
default=ApplicationTypeChoices.SIMPLE, max_length=256)
81-
problem_optimization_prompt = models.CharField(verbose_name="问题优化提示词", max_length=102400, blank=True,
82-
null=True,
83-
default="()里面是用户问题,根据上下文回答揣测用户问题({question}) 要求: 输出一个补全问题,并且放在<data></data>标签中")
84-
tts_model = models.ForeignKey(Model, related_name='tts_model_id', on_delete=models.SET_NULL, db_constraint=False,
85-
blank=True, null=True)
86-
stt_model = models.ForeignKey(Model, related_name='stt_model_id', on_delete=models.SET_NULL, db_constraint=False,
87-
blank=True, null=True)
85+
type = models.CharField(
86+
verbose_name="应用类型",
87+
choices=ApplicationTypeChoices.choices,
88+
default=ApplicationTypeChoices.SIMPLE,
89+
max_length=256,
90+
)
91+
problem_optimization_prompt = models.CharField(
92+
verbose_name="问题优化提示词",
93+
max_length=102400,
94+
blank=True,
95+
null=True,
96+
default="()里面是用户问题,根据上下文回答揣测用户问题({question}) 要求: 输出一个补全问题,并且放在<data></data>标签中",
97+
)
98+
tts_model = models.ForeignKey(
99+
Model, related_name="tts_model_id", on_delete=models.SET_NULL, db_constraint=False, blank=True, null=True
100+
)
101+
stt_model = models.ForeignKey(
102+
Model, related_name="stt_model_id", on_delete=models.SET_NULL, db_constraint=False, blank=True, null=True
103+
)
88104
tts_model_enable = models.BooleanField(verbose_name="语音合成模型是否启用", default=False)
89105
stt_model_enable = models.BooleanField(verbose_name="语音识别模型是否启用", default=False)
90106
tts_type = models.CharField(verbose_name="语音播放类型", max_length=20, default="BROWSER")
@@ -105,26 +121,29 @@ class Application(AppModelMixin):
105121
skill_tool_ids = models.JSONField(verbose_name="技能ID列表", default=list)
106122
mcp_output_enable = models.BooleanField(verbose_name="MCP输出是否启用", default=True)
107123
file_clean_time = models.IntegerField(verbose_name="文件清理时间", default=180)
108-
long_term_enable = models.BooleanField(verbose_name='长期记忆是否开启', default=False)
109-
long_term_model = models.ForeignKey(Model, related_name='long_term_model_id', on_delete=models.SET_NULL,
110-
db_constraint=False, blank=True, null=True)
124+
long_term_enable = models.BooleanField(verbose_name="长期记忆是否开启", default=False)
125+
long_term_model = models.ForeignKey(
126+
Model, related_name="long_term_model_id", on_delete=models.SET_NULL, db_constraint=False, blank=True, null=True
127+
)
111128
long_term_model_params_setting = models.JSONField(verbose_name="长期记忆模型参数相关设置", default=dict)
112-
long_term_trigger_type = models.CharField(verbose_name='长期记忆触发类型', default='ROUND')
113-
long_term_trigger_setting = models.JSONField(verbose_name='长期记忆触发配置', default=dict)
129+
long_term_trigger_type = models.CharField(verbose_name="长期记忆触发类型", default="ROUND")
130+
long_term_trigger_setting = models.JSONField(verbose_name="长期记忆触发配置", default=dict)
114131

115132
@staticmethod
116133
def get_default_model_prompt():
117-
return ('已知信息:'
118-
'\n{data}'
119-
'\n回答要求:'
120-
'\n- 如果你不知道答案或者没有从获取答案,请回答“没有在知识库中查找到相关信息,建议咨询相关技术支持或参考官方文档进行操作”。'
121-
'\n- 避免提及你是从<data></data>中获得的知识。'
122-
'\n- 请保持答案与<data></data>中描述的一致。'
123-
'\n- 请使用markdown 语法优化答案的格式。'
124-
'\n- <data></data>中的图片链接、链接地址和脚本语言请完整返回。'
125-
'\n- 请使用与问题相同的语言来回答。'
126-
'\n问题:'
127-
'\n{question}')
134+
return (
135+
"已知信息:"
136+
"\n{data}"
137+
"\n回答要求:"
138+
"\n- 如果你不知道答案或者没有从获取答案,请回答“没有在知识库中查找到相关信息,建议咨询相关技术支持或参考官方文档进行操作”。"
139+
"\n- 避免提及你是从<data></data>中获得的知识。"
140+
"\n- 请保持答案与<data></data>中描述的一致。"
141+
"\n- 请使用markdown 语法优化答案的格式。"
142+
"\n- <data></data>中的图片链接、链接地址和脚本语言请完整返回。"
143+
"\n- 请使用与问题相同的语言来回答。"
144+
"\n问题:"
145+
"\n{question}"
146+
)
128147

129148
class Meta:
130149
db_table = "application"
@@ -160,15 +179,21 @@ class ApplicationVersion(AppModelMixin):
160179
problem_optimization = models.BooleanField(verbose_name="问题优化", default=False)
161180
icon = models.CharField(max_length=256, verbose_name="应用icon", default="./favicon.ico")
162181
work_flow = models.JSONField(verbose_name="工作流数据", default=dict)
163-
type = models.CharField(verbose_name="应用类型", choices=ApplicationTypeChoices.choices,
164-
default=ApplicationTypeChoices.SIMPLE, max_length=256)
165-
problem_optimization_prompt = models.CharField(verbose_name="问题优化提示词", max_length=102400, blank=True,
166-
null=True,
167-
default="()里面是用户问题,根据上下文回答揣测用户问题({question}) 要求: 输出一个补全问题,并且放在<data></data>标签中")
168-
tts_model_id = models.UUIDField(verbose_name="文本转语音模型id",
169-
blank=True, null=True)
170-
stt_model_id = models.UUIDField(verbose_name="语音转文本模型id",
171-
blank=True, null=True)
182+
type = models.CharField(
183+
verbose_name="应用类型",
184+
choices=ApplicationTypeChoices.choices,
185+
default=ApplicationTypeChoices.SIMPLE,
186+
max_length=256,
187+
)
188+
problem_optimization_prompt = models.CharField(
189+
verbose_name="问题优化提示词",
190+
max_length=102400,
191+
blank=True,
192+
null=True,
193+
default="()里面是用户问题,根据上下文回答揣测用户问题({question}) 要求: 输出一个补全问题,并且放在<data></data>标签中",
194+
)
195+
tts_model_id = models.UUIDField(verbose_name="文本转语音模型id", blank=True, null=True)
196+
stt_model_id = models.UUIDField(verbose_name="语音转文本模型id", blank=True, null=True)
172197
tts_model_enable = models.BooleanField(verbose_name="语音合成模型是否启用", default=False)
173198
stt_model_enable = models.BooleanField(verbose_name="语音识别模型是否启用", default=False)
174199
tts_type = models.CharField(verbose_name="语音播放类型", max_length=20, default="BROWSER")
@@ -187,11 +212,11 @@ class ApplicationVersion(AppModelMixin):
187212
application_ids = models.JSONField(verbose_name="应用ID列表", default=list)
188213
skill_tool_ids = models.JSONField(verbose_name="技能ID列表", default=list)
189214
mcp_output_enable = models.BooleanField(verbose_name="MCP输出是否启用", default=True)
190-
long_term_enable = models.BooleanField(verbose_name='长期记忆是否开启', default=False)
215+
long_term_enable = models.BooleanField(verbose_name="长期记忆是否开启", default=False)
191216
long_term_model_id = models.UUIDField(verbose_name="长期记忆模型id", blank=True, null=True)
192217
long_term_model_params_setting = models.JSONField(verbose_name="长期记忆模型参数相关设置", default=dict)
193-
long_term_trigger_type = models.CharField(verbose_name='长期记忆触发类型', default='ROUND')
194-
long_term_trigger_setting = models.JSONField(verbose_name='长期记忆触发配置', default=dict)
218+
long_term_trigger_type = models.CharField(verbose_name="长期记忆触发类型", default="ROUND")
219+
long_term_trigger_setting = models.JSONField(verbose_name="长期记忆触发配置", default=dict)
195220
knowledge_ids = models.JSONField(verbose_name="数据集id列表", default=list)
196221

197222
class Meta:

‎apps/application/serializers/application.py‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -557,6 +557,9 @@ class ApplicationListResponse(serializers.Serializer):
557557
required=True, label=_("Application Description"), help_text=_("Application Description")
558558
)
559559
is_publish = serializers.BooleanField(required=True, label=_("Model id"), help_text=_("Model id"))
560+
is_portal = serializers.BooleanField(
561+
required=True, label=_("Whether to publish on portal"), help_text=_("Whether to publish on portal")
562+
)
560563
type = serializers.CharField(required=True, label=_("Application type"), help_text=_("Application type"))
561564
resource_type = serializers.CharField(required=True, label=_("Resource type"), help_text=_("Resource type"))
562565
user_id = serializers.CharField(required=True, label=_("Affiliation user"), help_text=_("Affiliation user"))
@@ -690,6 +693,7 @@ class ApplicationImportRequest(serializers.Serializer):
690693

691694
class ApplicationEditSerializer(serializers.Serializer):
692695
name = serializers.CharField(required=False, max_length=64, min_length=1, label=_("Application Name"))
696+
is_portal = serializers.BooleanField(required=False, label=_("Whether to publish on portal"))
693697
desc = serializers.CharField(
694698
required=False,
695699
max_length=256,
@@ -1422,6 +1426,7 @@ def edit(self, instance: Dict, with_valid=True):
14221426
ToolExecutor().validate_mcp_transport(json.dumps(instance.get("mcp_servers")))
14231427
update_keys = [
14241428
"name",
1429+
"is_portal",
14251430
"desc",
14261431
"model_id",
14271432
"multiple_rounds_dialogue",

‎apps/application/sql/list_application.sql‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ select *
22
from (select application."id"::text, application."name",
33
application."desc",
44
application."is_publish",
5+
application."is_portal",
56
application."type",
67
'application' as "resource_type",
78
application."workspace_id",

‎apps/application/sql/list_application_user.sql‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ select *
22
from (select application."id"::text, application."name",
33
application."desc",
44
application."is_publish",
5+
application."is_portal",
56
application."type",
67
'application' as "resource_type",
78
application."workspace_id",

‎apps/application/sql/list_application_user_ee.sql‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ select *
22
from (select application."id"::text, application."name",
33
application."desc",
44
application."is_publish",
5+
application."is_portal",
56
application."type",
67
'application' as "resource_type",
78
application."workspace_id",

‎apps/chat/serializers/portal.py‎

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ class PortalApplicationAuthMixin:
3030
def get_authorized_application_queryset(user_id):
3131
public_apps = ApplicationAccessToken.objects.filter(application_id=OuterRef("id"), authentication=False)
3232
if not ChatUser.objects.filter(id=user_id).exists():
33-
return Application.objects.filter(is_publish=True).filter(Exists(public_apps))
33+
return Application.objects.filter(is_publish=True, is_portal=True).filter(Exists(public_apps))
3434
authed_token_exists = ApplicationAccessToken.objects.filter(application_id=OuterRef("id"), authentication=True)
3535
direct_auth = ResourceChatUserAuthorize.objects.filter(
3636
resource_id=OuterRef("id"), resource_type=ResourceType.APPLICATION.value, is_auth=True, user_id=user_id
@@ -42,7 +42,7 @@ def get_authorized_application_queryset(user_id):
4242
is_auth=True,
4343
user_group_id__in=user_groups,
4444
)
45-
return Application.objects.filter(is_publish=True).filter(
45+
return Application.objects.filter(is_publish=True, is_portal=True).filter(
4646
Exists(public_apps) | (Exists(authed_token_exists) & (Exists(direct_auth) | Exists(group_auth)))
4747
)
4848

@@ -56,6 +56,7 @@ class ApplicationResponseSerializer(serializers.Serializer):
5656
dialogue_number = serializers.IntegerField(required=True)
5757
prologue = serializers.CharField(required=True)
5858
is_publish = serializers.BooleanField(required=True)
59+
is_portal = serializers.BooleanField(required=True)
5960

6061

6162
class PortalApplicationSerializer(serializers.Serializer):
@@ -65,7 +66,7 @@ class Query(PortalApplicationAuthMixin, serializers.Serializer):
6566
)
6667

6768
def get_query_set(self):
68-
queryset = Application.objects.filter(is_publish=True)
69+
queryset = Application.objects.filter(is_publish=True, is_portal=True)
6970
name = self.data.get("name")
7071
if name:
7172
queryset = queryset.filter(name__icontains=name)

0 commit comments

Comments
 (0)