Skip to content

Commit e7a3090

Browse files
authored
feat: application upload file (#3487)
1 parent 0c874bd commit e7a3090

File tree

9 files changed

+140
-139
lines changed

9 files changed

+140
-139
lines changed

apps/application/chat_pipeline/step/search_dataset_step/impl/base_search_dataset_step.py

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -24,17 +24,7 @@
2424
from knowledge.models import SearchMode
2525
from maxkb.conf import PROJECT_DIR
2626
from models_provider.models import Model
27-
from models_provider.tools import get_model
28-
29-
30-
def get_model_by_id(_id, workspace_id):
31-
model = QuerySet(Model).filter(id=_id, model_type="EMBEDDING")
32-
get_authorized_model = DatabaseModelManage.get_model("get_authorized_model")
33-
if get_authorized_model is not None:
34-
model = get_authorized_model(model, workspace_id)
35-
if model is None:
36-
raise Exception(_("Model does not exist"))
37-
return model
27+
from models_provider.tools import get_model, get_model_by_id
3828

3929

4030
def get_embedding_id(knowledge_id_list):
@@ -65,6 +55,8 @@ def execute(self, problem_text: str, knowledge_id_list: list[str], exclude_docum
6555
exec_problem_text = padding_problem_text if padding_problem_text is not None else problem_text
6656
model_id = get_embedding_id(knowledge_id_list)
6757
model = get_model_by_id(model_id, workspace_id)
58+
if model.model_type != "EMBEDDING":
59+
raise Exception(_("Model does not exist"))
6860
self.context['model_name'] = model.name
6961
embedding_model = ModelManage.get_model(model_id, lambda _id: get_model(model))
7062
embedding_value = embedding_model.embed_query(exec_problem_text)

apps/application/flow/step_node/document_extract_node/impl/base_document_extract_node.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ def save_image(image_list):
7171

7272
for doc in document:
7373
file = QuerySet(File).filter(id=doc['file_id']).first()
74-
buffer = io.BytesIO(file.get_bytes().tobytes())
74+
buffer = io.BytesIO(file.get_bytes())
7575
buffer.name = doc['name'] # this is the important line
7676

7777
for split_handle in (parse_table_handle_list + split_handles):

apps/chat/views/chat.py

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from django.http import HttpResponse
1010
from django.utils.translation import gettext_lazy as _
1111
from drf_spectacular.utils import extend_schema
12+
from rest_framework.parsers import MultiPartParser
1213
from rest_framework.request import Request
1314
from rest_framework.views import APIView
1415

@@ -24,6 +25,8 @@
2425
from common.constants.permission_constants import ChatAuth
2526
from common.exception.app_exception import AppAuthenticationFailed
2627
from common.result import result
28+
from knowledge.models import FileSourceType
29+
from oss.serializers.file import FileSerializer
2730
from users.api import CaptchaAPI
2831
from users.serializers.login import CaptchaSerializer
2932

@@ -134,7 +137,7 @@ class CaptchaView(APIView):
134137
summary=_("Get Chat captcha"),
135138
description=_("Get Chat captcha"),
136139
operation_id=_("Get Chat captcha"), # type: ignore
137-
tags=[_("User Management")], # type: ignore
140+
tags=[_("Chat")], # type: ignore
138141
responses=CaptchaAPI.get_response())
139142
def get(self, request: Request):
140143
return result.success(CaptchaSerializer().generate())
@@ -150,7 +153,7 @@ class SpeechToText(APIView):
150153
operation_id=_("speech to text"), # type: ignore
151154
request=SpeechToTextAPI.get_request(),
152155
responses=SpeechToTextAPI.get_response(),
153-
tags=[_('Application')] # type: ignore
156+
tags=[_('Chat')] # type: ignore
154157
)
155158
def post(self, request: Request):
156159
return result.success(
@@ -169,10 +172,34 @@ class TextToSpeech(APIView):
169172
operation_id=_("text to speech"), # type: ignore
170173
request=TextToSpeechAPI.get_request(),
171174
responses=TextToSpeechAPI.get_response(),
172-
tags=[_('Application')] # type: ignore
175+
tags=[_('Chat')] # type: ignore
173176
)
174177
def post(self, request: Request):
175178
byte_data = TextToSpeechSerializers(
176179
data={'application_id': request.auth.application_id}).text_to_speech(request.data)
177180
return HttpResponse(byte_data, status=200, headers={'Content-Type': 'audio/mp3',
178181
'Content-Disposition': 'attachment; filename="abc.mp3"'})
182+
183+
184+
class UploadFile(APIView):
185+
authentication_classes = [TokenAuth]
186+
parser_classes = [MultiPartParser]
187+
188+
@extend_schema(
189+
methods=['POST'],
190+
description=_("Upload files"),
191+
summary=_("Upload files"),
192+
operation_id=_("Upload files"), # type: ignore
193+
request=TextToSpeechAPI.get_request(),
194+
responses=TextToSpeechAPI.get_response(),
195+
tags=[_('Application')] # type: ignore
196+
)
197+
def post(self, request: Request, chat_id: str):
198+
files = request.FILES.getlist('file')
199+
file_ids = []
200+
meta = {}
201+
for file in files:
202+
file_url = FileSerializer(
203+
data={'file': file, 'meta': meta, 'source_id': chat_id, 'source_type': FileSourceType.CHAT, }).upload()
204+
file_ids.append({'name': file.name, 'url': file_url, 'file_id': file_url.split('/')[-1]})
205+
return result.success(file_ids)

