mirror of
https://github.com/1Panel-dev/MaxKB.git
synced 2025-12-26 01:33:05 +00:00
feat: application save (#3150)
Some checks are pending
sync2gitee / repo-sync (push) Waiting to run
Some checks are pending
sync2gitee / repo-sync (push) Waiting to run
This commit is contained in:
parent
60ff19be17
commit
080a6031bd
|
|
@ -13,12 +13,18 @@ from rest_framework import serializers
|
|||
|
||||
from application.serializers.application import ApplicationCreateSerializer
|
||||
from common.mixins.api_mixin import APIMixin
|
||||
from common.result import ResultSerializer
|
||||
|
||||
|
||||
class ApplicationCreateRequest(ApplicationCreateSerializer.SimplateRequest):
|
||||
work_flow = serializers.DictField(required=True, label=_("Workflow Objects"))
|
||||
|
||||
|
||||
class ApplicationCreateResponse(ResultSerializer):
|
||||
def get_data(self):
|
||||
return ApplicationCreateSerializer.ApplicationResponse()
|
||||
|
||||
|
||||
class ApplicationCreateAPI(APIMixin):
|
||||
@staticmethod
|
||||
def get_parameters():
|
||||
|
|
@ -38,4 +44,4 @@ class ApplicationCreateAPI(APIMixin):
|
|||
|
||||
@staticmethod
|
||||
def get_response():
|
||||
return FolderCreateResponse
|
||||
return ApplicationCreateResponse
|
||||
|
|
|
|||
|
|
@ -0,0 +1,53 @@
|
|||
# Generated by Django 5.2 on 2025-05-27 03:05
|
||||
|
||||
import django.contrib.postgres.fields
|
||||
import django.db.models.deletion
|
||||
import uuid_utils.compat
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('application', '0002_applicationapikey'),
|
||||
('knowledge', '0007_alter_document_status_alter_paragraph_status_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='ApplicationAccessToken',
|
||||
fields=[
|
||||
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
|
||||
('update_time', models.DateTimeField(auto_now=True, verbose_name='修改时间')),
|
||||
('application', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, primary_key=True, serialize=False, to='application.application', verbose_name='应用id')),
|
||||
('access_token', models.CharField(max_length=128, unique=True, verbose_name='用户公开访问 认证token')),
|
||||
('is_active', models.BooleanField(default=True, verbose_name='是否开启公开访问')),
|
||||
('access_num', models.IntegerField(default=100, verbose_name='访问次数')),
|
||||
('white_active', models.BooleanField(default=False, verbose_name='是否开启白名单')),
|
||||
('white_list', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(blank=True, max_length=128), default=list, size=None, verbose_name='白名单列表')),
|
||||
('show_source', models.BooleanField(default=False, verbose_name='是否显示知识来源')),
|
||||
('language', models.CharField(default=None, max_length=10, null=True, verbose_name='语言')),
|
||||
],
|
||||
options={
|
||||
'db_table': 'application_access_token',
|
||||
},
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='application',
|
||||
name='is_publish',
|
||||
field=models.BooleanField(default=False, verbose_name='是否发布'),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='ApplicationKnowledgeMapping',
|
||||
fields=[
|
||||
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
|
||||
('update_time', models.DateTimeField(auto_now=True, verbose_name='修改时间')),
|
||||
('id', models.UUIDField(default=uuid_utils.compat.uuid7, editable=False, primary_key=True, serialize=False, verbose_name='主键id')),
|
||||
('application', models.ForeignKey(on_delete=django.db.models.deletion.DO_NOTHING, to='application.application')),
|
||||
('knowledge', models.ForeignKey(on_delete=django.db.models.deletion.DO_NOTHING, to='knowledge.knowledge')),
|
||||
],
|
||||
options={
|
||||
'db_table': 'application_knowledge_mapping',
|
||||
},
|
||||
),
|
||||
]
|
||||
|
|
@ -6,3 +6,5 @@
|
|||
@date:2025/5/7 15:14
|
||||
@desc:
|
||||
"""
|
||||
from .application import *
|
||||
from .application_access_token import *
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ from mptt.fields import TreeForeignKey
|
|||
from mptt.models import MPTTModel
|
||||
|
||||
from common.mixins.app_model_mixin import AppModelMixin
|
||||
from knowledge.models import Knowledge
|
||||
from models_provider.models import Model
|
||||
from users.models import User
|
||||
|
||||
|
|
@ -59,6 +60,7 @@ class Application(AppModelMixin):
|
|||
id = models.UUIDField(primary_key=True, max_length=128, default=uuid.uuid7, editable=False, verbose_name="主键id")
|
||||
workspace_id = models.CharField(max_length=64, verbose_name="工作空间id", default="default", db_index=True)
|
||||
folder = models.ForeignKey(ApplicationFolder, on_delete=models.DO_NOTHING, verbose_name="文件夹id", default='root')
|
||||
is_publish = models.BooleanField(verbose_name="是否发布", default=False)
|
||||
name = models.CharField(max_length=128, verbose_name="应用名称")
|
||||
desc = models.CharField(max_length=512, verbose_name="引用描述", default="")
|
||||
prologue = models.CharField(max_length=40960, verbose_name="开场白", default="")
|
||||
|
|
@ -106,3 +108,12 @@ class Application(AppModelMixin):
|
|||
|
||||
class Meta:
|
||||
db_table = "application"
|
||||
|
||||
|
||||
class ApplicationKnowledgeMapping(AppModelMixin):
|
||||
id = models.UUIDField(primary_key=True, max_length=128, default=uuid.uuid7, editable=False, verbose_name="主键id")
|
||||
application = models.ForeignKey(Application, on_delete=models.DO_NOTHING)
|
||||
knowledge = models.ForeignKey(Knowledge, on_delete=models.DO_NOTHING)
|
||||
|
||||
class Meta:
|
||||
db_table = "application_knowledge_mapping"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,33 @@
|
|||
# coding=utf-8
|
||||
"""
|
||||
@project: MaxKB
|
||||
@Author:虎虎
|
||||
@file: application_access_token.py
|
||||
@date:2025/5/27 9:55
|
||||
@desc:
|
||||
"""
|
||||
from django.contrib.postgres.fields import ArrayField
|
||||
from django.db import models
|
||||
|
||||
from application.models.application import Application
|
||||
from common.mixins.app_model_mixin import AppModelMixin
|
||||
|
||||
|
||||
class ApplicationAccessToken(AppModelMixin):
|
||||
"""
|
||||
应用认证token
|
||||
"""
|
||||
application = models.OneToOneField(Application, primary_key=True, on_delete=models.CASCADE, verbose_name="应用id")
|
||||
access_token = models.CharField(max_length=128, verbose_name="用户公开访问 认证token", unique=True)
|
||||
is_active = models.BooleanField(default=True, verbose_name="是否开启公开访问")
|
||||
access_num = models.IntegerField(default=100, verbose_name="访问次数")
|
||||
white_active = models.BooleanField(default=False, verbose_name="是否开启白名单")
|
||||
white_list = ArrayField(verbose_name="白名单列表",
|
||||
base_field=models.CharField(max_length=128, blank=True)
|
||||
, default=list)
|
||||
show_source = models.BooleanField(default=False, verbose_name="是否显示知识来源")
|
||||
|
||||
language = models.CharField(max_length=10, verbose_name="语言", default=None, null=True)
|
||||
|
||||
class Meta:
|
||||
db_table = "application_access_token"
|
||||
|
|
@ -6,6 +6,7 @@
|
|||
@date:2025/5/26 17:03
|
||||
@desc:
|
||||
"""
|
||||
import hashlib
|
||||
import re
|
||||
from typing import Dict
|
||||
|
||||
|
|
@ -16,7 +17,8 @@ from django.db.models import QuerySet
|
|||
from django.utils.translation import gettext_lazy as _
|
||||
from rest_framework import serializers
|
||||
|
||||
from application.models.application import Application, ApplicationTypeChoices
|
||||
from application.models.application import Application, ApplicationTypeChoices, ApplicationKnowledgeMapping
|
||||
from application.models.application_access_token import ApplicationAccessToken
|
||||
from common.exception.app_exception import AppApiException
|
||||
from knowledge.models import Knowledge
|
||||
from models_provider.models import Model
|
||||
|
|
@ -94,6 +96,11 @@ class ModelSettingSerializer(serializers.Serializer):
|
|||
|
||||
|
||||
class ApplicationCreateSerializer(serializers.Serializer):
|
||||
class ApplicationResponse(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = Application
|
||||
fields = "__all__"
|
||||
|
||||
class WorkflowRequest(serializers.Serializer):
|
||||
name = serializers.CharField(required=True, max_length=64, min_length=1,
|
||||
label=_("Application Name"))
|
||||
|
|
@ -105,7 +112,7 @@ class ApplicationCreateSerializer(serializers.Serializer):
|
|||
label=_("Opening remarks"))
|
||||
|
||||
@staticmethod
|
||||
def to_application_model(user_id: str, application: Dict):
|
||||
def to_application_model(user_id: str, workspace_id: str, application: Dict):
|
||||
default_workflow = application.get('work_flow')
|
||||
for node in default_workflow.get('nodes'):
|
||||
if node.get('id') == 'base-node':
|
||||
|
|
@ -115,6 +122,7 @@ class ApplicationCreateSerializer(serializers.Serializer):
|
|||
return Application(id=uuid.uuid7(),
|
||||
name=application.get('name'),
|
||||
desc=application.get('desc'),
|
||||
workspace_id=workspace_id,
|
||||
prologue="",
|
||||
dialogue_number=0,
|
||||
user_id=user_id, model_id=None,
|
||||
|
|
@ -176,7 +184,70 @@ class ApplicationCreateSerializer(serializers.Serializer):
|
|||
ModelKnowledgeAssociation(data={'user_id': user_id, 'model_id': self.data.get('model_id'),
|
||||
'knowledge_id_list': self.data.get('knowledge_id_list')}).is_valid()
|
||||
|
||||
@staticmethod
|
||||
def to_application_model(user_id: str, application: Dict):
|
||||
return Application(id=uuid.uuid1(), name=application.get('name'), desc=application.get('desc'),
|
||||
prologue=application.get('prologue'),
|
||||
dialogue_number=application.get('dialogue_number', 0),
|
||||
user_id=user_id, model_id=application.get('model_id'),
|
||||
dataset_setting=application.get('dataset_setting'),
|
||||
model_setting=application.get('model_setting'),
|
||||
problem_optimization=application.get('problem_optimization'),
|
||||
type=ApplicationTypeChoices.SIMPLE,
|
||||
model_params_setting=application.get('model_params_setting', {}),
|
||||
problem_optimization_prompt=application.get('problem_optimization_prompt', None),
|
||||
stt_model_enable=application.get('stt_model_enable', False),
|
||||
stt_model_id=application.get('stt_model', None),
|
||||
tts_model_id=application.get('tts_model', None),
|
||||
tts_model_enable=application.get('tts_model_enable', False),
|
||||
tts_model_params_setting=application.get('tts_model_params_setting', {}),
|
||||
tts_type=application.get('tts_type', None),
|
||||
file_upload_enable=application.get('file_upload_enable', False),
|
||||
file_upload_setting=application.get('file_upload_setting', {}),
|
||||
work_flow={}
|
||||
)
|
||||
|
||||
|
||||
class ApplicationSerializer(serializers.Serializer):
|
||||
def insert(self):
|
||||
pass
|
||||
workspace_id = serializers.CharField(required=True, label=_('workspace id'))
|
||||
user_id = serializers.UUIDField(required=True, label=_("User ID"))
|
||||
|
||||
def insert(self, instance: Dict, with_valid=True):
|
||||
application_type = instance.get('type')
|
||||
if 'WORK_FLOW' == application_type:
|
||||
return self.insert_workflow(instance)
|
||||
else:
|
||||
return self.insert_simple(instance)
|
||||
|
||||
def insert_workflow(self, instance: Dict):
|
||||
self.is_valid(raise_exception=True)
|
||||
user_id = self.data.get('user_id')
|
||||
ApplicationCreateSerializer.WorkflowRequest(data=instance).is_valid(raise_exception=True)
|
||||
application_model = ApplicationCreateSerializer.WorkflowRequest.to_application_model(user_id, instance)
|
||||
application_model.save()
|
||||
# 插入认证信息
|
||||
ApplicationAccessToken(application_id=application_model.id,
|
||||
access_token=hashlib.md5(str(uuid.uuid1()).encode()).hexdigest()[8:24]).save()
|
||||
return ApplicationCreateSerializer.ApplicationResponse(application_model).data
|
||||
|
||||
@staticmethod
|
||||
def to_application_knowledge_mapping(application_id: str, dataset_id: str):
|
||||
return ApplicationKnowledgeMapping(id=uuid.uuid1(), application_id=application_id, dataset_id=dataset_id)
|
||||
|
||||
def insert_simple(self, instance: Dict):
|
||||
self.is_valid(raise_exception=True)
|
||||
user_id = self.data.get('user_id')
|
||||
ApplicationCreateSerializer.SimplateRequest(data=instance).is_valid(user_id=user_id, raise_exception=True)
|
||||
application_model = ApplicationCreateSerializer.SimplateRequest.to_application_model(user_id, instance)
|
||||
dataset_id_list = instance.get('knowledge_id_list', [])
|
||||
application_knowledge_mapping_model_list = [
|
||||
self.to_application_knowledge_mapping(application_model.id, dataset_id) for
|
||||
dataset_id in dataset_id_list]
|
||||
# 插入应用
|
||||
application_model.save()
|
||||
# 插入认证信息
|
||||
ApplicationAccessToken(application_id=application_model.id,
|
||||
access_token=hashlib.md5(str(uuid.uuid1()).encode()).hexdigest()[8:24]).save()
|
||||
# 插入关联数据
|
||||
QuerySet(ApplicationKnowledgeMapping).bulk_create(application_knowledge_mapping_model_list)
|
||||
return ApplicationCreateSerializer.ApplicationResponse(application_model).data
|
||||
|
|
|
|||
|
|
@ -5,5 +5,6 @@ from . import views
|
|||
app_name = 'application'
|
||||
|
||||
urlpatterns = [
|
||||
path('workspace/<str:workspace_id>/application/<str:application_id>/application_key', views.ApplicationKey.as_view()),
|
||||
]
|
||||
path('workspace/<str:workspace_id>/application', views.Application.as_view(), name='application'),
|
||||
path('workspace/<str:workspace_id>/application/<str:application_id>/application_key',
|
||||
views.ApplicationKey.as_view())]
|
||||
|
|
|
|||
|
|
@ -6,4 +6,5 @@
|
|||
@date:2025/5/9 18:51
|
||||
@desc:
|
||||
"""
|
||||
from .application_api_key import *
|
||||
from .application_api_key import *
|
||||
from .application import *
|
||||
|
|
|
|||
|
|
@ -14,9 +14,11 @@ from rest_framework.views import APIView
|
|||
from application.api.application_api import ApplicationCreateAPI
|
||||
from application.serializers.application import ApplicationSerializer
|
||||
from common import result
|
||||
from common.auth import TokenAuth
|
||||
|
||||
|
||||
class Application(APIView):
|
||||
authentication_classes = [TokenAuth]
|
||||
|
||||
@extend_schema(
|
||||
methods=['POST'],
|
||||
|
|
@ -28,5 +30,6 @@ class Application(APIView):
|
|||
responses=ApplicationCreateAPI.get_response(),
|
||||
tags=[_('Application')] # type: ignore
|
||||
)
|
||||
def post(self, request: Request):
|
||||
return result.success(ApplicationSerializer.insert(request.data))
|
||||
def post(self, request: Request, workspace_id: str):
|
||||
return result.success(
|
||||
ApplicationSerializer(data={'workspace_id': workspace_id, 'user_id': request.user.id}).insert(request.data))
|
||||
|
|
|
|||
|
|
@ -0,0 +1,27 @@
|
|||
# Generated by Django 5.2 on 2025-05-27 03:05
|
||||
|
||||
import knowledge.models.knowledge
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('knowledge', '0006_knowledgefolder_desc_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='document',
|
||||
name='status',
|
||||
field=models.CharField(default=knowledge.models.knowledge.Status.__str__, max_length=20, verbose_name='状态'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='paragraph',
|
||||
name='status',
|
||||
field=models.CharField(default=knowledge.models.knowledge.Status.__str__, max_length=20, verbose_name='状态'),
|
||||
),
|
||||
migrations.DeleteModel(
|
||||
name='ApplicationKnowledgeMapping',
|
||||
),
|
||||
]
|
||||
|
|
@ -202,15 +202,6 @@ class ProblemParagraphMapping(AppModelMixin):
|
|||
db_table = "problem_paragraph_mapping"
|
||||
|
||||
|
||||
class ApplicationKnowledgeMapping(AppModelMixin):
|
||||
id = models.UUIDField(primary_key=True, max_length=128, default=uuid.uuid7, editable=False, verbose_name="主键id")
|
||||
# application = models.ForeignKey(Application, on_delete=models.DO_NOTHING)
|
||||
knowledge = models.ForeignKey(Knowledge, on_delete=models.DO_NOTHING)
|
||||
|
||||
class Meta:
|
||||
db_table = "application_knowledge_mapping"
|
||||
|
||||
|
||||
class SourceType(models.IntegerChoices):
|
||||
"""订单类型"""
|
||||
PROBLEM = 0, '问题'
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ from django.db.models.functions import Reverse, Substr
|
|||
from django.utils.translation import gettext_lazy as _
|
||||
from rest_framework import serializers
|
||||
|
||||
from application.models import ApplicationKnowledgeMapping
|
||||
from common.config.embedding_config import VectorStore
|
||||
from common.db.search import native_search, get_dynamics_model, native_page_search
|
||||
from common.db.sql_execute import select_list
|
||||
|
|
@ -23,7 +24,7 @@ from common.utils.common import valid_license, post, get_file_content
|
|||
from common.utils.fork import Fork, ChildLink
|
||||
from common.utils.split_model import get_split_model
|
||||
from knowledge.models import Knowledge, KnowledgeScope, KnowledgeType, Document, Paragraph, Problem, \
|
||||
ProblemParagraphMapping, ApplicationKnowledgeMapping, TaskType, State, SearchMode, KnowledgeFolder
|
||||
ProblemParagraphMapping, TaskType, State, SearchMode, KnowledgeFolder
|
||||
from knowledge.serializers.common import ProblemParagraphManage, get_embedding_model_id_by_knowledge_id, MetaSerializer, \
|
||||
GenerateRelatedSerializer, get_embedding_model_by_knowledge_id, list_paragraph
|
||||
from knowledge.serializers.document import DocumentSerializers
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ INSTALLED_APPS = [
|
|||
'drf_spectacular_sidecar',
|
||||
'users.apps.UsersConfig',
|
||||
'tools.apps.ToolConfig',
|
||||
'knowledge.apps.KnowledgeConfig',
|
||||
'knowledge',
|
||||
'common',
|
||||
'system_manage',
|
||||
'models_provider',
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ urlpatterns = [
|
|||
path("api/", include("folders.urls")),
|
||||
path("api/", include("knowledge.urls")),
|
||||
path("api/", include("system_manage.urls")),
|
||||
path("api/", include("application.urls"))
|
||||
]
|
||||
urlpatterns += [
|
||||
path('schema/', SpectacularAPIView.as_view(), name='schema'), # schema的配置文件的路由,下面两个ui也是根据这个配置文件来生成的
|
||||
|
|
|
|||
|
|
@ -0,0 +1,18 @@
|
|||
# Generated by Django 5.2 on 2025-05-27 02:15
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('users', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='user',
|
||||
name='nick_name',
|
||||
field=models.CharField(max_length=150, unique=True, verbose_name='昵称'),
|
||||
),
|
||||
]
|
||||
Loading…
Reference in New Issue