apps/knowledge/models/knowledge.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,6 @@ def default_status_meta():
9595
return {"state_time": {}}
9696

9797

98-
99-
10098
class KnowledgeFolder(MPTTModel, AppModelMixin):
10199
id = models.CharField(primary_key=True, max_length=64, editable=False, verbose_name="主键id")
102100
name = models.CharField(max_length=64, verbose_name="文件夹名称")
@@ -133,9 +131,11 @@ class Knowledge(AppModelMixin):
133131
class Meta:
134132
db_table = "knowledge"
135133

134+
136135
def get_default_status():
137136
return Status('').__str__()
138137

138+
139139
class Document(AppModelMixin):
140140
"""
141141
文档表
@@ -224,10 +224,12 @@ class FileSourceType(models.TextChoices):
224224
TOOL = "TOOL"
225225
# 文档
226226
DOCUMENT = "DOCUMENT"
227+
# 对话
228+
CHAT = "CHAT"
227229
# 临时30分钟 数据30分钟后被清理 source_id 为TEMPORARY_30_MINUTE
228230
TEMPORARY_30_MINUTE = "TEMPORARY_30_MINUTE"
229231
# 临时120分钟 数据120分钟后被清理 source_id为TEMPORARY_100_MINUTE
230-
TEMPORARY_120_MINUTE = "TEMPORARY_100_MINUTE"
232+
TEMPORARY_120_MINUTE = "TEMPORARY_120_MINUTE"
231233
# 临时1天 数据1天后被清理 source_id为TEMPORARY_1_DAY
232234
TEMPORARY_1_DAY = "TEMPORARY_1_DAY"
233235

apps/maxkb/urls.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
path(admin_api_prefix, include("system_manage.urls")),
4343
path(admin_api_prefix, include("application.urls")),
4444
path(admin_api_prefix, include("oss.urls")),
45+
path(chat_api_prefix, include("oss.urls")),
4546
path(chat_api_prefix, include("chat.urls")),
4647
path(f'{admin_ui_prefix[1:]}/', include('oss.retrieval_urls')),
4748
path(f'{chat_ui_prefix[1:]}/', include('oss.retrieval_urls')),

ui/src/api/application/application.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,30 @@ const getMcpTools: (application_id: String, loading?: Ref<boolean>) => Promise<R
296296
return get(`${prefix.value}/${application_id}/mcp_tools`, undefined, loading)
297297
}
298298

299+
/**
300+
* 上传文件
301+
* @param 参数 file:file
302+
*/
303+
const uploadFile: (
304+
file: any,
305+
sourceId: string,
306+
resourceType:
307+
| 'KNOWLEDGE'
308+
| 'APPLICATION'
309+
| 'TOOL'
310+
| 'DOCUMENT'
311+
| 'CHAT'
312+
| 'TEMPORARY_30_MINUTE'
313+
| 'TEMPORARY_120_MINUTE'
314+
| 'TEMPORARY_1_DAY',
315+
) => Promise<Result<any>> = (file, sourceId, resourceType) => {
316+
const fd = new FormData()
317+
fd.append('file', file)
318+
fd.append('source_id', sourceId)
319+
fd.append('source_type', resourceType)
320+
return post(`/oss/file`, fd)
321+
}
322+
299323
export default {
300324
getAllApplication,
301325
getApplication,
@@ -321,4 +345,5 @@ export default {
321345
postTextToSpeech,
322346
speechToText,
323347
getMcpTools,
348+
uploadFile,
324349
}

ui/src/api/chat/chat.ts

Lines changed: 39 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -265,30 +265,57 @@ const speechToText: (data: any, loading?: Ref<boolean>) => Promise<Result<any>>
265265
return post(`speech_to_text`, data, undefined, loading)
266266
}
267267
/**
268-
*
268+
*
269269
* @param chat_id 对话ID
270-
* @param loading
271-
* @returns
270+
* @param loading
271+
* @returns
272272
*/
273-
const deleteChat: (chat_id:string, loading?: Ref<boolean>) => Promise<Result<any>> = (
273+
const deleteChat: (chat_id: string, loading?: Ref<boolean>) => Promise<Result<any>> = (
274274
chat_id,
275275
loading,
276276
) => {
277277
return del(`historical_conversation/${chat_id}`, loading)
278278
}
279279
/**
280-
*
280+
*
281281
* @param chat_id 对话id
282282
* @param data 对话简介
283-
* @param loading
284-
* @returns
283+
* @param loading
284+
* @returns
285285
*/
286-
const modifyChat: (chat_id:string, data:any, loading?: Ref<boolean> ) => Promise<Result<any>> = (
287-
chat_id,data,loading
286+
const modifyChat: (chat_id: string, data: any, loading?: Ref<boolean>) => Promise<Result<any>> = (
287+
chat_id,
288+
data,
289+
loading,
288290
) => {
289291
return put(`historical_conversation/${chat_id}`, data, undefined, loading)
290292
}
291-
293+
/**
294+
* 上传文件
295+
* @param file 文件
296+
* @param sourceId 资源id
297+
* @param resourceType 资源类型
298+
* @returns
299+
*/
300+
const uploadFile: (
301+
file: any,
302+
sourceId: string,
303+
resourceType:
304+
| 'KNOWLEDGE'
305+
| 'APPLICATION'
306+
| 'TOOL'
307+
| 'DOCUMENT'
308+
| 'CHAT'
309+
| 'TEMPORARY_30_MINUTE'
310+
| 'TEMPORARY_120_MINUTE'
311+
| 'TEMPORARY_1_DAY',
312+
) => Promise<Result<any>> = (file, sourceId, sourceType) => {
313+
const fd = new FormData()
314+
fd.append('file', file)
315+
fd.append('source_id', sourceId)
316+
fd.append('source_type', sourceType)
317+
return post(`/oss/file`, fd)
318+
}
292319
export default {
293320
open,
294321
chat,
@@ -316,5 +343,6 @@ export default {
316343
textToSpeech,
317344
speechToText,
318345
deleteChat,
319-
modifyChat
346+
modifyChat,
347+
uploadFile,
320348
}

0 commit comments

Comments
 (0)