瀏覽代碼

Unified API response json schema (#3170)

### What problem does this PR solve?

Unified API response json schema

### Type of change

- [x] Refactoring
tags/v0.14.0
Zhichang Yu 1 年之前
父節點
當前提交
185c6a0c71
沒有連結到貢獻者的電子郵件帳戶。
共有 53 個檔案被更改,包括 1458 行新增1470 行删除
  1. 47
    47
      api/apps/api_app.py
  2. 15
    15
      api/apps/canvas_app.py
  3. 22
    23
      api/apps/chunk_app.py
  4. 26
    26
      api/apps/conversation_app.py
  5. 10
    10
      api/apps/dialog_app.py
  6. 48
    48
      api/apps/document_app.py
  7. 11
    15
      api/apps/file2document_app.py
  8. 29
    32
      api/apps/file_app.py
  9. 15
    15
      api/apps/kb_app.py
  10. 2
    2
      api/apps/llm_app.py
  11. 20
    20
      api/apps/sdk/chat.py
  12. 535
    535
      api/apps/sdk/dataset.py
  13. 5
    5
      api/apps/sdk/dify_retrieval.py
  14. 48
    48
      api/apps/sdk/doc.py
  15. 394
    394
      api/apps/sdk/session.py
  16. 3
    5
      api/apps/system_app.py
  17. 3
    3
      api/apps/tenant_app.py
  18. 24
    24
      api/apps/user_app.py
  19. 36
    36
      api/utils/api_utils.py
  20. 1
    1
      docs/references/faq.md
  21. 7
    9
      intergrations/chatgpt-on-wechat/plugins/ragflow_chat.py
  22. 6
    6
      sdk/python/test/conftest.py
  23. 1
    1
      sdk/python/test/ragflow.txt
  24. 4
    4
      web/src/components/message-input/index.tsx
  25. 2
    2
      web/src/components/message-item/hooks.ts
  26. 2
    2
      web/src/components/pdf-previewer/hooks.ts
  27. 15
    15
      web/src/hooks/chat-hooks.ts
  28. 7
    7
      web/src/hooks/chunk-hooks.ts
  29. 22
    22
      web/src/hooks/document-hooks.ts
  30. 12
    12
      web/src/hooks/file-manager-hooks.ts
  31. 4
    4
      web/src/hooks/flow-hooks.ts
  32. 4
    4
      web/src/hooks/knowledge-hooks.ts
  33. 10
    10
      web/src/hooks/llm-hooks.tsx
  34. 2
    2
      web/src/hooks/logic-hooks.ts
  35. 6
    6
      web/src/hooks/login-hooks.ts
  36. 12
    12
      web/src/hooks/user-setting-hooks.tsx
  37. 2
    2
      web/src/interfaces/database/base.ts
  38. 1
    1
      web/src/pages/add-knowledge/components/knowledge-chunk/components/chunk-creating-modal/index.tsx
  39. 2
    2
      web/src/pages/add-knowledge/components/knowledge-chunk/hooks.ts
  40. 7
    7
      web/src/pages/add-knowledge/components/knowledge-file/hooks.ts
  41. 5
    5
      web/src/pages/chat/hooks.ts
  42. 2
    2
      web/src/pages/chat/shared-hooks.ts
  43. 2
    2
      web/src/pages/document-viewer/hooks.ts
  44. 2
    2
      web/src/pages/file-manager/hooks.ts
  45. 1
    1
      web/src/pages/file-manager/move-file-modal/async-tree-select.tsx
  46. 2
    2
      web/src/pages/flow/chat/hooks.ts
  47. 3
    3
      web/src/pages/flow/hooks.ts
  48. 1
    1
      web/src/pages/flow/list/hooks.ts
  49. 1
    1
      web/src/pages/flow/utils.ts
  50. 1
    1
      web/src/pages/knowledge/hooks.ts
  51. 4
    4
      web/src/pages/login/index.tsx
  52. 4
    4
      web/src/pages/user-setting/setting-team/hooks.ts
  53. 8
    8
      web/src/utils/request.ts

+ 47
- 47
api/apps/api_app.py 查看文件

try: try:
tenants = UserTenantService.query(user_id=current_user.id) tenants = UserTenantService.query(user_id=current_user.id)
if not tenants: if not tenants:
return get_data_error_result(retmsg="Tenant not found!")
return get_data_error_result(message="Tenant not found!")


tenant_id = tenants[0].tenant_id tenant_id = tenants[0].tenant_id
obj = {"tenant_id": tenant_id, "token": generate_confirmation_token(tenant_id), obj = {"tenant_id": tenant_id, "token": generate_confirmation_token(tenant_id),
obj["dialog_id"] = req["dialog_id"] obj["dialog_id"] = req["dialog_id"]


if not APITokenService.save(**obj): if not APITokenService.save(**obj):
return get_data_error_result(retmsg="Fail to new a dialog!")
return get_data_error_result(message="Fail to new a dialog!")


return get_json_result(data=obj) return get_json_result(data=obj)
except Exception as e: except Exception as e:
try: try:
tenants = UserTenantService.query(user_id=current_user.id) tenants = UserTenantService.query(user_id=current_user.id)
if not tenants: if not tenants:
return get_data_error_result(retmsg="Tenant not found!")
return get_data_error_result(message="Tenant not found!")


id = request.args["dialog_id"] if "dialog_id" in request.args else request.args["canvas_id"] id = request.args["dialog_id"] if "dialog_id" in request.args else request.args["canvas_id"]
objs = APITokenService.query(tenant_id=tenants[0].tenant_id, dialog_id=id) objs = APITokenService.query(tenant_id=tenants[0].tenant_id, dialog_id=id)
try: try:
tenants = UserTenantService.query(user_id=current_user.id) tenants = UserTenantService.query(user_id=current_user.id)
if not tenants: if not tenants:
return get_data_error_result(retmsg="Tenant not found!")
return get_data_error_result(message="Tenant not found!")
objs = API4ConversationService.stats( objs = API4ConversationService.stats(
tenants[0].tenant_id, tenants[0].tenant_id,
request.args.get( request.args.get(
objs = APIToken.query(token=token) objs = APIToken.query(token=token)
if not objs: if not objs:
return get_json_result( return get_json_result(
data=False, retmsg='Token is not valid!"', retcode=RetCode.AUTHENTICATION_ERROR)
data=False, message='Token is not valid!"', code=RetCode.AUTHENTICATION_ERROR)
req = request.json req = request.json
try: try:
if objs[0].source == "agent": if objs[0].source == "agent":
else: else:
e, dia = DialogService.get_by_id(objs[0].dialog_id) e, dia = DialogService.get_by_id(objs[0].dialog_id)
if not e: if not e:
return get_data_error_result(retmsg="Dialog not found")
return get_data_error_result(message="Dialog not found")
conv = { conv = {
"id": get_uuid(), "id": get_uuid(),
"dialog_id": dia.id, "dialog_id": dia.id,
objs = APIToken.query(token=token) objs = APIToken.query(token=token)
if not objs: if not objs:
return get_json_result( return get_json_result(
data=False, retmsg='Token is not valid!"', retcode=RetCode.AUTHENTICATION_ERROR)
data=False, message='Token is not valid!"', code=RetCode.AUTHENTICATION_ERROR)
req = request.json req = request.json
e, conv = API4ConversationService.get_by_id(req["conversation_id"]) e, conv = API4ConversationService.get_by_id(req["conversation_id"])
if not e: if not e:
return get_data_error_result(retmsg="Conversation not found!")
return get_data_error_result(message="Conversation not found!")
if "quote" not in req: req["quote"] = False if "quote" not in req: req["quote"] = False


msg = [] msg = []
ans = {"answer": ans["content"], "reference": ans.get("reference", [])} ans = {"answer": ans["content"], "reference": ans.get("reference", [])}
fillin_conv(ans) fillin_conv(ans)
rename_field(ans) rename_field(ans)
yield "data:" + json.dumps({"retcode": 0, "retmsg": "", "data": ans},
yield "data:" + json.dumps({"code": 0, "message": "", "data": ans},
ensure_ascii=False) + "\n\n" ensure_ascii=False) + "\n\n"


canvas.messages.append({"role": "assistant", "content": final_ans["content"], "id": message_id}) canvas.messages.append({"role": "assistant", "content": final_ans["content"], "id": message_id})
cvs.dsl = json.loads(str(canvas)) cvs.dsl = json.loads(str(canvas))
API4ConversationService.append_message(conv.id, conv.to_dict()) API4ConversationService.append_message(conv.id, conv.to_dict())
except Exception as e: except Exception as e:
yield "data:" + json.dumps({"retcode": 500, "retmsg": str(e),
yield "data:" + json.dumps({"code": 500, "message": str(e),
"data": {"answer": "**ERROR**: " + str(e), "reference": []}}, "data": {"answer": "**ERROR**: " + str(e), "reference": []}},
ensure_ascii=False) + "\n\n" ensure_ascii=False) + "\n\n"
yield "data:" + json.dumps({"retcode": 0, "retmsg": "", "data": True}, ensure_ascii=False) + "\n\n"
yield "data:" + json.dumps({"code": 0, "message": "", "data": True}, ensure_ascii=False) + "\n\n"


resp = Response(sse(), mimetype="text/event-stream") resp = Response(sse(), mimetype="text/event-stream")
resp.headers.add_header("Cache-control", "no-cache") resp.headers.add_header("Cache-control", "no-cache")
conv.message.append(msg[-1]) conv.message.append(msg[-1])
e, dia = DialogService.get_by_id(conv.dialog_id) e, dia = DialogService.get_by_id(conv.dialog_id)
if not e: if not e:
return get_data_error_result(retmsg="Dialog not found!")
return get_data_error_result(message="Dialog not found!")
del req["conversation_id"] del req["conversation_id"]
del req["messages"] del req["messages"]


for ans in chat(dia, msg, True, **req): for ans in chat(dia, msg, True, **req):
fillin_conv(ans) fillin_conv(ans)
rename_field(ans) rename_field(ans)
yield "data:" + json.dumps({"retcode": 0, "retmsg": "", "data": ans},
yield "data:" + json.dumps({"code": 0, "message": "", "data": ans},
ensure_ascii=False) + "\n\n" ensure_ascii=False) + "\n\n"
API4ConversationService.append_message(conv.id, conv.to_dict()) API4ConversationService.append_message(conv.id, conv.to_dict())
except Exception as e: except Exception as e:
yield "data:" + json.dumps({"retcode": 500, "retmsg": str(e),
yield "data:" + json.dumps({"code": 500, "message": str(e),
"data": {"answer": "**ERROR**: " + str(e), "reference": []}}, "data": {"answer": "**ERROR**: " + str(e), "reference": []}},
ensure_ascii=False) + "\n\n" ensure_ascii=False) + "\n\n"
yield "data:" + json.dumps({"retcode": 0, "retmsg": "", "data": True}, ensure_ascii=False) + "\n\n"
yield "data:" + json.dumps({"code": 0, "message": "", "data": True}, ensure_ascii=False) + "\n\n"


if req.get("stream", True): if req.get("stream", True):
resp = Response(stream(), mimetype="text/event-stream") resp = Response(stream(), mimetype="text/event-stream")
objs = APIToken.query(token=token) objs = APIToken.query(token=token)
if not objs: if not objs:
return get_json_result( return get_json_result(
data=False, retmsg='Token is not valid!"', retcode=RetCode.AUTHENTICATION_ERROR)
data=False, message='Token is not valid!"', code=RetCode.AUTHENTICATION_ERROR)
try: try:
e, conv = API4ConversationService.get_by_id(conversation_id) e, conv = API4ConversationService.get_by_id(conversation_id)
if not e: if not e:
return get_data_error_result(retmsg="Conversation not found!")
return get_data_error_result(message="Conversation not found!")


conv = conv.to_dict() conv = conv.to_dict()
if token != APIToken.query(dialog_id=conv['dialog_id'])[0].token: if token != APIToken.query(dialog_id=conv['dialog_id'])[0].token:
return get_json_result(data=False, retmsg='Token is not valid for this conversation_id!"',
retcode=RetCode.AUTHENTICATION_ERROR)
return get_json_result(data=False, message='Token is not valid for this conversation_id!"',
code=RetCode.AUTHENTICATION_ERROR)
for referenct_i in conv['reference']: for referenct_i in conv['reference']:
if referenct_i is None or len(referenct_i) == 0: if referenct_i is None or len(referenct_i) == 0:
objs = APIToken.query(token=token) objs = APIToken.query(token=token)
if not objs: if not objs:
return get_json_result( return get_json_result(
data=False, retmsg='Token is not valid!"', retcode=RetCode.AUTHENTICATION_ERROR)
data=False, message='Token is not valid!"', code=RetCode.AUTHENTICATION_ERROR)


kb_name = request.form.get("kb_name").strip() kb_name = request.form.get("kb_name").strip()
tenant_id = objs[0].tenant_id tenant_id = objs[0].tenant_id
e, kb = KnowledgebaseService.get_by_name(kb_name, tenant_id) e, kb = KnowledgebaseService.get_by_name(kb_name, tenant_id)
if not e: if not e:
return get_data_error_result( return get_data_error_result(
retmsg="Can't find this knowledgebase!")
message="Can't find this knowledgebase!")
kb_id = kb.id kb_id = kb.id
except Exception as e: except Exception as e:
return server_error_response(e) return server_error_response(e)


if 'file' not in request.files: if 'file' not in request.files:
return get_json_result( return get_json_result(
data=False, retmsg='No file part!', retcode=RetCode.ARGUMENT_ERROR)
data=False, message='No file part!', code=RetCode.ARGUMENT_ERROR)


file = request.files['file'] file = request.files['file']
if file.filename == '': if file.filename == '':
return get_json_result( return get_json_result(
data=False, retmsg='No file selected!', retcode=RetCode.ARGUMENT_ERROR)
data=False, message='No file selected!', code=RetCode.ARGUMENT_ERROR)


root_folder = FileService.get_root_folder(tenant_id) root_folder = FileService.get_root_folder(tenant_id)
pf_id = root_folder["id"] pf_id = root_folder["id"]
try: try:
if DocumentService.get_doc_count(kb.tenant_id) >= int(os.environ.get('MAX_FILE_NUM_PER_USER', 8192)): if DocumentService.get_doc_count(kb.tenant_id) >= int(os.environ.get('MAX_FILE_NUM_PER_USER', 8192)):
return get_data_error_result( return get_data_error_result(
retmsg="Exceed the maximum file number of a free user!")
message="Exceed the maximum file number of a free user!")


filename = duplicate_name( filename = duplicate_name(
DocumentService.query, DocumentService.query,
filetype = filename_type(filename) filetype = filename_type(filename)
if not filetype: if not filetype:
return get_data_error_result( return get_data_error_result(
retmsg="This type of file has not been supported yet!")
message="This type of file has not been supported yet!")


location = filename location = filename
while STORAGE_IMPL.obj_exist(kb_id, location): while STORAGE_IMPL.obj_exist(kb_id, location):
# if str(req["run"]) == TaskStatus.CANCEL.value: # if str(req["run"]) == TaskStatus.CANCEL.value:
tenant_id = DocumentService.get_tenant_id(doc["id"]) tenant_id = DocumentService.get_tenant_id(doc["id"])
if not tenant_id: if not tenant_id:
return get_data_error_result(retmsg="Tenant not found!")
return get_data_error_result(message="Tenant not found!")


# e, doc = DocumentService.get_by_id(doc["id"]) # e, doc = DocumentService.get_by_id(doc["id"])
TaskService.filter_delete([Task.doc_id == doc["id"]]) TaskService.filter_delete([Task.doc_id == doc["id"]])
objs = APIToken.query(token=token) objs = APIToken.query(token=token)
if not objs: if not objs:
return get_json_result( return get_json_result(
data=False, retmsg='Token is not valid!"', retcode=RetCode.AUTHENTICATION_ERROR)
data=False, message='Token is not valid!"', code=RetCode.AUTHENTICATION_ERROR)


if 'file' not in request.files: if 'file' not in request.files:
return get_json_result( return get_json_result(
data=False, retmsg='No file part!', retcode=RetCode.ARGUMENT_ERROR)
data=False, message='No file part!', code=RetCode.ARGUMENT_ERROR)


file_objs = request.files.getlist('file') file_objs = request.files.getlist('file')
for file_obj in file_objs: for file_obj in file_objs:
if file_obj.filename == '': if file_obj.filename == '':
return get_json_result( return get_json_result(
data=False, retmsg='No file selected!', retcode=RetCode.ARGUMENT_ERROR)
data=False, message='No file selected!', code=RetCode.ARGUMENT_ERROR)


doc_ids = doc_upload_and_parse(request.form.get("conversation_id"), file_objs, objs[0].tenant_id) doc_ids = doc_upload_and_parse(request.form.get("conversation_id"), file_objs, objs[0].tenant_id)
return get_json_result(data=doc_ids) return get_json_result(data=doc_ids)
objs = APIToken.query(token=token) objs = APIToken.query(token=token)
if not objs: if not objs:
return get_json_result( return get_json_result(
data=False, retmsg='Token is not valid!"', retcode=RetCode.AUTHENTICATION_ERROR)
data=False, message='Token is not valid!"', code=RetCode.AUTHENTICATION_ERROR)


req = request.json req = request.json


doc_id = req['doc_id'] doc_id = req['doc_id']
else: else:
return get_json_result( return get_json_result(
data=False, retmsg="Can't find doc_name or doc_id"
data=False, message="Can't find doc_name or doc_id"
) )


res = retrievaler.chunk_list(doc_id=doc_id, tenant_id=tenant_id) res = retrievaler.chunk_list(doc_id=doc_id, tenant_id=tenant_id)
objs = APIToken.query(token=token) objs = APIToken.query(token=token)
if not objs: if not objs:
return get_json_result( return get_json_result(
data=False, retmsg='Token is not valid!"', retcode=RetCode.AUTHENTICATION_ERROR)
data=False, message='Token is not valid!"', code=RetCode.AUTHENTICATION_ERROR)


req = request.json req = request.json
tenant_id = objs[0].tenant_id tenant_id = objs[0].tenant_id
e, kb = KnowledgebaseService.get_by_name(kb_name, tenant_id) e, kb = KnowledgebaseService.get_by_name(kb_name, tenant_id)
if not e: if not e:
return get_data_error_result( return get_data_error_result(
retmsg="Can't find this knowledgebase!")
message="Can't find this knowledgebase!")
kb_id = kb.id kb_id = kb.id


except Exception as e: except Exception as e:
objs = APIToken.query(token=token) objs = APIToken.query(token=token)
if not objs: if not objs:
return get_json_result( return get_json_result(
data=False, retmsg='Token is not valid!"', retcode=RetCode.AUTHENTICATION_ERROR)
data=False, message='Token is not valid!"', code=RetCode.AUTHENTICATION_ERROR)
req = request.json req = request.json
doc_ids = req["doc_ids"] doc_ids = req["doc_ids"]
docs = DocumentService.get_by_ids(doc_ids) docs = DocumentService.get_by_ids(doc_ids)
objs = APIToken.query(token=token) objs = APIToken.query(token=token)
if not objs: if not objs:
return get_json_result( return get_json_result(
data=False, retmsg='Token is not valid!"', retcode=RetCode.AUTHENTICATION_ERROR)
data=False, message='Token is not valid!"', code=RetCode.AUTHENTICATION_ERROR)


tenant_id = objs[0].tenant_id tenant_id = objs[0].tenant_id
req = request.json req = request.json


if not doc_ids: if not doc_ids:
return get_json_result( return get_json_result(
data=False, retmsg="Can't find doc_names or doc_ids"
data=False, message="Can't find doc_names or doc_ids"
) )


except Exception as e: except Exception as e:
try: try:
e, doc = DocumentService.get_by_id(doc_id) e, doc = DocumentService.get_by_id(doc_id)
if not e: if not e:
return get_data_error_result(retmsg="Document not found!")
return get_data_error_result(message="Document not found!")
tenant_id = DocumentService.get_tenant_id(doc_id) tenant_id = DocumentService.get_tenant_id(doc_id)
if not tenant_id: if not tenant_id:
return get_data_error_result(retmsg="Tenant not found!")
return get_data_error_result(message="Tenant not found!")


b, n = File2DocumentService.get_storage_address(doc_id=doc_id) b, n = File2DocumentService.get_storage_address(doc_id=doc_id)


if not DocumentService.remove_document(doc, tenant_id): if not DocumentService.remove_document(doc, tenant_id):
return get_data_error_result( return get_data_error_result(
retmsg="Database error (Document removal)!")
message="Database error (Document removal)!")


f2d = File2DocumentService.get_by_document_id(doc_id) f2d = File2DocumentService.get_by_document_id(doc_id)
FileService.filter_delete([File.source_type == FileSource.KNOWLEDGEBASE, File.id == f2d[0].file_id]) FileService.filter_delete([File.source_type == FileSource.KNOWLEDGEBASE, File.id == f2d[0].file_id])
errors += str(e) errors += str(e)


if errors: if errors:
return get_json_result(data=False, retmsg=errors, retcode=RetCode.SERVER_ERROR)
return get_json_result(data=False, message=errors, code=RetCode.SERVER_ERROR)


return get_json_result(data=True) return get_json_result(data=True)


objs = APIToken.query(token=token) objs = APIToken.query(token=token)
if not objs: if not objs:
return get_json_result( return get_json_result(
data=False, retmsg='Token is not valid!"', retcode=RetCode.AUTHENTICATION_ERROR)
data=False, message='Token is not valid!"', code=RetCode.AUTHENTICATION_ERROR)


e, conv = API4ConversationService.get_by_id(req["conversation_id"]) e, conv = API4ConversationService.get_by_id(req["conversation_id"])
if not e: if not e:
return get_data_error_result(retmsg="Conversation not found!")
return get_data_error_result(message="Conversation not found!")
if "quote" not in req: req["quote"] = True if "quote" not in req: req["quote"] = True


msg = [] msg = []
conv.message.append(msg[-1]) conv.message.append(msg[-1])
e, dia = DialogService.get_by_id(conv.dialog_id) e, dia = DialogService.get_by_id(conv.dialog_id)
if not e: if not e:
return get_data_error_result(retmsg="Dialog not found!")
return get_data_error_result(message="Dialog not found!")
del req["conversation_id"] del req["conversation_id"]


if not conv.reference: if not conv.reference:
objs = APIToken.query(token=token) objs = APIToken.query(token=token)
if not objs: if not objs:
return get_json_result( return get_json_result(
data=False, retmsg='Token is not valid!"', retcode=RetCode.AUTHENTICATION_ERROR)
data=False, message='Token is not valid!"', code=RetCode.AUTHENTICATION_ERROR)


req = request.json req = request.json
kb_ids = req.get("kb_id",[]) kb_ids = req.get("kb_id",[])
embd_nms = list(set([kb.embd_id for kb in kbs])) embd_nms = list(set([kb.embd_id for kb in kbs]))
if len(embd_nms) != 1: if len(embd_nms) != 1:
return get_json_result( return get_json_result(
data=False, retmsg='Knowledge bases use different embedding models or does not exist."', retcode=RetCode.AUTHENTICATION_ERROR)
data=False, message='Knowledge bases use different embedding models or does not exist."', code=RetCode.AUTHENTICATION_ERROR)


embd_mdl = TenantLLMService.model_instance( embd_mdl = TenantLLMService.model_instance(
kbs[0].tenant_id, LLMType.EMBEDDING.value, llm_name=kbs[0].embd_id) kbs[0].tenant_id, LLMType.EMBEDDING.value, llm_name=kbs[0].embd_id)
return get_json_result(data=ranks) return get_json_result(data=ranks)
except Exception as e: except Exception as e:
if str(e).find("not_found") > 0: if str(e).find("not_found") > 0:
return get_json_result(data=False, retmsg=f'No chunk found! Check the chunk status please!',
retcode=RetCode.DATA_ERROR)
return get_json_result(data=False, message='No chunk found! Check the chunk status please!',
code=RetCode.DATA_ERROR)
return server_error_response(e) return server_error_response(e)

+ 15
- 15
api/apps/canvas_app.py 查看文件

for i in request.json["canvas_ids"]: for i in request.json["canvas_ids"]:
if not UserCanvasService.query(user_id=current_user.id,id=i): if not UserCanvasService.query(user_id=current_user.id,id=i):
return get_json_result( return get_json_result(
data=False, retmsg=f'Only owner of canvas authorized for this operation.',
retcode=RetCode.OPERATING_ERROR)
data=False, message='Only owner of canvas authorized for this operation.',
code=RetCode.OPERATING_ERROR)
UserCanvasService.delete_by_id(i) UserCanvasService.delete_by_id(i)
return get_json_result(data=True) return get_json_result(data=True)


return server_error_response(ValueError("Duplicated title.")) return server_error_response(ValueError("Duplicated title."))
req["id"] = get_uuid() req["id"] = get_uuid()
if not UserCanvasService.save(**req): if not UserCanvasService.save(**req):
return get_data_error_result(retmsg="Fail to save canvas.")
return get_data_error_result(message="Fail to save canvas.")
else: else:
if not UserCanvasService.query(user_id=current_user.id, id=req["id"]): if not UserCanvasService.query(user_id=current_user.id, id=req["id"]):
return get_json_result( return get_json_result(
data=False, retmsg=f'Only owner of canvas authorized for this operation.',
retcode=RetCode.OPERATING_ERROR)
data=False, message='Only owner of canvas authorized for this operation.',
code=RetCode.OPERATING_ERROR)
UserCanvasService.update_by_id(req["id"], req) UserCanvasService.update_by_id(req["id"], req)
return get_json_result(data=req) return get_json_result(data=req)


def get(canvas_id): def get(canvas_id):
e, c = UserCanvasService.get_by_id(canvas_id) e, c = UserCanvasService.get_by_id(canvas_id)
if not e: if not e:
return get_data_error_result(retmsg="canvas not found.")
return get_data_error_result(message="canvas not found.")
return get_json_result(data=c.to_dict()) return get_json_result(data=c.to_dict())




stream = req.get("stream", True) stream = req.get("stream", True)
e, cvs = UserCanvasService.get_by_id(req["id"]) e, cvs = UserCanvasService.get_by_id(req["id"])
if not e: if not e:
return get_data_error_result(retmsg="canvas not found.")
return get_data_error_result(message="canvas not found.")
if not UserCanvasService.query(user_id=current_user.id, id=req["id"]): if not UserCanvasService.query(user_id=current_user.id, id=req["id"]):
return get_json_result( return get_json_result(
data=False, retmsg=f'Only owner of canvas authorized for this operation.',
retcode=RetCode.OPERATING_ERROR)
data=False, message='Only owner of canvas authorized for this operation.',
code=RetCode.OPERATING_ERROR)


if not isinstance(cvs.dsl, str): if not isinstance(cvs.dsl, str):
cvs.dsl = json.dumps(cvs.dsl, ensure_ascii=False) cvs.dsl = json.dumps(cvs.dsl, ensure_ascii=False)
for k in ans.keys(): for k in ans.keys():
final_ans[k] = ans[k] final_ans[k] = ans[k]
ans = {"answer": ans["content"], "reference": ans.get("reference", [])} ans = {"answer": ans["content"], "reference": ans.get("reference", [])}
yield "data:" + json.dumps({"retcode": 0, "retmsg": "", "data": ans}, ensure_ascii=False) + "\n\n"
yield "data:" + json.dumps({"code": 0, "message": "", "data": ans}, ensure_ascii=False) + "\n\n"


canvas.messages.append({"role": "assistant", "content": final_ans["content"], "id": message_id}) canvas.messages.append({"role": "assistant", "content": final_ans["content"], "id": message_id})
canvas.history.append(("assistant", final_ans["content"])) canvas.history.append(("assistant", final_ans["content"]))
cvs.dsl = json.loads(str(canvas)) cvs.dsl = json.loads(str(canvas))
UserCanvasService.update_by_id(req["id"], cvs.to_dict()) UserCanvasService.update_by_id(req["id"], cvs.to_dict())
except Exception as e: except Exception as e:
yield "data:" + json.dumps({"retcode": 500, "retmsg": str(e),
yield "data:" + json.dumps({"code": 500, "message": str(e),
"data": {"answer": "**ERROR**: " + str(e), "reference": []}}, "data": {"answer": "**ERROR**: " + str(e), "reference": []}},
ensure_ascii=False) + "\n\n" ensure_ascii=False) + "\n\n"
yield "data:" + json.dumps({"retcode": 0, "retmsg": "", "data": True}, ensure_ascii=False) + "\n\n"
yield "data:" + json.dumps({"code": 0, "message": "", "data": True}, ensure_ascii=False) + "\n\n"


resp = Response(sse(), mimetype="text/event-stream") resp = Response(sse(), mimetype="text/event-stream")
resp.headers.add_header("Cache-control", "no-cache") resp.headers.add_header("Cache-control", "no-cache")
try: try:
e, user_canvas = UserCanvasService.get_by_id(req["id"]) e, user_canvas = UserCanvasService.get_by_id(req["id"])
if not e: if not e:
return get_data_error_result(retmsg="canvas not found.")
return get_data_error_result(message="canvas not found.")
if not UserCanvasService.query(user_id=current_user.id, id=req["id"]): if not UserCanvasService.query(user_id=current_user.id, id=req["id"]):
return get_json_result( return get_json_result(
data=False, retmsg=f'Only owner of canvas authorized for this operation.',
retcode=RetCode.OPERATING_ERROR)
data=False, message='Only owner of canvas authorized for this operation.',
code=RetCode.OPERATING_ERROR)


canvas = Canvas(json.dumps(user_canvas.dsl), current_user.id) canvas = Canvas(json.dumps(user_canvas.dsl), current_user.id)
canvas.reset() canvas.reset()

+ 22
- 23
api/apps/chunk_app.py 查看文件

# #
import datetime import datetime
import json import json
import traceback


from flask import request from flask import request
from flask_login import login_required, current_user from flask_login import login_required, current_user
try: try:
tenant_id = DocumentService.get_tenant_id(req["doc_id"]) tenant_id = DocumentService.get_tenant_id(req["doc_id"])
if not tenant_id: if not tenant_id:
return get_data_error_result(retmsg="Tenant not found!")
return get_data_error_result(message="Tenant not found!")
e, doc = DocumentService.get_by_id(doc_id) e, doc = DocumentService.get_by_id(doc_id)
if not e: if not e:
return get_data_error_result(retmsg="Document not found!")
return get_data_error_result(message="Document not found!")
query = { query = {
"doc_ids": [doc_id], "page": page, "size": size, "question": question, "sort": True "doc_ids": [doc_id], "page": page, "size": size, "question": question, "sort": True
} }
return get_json_result(data=res) return get_json_result(data=res)
except Exception as e: except Exception as e:
if str(e).find("not_found") > 0: if str(e).find("not_found") > 0:
return get_json_result(data=False, retmsg=f'No chunk found!',
retcode=RetCode.DATA_ERROR)
return get_json_result(data=False, message='No chunk found!',
code=RetCode.DATA_ERROR)
return server_error_response(e) return server_error_response(e)




try: try:
tenants = UserTenantService.query(user_id=current_user.id) tenants = UserTenantService.query(user_id=current_user.id)
if not tenants: if not tenants:
return get_data_error_result(retmsg="Tenant not found!")
return get_data_error_result(message="Tenant not found!")
res = ELASTICSEARCH.get( res = ELASTICSEARCH.get(
chunk_id, search.index_name( chunk_id, search.index_name(
tenants[0].tenant_id)) tenants[0].tenant_id))
return get_json_result(data=res) return get_json_result(data=res)
except Exception as e: except Exception as e:
if str(e).find("NotFoundError") >= 0: if str(e).find("NotFoundError") >= 0:
return get_json_result(data=False, retmsg=f'Chunk not found!',
retcode=RetCode.DATA_ERROR)
return get_json_result(data=False, message='Chunk not found!',
code=RetCode.DATA_ERROR)
return server_error_response(e) return server_error_response(e)




try: try:
tenant_id = DocumentService.get_tenant_id(req["doc_id"]) tenant_id = DocumentService.get_tenant_id(req["doc_id"])
if not tenant_id: if not tenant_id:
return get_data_error_result(retmsg="Tenant not found!")
return get_data_error_result(message="Tenant not found!")


embd_id = DocumentService.get_embd_id(req["doc_id"]) embd_id = DocumentService.get_embd_id(req["doc_id"])
embd_mdl = LLMBundle(tenant_id, LLMType.EMBEDDING, embd_id) embd_mdl = LLMBundle(tenant_id, LLMType.EMBEDDING, embd_id)


e, doc = DocumentService.get_by_id(req["doc_id"]) e, doc = DocumentService.get_by_id(req["doc_id"])
if not e: if not e:
return get_data_error_result(retmsg="Document not found!")
return get_data_error_result(message="Document not found!")


if doc.parser_id == ParserType.QA: if doc.parser_id == ParserType.QA:
arr = [ arr = [
req["content_with_weight"]) if len(t) > 1] req["content_with_weight"]) if len(t) > 1]
if len(arr) != 2: if len(arr) != 2:
return get_data_error_result( return get_data_error_result(
retmsg="Q&A must be separated by TAB/ENTER key.")
message="Q&A must be separated by TAB/ENTER key.")
q, a = rmPrefix(arr[0]), rmPrefix(arr[1]) q, a = rmPrefix(arr[0]), rmPrefix(arr[1])
d = beAdoc(d, arr[0], arr[1], not any( d = beAdoc(d, arr[0], arr[1], not any(
[rag_tokenizer.is_chinese(t) for t in q + a])) [rag_tokenizer.is_chinese(t) for t in q + a]))
try: try:
tenant_id = DocumentService.get_tenant_id(req["doc_id"]) tenant_id = DocumentService.get_tenant_id(req["doc_id"])
if not tenant_id: if not tenant_id:
return get_data_error_result(retmsg="Tenant not found!")
return get_data_error_result(message="Tenant not found!")
if not ELASTICSEARCH.upsert([{"id": i, "available_int": int(req["available_int"])} for i in req["chunk_ids"]], if not ELASTICSEARCH.upsert([{"id": i, "available_int": int(req["available_int"])} for i in req["chunk_ids"]],
search.index_name(tenant_id)): search.index_name(tenant_id)):
return get_data_error_result(retmsg="Index updating failure")
return get_data_error_result(message="Index updating failure")
return get_json_result(data=True) return get_json_result(data=True)
except Exception as e: except Exception as e:
return server_error_response(e) return server_error_response(e)
try: try:
if not ELASTICSEARCH.deleteByQuery( if not ELASTICSEARCH.deleteByQuery(
Q("ids", values=req["chunk_ids"]), search.index_name(current_user.id)): Q("ids", values=req["chunk_ids"]), search.index_name(current_user.id)):
return get_data_error_result(retmsg="Index updating failure")
return get_data_error_result(message="Index updating failure")
e, doc = DocumentService.get_by_id(req["doc_id"]) e, doc = DocumentService.get_by_id(req["doc_id"])
if not e: if not e:
return get_data_error_result(retmsg="Document not found!")
return get_data_error_result(message="Document not found!")
deleted_chunk_ids = req["chunk_ids"] deleted_chunk_ids = req["chunk_ids"]
chunk_number = len(deleted_chunk_ids) chunk_number = len(deleted_chunk_ids)
DocumentService.decrement_chunk_num(doc.id, doc.kb_id, 1, chunk_number, 0) DocumentService.decrement_chunk_num(doc.id, doc.kb_id, 1, chunk_number, 0)
try: try:
e, doc = DocumentService.get_by_id(req["doc_id"]) e, doc = DocumentService.get_by_id(req["doc_id"])
if not e: if not e:
return get_data_error_result(retmsg="Document not found!")
return get_data_error_result(message="Document not found!")
d["kb_id"] = [doc.kb_id] d["kb_id"] = [doc.kb_id]
d["docnm_kwd"] = doc.name d["docnm_kwd"] = doc.name
d["doc_id"] = doc.id d["doc_id"] = doc.id


tenant_id = DocumentService.get_tenant_id(req["doc_id"]) tenant_id = DocumentService.get_tenant_id(req["doc_id"])
if not tenant_id: if not tenant_id:
return get_data_error_result(retmsg="Tenant not found!")
return get_data_error_result(message="Tenant not found!")


embd_id = DocumentService.get_embd_id(req["doc_id"]) embd_id = DocumentService.get_embd_id(req["doc_id"])
embd_mdl = LLMBundle(tenant_id, LLMType.EMBEDDING.value, embd_id) embd_mdl = LLMBundle(tenant_id, LLMType.EMBEDDING.value, embd_id)
break break
else: else:
return get_json_result( return get_json_result(
data=False, retmsg=f'Only owner of knowledgebase authorized for this operation.',
retcode=RetCode.OPERATING_ERROR)
data=False, message='Only owner of knowledgebase authorized for this operation.',
code=RetCode.OPERATING_ERROR)


e, kb = KnowledgebaseService.get_by_id(kb_id[0]) e, kb = KnowledgebaseService.get_by_id(kb_id[0])
if not e: if not e:
return get_data_error_result(retmsg="Knowledgebase not found!")
return get_data_error_result(message="Knowledgebase not found!")


embd_mdl = LLMBundle(kb.tenant_id, LLMType.EMBEDDING.value, llm_name=kb.embd_id) embd_mdl = LLMBundle(kb.tenant_id, LLMType.EMBEDDING.value, llm_name=kb.embd_id)


return get_json_result(data=ranks) return get_json_result(data=ranks)
except Exception as e: except Exception as e:
if str(e).find("not_found") > 0: if str(e).find("not_found") > 0:
return get_json_result(data=False, retmsg=f'No chunk found! Check the chunk status please!',
retcode=RetCode.DATA_ERROR)
return get_json_result(data=False, message='No chunk found! Check the chunk status please!',
code=RetCode.DATA_ERROR)
return server_error_response(e) return server_error_response(e)




ty = sres.field[id]["knowledge_graph_kwd"] ty = sres.field[id]["knowledge_graph_kwd"]
try: try:
content_json = json.loads(sres.field[id]["content_with_weight"]) content_json = json.loads(sres.field[id]["content_with_weight"])
except Exception as e:
except Exception:
continue continue


if ty == 'mind_map': if ty == 'mind_map':

+ 26
- 26
api/apps/conversation_app.py 查看文件

del req["conversation_id"] del req["conversation_id"]
try: try:
if not ConversationService.update_by_id(conv_id, req): if not ConversationService.update_by_id(conv_id, req):
return get_data_error_result(retmsg="Conversation not found!")
return get_data_error_result(message="Conversation not found!")
e, conv = ConversationService.get_by_id(conv_id) e, conv = ConversationService.get_by_id(conv_id)
if not e: if not e:
return get_data_error_result( return get_data_error_result(
retmsg="Fail to update a conversation!")
message="Fail to update a conversation!")
conv = conv.to_dict() conv = conv.to_dict()
return get_json_result(data=conv) return get_json_result(data=conv)
except Exception as e: except Exception as e:
try: try:
e, dia = DialogService.get_by_id(req["dialog_id"]) e, dia = DialogService.get_by_id(req["dialog_id"])
if not e: if not e:
return get_data_error_result(retmsg="Dialog not found")
return get_data_error_result(message="Dialog not found")
conv = { conv = {
"id": conv_id, "id": conv_id,
"dialog_id": req["dialog_id"], "dialog_id": req["dialog_id"],
ConversationService.save(**conv) ConversationService.save(**conv)
e, conv = ConversationService.get_by_id(conv["id"]) e, conv = ConversationService.get_by_id(conv["id"])
if not e: if not e:
return get_data_error_result(retmsg="Fail to new a conversation!")
return get_data_error_result(message="Fail to new a conversation!")
conv = conv.to_dict() conv = conv.to_dict()
return get_json_result(data=conv) return get_json_result(data=conv)
except Exception as e: except Exception as e:
try: try:
e, conv = ConversationService.get_by_id(conv_id) e, conv = ConversationService.get_by_id(conv_id)
if not e: if not e:
return get_data_error_result(retmsg="Conversation not found!")
return get_data_error_result(message="Conversation not found!")
tenants = UserTenantService.query(user_id=current_user.id) tenants = UserTenantService.query(user_id=current_user.id)
for tenant in tenants: for tenant in tenants:
if DialogService.query(tenant_id=tenant.tenant_id, id=conv.dialog_id): if DialogService.query(tenant_id=tenant.tenant_id, id=conv.dialog_id):
break break
else: else:
return get_json_result( return get_json_result(
data=False, retmsg=f'Only owner of conversation authorized for this operation.',
retcode=RetCode.OPERATING_ERROR)
data=False, message='Only owner of conversation authorized for this operation.',
code=RetCode.OPERATING_ERROR)
conv = conv.to_dict() conv = conv.to_dict()
return get_json_result(data=conv) return get_json_result(data=conv)
except Exception as e: except Exception as e:
for cid in conv_ids: for cid in conv_ids:
exist, conv = ConversationService.get_by_id(cid) exist, conv = ConversationService.get_by_id(cid)
if not exist: if not exist:
return get_data_error_result(retmsg="Conversation not found!")
return get_data_error_result(message="Conversation not found!")
tenants = UserTenantService.query(user_id=current_user.id) tenants = UserTenantService.query(user_id=current_user.id)
for tenant in tenants: for tenant in tenants:
if DialogService.query(tenant_id=tenant.tenant_id, id=conv.dialog_id): if DialogService.query(tenant_id=tenant.tenant_id, id=conv.dialog_id):
break break
else: else:
return get_json_result( return get_json_result(
data=False, retmsg=f'Only owner of conversation authorized for this operation.',
retcode=RetCode.OPERATING_ERROR)
data=False, message='Only owner of conversation authorized for this operation.',
code=RetCode.OPERATING_ERROR)
ConversationService.delete_by_id(cid) ConversationService.delete_by_id(cid)
return get_json_result(data=True) return get_json_result(data=True)
except Exception as e: except Exception as e:
try: try:
if not DialogService.query(tenant_id=current_user.id, id=dialog_id): if not DialogService.query(tenant_id=current_user.id, id=dialog_id):
return get_json_result( return get_json_result(
data=False, retmsg=f'Only owner of dialog authorized for this operation.',
retcode=RetCode.OPERATING_ERROR)
data=False, message='Only owner of dialog authorized for this operation.',
code=RetCode.OPERATING_ERROR)
convs = ConversationService.query( convs = ConversationService.query(
dialog_id=dialog_id, dialog_id=dialog_id,
order_by=ConversationService.model.create_time, order_by=ConversationService.model.create_time,
try: try:
e, conv = ConversationService.get_by_id(req["conversation_id"]) e, conv = ConversationService.get_by_id(req["conversation_id"])
if not e: if not e:
return get_data_error_result(retmsg="Conversation not found!")
return get_data_error_result(message="Conversation not found!")
conv.message = deepcopy(req["messages"]) conv.message = deepcopy(req["messages"])
e, dia = DialogService.get_by_id(conv.dialog_id) e, dia = DialogService.get_by_id(conv.dialog_id)
if not e: if not e:
return get_data_error_result(retmsg="Dialog not found!")
return get_data_error_result(message="Dialog not found!")
del req["conversation_id"] del req["conversation_id"]
del req["messages"] del req["messages"]


try: try:
for ans in chat(dia, msg, True, **req): for ans in chat(dia, msg, True, **req):
fillin_conv(ans) fillin_conv(ans)
yield "data:" + json.dumps({"retcode": 0, "retmsg": "", "data": ans}, ensure_ascii=False) + "\n\n"
yield "data:" + json.dumps({"code": 0, "message": "", "data": ans}, ensure_ascii=False) + "\n\n"
ConversationService.update_by_id(conv.id, conv.to_dict()) ConversationService.update_by_id(conv.id, conv.to_dict())
except Exception as e: except Exception as e:
traceback.print_exc() traceback.print_exc()
yield "data:" + json.dumps({"retcode": 500, "retmsg": str(e),
yield "data:" + json.dumps({"code": 500, "message": str(e),
"data": {"answer": "**ERROR**: " + str(e), "reference": []}}, "data": {"answer": "**ERROR**: " + str(e), "reference": []}},
ensure_ascii=False) + "\n\n" ensure_ascii=False) + "\n\n"
yield "data:" + json.dumps({"retcode": 0, "retmsg": "", "data": True}, ensure_ascii=False) + "\n\n"
yield "data:" + json.dumps({"code": 0, "message": "", "data": True}, ensure_ascii=False) + "\n\n"


if req.get("stream", True): if req.get("stream", True):
resp = Response(stream(), mimetype="text/event-stream") resp = Response(stream(), mimetype="text/event-stream")


tenants = TenantService.get_info_by(current_user.id) tenants = TenantService.get_info_by(current_user.id)
if not tenants: if not tenants:
return get_data_error_result(retmsg="Tenant not found!")
return get_data_error_result(message="Tenant not found!")


tts_id = tenants[0]["tts_id"] tts_id = tenants[0]["tts_id"]
if not tts_id: if not tts_id:
return get_data_error_result(retmsg="No default TTS model is set")
return get_data_error_result(message="No default TTS model is set")


tts_mdl = LLMBundle(tenants[0]["tenant_id"], LLMType.TTS, tts_id) tts_mdl = LLMBundle(tenants[0]["tenant_id"], LLMType.TTS, tts_id)


for chunk in tts_mdl.tts(txt): for chunk in tts_mdl.tts(txt):
yield chunk yield chunk
except Exception as e: except Exception as e:
yield ("data:" + json.dumps({"retcode": 500, "retmsg": str(e),
yield ("data:" + json.dumps({"code": 500, "message": str(e),
"data": {"answer": "**ERROR**: " + str(e)}}, "data": {"answer": "**ERROR**: " + str(e)}},
ensure_ascii=False)).encode('utf-8') ensure_ascii=False)).encode('utf-8')


req = request.json req = request.json
e, conv = ConversationService.get_by_id(req["conversation_id"]) e, conv = ConversationService.get_by_id(req["conversation_id"])
if not e: if not e:
return get_data_error_result(retmsg="Conversation not found!")
return get_data_error_result(message="Conversation not found!")


conv = conv.to_dict() conv = conv.to_dict()
for i, msg in enumerate(conv["message"]): for i, msg in enumerate(conv["message"]):
req = request.json req = request.json
e, conv = ConversationService.get_by_id(req["conversation_id"]) e, conv = ConversationService.get_by_id(req["conversation_id"])
if not e: if not e:
return get_data_error_result(retmsg="Conversation not found!")
return get_data_error_result(message="Conversation not found!")
up_down = req.get("set") up_down = req.get("set")
feedback = req.get("feedback", "") feedback = req.get("feedback", "")
conv = conv.to_dict() conv = conv.to_dict()
nonlocal req, uid nonlocal req, uid
try: try:
for ans in ask(req["question"], req["kb_ids"], uid): for ans in ask(req["question"], req["kb_ids"], uid):
yield "data:" + json.dumps({"retcode": 0, "retmsg": "", "data": ans}, ensure_ascii=False) + "\n\n"
yield "data:" + json.dumps({"code": 0, "message": "", "data": ans}, ensure_ascii=False) + "\n\n"
except Exception as e: except Exception as e:
yield "data:" + json.dumps({"retcode": 500, "retmsg": str(e),
yield "data:" + json.dumps({"code": 500, "message": str(e),
"data": {"answer": "**ERROR**: " + str(e), "reference": []}}, "data": {"answer": "**ERROR**: " + str(e), "reference": []}},
ensure_ascii=False) + "\n\n" ensure_ascii=False) + "\n\n"
yield "data:" + json.dumps({"retcode": 0, "retmsg": "", "data": True}, ensure_ascii=False) + "\n\n"
yield "data:" + json.dumps({"code": 0, "message": "", "data": True}, ensure_ascii=False) + "\n\n"


resp = Response(stream(), mimetype="text/event-stream") resp = Response(stream(), mimetype="text/event-stream")
resp.headers.add_header("Cache-control", "no-cache") resp.headers.add_header("Cache-control", "no-cache")
kb_ids = req["kb_ids"] kb_ids = req["kb_ids"]
e, kb = KnowledgebaseService.get_by_id(kb_ids[0]) e, kb = KnowledgebaseService.get_by_id(kb_ids[0])
if not e: if not e:
return get_data_error_result(retmsg="Knowledgebase not found!")
return get_data_error_result(message="Knowledgebase not found!")


embd_mdl = TenantLLMService.model_instance( embd_mdl = TenantLLMService.model_instance(
kb.tenant_id, LLMType.EMBEDDING.value, llm_name=kb.embd_id) kb.tenant_id, LLMType.EMBEDDING.value, llm_name=kb.embd_id)

+ 10
- 10
api/apps/dialog_app.py 查看文件

continue continue
if prompt_config["system"].find("{%s}" % p["key"]) < 0: if prompt_config["system"].find("{%s}" % p["key"]) < 0:
return get_data_error_result( return get_data_error_result(
retmsg="Parameter '{}' is not used".format(p["key"]))
message="Parameter '{}' is not used".format(p["key"]))


try: try:
e, tenant = TenantService.get_by_id(current_user.id) e, tenant = TenantService.get_by_id(current_user.id)
if not e: if not e:
return get_data_error_result(retmsg="Tenant not found!")
return get_data_error_result(message="Tenant not found!")
llm_id = req.get("llm_id", tenant.llm_id) llm_id = req.get("llm_id", tenant.llm_id)
if not dialog_id: if not dialog_id:
if not req.get("kb_ids"): if not req.get("kb_ids"):
return get_data_error_result( return get_data_error_result(
retmsg="Fail! Please select knowledgebase!")
message="Fail! Please select knowledgebase!")
dia = { dia = {
"id": get_uuid(), "id": get_uuid(),
"tenant_id": current_user.id, "tenant_id": current_user.id,
"icon": icon "icon": icon
} }
if not DialogService.save(**dia): if not DialogService.save(**dia):
return get_data_error_result(retmsg="Fail to new a dialog!")
return get_data_error_result(message="Fail to new a dialog!")
e, dia = DialogService.get_by_id(dia["id"]) e, dia = DialogService.get_by_id(dia["id"])
if not e: if not e:
return get_data_error_result(retmsg="Fail to new a dialog!")
return get_data_error_result(message="Fail to new a dialog!")
return get_json_result(data=dia.to_json()) return get_json_result(data=dia.to_json())
else: else:
del req["dialog_id"] del req["dialog_id"]
if "kb_names" in req: if "kb_names" in req:
del req["kb_names"] del req["kb_names"]
if not DialogService.update_by_id(dialog_id, req): if not DialogService.update_by_id(dialog_id, req):
return get_data_error_result(retmsg="Dialog not found!")
return get_data_error_result(message="Dialog not found!")
e, dia = DialogService.get_by_id(dialog_id) e, dia = DialogService.get_by_id(dialog_id)
if not e: if not e:
return get_data_error_result(retmsg="Fail to update a dialog!")
return get_data_error_result(message="Fail to update a dialog!")
dia = dia.to_dict() dia = dia.to_dict()
dia["kb_ids"], dia["kb_names"] = get_kb_names(dia["kb_ids"]) dia["kb_ids"], dia["kb_names"] = get_kb_names(dia["kb_ids"])
return get_json_result(data=dia) return get_json_result(data=dia)
try: try:
e, dia = DialogService.get_by_id(dialog_id) e, dia = DialogService.get_by_id(dialog_id)
if not e: if not e:
return get_data_error_result(retmsg="Dialog not found!")
return get_data_error_result(message="Dialog not found!")
dia = dia.to_dict() dia = dia.to_dict()
dia["kb_ids"], dia["kb_names"] = get_kb_names(dia["kb_ids"]) dia["kb_ids"], dia["kb_names"] = get_kb_names(dia["kb_ids"])
return get_json_result(data=dia) return get_json_result(data=dia)
break break
else: else:
return get_json_result( return get_json_result(
data=False, retmsg=f'Only owner of dialog authorized for this operation.',
retcode=RetCode.OPERATING_ERROR)
data=False, message='Only owner of dialog authorized for this operation.',
code=RetCode.OPERATING_ERROR)
dialog_list.append({"id": id,"status":StatusEnum.INVALID.value}) dialog_list.append({"id": id,"status":StatusEnum.INVALID.value})
DialogService.update_many_by_id(dialog_list) DialogService.update_many_by_id(dialog_list)
return get_json_result(data=True) return get_json_result(data=True)

+ 48
- 48
api/apps/document_app.py 查看文件

kb_id = request.form.get("kb_id") kb_id = request.form.get("kb_id")
if not kb_id: if not kb_id:
return get_json_result( return get_json_result(
data=False, retmsg='Lack of "KB ID"', retcode=RetCode.ARGUMENT_ERROR)
data=False, message='Lack of "KB ID"', code=RetCode.ARGUMENT_ERROR)
if 'file' not in request.files: if 'file' not in request.files:
return get_json_result( return get_json_result(
data=False, retmsg='No file part!', retcode=RetCode.ARGUMENT_ERROR)
data=False, message='No file part!', code=RetCode.ARGUMENT_ERROR)


file_objs = request.files.getlist('file') file_objs = request.files.getlist('file')
for file_obj in file_objs: for file_obj in file_objs:
if file_obj.filename == '': if file_obj.filename == '':
return get_json_result( return get_json_result(
data=False, retmsg='No file selected!', retcode=RetCode.ARGUMENT_ERROR)
data=False, message='No file selected!', code=RetCode.ARGUMENT_ERROR)


e, kb = KnowledgebaseService.get_by_id(kb_id) e, kb = KnowledgebaseService.get_by_id(kb_id)
if not e: if not e:
err, _ = FileService.upload_document(kb, file_objs, current_user.id) err, _ = FileService.upload_document(kb, file_objs, current_user.id)
if err: if err:
return get_json_result( return get_json_result(
data=False, retmsg="\n".join(err), retcode=RetCode.SERVER_ERROR)
data=False, message="\n".join(err), code=RetCode.SERVER_ERROR)
return get_json_result(data=True) return get_json_result(data=True)




kb_id = request.form.get("kb_id") kb_id = request.form.get("kb_id")
if not kb_id: if not kb_id:
return get_json_result( return get_json_result(
data=False, retmsg='Lack of "KB ID"', retcode=RetCode.ARGUMENT_ERROR)
data=False, message='Lack of "KB ID"', code=RetCode.ARGUMENT_ERROR)
name = request.form.get("name") name = request.form.get("name")
url = request.form.get("url") url = request.form.get("url")
if not is_valid_url(url): if not is_valid_url(url):
return get_json_result( return get_json_result(
data=False, retmsg='The URL format is invalid', retcode=RetCode.ARGUMENT_ERROR)
data=False, message='The URL format is invalid', code=RetCode.ARGUMENT_ERROR)
e, kb = KnowledgebaseService.get_by_id(kb_id) e, kb = KnowledgebaseService.get_by_id(kb_id)
if not e: if not e:
raise LookupError("Can't find this knowledgebase!") raise LookupError("Can't find this knowledgebase!")
kb_id = req["kb_id"] kb_id = req["kb_id"]
if not kb_id: if not kb_id:
return get_json_result( return get_json_result(
data=False, retmsg='Lack of "KB ID"', retcode=RetCode.ARGUMENT_ERROR)
data=False, message='Lack of "KB ID"', code=RetCode.ARGUMENT_ERROR)


try: try:
e, kb = KnowledgebaseService.get_by_id(kb_id) e, kb = KnowledgebaseService.get_by_id(kb_id)
if not e: if not e:
return get_data_error_result( return get_data_error_result(
retmsg="Can't find this knowledgebase!")
message="Can't find this knowledgebase!")


if DocumentService.query(name=req["name"], kb_id=kb_id): if DocumentService.query(name=req["name"], kb_id=kb_id):
return get_data_error_result( return get_data_error_result(
retmsg="Duplicated document name in the same knowledgebase.")
message="Duplicated document name in the same knowledgebase.")


doc = DocumentService.insert({ doc = DocumentService.insert({
"id": get_uuid(), "id": get_uuid(),
kb_id = request.args.get("kb_id") kb_id = request.args.get("kb_id")
if not kb_id: if not kb_id:
return get_json_result( return get_json_result(
data=False, retmsg='Lack of "KB ID"', retcode=RetCode.ARGUMENT_ERROR)
data=False, message='Lack of "KB ID"', code=RetCode.ARGUMENT_ERROR)
tenants = UserTenantService.query(user_id=current_user.id) tenants = UserTenantService.query(user_id=current_user.id)
for tenant in tenants: for tenant in tenants:
if KnowledgebaseService.query( if KnowledgebaseService.query(
break break
else: else:
return get_json_result( return get_json_result(
data=False, retmsg=f'Only owner of knowledgebase authorized for this operation.',
retcode=RetCode.OPERATING_ERROR)
data=False, message='Only owner of knowledgebase authorized for this operation.',
code=RetCode.OPERATING_ERROR)
keywords = request.args.get("keywords", "") keywords = request.args.get("keywords", "")


page_number = int(request.args.get("page", 1)) page_number = int(request.args.get("page", 1))
if not DocumentService.accessible(doc_id, current_user.id): if not DocumentService.accessible(doc_id, current_user.id):
return get_json_result( return get_json_result(
data=False, data=False,
retmsg='No authorization.',
retcode=RetCode.AUTHENTICATION_ERROR
message='No authorization.',
code=RetCode.AUTHENTICATION_ERROR
) )
docs = DocumentService.get_by_ids(doc_ids) docs = DocumentService.get_by_ids(doc_ids)
return get_json_result(data=list(docs.dicts())) return get_json_result(data=list(docs.dicts()))
doc_ids = request.args.get("doc_ids").split(",") doc_ids = request.args.get("doc_ids").split(",")
if not doc_ids: if not doc_ids:
return get_json_result( return get_json_result(
data=False, retmsg='Lack of "Document ID"', retcode=RetCode.ARGUMENT_ERROR)
data=False, message='Lack of "Document ID"', code=RetCode.ARGUMENT_ERROR)


try: try:
docs = DocumentService.get_thumbnails(doc_ids) docs = DocumentService.get_thumbnails(doc_ids)
if str(req["status"]) not in ["0", "1"]: if str(req["status"]) not in ["0", "1"]:
return get_json_result( return get_json_result(
data=False, data=False,
retmsg='"Status" must be either 0 or 1!',
retcode=RetCode.ARGUMENT_ERROR)
message='"Status" must be either 0 or 1!',
code=RetCode.ARGUMENT_ERROR)


if not DocumentService.accessible(req["doc_id"], current_user.id): if not DocumentService.accessible(req["doc_id"], current_user.id):
return get_json_result( return get_json_result(
data=False, data=False,
retmsg='No authorization.',
retcode=RetCode.AUTHENTICATION_ERROR)
message='No authorization.',
code=RetCode.AUTHENTICATION_ERROR)


try: try:
e, doc = DocumentService.get_by_id(req["doc_id"]) e, doc = DocumentService.get_by_id(req["doc_id"])
if not e: if not e:
return get_data_error_result(retmsg="Document not found!")
return get_data_error_result(message="Document not found!")
e, kb = KnowledgebaseService.get_by_id(doc.kb_id) e, kb = KnowledgebaseService.get_by_id(doc.kb_id)
if not e: if not e:
return get_data_error_result( return get_data_error_result(
retmsg="Can't find this knowledgebase!")
message="Can't find this knowledgebase!")


if not DocumentService.update_by_id( if not DocumentService.update_by_id(
req["doc_id"], {"status": str(req["status"])}): req["doc_id"], {"status": str(req["status"])}):
return get_data_error_result( return get_data_error_result(
retmsg="Database error (Document update)!")
message="Database error (Document update)!")


if str(req["status"]) == "0": if str(req["status"]) == "0":
ELASTICSEARCH.updateScriptByQuery(Q("term", doc_id=req["doc_id"]), ELASTICSEARCH.updateScriptByQuery(Q("term", doc_id=req["doc_id"]),
if not DocumentService.accessible4deletion(doc_id, current_user.id): if not DocumentService.accessible4deletion(doc_id, current_user.id):
return get_json_result( return get_json_result(
data=False, data=False,
retmsg='No authorization.',
retcode=RetCode.AUTHENTICATION_ERROR
message='No authorization.',
code=RetCode.AUTHENTICATION_ERROR
) )


root_folder = FileService.get_root_folder(current_user.id) root_folder = FileService.get_root_folder(current_user.id)
try: try:
e, doc = DocumentService.get_by_id(doc_id) e, doc = DocumentService.get_by_id(doc_id)
if not e: if not e:
return get_data_error_result(retmsg="Document not found!")
return get_data_error_result(message="Document not found!")
tenant_id = DocumentService.get_tenant_id(doc_id) tenant_id = DocumentService.get_tenant_id(doc_id)
if not tenant_id: if not tenant_id:
return get_data_error_result(retmsg="Tenant not found!")
return get_data_error_result(message="Tenant not found!")


b, n = File2DocumentService.get_storage_address(doc_id=doc_id) b, n = File2DocumentService.get_storage_address(doc_id=doc_id)


if not DocumentService.remove_document(doc, tenant_id): if not DocumentService.remove_document(doc, tenant_id):
return get_data_error_result( return get_data_error_result(
retmsg="Database error (Document removal)!")
message="Database error (Document removal)!")


f2d = File2DocumentService.get_by_document_id(doc_id) f2d = File2DocumentService.get_by_document_id(doc_id)
FileService.filter_delete([File.source_type == FileSource.KNOWLEDGEBASE, File.id == f2d[0].file_id]) FileService.filter_delete([File.source_type == FileSource.KNOWLEDGEBASE, File.id == f2d[0].file_id])
errors += str(e) errors += str(e)


if errors: if errors:
return get_json_result(data=False, retmsg=errors, retcode=RetCode.SERVER_ERROR)
return get_json_result(data=False, message=errors, code=RetCode.SERVER_ERROR)


return get_json_result(data=True) return get_json_result(data=True)


if not DocumentService.accessible(doc_id, current_user.id): if not DocumentService.accessible(doc_id, current_user.id):
return get_json_result( return get_json_result(
data=False, data=False,
retmsg='No authorization.',
retcode=RetCode.AUTHENTICATION_ERROR
message='No authorization.',
code=RetCode.AUTHENTICATION_ERROR
) )
try: try:
for id in req["doc_ids"]: for id in req["doc_ids"]:
# if str(req["run"]) == TaskStatus.CANCEL.value: # if str(req["run"]) == TaskStatus.CANCEL.value:
tenant_id = DocumentService.get_tenant_id(id) tenant_id = DocumentService.get_tenant_id(id)
if not tenant_id: if not tenant_id:
return get_data_error_result(retmsg="Tenant not found!")
return get_data_error_result(message="Tenant not found!")
ELASTICSEARCH.deleteByQuery( ELASTICSEARCH.deleteByQuery(
Q("match", doc_id=id), idxnm=search.index_name(tenant_id)) Q("match", doc_id=id), idxnm=search.index_name(tenant_id))


if not DocumentService.accessible(req["doc_id"], current_user.id): if not DocumentService.accessible(req["doc_id"], current_user.id):
return get_json_result( return get_json_result(
data=False, data=False,
retmsg='No authorization.',
retcode=RetCode.AUTHENTICATION_ERROR
message='No authorization.',
code=RetCode.AUTHENTICATION_ERROR
) )
try: try:
e, doc = DocumentService.get_by_id(req["doc_id"]) e, doc = DocumentService.get_by_id(req["doc_id"])
if not e: if not e:
return get_data_error_result(retmsg="Document not found!")
return get_data_error_result(message="Document not found!")
if pathlib.Path(req["name"].lower()).suffix != pathlib.Path( if pathlib.Path(req["name"].lower()).suffix != pathlib.Path(
doc.name.lower()).suffix: doc.name.lower()).suffix:
return get_json_result( return get_json_result(
data=False, data=False,
retmsg="The extension of file can't be changed",
retcode=RetCode.ARGUMENT_ERROR)
message="The extension of file can't be changed",
code=RetCode.ARGUMENT_ERROR)
for d in DocumentService.query(name=req["name"], kb_id=doc.kb_id): for d in DocumentService.query(name=req["name"], kb_id=doc.kb_id):
if d.name == req["name"]: if d.name == req["name"]:
return get_data_error_result( return get_data_error_result(
retmsg="Duplicated document name in the same knowledgebase.")
message="Duplicated document name in the same knowledgebase.")


if not DocumentService.update_by_id( if not DocumentService.update_by_id(
req["doc_id"], {"name": req["name"]}): req["doc_id"], {"name": req["name"]}):
return get_data_error_result( return get_data_error_result(
retmsg="Database error (Document rename)!")
message="Database error (Document rename)!")


informs = File2DocumentService.get_by_document_id(req["doc_id"]) informs = File2DocumentService.get_by_document_id(req["doc_id"])
if informs: if informs:
try: try:
e, doc = DocumentService.get_by_id(doc_id) e, doc = DocumentService.get_by_id(doc_id)
if not e: if not e:
return get_data_error_result(retmsg="Document not found!")
return get_data_error_result(message="Document not found!")


b, n = File2DocumentService.get_storage_address(doc_id=doc_id) b, n = File2DocumentService.get_storage_address(doc_id=doc_id)
response = flask.make_response(STORAGE_IMPL.get(b, n)) response = flask.make_response(STORAGE_IMPL.get(b, n))
if not DocumentService.accessible(req["doc_id"], current_user.id): if not DocumentService.accessible(req["doc_id"], current_user.id):
return get_json_result( return get_json_result(
data=False, data=False,
retmsg='No authorization.',
retcode=RetCode.AUTHENTICATION_ERROR
message='No authorization.',
code=RetCode.AUTHENTICATION_ERROR
) )
try: try:
e, doc = DocumentService.get_by_id(req["doc_id"]) e, doc = DocumentService.get_by_id(req["doc_id"])
if not e: if not e:
return get_data_error_result(retmsg="Document not found!")
return get_data_error_result(message="Document not found!")
if doc.parser_id.lower() == req["parser_id"].lower(): if doc.parser_id.lower() == req["parser_id"].lower():
if "parser_config" in req: if "parser_config" in req:
if req["parser_config"] == doc.parser_config: if req["parser_config"] == doc.parser_config:
if ((doc.type == FileType.VISUAL and req["parser_id"] != "picture") if ((doc.type == FileType.VISUAL and req["parser_id"] != "picture")
or (re.search( or (re.search(
r"\.(ppt|pptx|pages)$", doc.name) and req["parser_id"] != "presentation")): r"\.(ppt|pptx|pages)$", doc.name) and req["parser_id"] != "presentation")):
return get_data_error_result(retmsg="Not supported yet!")
return get_data_error_result(message="Not supported yet!")


e = DocumentService.update_by_id(doc.id, e = DocumentService.update_by_id(doc.id,
{"parser_id": req["parser_id"], "progress": 0, "progress_msg": "", {"parser_id": req["parser_id"], "progress": 0, "progress_msg": "",
"run": TaskStatus.UNSTART.value}) "run": TaskStatus.UNSTART.value})
if not e: if not e:
return get_data_error_result(retmsg="Document not found!")
return get_data_error_result(message="Document not found!")
if "parser_config" in req: if "parser_config" in req:
DocumentService.update_parser_config(doc.id, req["parser_config"]) DocumentService.update_parser_config(doc.id, req["parser_config"])
if doc.token_num > 0: if doc.token_num > 0:
e = DocumentService.increment_chunk_num(doc.id, doc.kb_id, doc.token_num * -1, doc.chunk_num * -1, e = DocumentService.increment_chunk_num(doc.id, doc.kb_id, doc.token_num * -1, doc.chunk_num * -1,
doc.process_duation * -1) doc.process_duation * -1)
if not e: if not e:
return get_data_error_result(retmsg="Document not found!")
return get_data_error_result(message="Document not found!")
tenant_id = DocumentService.get_tenant_id(req["doc_id"]) tenant_id = DocumentService.get_tenant_id(req["doc_id"])
if not tenant_id: if not tenant_id:
return get_data_error_result(retmsg="Tenant not found!")
return get_data_error_result(message="Tenant not found!")
ELASTICSEARCH.deleteByQuery( ELASTICSEARCH.deleteByQuery(
Q("match", doc_id=doc.id), idxnm=search.index_name(tenant_id)) Q("match", doc_id=doc.id), idxnm=search.index_name(tenant_id))


def upload_and_parse(): def upload_and_parse():
if 'file' not in request.files: if 'file' not in request.files:
return get_json_result( return get_json_result(
data=False, retmsg='No file part!', retcode=RetCode.ARGUMENT_ERROR)
data=False, message='No file part!', code=RetCode.ARGUMENT_ERROR)


file_objs = request.files.getlist('file') file_objs = request.files.getlist('file')
for file_obj in file_objs: for file_obj in file_objs:
if file_obj.filename == '': if file_obj.filename == '':
return get_json_result( return get_json_result(
data=False, retmsg='No file selected!', retcode=RetCode.ARGUMENT_ERROR)
data=False, message='No file selected!', code=RetCode.ARGUMENT_ERROR)


doc_ids = doc_upload_and_parse(request.form.get("conversation_id"), file_objs, current_user.id) doc_ids = doc_upload_and_parse(request.form.get("conversation_id"), file_objs, current_user.id)



+ 11
- 15
api/apps/file2document_app.py 查看文件

# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License # limitations under the License
# #
from elasticsearch_dsl import Q


from api.db.db_models import File2Document
from api.db.services.file2document_service import File2DocumentService from api.db.services.file2document_service import File2DocumentService
from api.db.services.file_service import FileService from api.db.services.file_service import FileService


from api.db.services.document_service import DocumentService from api.db.services.document_service import DocumentService
from api.settings import RetCode from api.settings import RetCode
from api.utils.api_utils import get_json_result from api.utils.api_utils import get_json_result
from rag.nlp import search
from rag.utils.es_conn import ELASTICSEARCH




@manager.route('/convert', methods=['POST']) @manager.route('/convert', methods=['POST'])
doc_id = inform.document_id doc_id = inform.document_id
e, doc = DocumentService.get_by_id(doc_id) e, doc = DocumentService.get_by_id(doc_id)
if not e: if not e:
return get_data_error_result(retmsg="Document not found!")
return get_data_error_result(message="Document not found!")
tenant_id = DocumentService.get_tenant_id(doc_id) tenant_id = DocumentService.get_tenant_id(doc_id)
if not tenant_id: if not tenant_id:
return get_data_error_result(retmsg="Tenant not found!")
return get_data_error_result(message="Tenant not found!")
if not DocumentService.remove_document(doc, tenant_id): if not DocumentService.remove_document(doc, tenant_id):
return get_data_error_result( return get_data_error_result(
retmsg="Database error (Document removal)!")
message="Database error (Document removal)!")
File2DocumentService.delete_by_file_id(id) File2DocumentService.delete_by_file_id(id)


# insert # insert
e, kb = KnowledgebaseService.get_by_id(kb_id) e, kb = KnowledgebaseService.get_by_id(kb_id)
if not e: if not e:
return get_data_error_result( return get_data_error_result(
retmsg="Can't find this knowledgebase!")
message="Can't find this knowledgebase!")
e, file = FileService.get_by_id(id) e, file = FileService.get_by_id(id)
if not e: if not e:
return get_data_error_result( return get_data_error_result(
retmsg="Can't find this file!")
message="Can't find this file!")


doc = DocumentService.insert({ doc = DocumentService.insert({
"id": get_uuid(), "id": get_uuid(),
file_ids = req["file_ids"] file_ids = req["file_ids"]
if not file_ids: if not file_ids:
return get_json_result( return get_json_result(
data=False, retmsg='Lack of "Files ID"', retcode=RetCode.ARGUMENT_ERROR)
data=False, message='Lack of "Files ID"', code=RetCode.ARGUMENT_ERROR)
try: try:
for file_id in file_ids: for file_id in file_ids:
informs = File2DocumentService.get_by_file_id(file_id) informs = File2DocumentService.get_by_file_id(file_id)
if not informs: if not informs:
return get_data_error_result(retmsg="Inform not found!")
return get_data_error_result(message="Inform not found!")
for inform in informs: for inform in informs:
if not inform: if not inform:
return get_data_error_result(retmsg="Inform not found!")
return get_data_error_result(message="Inform not found!")
File2DocumentService.delete_by_file_id(file_id) File2DocumentService.delete_by_file_id(file_id)
doc_id = inform.document_id doc_id = inform.document_id
e, doc = DocumentService.get_by_id(doc_id) e, doc = DocumentService.get_by_id(doc_id)
if not e: if not e:
return get_data_error_result(retmsg="Document not found!")
return get_data_error_result(message="Document not found!")
tenant_id = DocumentService.get_tenant_id(doc_id) tenant_id = DocumentService.get_tenant_id(doc_id)
if not tenant_id: if not tenant_id:
return get_data_error_result(retmsg="Tenant not found!")
return get_data_error_result(message="Tenant not found!")
if not DocumentService.remove_document(doc, tenant_id): if not DocumentService.remove_document(doc, tenant_id):
return get_data_error_result( return get_data_error_result(
retmsg="Database error (Document removal)!")
message="Database error (Document removal)!")
return get_json_result(data=True) return get_json_result(data=True)
except Exception as e: except Exception as e:
return server_error_response(e) return server_error_response(e)

+ 29
- 32
api/apps/file_app.py 查看文件

import re import re


import flask import flask
from elasticsearch_dsl import Q
from flask import request from flask import request
from flask_login import login_required, current_user from flask_login import login_required, current_user


from api.settings import RetCode from api.settings import RetCode
from api.utils.api_utils import get_json_result from api.utils.api_utils import get_json_result
from api.utils.file_utils import filename_type from api.utils.file_utils import filename_type
from rag.nlp import search
from rag.utils.es_conn import ELASTICSEARCH
from rag.utils.storage_factory import STORAGE_IMPL from rag.utils.storage_factory import STORAGE_IMPL






if 'file' not in request.files: if 'file' not in request.files:
return get_json_result( return get_json_result(
data=False, retmsg='No file part!', retcode=RetCode.ARGUMENT_ERROR)
data=False, message='No file part!', code=RetCode.ARGUMENT_ERROR)
file_objs = request.files.getlist('file') file_objs = request.files.getlist('file')


for file_obj in file_objs: for file_obj in file_objs:
if file_obj.filename == '': if file_obj.filename == '':
return get_json_result( return get_json_result(
data=False, retmsg='No file selected!', retcode=RetCode.ARGUMENT_ERROR)
data=False, message='No file selected!', code=RetCode.ARGUMENT_ERROR)
file_res = [] file_res = []
try: try:
for file_obj in file_objs: for file_obj in file_objs:
e, file = FileService.get_by_id(pf_id) e, file = FileService.get_by_id(pf_id)
if not e: if not e:
return get_data_error_result( return get_data_error_result(
retmsg="Can't find this folder!")
message="Can't find this folder!")
MAX_FILE_NUM_PER_USER = int(os.environ.get('MAX_FILE_NUM_PER_USER', 0)) MAX_FILE_NUM_PER_USER = int(os.environ.get('MAX_FILE_NUM_PER_USER', 0))
if MAX_FILE_NUM_PER_USER > 0 and DocumentService.get_doc_count(current_user.id) >= MAX_FILE_NUM_PER_USER: if MAX_FILE_NUM_PER_USER > 0 and DocumentService.get_doc_count(current_user.id) >= MAX_FILE_NUM_PER_USER:
return get_data_error_result( return get_data_error_result(
retmsg="Exceed the maximum file number of a free user!")
message="Exceed the maximum file number of a free user!")


# split file name path # split file name path
if not file_obj.filename: if not file_obj.filename:
if file_len != len_id_list: if file_len != len_id_list:
e, file = FileService.get_by_id(file_id_list[len_id_list - 1]) e, file = FileService.get_by_id(file_id_list[len_id_list - 1])
if not e: if not e:
return get_data_error_result(retmsg="Folder not found!")
return get_data_error_result(message="Folder not found!")
last_folder = FileService.create_folder(file, file_id_list[len_id_list - 1], file_obj_names, last_folder = FileService.create_folder(file, file_id_list[len_id_list - 1], file_obj_names,
len_id_list) len_id_list)
else: else:
e, file = FileService.get_by_id(file_id_list[len_id_list - 2]) e, file = FileService.get_by_id(file_id_list[len_id_list - 2])
if not e: if not e:
return get_data_error_result(retmsg="Folder not found!")
return get_data_error_result(message="Folder not found!")
last_folder = FileService.create_folder(file, file_id_list[len_id_list - 2], file_obj_names, last_folder = FileService.create_folder(file, file_id_list[len_id_list - 2], file_obj_names,
len_id_list) len_id_list)


try: try:
if not FileService.is_parent_folder_exist(pf_id): if not FileService.is_parent_folder_exist(pf_id):
return get_json_result( return get_json_result(
data=False, retmsg="Parent Folder Doesn't Exist!", retcode=RetCode.OPERATING_ERROR)
data=False, message="Parent Folder Doesn't Exist!", code=RetCode.OPERATING_ERROR)
if FileService.query(name=req["name"], parent_id=pf_id): if FileService.query(name=req["name"], parent_id=pf_id):
return get_data_error_result( return get_data_error_result(
retmsg="Duplicated folder name in the same folder.")
message="Duplicated folder name in the same folder.")


if input_file_type == FileType.FOLDER.value: if input_file_type == FileType.FOLDER.value:
file_type = FileType.FOLDER.value file_type = FileType.FOLDER.value
try: try:
e, file = FileService.get_by_id(pf_id) e, file = FileService.get_by_id(pf_id)
if not e: if not e:
return get_data_error_result(retmsg="Folder not found!")
return get_data_error_result(message="Folder not found!")


files, total = FileService.get_by_pf_id( files, total = FileService.get_by_pf_id(
current_user.id, pf_id, page_number, items_per_page, orderby, desc, keywords) current_user.id, pf_id, page_number, items_per_page, orderby, desc, keywords)


parent_folder = FileService.get_parent_folder(pf_id) parent_folder = FileService.get_parent_folder(pf_id)
if not FileService.get_parent_folder(pf_id): if not FileService.get_parent_folder(pf_id):
return get_json_result(retmsg="File not found!")
return get_json_result(message="File not found!")


return get_json_result(data={"total": total, "files": files, "parent_folder": parent_folder.to_json()}) return get_json_result(data={"total": total, "files": files, "parent_folder": parent_folder.to_json()})
except Exception as e: except Exception as e:
try: try:
e, file = FileService.get_by_id(file_id) e, file = FileService.get_by_id(file_id)
if not e: if not e:
return get_data_error_result(retmsg="Folder not found!")
return get_data_error_result(message="Folder not found!")


parent_folder = FileService.get_parent_folder(file_id) parent_folder = FileService.get_parent_folder(file_id)
return get_json_result(data={"parent_folder": parent_folder.to_json()}) return get_json_result(data={"parent_folder": parent_folder.to_json()})
try: try:
e, file = FileService.get_by_id(file_id) e, file = FileService.get_by_id(file_id)
if not e: if not e:
return get_data_error_result(retmsg="Folder not found!")
return get_data_error_result(message="Folder not found!")


parent_folders = FileService.get_all_parent_folders(file_id) parent_folders = FileService.get_all_parent_folders(file_id)
parent_folders_res = [] parent_folders_res = []
for file_id in file_ids: for file_id in file_ids:
e, file = FileService.get_by_id(file_id) e, file = FileService.get_by_id(file_id)
if not e: if not e:
return get_data_error_result(retmsg="File or Folder not found!")
return get_data_error_result(message="File or Folder not found!")
if not file.tenant_id: if not file.tenant_id:
return get_data_error_result(retmsg="Tenant not found!")
return get_data_error_result(message="Tenant not found!")
if file.source_type == FileSource.KNOWLEDGEBASE: if file.source_type == FileSource.KNOWLEDGEBASE:
continue continue


for inner_file_id in file_id_list: for inner_file_id in file_id_list:
e, file = FileService.get_by_id(inner_file_id) e, file = FileService.get_by_id(inner_file_id)
if not e: if not e:
return get_data_error_result(retmsg="File not found!")
return get_data_error_result(message="File not found!")
STORAGE_IMPL.rm(file.parent_id, file.location) STORAGE_IMPL.rm(file.parent_id, file.location)
FileService.delete_folder_by_pf_id(current_user.id, file_id) FileService.delete_folder_by_pf_id(current_user.id, file_id)
else: else:
if not FileService.delete(file): if not FileService.delete(file):
return get_data_error_result( return get_data_error_result(
retmsg="Database error (File removal)!")
message="Database error (File removal)!")


# delete file2document # delete file2document
informs = File2DocumentService.get_by_file_id(file_id) informs = File2DocumentService.get_by_file_id(file_id)
doc_id = inform.document_id doc_id = inform.document_id
e, doc = DocumentService.get_by_id(doc_id) e, doc = DocumentService.get_by_id(doc_id)
if not e: if not e:
return get_data_error_result(retmsg="Document not found!")
return get_data_error_result(message="Document not found!")
tenant_id = DocumentService.get_tenant_id(doc_id) tenant_id = DocumentService.get_tenant_id(doc_id)
if not tenant_id: if not tenant_id:
return get_data_error_result(retmsg="Tenant not found!")
return get_data_error_result(message="Tenant not found!")
if not DocumentService.remove_document(doc, tenant_id): if not DocumentService.remove_document(doc, tenant_id):
return get_data_error_result( return get_data_error_result(
retmsg="Database error (Document removal)!")
message="Database error (Document removal)!")
File2DocumentService.delete_by_file_id(file_id) File2DocumentService.delete_by_file_id(file_id)


return get_json_result(data=True) return get_json_result(data=True)
try: try:
e, file = FileService.get_by_id(req["file_id"]) e, file = FileService.get_by_id(req["file_id"])
if not e: if not e:
return get_data_error_result(retmsg="File not found!")
return get_data_error_result(message="File not found!")
if file.type != FileType.FOLDER.value \ if file.type != FileType.FOLDER.value \
and pathlib.Path(req["name"].lower()).suffix != pathlib.Path( and pathlib.Path(req["name"].lower()).suffix != pathlib.Path(
file.name.lower()).suffix: file.name.lower()).suffix:
return get_json_result( return get_json_result(
data=False, data=False,
retmsg="The extension of file can't be changed",
retcode=RetCode.ARGUMENT_ERROR)
message="The extension of file can't be changed",
code=RetCode.ARGUMENT_ERROR)
for file in FileService.query(name=req["name"], pf_id=file.parent_id): for file in FileService.query(name=req["name"], pf_id=file.parent_id):
if file.name == req["name"]: if file.name == req["name"]:
return get_data_error_result( return get_data_error_result(
retmsg="Duplicated file name in the same folder.")
message="Duplicated file name in the same folder.")


if not FileService.update_by_id( if not FileService.update_by_id(
req["file_id"], {"name": req["name"]}): req["file_id"], {"name": req["name"]}):
return get_data_error_result( return get_data_error_result(
retmsg="Database error (File rename)!")
message="Database error (File rename)!")


informs = File2DocumentService.get_by_file_id(req["file_id"]) informs = File2DocumentService.get_by_file_id(req["file_id"])
if informs: if informs:
if not DocumentService.update_by_id( if not DocumentService.update_by_id(
informs[0].document_id, {"name": req["name"]}): informs[0].document_id, {"name": req["name"]}):
return get_data_error_result( return get_data_error_result(
retmsg="Database error (Document rename)!")
message="Database error (Document rename)!")


return get_json_result(data=True) return get_json_result(data=True)
except Exception as e: except Exception as e:
try: try:
e, file = FileService.get_by_id(file_id) e, file = FileService.get_by_id(file_id)
if not e: if not e:
return get_data_error_result(retmsg="Document not found!")
return get_data_error_result(message="Document not found!")
b, n = File2DocumentService.get_storage_address(file_id=file_id) b, n = File2DocumentService.get_storage_address(file_id=file_id)
response = flask.make_response(STORAGE_IMPL.get(b, n)) response = flask.make_response(STORAGE_IMPL.get(b, n))
ext = re.search(r"\.([^.]+)$", file.name) ext = re.search(r"\.([^.]+)$", file.name)
for file_id in file_ids: for file_id in file_ids:
e, file = FileService.get_by_id(file_id) e, file = FileService.get_by_id(file_id)
if not e: if not e:
return get_data_error_result(retmsg="File or Folder not found!")
return get_data_error_result(message="File or Folder not found!")
if not file.tenant_id: if not file.tenant_id:
return get_data_error_result(retmsg="Tenant not found!")
return get_data_error_result(message="Tenant not found!")
fe, _ = FileService.get_by_id(parent_id) fe, _ = FileService.get_by_id(parent_id)
if not fe: if not fe:
return get_data_error_result(retmsg="Parent Folder not found!")
return get_data_error_result(message="Parent Folder not found!")
FileService.move_file(file_ids, parent_id) FileService.move_file(file_ids, parent_id)
return get_json_result(data=True) return get_json_result(data=True)
except Exception as e: except Exception as e:

+ 15
- 15
api/apps/kb_app.py 查看文件

req["created_by"] = current_user.id req["created_by"] = current_user.id
e, t = TenantService.get_by_id(current_user.id) e, t = TenantService.get_by_id(current_user.id)
if not e: if not e:
return get_data_error_result(retmsg="Tenant not found.")
return get_data_error_result(message="Tenant not found.")
req["embd_id"] = t.embd_id req["embd_id"] = t.embd_id
if not KnowledgebaseService.save(**req): if not KnowledgebaseService.save(**req):
return get_data_error_result() return get_data_error_result()
if not KnowledgebaseService.accessible4deletion(req["kb_id"], current_user.id): if not KnowledgebaseService.accessible4deletion(req["kb_id"], current_user.id):
return get_json_result( return get_json_result(
data=False, data=False,
retmsg='No authorization.',
retcode=RetCode.AUTHENTICATION_ERROR
message='No authorization.',
code=RetCode.AUTHENTICATION_ERROR
) )
try: try:
if not KnowledgebaseService.query( if not KnowledgebaseService.query(
created_by=current_user.id, id=req["kb_id"]): created_by=current_user.id, id=req["kb_id"]):
return get_json_result( return get_json_result(
data=False, retmsg=f'Only owner of knowledgebase authorized for this operation.', retcode=RetCode.OPERATING_ERROR)
data=False, message='Only owner of knowledgebase authorized for this operation.', code=RetCode.OPERATING_ERROR)


e, kb = KnowledgebaseService.get_by_id(req["kb_id"]) e, kb = KnowledgebaseService.get_by_id(req["kb_id"])
if not e: if not e:
return get_data_error_result( return get_data_error_result(
retmsg="Can't find this knowledgebase!")
message="Can't find this knowledgebase!")


if req["name"].lower() != kb.name.lower() \ if req["name"].lower() != kb.name.lower() \
and len(KnowledgebaseService.query(name=req["name"], tenant_id=current_user.id, status=StatusEnum.VALID.value)) > 1: and len(KnowledgebaseService.query(name=req["name"], tenant_id=current_user.id, status=StatusEnum.VALID.value)) > 1:
return get_data_error_result( return get_data_error_result(
retmsg="Duplicated knowledgebase name.")
message="Duplicated knowledgebase name.")


del req["kb_id"] del req["kb_id"]
if not KnowledgebaseService.update_by_id(kb.id, req): if not KnowledgebaseService.update_by_id(kb.id, req):
e, kb = KnowledgebaseService.get_by_id(kb.id) e, kb = KnowledgebaseService.get_by_id(kb.id)
if not e: if not e:
return get_data_error_result( return get_data_error_result(
retmsg="Database error (Knowledgebase rename)!")
message="Database error (Knowledgebase rename)!")


return get_json_result(data=kb.to_json()) return get_json_result(data=kb.to_json())
except Exception as e: except Exception as e:
break break
else: else:
return get_json_result( return get_json_result(
data=False, retmsg=f'Only owner of knowledgebase authorized for this operation.',
retcode=RetCode.OPERATING_ERROR)
data=False, message='Only owner of knowledgebase authorized for this operation.',
code=RetCode.OPERATING_ERROR)
kb = KnowledgebaseService.get_detail(kb_id) kb = KnowledgebaseService.get_detail(kb_id)
if not kb: if not kb:
return get_data_error_result( return get_data_error_result(
retmsg="Can't find this knowledgebase!")
message="Can't find this knowledgebase!")
return get_json_result(data=kb) return get_json_result(data=kb)
except Exception as e: except Exception as e:
return server_error_response(e) return server_error_response(e)
if not KnowledgebaseService.accessible4deletion(req["kb_id"], current_user.id): if not KnowledgebaseService.accessible4deletion(req["kb_id"], current_user.id):
return get_json_result( return get_json_result(
data=False, data=False,
retmsg='No authorization.',
retcode=RetCode.AUTHENTICATION_ERROR
message='No authorization.',
code=RetCode.AUTHENTICATION_ERROR
) )
try: try:
kbs = KnowledgebaseService.query( kbs = KnowledgebaseService.query(
created_by=current_user.id, id=req["kb_id"]) created_by=current_user.id, id=req["kb_id"])
if not kbs: if not kbs:
return get_json_result( return get_json_result(
data=False, retmsg=f'Only owner of knowledgebase authorized for this operation.', retcode=RetCode.OPERATING_ERROR)
data=False, message='Only owner of knowledgebase authorized for this operation.', code=RetCode.OPERATING_ERROR)


for doc in DocumentService.query(kb_id=req["kb_id"]): for doc in DocumentService.query(kb_id=req["kb_id"]):
if not DocumentService.remove_document(doc, kbs[0].tenant_id): if not DocumentService.remove_document(doc, kbs[0].tenant_id):
return get_data_error_result( return get_data_error_result(
retmsg="Database error (Document removal)!")
message="Database error (Document removal)!")
f2d = File2DocumentService.get_by_document_id(doc.id) f2d = File2DocumentService.get_by_document_id(doc.id)
FileService.filter_delete([File.source_type == FileSource.KNOWLEDGEBASE, File.id == f2d[0].file_id]) FileService.filter_delete([File.source_type == FileSource.KNOWLEDGEBASE, File.id == f2d[0].file_id])
File2DocumentService.delete_by_document_id(doc.id) File2DocumentService.delete_by_document_id(doc.id)


if not KnowledgebaseService.delete_by_id(req["kb_id"]): if not KnowledgebaseService.delete_by_id(req["kb_id"]):
return get_data_error_result( return get_data_error_result(
retmsg="Database error (Knowledgebase removal)!")
message="Database error (Knowledgebase removal)!")
return get_json_result(data=True) return get_json_result(data=True)
except Exception as e: except Exception as e:
return server_error_response(e) return server_error_response(e)

+ 2
- 2
api/apps/llm_app.py 查看文件

break break


if msg: if msg:
return get_data_error_result(retmsg=msg)
return get_data_error_result(message=msg)


llm_config = { llm_config = {
"api_key": req["api_key"], "api_key": req["api_key"],
pass pass


if msg: if msg:
return get_data_error_result(retmsg=msg)
return get_data_error_result(message=msg)


if not TenantLLMService.filter_update( if not TenantLLMService.filter_update(
[TenantLLM.tenant_id == current_user.id, TenantLLM.llm_factory == factory, TenantLLM.llm_name == llm["llm_name"]], llm): [TenantLLM.tenant_id == current_user.id, TenantLLM.llm_factory == factory, TenantLLM.llm_name == llm["llm_name"]], llm):

+ 20
- 20
api/apps/sdk/chat.py 查看文件

req=request.json req=request.json
ids= req.get("dataset_ids") ids= req.get("dataset_ids")
if not ids: if not ids:
return get_error_data_result(retmsg="`dataset_ids` is required")
return get_error_data_result(message="`dataset_ids` is required")
for kb_id in ids: for kb_id in ids:
kbs = KnowledgebaseService.query(id=kb_id,tenant_id=tenant_id) kbs = KnowledgebaseService.query(id=kb_id,tenant_id=tenant_id)
if not kbs: if not kbs:
kbs = KnowledgebaseService.get_by_ids(ids) kbs = KnowledgebaseService.get_by_ids(ids)
embd_count = list(set([kb.embd_id for kb in kbs])) embd_count = list(set([kb.embd_id for kb in kbs]))
if len(embd_count) != 1: if len(embd_count) != 1:
return get_result(retmsg='Datasets use different embedding models."',retcode=RetCode.AUTHENTICATION_ERROR)
return get_result(message='Datasets use different embedding models."',code=RetCode.AUTHENTICATION_ERROR)
req["kb_ids"] = ids req["kb_ids"] = ids
# llm # llm
llm = req.get("llm") llm = req.get("llm")
req["llm_setting"] = req.pop("llm") req["llm_setting"] = req.pop("llm")
e, tenant = TenantService.get_by_id(tenant_id) e, tenant = TenantService.get_by_id(tenant_id)
if not e: if not e:
return get_error_data_result(retmsg="Tenant not found!")
return get_error_data_result(message="Tenant not found!")
# prompt # prompt
prompt = req.get("prompt") prompt = req.get("prompt")
key_mapping = {"parameters": "variables", key_mapping = {"parameters": "variables",
if not req.get("llm_id"): if not req.get("llm_id"):
req["llm_id"] = tenant.llm_id req["llm_id"] = tenant.llm_id
if not req.get("name"): if not req.get("name"):
return get_error_data_result(retmsg="`name` is required.")
return get_error_data_result(message="`name` is required.")
if DialogService.query(name=req["name"], tenant_id=tenant_id, status=StatusEnum.VALID.value): if DialogService.query(name=req["name"], tenant_id=tenant_id, status=StatusEnum.VALID.value):
return get_error_data_result(retmsg="Duplicated chat name in creating chat.")
return get_error_data_result(message="Duplicated chat name in creating chat.")
# tenant_id # tenant_id
if req.get("tenant_id"): if req.get("tenant_id"):
return get_error_data_result(retmsg="`tenant_id` must not be provided.")
return get_error_data_result(message="`tenant_id` must not be provided.")
req["tenant_id"] = tenant_id req["tenant_id"] = tenant_id
# prompt more parameter # prompt more parameter
default_prompt = { default_prompt = {
continue continue
if req['prompt_config']["system"].find("{%s}" % p["key"]) < 0: if req['prompt_config']["system"].find("{%s}" % p["key"]) < 0:
return get_error_data_result( return get_error_data_result(
retmsg="Parameter '{}' is not used".format(p["key"]))
message="Parameter '{}' is not used".format(p["key"]))
# save # save
if not DialogService.save(**req): if not DialogService.save(**req):
return get_error_data_result(retmsg="Fail to new a chat!")
return get_error_data_result(message="Fail to new a chat!")
# response # response
e, res = DialogService.get_by_id(req["id"]) e, res = DialogService.get_by_id(req["id"])
if not e: if not e:
return get_error_data_result(retmsg="Fail to new a chat!")
return get_error_data_result(message="Fail to new a chat!")
res = res.to_json() res = res.to_json()
renamed_dict = {} renamed_dict = {}
for key, value in res["prompt_config"].items(): for key, value in res["prompt_config"].items():
@token_required @token_required
def update(tenant_id,chat_id): def update(tenant_id,chat_id):
if not DialogService.query(tenant_id=tenant_id, id=chat_id, status=StatusEnum.VALID.value): if not DialogService.query(tenant_id=tenant_id, id=chat_id, status=StatusEnum.VALID.value):
return get_error_data_result(retmsg='You do not own the chat')
return get_error_data_result(message='You do not own the chat')
req =request.json req =request.json
ids = req.get("dataset_ids") ids = req.get("dataset_ids")
if "show_quotation" in req: if "show_quotation" in req:
embd_count=list(set([kb.embd_id for kb in kbs])) embd_count=list(set([kb.embd_id for kb in kbs]))
if len(embd_count) != 1 : if len(embd_count) != 1 :
return get_result( return get_result(
retmsg='Datasets use different embedding models."',
retcode=RetCode.AUTHENTICATION_ERROR)
message='Datasets use different embedding models."',
code=RetCode.AUTHENTICATION_ERROR)
req["kb_ids"] = ids req["kb_ids"] = ids
llm = req.get("llm") llm = req.get("llm")
if llm: if llm:
req["llm_setting"] = req.pop("llm") req["llm_setting"] = req.pop("llm")
e, tenant = TenantService.get_by_id(tenant_id) e, tenant = TenantService.get_by_id(tenant_id)
if not e: if not e:
return get_error_data_result(retmsg="Tenant not found!")
return get_error_data_result(message="Tenant not found!")
if req.get("rerank_model"): if req.get("rerank_model"):
if not TenantLLMService.query(tenant_id=tenant_id,llm_name=req.get("rerank_model"),model_type="rerank"): if not TenantLLMService.query(tenant_id=tenant_id,llm_name=req.get("rerank_model"),model_type="rerank"):
return get_error_data_result(f"`rerank_model` {req.get('rerank_model')} doesn't exist") return get_error_data_result(f"`rerank_model` {req.get('rerank_model')} doesn't exist")
res = res.to_json() res = res.to_json()
if "name" in req: if "name" in req:
if not req.get("name"): if not req.get("name"):
return get_error_data_result(retmsg="`name` is not empty.")
return get_error_data_result(message="`name` is not empty.")
if req["name"].lower() != res["name"].lower() \ if req["name"].lower() != res["name"].lower() \
and len( and len(
DialogService.query(name=req["name"], tenant_id=tenant_id, status=StatusEnum.VALID.value)) > 0: DialogService.query(name=req["name"], tenant_id=tenant_id, status=StatusEnum.VALID.value)) > 0:
return get_error_data_result(retmsg="Duplicated chat name in updating dataset.")
return get_error_data_result(message="Duplicated chat name in updating dataset.")
if "prompt_config" in req: if "prompt_config" in req:
res["prompt_config"].update(req["prompt_config"]) res["prompt_config"].update(req["prompt_config"])
for p in res["prompt_config"]["parameters"]: for p in res["prompt_config"]["parameters"]:
if p["optional"]: if p["optional"]:
continue continue
if res["prompt_config"]["system"].find("{%s}" % p["key"]) < 0: if res["prompt_config"]["system"].find("{%s}" % p["key"]) < 0:
return get_error_data_result(retmsg="Parameter '{}' is not used".format(p["key"]))
return get_error_data_result(message="Parameter '{}' is not used".format(p["key"]))
if "llm_setting" in req: if "llm_setting" in req:
res["llm_setting"].update(req["llm_setting"]) res["llm_setting"].update(req["llm_setting"])
req["prompt_config"] = res["prompt_config"] req["prompt_config"] = res["prompt_config"]
if "dataset_ids" in req: if "dataset_ids" in req:
req.pop("dataset_ids") req.pop("dataset_ids")
if not DialogService.update_by_id(chat_id, req): if not DialogService.update_by_id(chat_id, req):
return get_error_data_result(retmsg="Chat not found!")
return get_error_data_result(message="Chat not found!")
return get_result() return get_result()




id_list=ids id_list=ids
for id in id_list: for id in id_list:
if not DialogService.query(tenant_id=tenant_id, id=id, status=StatusEnum.VALID.value): if not DialogService.query(tenant_id=tenant_id, id=id, status=StatusEnum.VALID.value):
return get_error_data_result(retmsg=f"You don't own the chat {id}")
return get_error_data_result(message=f"You don't own the chat {id}")
temp_dict = {"status": StatusEnum.INVALID.value} temp_dict = {"status": StatusEnum.INVALID.value}
DialogService.update_by_id(id, temp_dict) DialogService.update_by_id(id, temp_dict)
return get_result() return get_result()
name = request.args.get("name") name = request.args.get("name")
chat = DialogService.query(id=id,name=name,status=StatusEnum.VALID.value) chat = DialogService.query(id=id,name=name,status=StatusEnum.VALID.value)
if not chat: if not chat:
return get_error_data_result(retmsg="The chat doesn't exist")
return get_error_data_result(message="The chat doesn't exist")
page_number = int(request.args.get("page", 1)) page_number = int(request.args.get("page", 1))
items_per_page = int(request.args.get("page_size", 1024)) items_per_page = int(request.args.get("page_size", 1024))
orderby = request.args.get("orderby", "create_time") orderby = request.args.get("orderby", "create_time")
for kb_id in res["kb_ids"]: for kb_id in res["kb_ids"]:
kb = KnowledgebaseService.query(id=kb_id) kb = KnowledgebaseService.query(id=kb_id)
if not kb : if not kb :
return get_error_data_result(retmsg=f"Don't exist the kb {kb_id}")
return get_error_data_result(message=f"Don't exist the kb {kb_id}")
kb_list.append(kb[0].to_json()) kb_list.append(kb[0].to_json())
del res["kb_ids"] del res["kb_ids"]
res["datasets"] = kb_list res["datasets"] = kb_list

+ 535
- 535
api/apps/sdk/dataset.py
文件差異過大導致無法顯示
查看文件


+ 5
- 5
api/apps/sdk/dify_retrieval.py 查看文件



e, kb = KnowledgebaseService.get_by_id(kb_id) e, kb = KnowledgebaseService.get_by_id(kb_id)
if not e: if not e:
return build_error_result(error_msg="Knowledgebase not found!", retcode=RetCode.NOT_FOUND)
return build_error_result(message="Knowledgebase not found!", code=RetCode.NOT_FOUND)


if kb.tenant_id != tenant_id: if kb.tenant_id != tenant_id:
return build_error_result(error_msg="Knowledgebase not found!", retcode=RetCode.NOT_FOUND)
return build_error_result(message="Knowledgebase not found!", code=RetCode.NOT_FOUND)


embd_mdl = LLMBundle(kb.tenant_id, LLMType.EMBEDDING.value, llm_name=kb.embd_id) embd_mdl = LLMBundle(kb.tenant_id, LLMType.EMBEDDING.value, llm_name=kb.embd_id)


except Exception as e: except Exception as e:
if str(e).find("not_found") > 0: if str(e).find("not_found") > 0:
return build_error_result( return build_error_result(
error_msg=f'No chunk found! Check the chunk status please!',
retcode=RetCode.NOT_FOUND
message='No chunk found! Check the chunk status please!',
code=RetCode.NOT_FOUND
) )
return build_error_result(error_msg=str(e), retcode=RetCode.SERVER_ERROR)
return build_error_result(message=str(e), code=RetCode.SERVER_ERROR)

+ 48
- 48
api/apps/sdk/doc.py 查看文件

""" """
if "file" not in request.files: if "file" not in request.files:
return get_error_data_result( return get_error_data_result(
retmsg="No file part!", retcode=RetCode.ARGUMENT_ERROR
message="No file part!", code=RetCode.ARGUMENT_ERROR
) )
file_objs = request.files.getlist("file") file_objs = request.files.getlist("file")
for file_obj in file_objs: for file_obj in file_objs:
if file_obj.filename == "": if file_obj.filename == "":
return get_result( return get_result(
retmsg="No file selected!", retcode=RetCode.ARGUMENT_ERROR
message="No file selected!", code=RetCode.ARGUMENT_ERROR
) )
# total size # total size
total_size = 0 total_size = 0
MAX_TOTAL_FILE_SIZE = 10 * 1024 * 1024 MAX_TOTAL_FILE_SIZE = 10 * 1024 * 1024
if total_size > MAX_TOTAL_FILE_SIZE: if total_size > MAX_TOTAL_FILE_SIZE:
return get_result( return get_result(
retmsg=f"Total file size exceeds 10MB limit! ({total_size / (1024 * 1024):.2f} MB)",
retcode=RetCode.ARGUMENT_ERROR,
message=f"Total file size exceeds 10MB limit! ({total_size / (1024 * 1024):.2f} MB)",
code=RetCode.ARGUMENT_ERROR,
) )
e, kb = KnowledgebaseService.get_by_id(dataset_id) e, kb = KnowledgebaseService.get_by_id(dataset_id)
if not e: if not e:
raise LookupError(f"Can't find the dataset with ID {dataset_id}!") raise LookupError(f"Can't find the dataset with ID {dataset_id}!")
err, files = FileService.upload_document(kb, file_objs, tenant_id) err, files = FileService.upload_document(kb, file_objs, tenant_id)
if err: if err:
return get_result(retmsg="\n".join(err), retcode=RetCode.SERVER_ERROR)
return get_result(message="\n".join(err), code=RetCode.SERVER_ERROR)
# rename key's name # rename key's name
renamed_doc_list = [] renamed_doc_list = []
for file in files: for file in files:
""" """
req = request.json req = request.json
if not KnowledgebaseService.query(id=dataset_id, tenant_id=tenant_id): if not KnowledgebaseService.query(id=dataset_id, tenant_id=tenant_id):
return get_error_data_result(retmsg="You don't own the dataset.")
return get_error_data_result(message="You don't own the dataset.")
doc = DocumentService.query(kb_id=dataset_id, id=document_id) doc = DocumentService.query(kb_id=dataset_id, id=document_id)
if not doc: if not doc:
return get_error_data_result(retmsg="The dataset doesn't own the document.")
return get_error_data_result(message="The dataset doesn't own the document.")
doc = doc[0] doc = doc[0]
if "chunk_count" in req: if "chunk_count" in req:
if req["chunk_count"] != doc.chunk_num: if req["chunk_count"] != doc.chunk_num:
return get_error_data_result(retmsg="Can't change `chunk_count`.")
return get_error_data_result(message="Can't change `chunk_count`.")
if "token_count" in req: if "token_count" in req:
if req["token_count"] != doc.token_num: if req["token_count"] != doc.token_num:
return get_error_data_result(retmsg="Can't change `token_count`.")
return get_error_data_result(message="Can't change `token_count`.")
if "progress" in req: if "progress" in req:
if req["progress"] != doc.progress: if req["progress"] != doc.progress:
return get_error_data_result(retmsg="Can't change `progress`.")
return get_error_data_result(message="Can't change `progress`.")


if "name" in req and req["name"] != doc.name: if "name" in req and req["name"] != doc.name:
if ( if (
!= pathlib.Path(doc.name.lower()).suffix != pathlib.Path(doc.name.lower()).suffix
): ):
return get_result( return get_result(
retmsg="The extension of file can't be changed",
retcode=RetCode.ARGUMENT_ERROR,
message="The extension of file can't be changed",
code=RetCode.ARGUMENT_ERROR,
) )
for d in DocumentService.query(name=req["name"], kb_id=doc.kb_id): for d in DocumentService.query(name=req["name"], kb_id=doc.kb_id):
if d.name == req["name"]: if d.name == req["name"]:
return get_error_data_result( return get_error_data_result(
retmsg="Duplicated document name in the same dataset."
message="Duplicated document name in the same dataset."
) )
if not DocumentService.update_by_id(document_id, {"name": req["name"]}): if not DocumentService.update_by_id(document_id, {"name": req["name"]}):
return get_error_data_result(retmsg="Database error (Document rename)!")
return get_error_data_result(message="Database error (Document rename)!")


informs = File2DocumentService.get_by_document_id(document_id) informs = File2DocumentService.get_by_document_id(document_id)
if informs: if informs:
return get_result() return get_result()


if doc.type == FileType.VISUAL or re.search(r"\.(ppt|pptx|pages)$", doc.name): if doc.type == FileType.VISUAL or re.search(r"\.(ppt|pptx|pages)$", doc.name):
return get_error_data_result(retmsg="Not supported yet!")
return get_error_data_result(message="Not supported yet!")


e = DocumentService.update_by_id( e = DocumentService.update_by_id(
doc.id, doc.id,
}, },
) )
if not e: if not e:
return get_error_data_result(retmsg="Document not found!")
return get_error_data_result(message="Document not found!")
req["parser_config"] = get_parser_config( req["parser_config"] = get_parser_config(
req["chunk_method"], req.get("parser_config") req["chunk_method"], req.get("parser_config")
) )
doc.process_duation * -1, doc.process_duation * -1,
) )
if not e: if not e:
return get_error_data_result(retmsg="Document not found!")
return get_error_data_result(message="Document not found!")
ELASTICSEARCH.deleteByQuery( ELASTICSEARCH.deleteByQuery(
Q("match", doc_id=doc.id), idxnm=search.index_name(tenant_id) Q("match", doc_id=doc.id), idxnm=search.index_name(tenant_id)
) )
type: object type: object
""" """
if not KnowledgebaseService.query(id=dataset_id, tenant_id=tenant_id): if not KnowledgebaseService.query(id=dataset_id, tenant_id=tenant_id):
return get_error_data_result(retmsg=f"You do not own the dataset {dataset_id}.")
return get_error_data_result(message=f"You do not own the dataset {dataset_id}.")
doc = DocumentService.query(kb_id=dataset_id, id=document_id) doc = DocumentService.query(kb_id=dataset_id, id=document_id)
if not doc: if not doc:
return get_error_data_result( return get_error_data_result(
retmsg=f"The dataset not own the document {document_id}."
message=f"The dataset not own the document {document_id}."
) )
# The process of downloading # The process of downloading
doc_id, doc_location = File2DocumentService.get_storage_address( doc_id, doc_location = File2DocumentService.get_storage_address(
description: Processing status. description: Processing status.
""" """
if not KnowledgebaseService.query(id=dataset_id, tenant_id=tenant_id): if not KnowledgebaseService.query(id=dataset_id, tenant_id=tenant_id):
return get_error_data_result(retmsg=f"You don't own the dataset {dataset_id}. ")
return get_error_data_result(message=f"You don't own the dataset {dataset_id}. ")
id = request.args.get("id") id = request.args.get("id")
name = request.args.get("name") name = request.args.get("name")
if not DocumentService.query(id=id, kb_id=dataset_id): if not DocumentService.query(id=id, kb_id=dataset_id):
return get_error_data_result(retmsg=f"You don't own the document {id}.")
return get_error_data_result(message=f"You don't own the document {id}.")
if not DocumentService.query(name=name, kb_id=dataset_id): if not DocumentService.query(name=name, kb_id=dataset_id):
return get_error_data_result(retmsg=f"You don't own the document {name}.")
return get_error_data_result(message=f"You don't own the document {name}.")
page = int(request.args.get("page", 1)) page = int(request.args.get("page", 1))
keywords = request.args.get("keywords", "") keywords = request.args.get("keywords", "")
page_size = int(request.args.get("page_size", 1024)) page_size = int(request.args.get("page_size", 1024))
type: object type: object
""" """
if not KnowledgebaseService.query(id=dataset_id, tenant_id=tenant_id): if not KnowledgebaseService.query(id=dataset_id, tenant_id=tenant_id):
return get_error_data_result(retmsg=f"You don't own the dataset {dataset_id}. ")
return get_error_data_result(message=f"You don't own the dataset {dataset_id}. ")
req = request.json req = request.json
if not req: if not req:
doc_ids = None doc_ids = None
try: try:
e, doc = DocumentService.get_by_id(doc_id) e, doc = DocumentService.get_by_id(doc_id)
if not e: if not e:
return get_error_data_result(retmsg="Document not found!")
return get_error_data_result(message="Document not found!")
tenant_id = DocumentService.get_tenant_id(doc_id) tenant_id = DocumentService.get_tenant_id(doc_id)
if not tenant_id: if not tenant_id:
return get_error_data_result(retmsg="Tenant not found!")
return get_error_data_result(message="Tenant not found!")


b, n = File2DocumentService.get_storage_address(doc_id=doc_id) b, n = File2DocumentService.get_storage_address(doc_id=doc_id)


if not DocumentService.remove_document(doc, tenant_id): if not DocumentService.remove_document(doc, tenant_id):
return get_error_data_result( return get_error_data_result(
retmsg="Database error (Document removal)!"
message="Database error (Document removal)!"
) )


f2d = File2DocumentService.get_by_document_id(doc_id) f2d = File2DocumentService.get_by_document_id(doc_id)
errors += str(e) errors += str(e)


if errors: if errors:
return get_result(retmsg=errors, retcode=RetCode.SERVER_ERROR)
return get_result(message=errors, code=RetCode.SERVER_ERROR)


return get_result() return get_result()


type: object type: object
""" """
if not KnowledgebaseService.query(id=dataset_id, tenant_id=tenant_id): if not KnowledgebaseService.query(id=dataset_id, tenant_id=tenant_id):
return get_error_data_result(retmsg=f"You don't own the dataset {dataset_id}.")
return get_error_data_result(message=f"You don't own the dataset {dataset_id}.")
req = request.json req = request.json
if not req.get("document_ids"): if not req.get("document_ids"):
return get_error_data_result("`document_ids` is required") return get_error_data_result("`document_ids` is required")
for id in req["document_ids"]: for id in req["document_ids"]:
doc = DocumentService.query(id=id, kb_id=dataset_id) doc = DocumentService.query(id=id, kb_id=dataset_id)
if not doc: if not doc:
return get_error_data_result(retmsg=f"You don't own the document {id}.")
return get_error_data_result(message=f"You don't own the document {id}.")
if doc[0].progress != 0.0: if doc[0].progress != 0.0:
return get_error_data_result( return get_error_data_result(
"Can't stop parsing document with progress at 0 or 100" "Can't stop parsing document with progress at 0 or 100"
type: object type: object
""" """
if not KnowledgebaseService.query(id=dataset_id, tenant_id=tenant_id): if not KnowledgebaseService.query(id=dataset_id, tenant_id=tenant_id):
return get_error_data_result(retmsg=f"You don't own the dataset {dataset_id}.")
return get_error_data_result(message=f"You don't own the dataset {dataset_id}.")
req = request.json req = request.json
if not req.get("document_ids"): if not req.get("document_ids"):
return get_error_data_result("`document_ids` is required") return get_error_data_result("`document_ids` is required")
for id in req["document_ids"]: for id in req["document_ids"]:
doc = DocumentService.query(id=id, kb_id=dataset_id) doc = DocumentService.query(id=id, kb_id=dataset_id)
if not doc: if not doc:
return get_error_data_result(retmsg=f"You don't own the document {id}.")
return get_error_data_result(message=f"You don't own the document {id}.")
if int(doc[0].progress) == 1 or int(doc[0].progress) == 0: if int(doc[0].progress) == 1 or int(doc[0].progress) == 0:
return get_error_data_result( return get_error_data_result(
"Can't stop parsing document with progress at 0 or 1" "Can't stop parsing document with progress at 0 or 1"
description: Document details. description: Document details.
""" """
if not KnowledgebaseService.query(id=dataset_id, tenant_id=tenant_id): if not KnowledgebaseService.query(id=dataset_id, tenant_id=tenant_id):
return get_error_data_result(retmsg=f"You don't own the dataset {dataset_id}.")
return get_error_data_result(message=f"You don't own the dataset {dataset_id}.")
doc = DocumentService.query(id=document_id, kb_id=dataset_id) doc = DocumentService.query(id=document_id, kb_id=dataset_id)
if not doc: if not doc:
return get_error_data_result( return get_error_data_result(
retmsg=f"You don't own the document {document_id}."
message=f"You don't own the document {document_id}."
) )
doc = doc[0] doc = doc[0]
req = request.args req = request.args
description: Important keywords. description: Important keywords.
""" """
if not KnowledgebaseService.query(id=dataset_id, tenant_id=tenant_id): if not KnowledgebaseService.query(id=dataset_id, tenant_id=tenant_id):
return get_error_data_result(retmsg=f"You don't own the dataset {dataset_id}.")
return get_error_data_result(message=f"You don't own the dataset {dataset_id}.")
doc = DocumentService.query(id=document_id, kb_id=dataset_id) doc = DocumentService.query(id=document_id, kb_id=dataset_id)
if not doc: if not doc:
return get_error_data_result( return get_error_data_result(
retmsg=f"You don't own the document {document_id}."
message=f"You don't own the document {document_id}."
) )
doc = doc[0] doc = doc[0]
req = request.json req = request.json
if not req.get("content"): if not req.get("content"):
return get_error_data_result(retmsg="`content` is required")
return get_error_data_result(message="`content` is required")
if "important_keywords" in req: if "important_keywords" in req:
if type(req["important_keywords"]) != list: if type(req["important_keywords"]) != list:
return get_error_data_result( return get_error_data_result(
type: object type: object
""" """
if not KnowledgebaseService.query(id=dataset_id, tenant_id=tenant_id): if not KnowledgebaseService.query(id=dataset_id, tenant_id=tenant_id):
return get_error_data_result(retmsg=f"You don't own the dataset {dataset_id}.")
return get_error_data_result(message=f"You don't own the dataset {dataset_id}.")
doc = DocumentService.query(id=document_id, kb_id=dataset_id) doc = DocumentService.query(id=document_id, kb_id=dataset_id)
if not doc: if not doc:
return get_error_data_result( return get_error_data_result(
retmsg=f"You don't own the document {document_id}."
message=f"You don't own the document {document_id}."
) )
doc = doc[0] doc = doc[0]
req = request.json req = request.json
if not ELASTICSEARCH.deleteByQuery( if not ELASTICSEARCH.deleteByQuery(
Q("ids", values=chunk_list), search.index_name(tenant_id) Q("ids", values=chunk_list), search.index_name(tenant_id)
): ):
return get_error_data_result(retmsg="Index updating failure")
return get_error_data_result(message="Index updating failure")
deleted_chunk_ids = chunk_list deleted_chunk_ids = chunk_list
chunk_number = len(deleted_chunk_ids) chunk_number = len(deleted_chunk_ids)
DocumentService.decrement_chunk_num(doc.id, doc.kb_id, 1, chunk_number, 0) DocumentService.decrement_chunk_num(doc.id, doc.kb_id, 1, chunk_number, 0)
""" """
try: try:
res = ELASTICSEARCH.get(chunk_id, search.index_name(tenant_id)) res = ELASTICSEARCH.get(chunk_id, search.index_name(tenant_id))
except Exception as e:
except Exception:
return get_error_data_result(f"Can't find this chunk {chunk_id}") return get_error_data_result(f"Can't find this chunk {chunk_id}")
if not KnowledgebaseService.query(id=dataset_id, tenant_id=tenant_id): if not KnowledgebaseService.query(id=dataset_id, tenant_id=tenant_id):
return get_error_data_result(retmsg=f"You don't own the dataset {dataset_id}.")
return get_error_data_result(message=f"You don't own the dataset {dataset_id}.")
doc = DocumentService.query(id=document_id, kb_id=dataset_id) doc = DocumentService.query(id=document_id, kb_id=dataset_id)
if not doc: if not doc:
return get_error_data_result( return get_error_data_result(
retmsg=f"You don't own the document {document_id}."
message=f"You don't own the document {document_id}."
) )
doc = doc[0] doc = doc[0]
query = { query = {
arr = [t for t in re.split(r"[\n\t]", d["content_with_weight"]) if len(t) > 1] arr = [t for t in re.split(r"[\n\t]", d["content_with_weight"]) if len(t) > 1]
if len(arr) != 2: if len(arr) != 2:
return get_error_data_result( return get_error_data_result(
retmsg="Q&A must be separated by TAB/ENTER key."
message="Q&A must be separated by TAB/ENTER key."
) )
q, a = rmPrefix(arr[0]), rmPrefix(arr[1]) q, a = rmPrefix(arr[0]), rmPrefix(arr[1])
d = beAdoc( d = beAdoc(
embd_nms = list(set([kb.embd_id for kb in kbs])) embd_nms = list(set([kb.embd_id for kb in kbs]))
if len(embd_nms) != 1: if len(embd_nms) != 1:
return get_result( return get_result(
retmsg='Datasets use different embedding models."',
retcode=RetCode.AUTHENTICATION_ERROR,
message='Datasets use different embedding models."',
code=RetCode.AUTHENTICATION_ERROR,
) )
if "question" not in req: if "question" not in req:
return get_error_data_result("`question` is required.") return get_error_data_result("`question` is required.")
try: try:
e, kb = KnowledgebaseService.get_by_id(kb_ids[0]) e, kb = KnowledgebaseService.get_by_id(kb_ids[0])
if not e: if not e:
return get_error_data_result(retmsg="Dataset not found!")
return get_error_data_result(message="Dataset not found!")
embd_mdl = TenantLLMService.model_instance( embd_mdl = TenantLLMService.model_instance(
kb.tenant_id, LLMType.EMBEDDING.value, llm_name=kb.embd_id kb.tenant_id, LLMType.EMBEDDING.value, llm_name=kb.embd_id
) )
except Exception as e: except Exception as e:
if str(e).find("not_found") > 0: if str(e).find("not_found") > 0:
return get_result( return get_result(
retmsg=f"No chunk found! Check the chunk status please!",
retcode=RetCode.DATA_ERROR,
message="No chunk found! Check the chunk status please!",
code=RetCode.DATA_ERROR,
) )
return server_error_response(e) return server_error_response(e)

+ 394
- 394
api/apps/sdk/session.py 查看文件

#
# Copyright 2024 The InfiniFlow Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
import json
from functools import partial
from uuid import uuid4
from flask import request, Response
from agent.canvas import Canvas
from api.db import StatusEnum
from api.db.db_models import API4Conversation
from api.db.services.api_service import API4ConversationService
from api.db.services.canvas_service import UserCanvasService
from api.db.services.dialog_service import DialogService, ConversationService, chat
from api.utils import get_uuid
from api.utils.api_utils import get_error_data_result
from api.utils.api_utils import get_result, token_required
@manager.route('/chats/<chat_id>/sessions', methods=['POST'])
@token_required
def create(tenant_id,chat_id):
req = request.json
req["dialog_id"] = chat_id
dia = DialogService.query(tenant_id=tenant_id, id=req["dialog_id"], status=StatusEnum.VALID.value)
if not dia:
return get_error_data_result(retmsg="You do not own the assistant.")
conv = {
"id": get_uuid(),
"dialog_id": req["dialog_id"],
"name": req.get("name", "New session"),
"message": [{"role": "assistant", "content": "Hi! I am your assistant,can I help you?"}]
}
if not conv.get("name"):
return get_error_data_result(retmsg="`name` can not be empty.")
ConversationService.save(**conv)
e, conv = ConversationService.get_by_id(conv["id"])
if not e:
return get_error_data_result(retmsg="Fail to create a session!")
conv = conv.to_dict()
conv['messages'] = conv.pop("message")
conv["chat_id"] = conv.pop("dialog_id")
del conv["reference"]
return get_result(data=conv)
@manager.route('/agents/<agent_id>/sessions', methods=['POST'])
@token_required
def create_agent_session(tenant_id, agent_id):
req = request.json
e, cvs = UserCanvasService.get_by_id(agent_id)
if not e:
return get_error_data_result("Agent not found.")
if cvs.user_id != tenant_id:
return get_error_data_result(retmsg="You do not own the agent.")
if not isinstance(cvs.dsl, str):
cvs.dsl = json.dumps(cvs.dsl, ensure_ascii=False)
canvas = Canvas(cvs.dsl, tenant_id)
conv = {
"id": get_uuid(),
"dialog_id": cvs.id,
"user_id": req.get("user_id", ""),
"message": [{"role": "assistant", "content": canvas.get_prologue()}],
"source": "agent"
}
API4ConversationService.save(**conv)
return get_result(data=conv)
@manager.route('/chats/<chat_id>/sessions/<session_id>', methods=['PUT'])
@token_required
def update(tenant_id,chat_id,session_id):
req = request.json
req["dialog_id"] = chat_id
conv_id = session_id
conv = ConversationService.query(id=conv_id,dialog_id=chat_id)
if not conv:
return get_error_data_result(retmsg="Session does not exist")
if not DialogService.query(id=chat_id, tenant_id=tenant_id, status=StatusEnum.VALID.value):
return get_error_data_result(retmsg="You do not own the session")
if "message" in req or "messages" in req:
return get_error_data_result(retmsg="`message` can not be change")
if "reference" in req:
return get_error_data_result(retmsg="`reference` can not be change")
if "name" in req and not req.get("name"):
return get_error_data_result(retmsg="`name` can not be empty.")
if not ConversationService.update_by_id(conv_id, req):
return get_error_data_result(retmsg="Session updates error")
return get_result()
@manager.route('/chats/<chat_id>/completions', methods=['POST'])
@token_required
def completion(tenant_id, chat_id):
req = request.json
if not req.get("session_id"):
conv = {
"id": get_uuid(),
"dialog_id": chat_id,
"name": req.get("name", "New session"),
"message": [{"role": "assistant", "content": "Hi! I am your assistant,can I help you?"}]
}
if not conv.get("name"):
return get_error_data_result(retmsg="`name` can not be empty.")
ConversationService.save(**conv)
e, conv = ConversationService.get_by_id(conv["id"])
session_id=conv.id
else:
session_id = req.get("session_id")
if not req.get("question"):
return get_error_data_result(retmsg="Please input your question.")
conv = ConversationService.query(id=session_id,dialog_id=chat_id)
if not conv:
return get_error_data_result(retmsg="Session does not exist")
conv = conv[0]
if not DialogService.query(id=chat_id, tenant_id=tenant_id, status=StatusEnum.VALID.value):
return get_error_data_result(retmsg="You do not own the chat")
msg = []
question = {
"content": req.get("question"),
"role": "user",
"id": str(uuid4())
}
conv.message.append(question)
for m in conv.message:
if m["role"] == "system": continue
if m["role"] == "assistant" and not msg: continue
msg.append(m)
message_id = msg[-1].get("id")
e, dia = DialogService.get_by_id(conv.dialog_id)
if not conv.reference:
conv.reference = []
conv.message.append({"role": "assistant", "content": "", "id": message_id})
conv.reference.append({"chunks": [], "doc_aggs": []})
def fillin_conv(ans):
nonlocal conv, message_id
if not conv.reference:
conv.reference.append(ans["reference"])
else:
conv.reference[-1] = ans["reference"]
conv.message[-1] = {"role": "assistant", "content": ans["answer"],
"id": message_id, "prompt": ans.get("prompt", "")}
ans["id"] = message_id
ans["session_id"]=session_id
def stream():
nonlocal dia, msg, req, conv
try:
for ans in chat(dia, msg, **req):
fillin_conv(ans)
yield "data:" + json.dumps({"code": 0, "data": ans}, ensure_ascii=False) + "\n\n"
ConversationService.update_by_id(conv.id, conv.to_dict())
except Exception as e:
yield "data:" + json.dumps({"code": 500, "message": str(e),
"data": {"answer": "**ERROR**: " + str(e),"reference": []}},
ensure_ascii=False) + "\n\n"
yield "data:" + json.dumps({"code": 0, "data": True}, ensure_ascii=False) + "\n\n"
if req.get("stream", True):
resp = Response(stream(), mimetype="text/event-stream")
resp.headers.add_header("Cache-control", "no-cache")
resp.headers.add_header("Connection", "keep-alive")
resp.headers.add_header("X-Accel-Buffering", "no")
resp.headers.add_header("Content-Type", "text/event-stream; charset=utf-8")
return resp
else:
answer = None
for ans in chat(dia, msg, **req):
answer = ans
fillin_conv(ans)
ConversationService.update_by_id(conv.id, conv.to_dict())
break
return get_result(data=answer)
@manager.route('/agents/<agent_id>/completions', methods=['POST'])
@token_required
def agent_completion(tenant_id, agent_id):
req = request.json
e, cvs = UserCanvasService.get_by_id(agent_id)
if not e:
return get_error_data_result("Agent not found.")
if cvs.user_id != tenant_id:
return get_error_data_result(retmsg="You do not own the agent.")
if not isinstance(cvs.dsl, str):
cvs.dsl = json.dumps(cvs.dsl, ensure_ascii=False)
canvas = Canvas(cvs.dsl, tenant_id)
msg = []
for m in req["messages"]:
if m["role"] == "system":
continue
if m["role"] == "assistant" and not msg:
continue
msg.append(m)
if not msg[-1].get("id"): msg[-1]["id"] = get_uuid()
message_id = msg[-1]["id"]
if not req.get("session_id"):
session_id = get_uuid()
conv = {
"id": session_id,
"dialog_id": cvs.id,
"user_id": req.get("user_id", ""),
"message": [{"role": "assistant", "content": canvas.get_prologue()}],
"source": "agent"
}
API4ConversationService.save(**conv)
conv = API4Conversation(**conv)
else:
session_id = req.get("session_id")
e, conv = API4ConversationService.get_by_id(req["session_id"])
if not e:
return get_error_data_result(retmsg="Session not found!")
if "quote" not in req: req["quote"] = False
stream = req.get("stream", True)
def fillin_conv(ans):
nonlocal conv, message_id
if not conv.reference:
conv.reference.append(ans["reference"])
else:
conv.reference[-1] = ans["reference"]
conv.message[-1] = {"role": "assistant", "content": ans["answer"], "id": message_id}
ans["id"] = message_id
ans["session_id"] = session_id
def rename_field(ans):
reference = ans['reference']
if not isinstance(reference, dict):
return
for chunk_i in reference.get('chunks', []):
if 'docnm_kwd' in chunk_i:
chunk_i['doc_name'] = chunk_i['docnm_kwd']
chunk_i.pop('docnm_kwd')
conv.message.append(msg[-1])
if not conv.reference:
conv.reference = []
conv.message.append({"role": "assistant", "content": "", "id": message_id})
conv.reference.append({"chunks": [], "doc_aggs": []})
final_ans = {"reference": [], "content": ""}
canvas.messages.append(msg[-1])
canvas.add_user_input(msg[-1]["content"])
answer = canvas.run(stream=stream)
assert answer is not None, "Nothing. Is it over?"
if stream:
assert isinstance(answer, partial), "Nothing. Is it over?"
def sse():
nonlocal answer, cvs, conv
try:
for ans in answer():
for k in ans.keys():
final_ans[k] = ans[k]
ans = {"answer": ans["content"], "reference": ans.get("reference", [])}
fillin_conv(ans)
rename_field(ans)
yield "data:" + json.dumps({"retcode": 0, "retmsg": "", "data": ans},
ensure_ascii=False) + "\n\n"
canvas.messages.append({"role": "assistant", "content": final_ans["content"], "id": message_id})
if final_ans.get("reference"):
canvas.reference.append(final_ans["reference"])
cvs.dsl = json.loads(str(canvas))
API4ConversationService.append_message(conv.id, conv.to_dict())
except Exception as e:
yield "data:" + json.dumps({"retcode": 500, "retmsg": str(e),
"data": {"answer": "**ERROR**: " + str(e), "reference": []}},
ensure_ascii=False) + "\n\n"
yield "data:" + json.dumps({"retcode": 0, "retmsg": "", "data": True}, ensure_ascii=False) + "\n\n"
resp = Response(sse(), mimetype="text/event-stream")
resp.headers.add_header("Cache-control", "no-cache")
resp.headers.add_header("Connection", "keep-alive")
resp.headers.add_header("X-Accel-Buffering", "no")
resp.headers.add_header("Content-Type", "text/event-stream; charset=utf-8")
return resp
final_ans["content"] = "\n".join(answer["content"]) if "content" in answer else ""
canvas.messages.append({"role": "assistant", "content": final_ans["content"], "id": message_id})
if final_ans.get("reference"):
canvas.reference.append(final_ans["reference"])
cvs.dsl = json.loads(str(canvas))
result = {"answer": final_ans["content"], "reference": final_ans.get("reference", [])}
fillin_conv(result)
API4ConversationService.append_message(conv.id, conv.to_dict())
rename_field(result)
return get_result(data=result)
@manager.route('/chats/<chat_id>/sessions', methods=['GET'])
@token_required
def list(chat_id,tenant_id):
if not DialogService.query(tenant_id=tenant_id, id=chat_id, status=StatusEnum.VALID.value):
return get_error_data_result(retmsg=f"You don't own the assistant {chat_id}.")
id = request.args.get("id")
name = request.args.get("name")
page_number = int(request.args.get("page", 1))
items_per_page = int(request.args.get("page_size", 1024))
orderby = request.args.get("orderby", "create_time")
if request.args.get("desc") == "False" or request.args.get("desc") == "false":
desc = False
else:
desc = True
convs = ConversationService.get_list(chat_id,page_number,items_per_page,orderby,desc,id,name)
if not convs:
return get_result(data=[])
for conv in convs:
conv['messages'] = conv.pop("message")
infos = conv["messages"]
for info in infos:
if "prompt" in info:
info.pop("prompt")
conv["chat"] = conv.pop("dialog_id")
if conv["reference"]:
messages = conv["messages"]
message_num = 0
chunk_num = 0
while message_num < len(messages):
if message_num != 0 and messages[message_num]["role"] != "user":
chunk_list = []
if "chunks" in conv["reference"][chunk_num]:
chunks = conv["reference"][chunk_num]["chunks"]
for chunk in chunks:
new_chunk = {
"id": chunk["chunk_id"],
"content": chunk["content_with_weight"],
"document_id": chunk["doc_id"],
"document_name": chunk["docnm_kwd"],
"dataset_id": chunk["kb_id"],
"image_id": chunk["img_id"],
"similarity": chunk["similarity"],
"vector_similarity": chunk["vector_similarity"],
"term_similarity": chunk["term_similarity"],
"positions": chunk["positions"],
}
chunk_list.append(new_chunk)
chunk_num += 1
messages[message_num]["reference"] = chunk_list
message_num += 1
del conv["reference"]
return get_result(data=convs)
@manager.route('/chats/<chat_id>/sessions', methods=["DELETE"])
@token_required
def delete(tenant_id,chat_id):
if not DialogService.query(id=chat_id, tenant_id=tenant_id, status=StatusEnum.VALID.value):
return get_error_data_result(retmsg="You don't own the chat")
req = request.json
convs = ConversationService.query(dialog_id=chat_id)
if not req:
ids = None
else:
ids=req.get("ids")
if not ids:
conv_list = []
for conv in convs:
conv_list.append(conv.id)
else:
conv_list=ids
for id in conv_list:
conv = ConversationService.query(id=id,dialog_id=chat_id)
if not conv:
return get_error_data_result(retmsg="The chat doesn't own the session")
ConversationService.delete_by_id(id)
return get_result()
#
# Copyright 2024 The InfiniFlow Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
import json
from functools import partial
from uuid import uuid4
from flask import request, Response
from agent.canvas import Canvas
from api.db import StatusEnum
from api.db.db_models import API4Conversation
from api.db.services.api_service import API4ConversationService
from api.db.services.canvas_service import UserCanvasService
from api.db.services.dialog_service import DialogService, ConversationService, chat
from api.utils import get_uuid
from api.utils.api_utils import get_error_data_result
from api.utils.api_utils import get_result, token_required
@manager.route('/chats/<chat_id>/sessions', methods=['POST'])
@token_required
def create(tenant_id,chat_id):
req = request.json
req["dialog_id"] = chat_id
dia = DialogService.query(tenant_id=tenant_id, id=req["dialog_id"], status=StatusEnum.VALID.value)
if not dia:
return get_error_data_result(message="You do not own the assistant.")
conv = {
"id": get_uuid(),
"dialog_id": req["dialog_id"],
"name": req.get("name", "New session"),
"message": [{"role": "assistant", "content": "Hi! I am your assistant,can I help you?"}]
}
if not conv.get("name"):
return get_error_data_result(message="`name` can not be empty.")
ConversationService.save(**conv)
e, conv = ConversationService.get_by_id(conv["id"])
if not e:
return get_error_data_result(message="Fail to create a session!")
conv = conv.to_dict()
conv['messages'] = conv.pop("message")
conv["chat_id"] = conv.pop("dialog_id")
del conv["reference"]
return get_result(data=conv)
@manager.route('/agents/<agent_id>/sessions', methods=['POST'])
@token_required
def create_agent_session(tenant_id, agent_id):
req = request.json
e, cvs = UserCanvasService.get_by_id(agent_id)
if not e:
return get_error_data_result("Agent not found.")
if cvs.user_id != tenant_id:
return get_error_data_result(message="You do not own the agent.")
if not isinstance(cvs.dsl, str):
cvs.dsl = json.dumps(cvs.dsl, ensure_ascii=False)
canvas = Canvas(cvs.dsl, tenant_id)
conv = {
"id": get_uuid(),
"dialog_id": cvs.id,
"user_id": req.get("user_id", ""),
"message": [{"role": "assistant", "content": canvas.get_prologue()}],
"source": "agent"
}
API4ConversationService.save(**conv)
return get_result(data=conv)
@manager.route('/chats/<chat_id>/sessions/<session_id>', methods=['PUT'])
@token_required
def update(tenant_id,chat_id,session_id):
req = request.json
req["dialog_id"] = chat_id
conv_id = session_id
conv = ConversationService.query(id=conv_id,dialog_id=chat_id)
if not conv:
return get_error_data_result(message="Session does not exist")
if not DialogService.query(id=chat_id, tenant_id=tenant_id, status=StatusEnum.VALID.value):
return get_error_data_result(message="You do not own the session")
if "message" in req or "messages" in req:
return get_error_data_result(message="`message` can not be change")
if "reference" in req:
return get_error_data_result(message="`reference` can not be change")
if "name" in req and not req.get("name"):
return get_error_data_result(message="`name` can not be empty.")
if not ConversationService.update_by_id(conv_id, req):
return get_error_data_result(message="Session updates error")
return get_result()
@manager.route('/chats/<chat_id>/completions', methods=['POST'])
@token_required
def completion(tenant_id, chat_id):
req = request.json
if not req.get("session_id"):
conv = {
"id": get_uuid(),
"dialog_id": chat_id,
"name": req.get("name", "New session"),
"message": [{"role": "assistant", "content": "Hi! I am your assistant,can I help you?"}]
}
if not conv.get("name"):
return get_error_data_result(message="`name` can not be empty.")
ConversationService.save(**conv)
e, conv = ConversationService.get_by_id(conv["id"])
session_id=conv.id
else:
session_id = req.get("session_id")
if not req.get("question"):
return get_error_data_result(message="Please input your question.")
conv = ConversationService.query(id=session_id,dialog_id=chat_id)
if not conv:
return get_error_data_result(message="Session does not exist")
conv = conv[0]
if not DialogService.query(id=chat_id, tenant_id=tenant_id, status=StatusEnum.VALID.value):
return get_error_data_result(message="You do not own the chat")
msg = []
question = {
"content": req.get("question"),
"role": "user",
"id": str(uuid4())
}
conv.message.append(question)
for m in conv.message:
if m["role"] == "system": continue
if m["role"] == "assistant" and not msg: continue
msg.append(m)
message_id = msg[-1].get("id")
e, dia = DialogService.get_by_id(conv.dialog_id)
if not conv.reference:
conv.reference = []
conv.message.append({"role": "assistant", "content": "", "id": message_id})
conv.reference.append({"chunks": [], "doc_aggs": []})
def fillin_conv(ans):
nonlocal conv, message_id
if not conv.reference:
conv.reference.append(ans["reference"])
else:
conv.reference[-1] = ans["reference"]
conv.message[-1] = {"role": "assistant", "content": ans["answer"],
"id": message_id, "prompt": ans.get("prompt", "")}
ans["id"] = message_id
ans["session_id"]=session_id
def stream():
nonlocal dia, msg, req, conv
try:
for ans in chat(dia, msg, **req):
fillin_conv(ans)
yield "data:" + json.dumps({"code": 0, "data": ans}, ensure_ascii=False) + "\n\n"
ConversationService.update_by_id(conv.id, conv.to_dict())
except Exception as e:
yield "data:" + json.dumps({"code": 500, "message": str(e),
"data": {"answer": "**ERROR**: " + str(e),"reference": []}},
ensure_ascii=False) + "\n\n"
yield "data:" + json.dumps({"code": 0, "data": True}, ensure_ascii=False) + "\n\n"
if req.get("stream", True):
resp = Response(stream(), mimetype="text/event-stream")
resp.headers.add_header("Cache-control", "no-cache")
resp.headers.add_header("Connection", "keep-alive")
resp.headers.add_header("X-Accel-Buffering", "no")
resp.headers.add_header("Content-Type", "text/event-stream; charset=utf-8")
return resp
else:
answer = None
for ans in chat(dia, msg, **req):
answer = ans
fillin_conv(ans)
ConversationService.update_by_id(conv.id, conv.to_dict())
break
return get_result(data=answer)
@manager.route('/agents/<agent_id>/completions', methods=['POST'])
@token_required
def agent_completion(tenant_id, agent_id):
req = request.json
e, cvs = UserCanvasService.get_by_id(agent_id)
if not e:
return get_error_data_result("Agent not found.")
if cvs.user_id != tenant_id:
return get_error_data_result(message="You do not own the agent.")
if not isinstance(cvs.dsl, str):
cvs.dsl = json.dumps(cvs.dsl, ensure_ascii=False)
canvas = Canvas(cvs.dsl, tenant_id)
msg = []
for m in req["messages"]:
if m["role"] == "system":
continue
if m["role"] == "assistant" and not msg:
continue
msg.append(m)
if not msg[-1].get("id"): msg[-1]["id"] = get_uuid()
message_id = msg[-1]["id"]
if not req.get("session_id"):
session_id = get_uuid()
conv = {
"id": session_id,
"dialog_id": cvs.id,
"user_id": req.get("user_id", ""),
"message": [{"role": "assistant", "content": canvas.get_prologue()}],
"source": "agent"
}
API4ConversationService.save(**conv)
conv = API4Conversation(**conv)
else:
session_id = req.get("session_id")
e, conv = API4ConversationService.get_by_id(req["session_id"])
if not e:
return get_error_data_result(message="Session not found!")
if "quote" not in req: req["quote"] = False
stream = req.get("stream", True)
def fillin_conv(ans):
nonlocal conv, message_id
if not conv.reference:
conv.reference.append(ans["reference"])
else:
conv.reference[-1] = ans["reference"]
conv.message[-1] = {"role": "assistant", "content": ans["answer"], "id": message_id}
ans["id"] = message_id
ans["session_id"] = session_id
def rename_field(ans):
reference = ans['reference']
if not isinstance(reference, dict):
return
for chunk_i in reference.get('chunks', []):
if 'docnm_kwd' in chunk_i:
chunk_i['doc_name'] = chunk_i['docnm_kwd']
chunk_i.pop('docnm_kwd')
conv.message.append(msg[-1])
if not conv.reference:
conv.reference = []
conv.message.append({"role": "assistant", "content": "", "id": message_id})
conv.reference.append({"chunks": [], "doc_aggs": []})
final_ans = {"reference": [], "content": ""}
canvas.messages.append(msg[-1])
canvas.add_user_input(msg[-1]["content"])
answer = canvas.run(stream=stream)
assert answer is not None, "Nothing. Is it over?"
if stream:
assert isinstance(answer, partial), "Nothing. Is it over?"
def sse():
nonlocal answer, cvs, conv
try:
for ans in answer():
for k in ans.keys():
final_ans[k] = ans[k]
ans = {"answer": ans["content"], "reference": ans.get("reference", [])}
fillin_conv(ans)
rename_field(ans)
yield "data:" + json.dumps({"code": 0, "message": "", "data": ans},
ensure_ascii=False) + "\n\n"
canvas.messages.append({"role": "assistant", "content": final_ans["content"], "id": message_id})
if final_ans.get("reference"):
canvas.reference.append(final_ans["reference"])
cvs.dsl = json.loads(str(canvas))
API4ConversationService.append_message(conv.id, conv.to_dict())
except Exception as e:
yield "data:" + json.dumps({"code": 500, "message": str(e),
"data": {"answer": "**ERROR**: " + str(e), "reference": []}},
ensure_ascii=False) + "\n\n"
yield "data:" + json.dumps({"code": 0, "message": "", "data": True}, ensure_ascii=False) + "\n\n"
resp = Response(sse(), mimetype="text/event-stream")
resp.headers.add_header("Cache-control", "no-cache")
resp.headers.add_header("Connection", "keep-alive")
resp.headers.add_header("X-Accel-Buffering", "no")
resp.headers.add_header("Content-Type", "text/event-stream; charset=utf-8")
return resp
final_ans["content"] = "\n".join(answer["content"]) if "content" in answer else ""
canvas.messages.append({"role": "assistant", "content": final_ans["content"], "id": message_id})
if final_ans.get("reference"):
canvas.reference.append(final_ans["reference"])
cvs.dsl = json.loads(str(canvas))
result = {"answer": final_ans["content"], "reference": final_ans.get("reference", [])}
fillin_conv(result)
API4ConversationService.append_message(conv.id, conv.to_dict())
rename_field(result)
return get_result(data=result)
@manager.route('/chats/<chat_id>/sessions', methods=['GET'])
@token_required
def list(chat_id,tenant_id):
if not DialogService.query(tenant_id=tenant_id, id=chat_id, status=StatusEnum.VALID.value):
return get_error_data_result(message=f"You don't own the assistant {chat_id}.")
id = request.args.get("id")
name = request.args.get("name")
page_number = int(request.args.get("page", 1))
items_per_page = int(request.args.get("page_size", 1024))
orderby = request.args.get("orderby", "create_time")
if request.args.get("desc") == "False" or request.args.get("desc") == "false":
desc = False
else:
desc = True
convs = ConversationService.get_list(chat_id,page_number,items_per_page,orderby,desc,id,name)
if not convs:
return get_result(data=[])
for conv in convs:
conv['messages'] = conv.pop("message")
infos = conv["messages"]
for info in infos:
if "prompt" in info:
info.pop("prompt")
conv["chat"] = conv.pop("dialog_id")
if conv["reference"]:
messages = conv["messages"]
message_num = 0
chunk_num = 0
while message_num < len(messages):
if message_num != 0 and messages[message_num]["role"] != "user":
chunk_list = []
if "chunks" in conv["reference"][chunk_num]:
chunks = conv["reference"][chunk_num]["chunks"]
for chunk in chunks:
new_chunk = {
"id": chunk["chunk_id"],
"content": chunk["content_with_weight"],
"document_id": chunk["doc_id"],
"document_name": chunk["docnm_kwd"],
"dataset_id": chunk["kb_id"],
"image_id": chunk["img_id"],
"similarity": chunk["similarity"],
"vector_similarity": chunk["vector_similarity"],
"term_similarity": chunk["term_similarity"],
"positions": chunk["positions"],
}
chunk_list.append(new_chunk)
chunk_num += 1
messages[message_num]["reference"] = chunk_list
message_num += 1
del conv["reference"]
return get_result(data=convs)
@manager.route('/chats/<chat_id>/sessions', methods=["DELETE"])
@token_required
def delete(tenant_id,chat_id):
if not DialogService.query(id=chat_id, tenant_id=tenant_id, status=StatusEnum.VALID.value):
return get_error_data_result(message="You don't own the chat")
req = request.json
convs = ConversationService.query(dialog_id=chat_id)
if not req:
ids = None
else:
ids=req.get("ids")
if not ids:
conv_list = []
for conv in convs:
conv_list.append(conv.id)
else:
conv_list=ids
for id in conv_list:
conv = ConversationService.query(id=id,dialog_id=chat_id)
if not conv:
return get_error_data_result(message="The chat doesn't own the session")
ConversationService.delete_by_id(id)
return get_result()

+ 3
- 5
api/apps/system_app.py 查看文件

get_data_error_result, get_data_error_result,
server_error_response, server_error_response,
generate_confirmation_token, generate_confirmation_token,
request,
validate_request,
) )
from api.versions import get_rag_version from api.versions import get_rag_version
from rag.utils.es_conn import ELASTICSEARCH from rag.utils.es_conn import ELASTICSEARCH
try: try:
tenants = UserTenantService.query(user_id=current_user.id) tenants = UserTenantService.query(user_id=current_user.id)
if not tenants: if not tenants:
return get_data_error_result(retmsg="Tenant not found!")
return get_data_error_result(message="Tenant not found!")


tenant_id = tenants[0].tenant_id tenant_id = tenants[0].tenant_id
obj = { obj = {
} }


if not APITokenService.save(**obj): if not APITokenService.save(**obj):
return get_data_error_result(retmsg="Fail to new a dialog!")
return get_data_error_result(message="Fail to new a dialog!")


return get_json_result(data=obj) return get_json_result(data=obj)
except Exception as e: except Exception as e:
try: try:
tenants = UserTenantService.query(user_id=current_user.id) tenants = UserTenantService.query(user_id=current_user.id)
if not tenants: if not tenants:
return get_data_error_result(retmsg="Tenant not found!")
return get_data_error_result(message="Tenant not found!")


objs = APITokenService.query(tenant_id=tenants[0].tenant_id) objs = APITokenService.query(tenant_id=tenants[0].tenant_id)
return get_json_result(data=[o.to_dict() for o in objs]) return get_json_result(data=[o.to_dict() for o in objs])

+ 3
- 3
api/apps/tenant_app.py 查看文件

req = request.json req = request.json
usrs = UserService.query(email=req["email"]) usrs = UserService.query(email=req["email"])
if not usrs: if not usrs:
return get_data_error_result(retmsg="User not found.")
return get_data_error_result(message="User not found.")


user_id = usrs[0].id user_id = usrs[0].id
user_tenants = UserTenantService.query(user_id=user_id, tenant_id=tenant_id) user_tenants = UserTenantService.query(user_id=user_id, tenant_id=tenant_id)
if user_tenants: if user_tenants:
if user_tenants[0].status == UserTenantRole.NORMAL.value: if user_tenants[0].status == UserTenantRole.NORMAL.value:
return get_data_error_result(retmsg="This user is in the team already.")
return get_data_error_result(retmsg="Invitation notification is sent.")
return get_data_error_result(message="This user is in the team already.")
return get_data_error_result(message="Invitation notification is sent.")


UserTenantService.save( UserTenantService.save(
id=get_uuid(), id=get_uuid(),

+ 24
- 24
api/apps/user_app.py 查看文件

current_timestamp, current_timestamp,
datetime_format, datetime_format,
) )
from api.db import UserTenantRole, LLMType, FileType
from api.db import UserTenantRole, FileType
from api.settings import ( from api.settings import (
RetCode, RetCode,
GITHUB_OAUTH, GITHUB_OAUTH,
""" """
if not request.json: if not request.json:
return get_json_result( return get_json_result(
data=False, retcode=RetCode.AUTHENTICATION_ERROR, retmsg="Unauthorized!"
data=False, code=RetCode.AUTHENTICATION_ERROR, message="Unauthorized!"
) )


email = request.json.get("email", "") email = request.json.get("email", "")
if not users: if not users:
return get_json_result( return get_json_result(
data=False, data=False,
retcode=RetCode.AUTHENTICATION_ERROR,
retmsg=f"Email: {email} is not registered!",
code=RetCode.AUTHENTICATION_ERROR,
message=f"Email: {email} is not registered!",
) )


password = request.json.get("password") password = request.json.get("password")
password = decrypt(password) password = decrypt(password)
except BaseException: except BaseException:
return get_json_result( return get_json_result(
data=False, retcode=RetCode.SERVER_ERROR, retmsg="Fail to crypt password"
data=False, code=RetCode.SERVER_ERROR, message="Fail to crypt password"
) )


user = UserService.query_user(email, password) user = UserService.query_user(email, password)
user.update_date = (datetime_format(datetime.now()),) user.update_date = (datetime_format(datetime.now()),)
user.save() user.save()
msg = "Welcome back!" msg = "Welcome back!"
return construct_response(data=response_data, auth=user.get_id(), retmsg=msg)
return construct_response(data=response_data, auth=user.get_id(), message=msg)
else: else:
return get_json_result( return get_json_result(
data=False, data=False,
retcode=RetCode.AUTHENTICATION_ERROR,
retmsg="Email and password do not match!",
code=RetCode.AUTHENTICATION_ERROR,
message="Email and password do not match!",
) )




"Authorization": f"Bearer {access_token}", "Authorization": f"Bearer {access_token}",
} }
res = requests.get( res = requests.get(
f"https://open.feishu.cn/open-apis/authen/v1/user_info", headers=headers
"https://open.feishu.cn/open-apis/authen/v1/user_info", headers=headers
) )
user_info = res.json()["data"] user_info = res.json()["data"]
user_info["email"] = None if user_info.get("email") == "" else user_info["email"] user_info["email"] = None if user_info.get("email") == "" else user_info["email"]
): ):
return get_json_result( return get_json_result(
data=False, data=False,
retcode=RetCode.AUTHENTICATION_ERROR,
retmsg="Password error!",
code=RetCode.AUTHENTICATION_ERROR,
message="Password error!",
) )


if new_password: if new_password:
except Exception as e: except Exception as e:
stat_logger.exception(e) stat_logger.exception(e)
return get_json_result( return get_json_result(
data=False, retmsg="Update failure!", retcode=RetCode.EXCEPTION_ERROR
data=False, message="Update failure!", code=RetCode.EXCEPTION_ERROR
) )




def rollback_user_registration(user_id): def rollback_user_registration(user_id):
try: try:
UserService.delete_by_id(user_id) UserService.delete_by_id(user_id)
except Exception as e:
except Exception:
pass pass
try: try:
TenantService.delete_by_id(user_id) TenantService.delete_by_id(user_id)
except Exception as e:
except Exception:
pass pass
try: try:
u = UserTenantService.query(tenant_id=user_id) u = UserTenantService.query(tenant_id=user_id)
if u: if u:
UserTenantService.delete_by_id(u[0].id) UserTenantService.delete_by_id(u[0].id)
except Exception as e:
except Exception:
pass pass
try: try:
TenantLLM.delete().where(TenantLLM.tenant_id == user_id).execute() TenantLLM.delete().where(TenantLLM.tenant_id == user_id).execute()
except Exception as e:
except Exception:
pass pass




if not re.match(r"^[\w\._-]+@([\w_-]+\.)+[\w-]{2,5}$", email_address): if not re.match(r"^[\w\._-]+@([\w_-]+\.)+[\w-]{2,5}$", email_address):
return get_json_result( return get_json_result(
data=False, data=False,
retmsg=f"Invalid email address: {email_address}!",
retcode=RetCode.OPERATING_ERROR,
message=f"Invalid email address: {email_address}!",
code=RetCode.OPERATING_ERROR,
) )


# Check if the email address is already used # Check if the email address is already used
if UserService.query(email=email_address): if UserService.query(email=email_address):
return get_json_result( return get_json_result(
data=False, data=False,
retmsg=f"Email: {email_address} has already registered!",
retcode=RetCode.OPERATING_ERROR,
message=f"Email: {email_address} has already registered!",
code=RetCode.OPERATING_ERROR,
) )


# Construct user info data # Construct user info data
return construct_response( return construct_response(
data=user.to_json(), data=user.to_json(),
auth=user.get_id(), auth=user.get_id(),
retmsg=f"{nickname}, welcome aboard!",
message=f"{nickname}, welcome aboard!",
) )
except Exception as e: except Exception as e:
rollback_user_registration(user_id) rollback_user_registration(user_id)
stat_logger.exception(e) stat_logger.exception(e)
return get_json_result( return get_json_result(
data=False, data=False,
retmsg=f"User registration failure, error: {str(e)}",
retcode=RetCode.EXCEPTION_ERROR,
message=f"User registration failure, error: {str(e)}",
code=RetCode.EXCEPTION_ERROR,
) )




try: try:
tenants = TenantService.get_info_by(current_user.id) tenants = TenantService.get_info_by(current_user.id)
if not tenants: if not tenants:
return get_data_error_result(retmsg="Tenant not found!")
return get_data_error_result(message="Tenant not found!")
return get_json_result(data=tenants[0]) return get_json_result(data=tenants[0])
except Exception as e: except Exception as e:
return server_error_response(e) return server_error_response(e)

+ 36
- 36
api/utils/api_utils.py 查看文件

return max(0, countdown) return max(0, countdown)




def get_data_error_result(retcode=RetCode.DATA_ERROR,
retmsg='Sorry! Data missing!'):
def get_data_error_result(code=RetCode.DATA_ERROR,
message='Sorry! Data missing!'):
import re import re
result_dict = { result_dict = {
"retcode": retcode,
"retmsg": re.sub(
"code": code,
"message": re.sub(
r"rag", r"rag",
"seceum", "seceum",
retmsg,
message,
flags=re.IGNORECASE)} flags=re.IGNORECASE)}
response = {} response = {}
for key, value in result_dict.items(): for key, value in result_dict.items():
if value is None and key != "retcode":
if value is None and key != "code":
continue continue
else: else:
response[key] = value response[key] = value
stat_logger.exception(e) stat_logger.exception(e)
try: try:
if e.code == 401: if e.code == 401:
return get_json_result(retcode=401, retmsg=repr(e))
return get_json_result(code=401, message=repr(e))
except BaseException: except BaseException:
pass pass
if len(e.args) > 1: if len(e.args) > 1:
return get_json_result( return get_json_result(
retcode=RetCode.EXCEPTION_ERROR, retmsg=repr(e.args[0]), data=e.args[1])
code=RetCode.EXCEPTION_ERROR, message=repr(e.args[0]), data=e.args[1])
if repr(e).find("index_not_found_exception") >= 0: if repr(e).find("index_not_found_exception") >= 0:
return get_json_result(retcode=RetCode.EXCEPTION_ERROR,
retmsg="No chunk found, please upload file and parse it.")
return get_json_result(code=RetCode.EXCEPTION_ERROR,
message="No chunk found, please upload file and parse it.")


return get_json_result(retcode=RetCode.EXCEPTION_ERROR, retmsg=repr(e))
return get_json_result(code=RetCode.EXCEPTION_ERROR, message=repr(e))




def error_response(response_code, retmsg=None):
if retmsg is None:
retmsg = HTTP_STATUS_CODES.get(response_code, 'Unknown Error')
def error_response(response_code, message=None):
if message is None:
message = HTTP_STATUS_CODES.get(response_code, 'Unknown Error')


return Response(json.dumps({ return Response(json.dumps({
'retmsg': retmsg,
'retcode': response_code,
'message': message,
'code': response_code,
}), status=response_code, mimetype='application/json') }), status=response_code, mimetype='application/json')




error_string += "required argument values: {}".format( error_string += "required argument values: {}".format(
",".join(["{}={}".format(a[0], a[1]) for a in error_arguments])) ",".join(["{}={}".format(a[0], a[1]) for a in error_arguments]))
return get_json_result( return get_json_result(
retcode=RetCode.ARGUMENT_ERROR, retmsg=error_string)
code=RetCode.ARGUMENT_ERROR, message=error_string)
return func(*_args, **_kwargs) return func(*_args, **_kwargs)


return decorated_function return decorated_function
return send_file(f, as_attachment=True, attachment_filename=filename) return send_file(f, as_attachment=True, attachment_filename=filename)




def get_json_result(retcode=RetCode.SUCCESS, retmsg='success', data=None):
response = {"retcode": retcode, "retmsg": retmsg, "data": data}
def get_json_result(code=RetCode.SUCCESS, message='success', data=None):
response = {"code": code, "message": message, "data": data}
return jsonify(response) return jsonify(response)


def apikey_required(func): def apikey_required(func):
objs = APIToken.query(token=token) objs = APIToken.query(token=token)
if not objs: if not objs:
return build_error_result( return build_error_result(
error_msg='API-KEY is invalid!', retcode=RetCode.FORBIDDEN
message='API-KEY is invalid!', code=RetCode.FORBIDDEN
) )
kwargs['tenant_id'] = objs[0].tenant_id kwargs['tenant_id'] = objs[0].tenant_id
return func(*args, **kwargs) return func(*args, **kwargs)
return decorated_function return decorated_function




def build_error_result(retcode=RetCode.FORBIDDEN, error_msg='success'):
response = {"error_code": retcode, "error_msg": error_msg}
def build_error_result(code=RetCode.FORBIDDEN, message='success'):
response = {"code": code, "message": message}
response = jsonify(response) response = jsonify(response)
response.status_code = retcode
response.status_code = code
return response return response




def construct_response(retcode=RetCode.SUCCESS,
retmsg='success', data=None, auth=None):
result_dict = {"retcode": retcode, "retmsg": retmsg, "data": data}
def construct_response(code=RetCode.SUCCESS,
message='success', data=None, auth=None):
result_dict = {"code": code, "message": message, "data": data}
response_dict = {} response_dict = {}
for key, value in result_dict.items(): for key, value in result_dict.items():
if value is None and key != "retcode":
if value is None and key != "code":
continue continue
else: else:
response_dict[key] = value response_dict[key] = value
objs = APIToken.query(token=token) objs = APIToken.query(token=token)
if not objs: if not objs:
return get_json_result( return get_json_result(
data=False, retmsg='Token is not valid!', retcode=RetCode.AUTHENTICATION_ERROR
data=False, message='Token is not valid!', code=RetCode.AUTHENTICATION_ERROR
) )
kwargs['tenant_id'] = objs[0].tenant_id kwargs['tenant_id'] = objs[0].tenant_id
return func(*args, **kwargs) return func(*args, **kwargs)
return decorated_function return decorated_function




def get_result(retcode=RetCode.SUCCESS, retmsg='error', data=None):
if retcode == 0:
def get_result(code=RetCode.SUCCESS, message='error', data=None):
if code == 0:
if data is not None: if data is not None:
response = {"code": retcode, "data": data}
response = {"code": code, "data": data}
else: else:
response = {"code": retcode}
response = {"code": code}
else: else:
response = {"code": retcode, "message": retmsg}
response = {"code": code, "message": message}
return jsonify(response) return jsonify(response)




def get_error_data_result(retmsg='Sorry! Data missing!', retcode=RetCode.DATA_ERROR,
def get_error_data_result(message='Sorry! Data missing!', code=RetCode.DATA_ERROR,
): ):
import re import re
result_dict = { result_dict = {
"code": retcode,
"code": code,
"message": re.sub( "message": re.sub(
r"rag", r"rag",
"seceum", "seceum",
retmsg,
message,
flags=re.IGNORECASE)} flags=re.IGNORECASE)}
response = {} response = {}
for key, value in result_dict.items(): for key, value in result_dict.items():

+ 1
- 1
docs/references/faq.md 查看文件



This is because you forgot to update the `vm.max_map_count` value in **/etc/sysctl.conf** and your change to this value was reset after a system reboot. This is because you forgot to update the `vm.max_map_count` value in **/etc/sysctl.conf** and your change to this value was reset after a system reboot.


#### 4.10 `{"data":null,"retcode":100,"retmsg":"<NotFound '404: Not Found'>"}`
#### 4.10 `{"data":null,"code":100,"message":"<NotFound '404: Not Found'>"}`


Your IP address or port number may be incorrect. If you are using the default configurations, enter `http://<IP_OF_YOUR_MACHINE>` (**NOT 9380, AND NO PORT NUMBER REQUIRED!**) in your browser. This should work. Your IP address or port number may be incorrect. If you are using the default configurations, enter `http://<IP_OF_YOUR_MACHINE>` (**NOT 9380, AND NO PORT NUMBER REQUIRED!**) in your browser. This should work.



+ 7
- 9
intergrations/chatgpt-on-wechat/plugins/ragflow_chat.py 查看文件

import requests import requests
import json
from bridge.context import Context, ContextType # Import Context, ContextType
from bridge.context import ContextType # Import Context, ContextType
from bridge.reply import Reply, ReplyType # Import Reply, ReplyType from bridge.reply import Reply, ReplyType # Import Reply, ReplyType
from bridge import * from bridge import *
from common.log import logger from common.log import logger
from config import conf
from plugins import Plugin, register # Import Plugin and register from plugins import Plugin, register # Import Plugin and register
from plugins.event import Event, EventContext, EventAction # Import event-related classes from plugins.event import Event, EventContext, EventAction # Import event-related classes


logger.debug(f"[RAGFlowChat] New conversation response: {response.text}") logger.debug(f"[RAGFlowChat] New conversation response: {response.text}")
if response.status_code == 200: if response.status_code == 200:
data = response.json() data = response.json()
if data.get("retcode") == 0:
if data.get("code") == 0:
conversation_id = data["data"]["id"] conversation_id = data["data"]["id"]
self.conversations[user_id] = conversation_id self.conversations[user_id] = conversation_id
else: else:
logger.error(f"[RAGFlowChat] Failed to create conversation: {data.get('retmsg')}")
return f"Sorry, unable to create a conversation: {data.get('retmsg')}"
logger.error(f"[RAGFlowChat] Failed to create conversation: {data.get('message')}")
return f"Sorry, unable to create a conversation: {data.get('message')}"
else: else:
logger.error(f"[RAGFlowChat] HTTP error when creating conversation: {response.status_code}") logger.error(f"[RAGFlowChat] HTTP error when creating conversation: {response.status_code}")
return f"Sorry, unable to connect to RAGFlow API (create conversation). HTTP status code: {response.status_code}" return f"Sorry, unable to connect to RAGFlow API (create conversation). HTTP status code: {response.status_code}"
logger.debug(f"[RAGFlowChat] Completion response: {response.text}") logger.debug(f"[RAGFlowChat] Completion response: {response.text}")
if response.status_code == 200: if response.status_code == 200:
data = response.json() data = response.json()
if data.get("retcode") == 0:
if data.get("code") == 0:
answer = data["data"]["answer"] answer = data["data"]["answer"]
return answer return answer
else: else:
logger.error(f"[RAGFlowChat] Failed to get answer: {data.get('retmsg')}")
return f"Sorry, unable to get a reply: {data.get('retmsg')}"
logger.error(f"[RAGFlowChat] Failed to get answer: {data.get('message')}")
return f"Sorry, unable to get a reply: {data.get('message')}"
else: else:
logger.error(f"[RAGFlowChat] HTTP error when getting answer: {response.status_code}") logger.error(f"[RAGFlowChat] HTTP error when getting answer: {response.status_code}")
return f"Sorry, unable to connect to RAGFlow API (get reply). HTTP status code: {response.status_code}" return f"Sorry, unable to connect to RAGFlow API (get reply). HTTP status code: {response.status_code}"

+ 6
- 6
sdk/python/test/conftest.py 查看文件

register_data = {"email":EMAIL,"nickname":name,"password":PASSWORD} register_data = {"email":EMAIL,"nickname":name,"password":PASSWORD}
res = requests.post(url=url,json=register_data) res = requests.post(url=url,json=register_data)
res = res.json() res = res.json()
if res.get("retcode") != 0:
raise Exception(res.get("retmsg"))
if res.get("code") != 0:
raise Exception(res.get("message"))


def login(): def login():
url = HOST_ADDRESS + "/v1/user/login" url = HOST_ADDRESS + "/v1/user/login"
login_data = {"email":EMAIL,"password":PASSWORD} login_data = {"email":EMAIL,"password":PASSWORD}
response=requests.post(url=url,json=login_data) response=requests.post(url=url,json=login_data)
res = response.json() res = response.json()
if res.get("retcode")!=0:
raise Exception(res.get("retmsg"))
if res.get("code")!=0:
raise Exception(res.get("message"))
auth = response.headers["Authorization"] auth = response.headers["Authorization"]
return auth return auth


auth = {"Authorization": auth} auth = {"Authorization": auth}
response = requests.post(url=url,headers=auth) response = requests.post(url=url,headers=auth)
res = response.json() res = response.json()
if res.get("retcode") != 0:
raise Exception(res.get("retmsg"))
if res.get("code") != 0:
raise Exception(res.get("message"))
return res["data"].get("token") return res["data"].get("token")



+ 1
- 1
sdk/python/test/ragflow.txt 查看文件

{"data":null,"retcode":100,"retmsg":"TypeError(\"download_document() got an unexpected keyword argument 'tenant_id'\")"}
{"data":null,"code":100,"message":"TypeError(\"download_document() got an unexpected keyword argument 'tenant_id'\")"}

+ 4
- 4
web/src/components/message-input/index.tsx 查看文件

}; };


const isUploadSuccess = (file: UploadFile) => { const isUploadSuccess = (file: UploadFile) => {
const retcode = get(file, 'response.retcode');
return typeof retcode === 'number' && retcode === 0;
const code = get(file, 'response.code');
return typeof code === 'number' && code === 0;
}; };


interface IProps { interface IProps {
const creatingRet = await createConversationBeforeUploadDocument( const creatingRet = await createConversationBeforeUploadDocument(
file.name, file.name,
); );
if (creatingRet?.retcode === 0) {
if (creatingRet?.code === 0) {
nextConversationId = creatingRet.data.id; nextConversationId = creatingRet.data.id;
} }
} }
originFileObj: file as any, originFileObj: file as any,
response: ret, response: ret,
percent: 100, percent: 100,
status: ret?.retcode === 0 ? 'done' : 'error',
status: ret?.code === 0 ? 'done' : 'error',
}); });
return nextList; return nextList;
}); });

+ 2
- 2
web/src/components/message-item/hooks.ts 查看文件

const onRemoveMessage = useCallback(async () => { const onRemoveMessage = useCallback(async () => {
const pureId = getMessagePureId(messageId); const pureId = getMessagePureId(messageId);
if (pureId) { if (pureId) {
const retcode = await deleteMessage(pureId);
if (retcode === 0) {
const code = await deleteMessage(pureId);
if (code === 0) {
removeMessageById?.(messageId); removeMessageById?.(messageId);
} }
} }

+ 2
- 2
web/src/components/pdf-previewer/hooks.ts 查看文件



const fetchDocument = useCallback(async () => { const fetchDocument = useCallback(async () => {
const { data } = await axios.get(url); const { data } = await axios.get(url);
if (data.retcode !== 0) {
setError(data?.retmsg);
if (data.code !== 0) {
setError(data?.message);
} }
}, [url]); }, [url]);
useEffect(() => { useEffect(() => {

+ 15
- 15
web/src/hooks/chat-hooks.ts 查看文件

console.log('🚀 ~ queryFn: ~ params:', params); console.log('🚀 ~ queryFn: ~ params:', params);
const { data } = await chatService.listDialog(); const { data } = await chatService.listDialog();


if (data.retcode === 0) {
if (data.code === 0) {
const list: IDialog[] = data.data; const list: IDialog[] = data.data;
if (list.length > 0) { if (list.length > 0) {
if (list.every((x) => x.id !== dialogId)) { if (list.every((x) => x.id !== dialogId)) {
mutationKey: ['setDialog'], mutationKey: ['setDialog'],
mutationFn: async (params: IDialog) => { mutationFn: async (params: IDialog) => {
const { data } = await chatService.setDialog(params); const { data } = await chatService.setDialog(params);
if (data.retcode === 0) {
if (data.code === 0) {
queryClient.invalidateQueries({ queryClient.invalidateQueries({
exact: false, exact: false,
queryKey: ['fetchDialogList'], queryKey: ['fetchDialogList'],
i18n.t(`message.${params.dialog_id ? 'modified' : 'created'}`), i18n.t(`message.${params.dialog_id ? 'modified' : 'created'}`),
); );
} }
return data?.retcode;
return data?.code;
}, },
}); });


mutationKey: ['removeDialog'], mutationKey: ['removeDialog'],
mutationFn: async (dialogIds: string[]) => { mutationFn: async (dialogIds: string[]) => {
const { data } = await chatService.removeDialog({ dialogIds }); const { data } = await chatService.removeDialog({ dialogIds });
if (data.retcode === 0) {
if (data.code === 0) {
queryClient.invalidateQueries({ queryKey: ['fetchDialogList'] }); queryClient.invalidateQueries({ queryKey: ['fetchDialogList'] });


message.success(i18n.t('message.deleted')); message.success(i18n.t('message.deleted'));
} }
return data.retcode;
return data.code;
}, },
}); });


enabled: !!dialogId, enabled: !!dialogId,
queryFn: async () => { queryFn: async () => {
const { data } = await chatService.listConversation({ dialogId }); const { data } = await chatService.listConversation({ dialogId });
if (data.retcode === 0 && data.data.length > 0) {
if (data.code === 0 && data.data.length > 0) {
handleClickConversation(data.data[0].id, ''); handleClickConversation(data.data[0].id, '');
} }
return data?.data; return data?.data;
? params.conversation_id ? params.conversation_id
: getConversationId(), : getConversationId(),
}); });
if (data.retcode === 0) {
if (data.code === 0) {
queryClient.invalidateQueries({ queryKey: ['fetchConversationList'] }); queryClient.invalidateQueries({ queryKey: ['fetchConversationList'] });
} }
return data; return data;
conversationIds, conversationIds,
dialogId, dialogId,
}); });
if (data.retcode === 0) {
if (data.code === 0) {
queryClient.invalidateQueries({ queryKey: ['fetchConversationList'] }); queryClient.invalidateQueries({ queryKey: ['fetchConversationList'] });
} }
return data.retcode;
return data.code;
}, },
}); });


conversationId, conversationId,
}); });


if (data.retcode === 0) {
if (data.code === 0) {
message.success(i18n.t(`message.deleted`)); message.success(i18n.t(`message.deleted`));
} }


return data.retcode;
return data.code;
}, },
}); });


...params, ...params,
conversationId, conversationId,
}); });
if (data.retcode === 0) {
if (data.code === 0) {
message.success(i18n.t(`message.operated`)); message.success(i18n.t(`message.operated`));
} }
return data.retcode;
return data.code;
}, },
}); });


mutationKey: ['createToken'], mutationKey: ['createToken'],
mutationFn: async (params: Record<string, any>) => { mutationFn: async (params: Record<string, any>) => {
const { data } = await chatService.createToken(params); const { data } = await chatService.createToken(params);
if (data.retcode === 0) {
if (data.code === 0) {
queryClient.invalidateQueries({ queryKey: ['fetchTokenList'] }); queryClient.invalidateQueries({ queryKey: ['fetchTokenList'] });
} }
return data?.data ?? []; return data?.data ?? [];
tokens: string[]; tokens: string[];
}) => { }) => {
const { data } = await chatService.removeToken(params); const { data } = await chatService.removeToken(params);
if (data.retcode === 0) {
if (data.code === 0) {
queryClient.invalidateQueries({ queryKey: ['fetchTokenList'] }); queryClient.invalidateQueries({ queryKey: ['fetchTokenList'] });
} }
return data?.data ?? []; return data?.data ?? [];

+ 7
- 7
web/src/hooks/chunk-hooks.ts 查看文件

available_int: available, available_int: available,
keywords: searchString, keywords: searchString,
}); });
if (data.retcode === 0) {
if (data.code === 0) {
const res = data.data; const res = data.data;
return { return {
data: res.chunks, data: res.chunks,
mutationKey: ['deleteChunk'], mutationKey: ['deleteChunk'],
mutationFn: async (params: { chunkIds: string[]; doc_id: string }) => { mutationFn: async (params: { chunkIds: string[]; doc_id: string }) => {
const { data } = await kbService.rm_chunk(params); const { data } = await kbService.rm_chunk(params);
if (data.retcode === 0) {
if (data.code === 0) {
setPaginationParams(1); setPaginationParams(1);
queryClient.invalidateQueries({ queryKey: ['fetchChunkList'] }); queryClient.invalidateQueries({ queryKey: ['fetchChunkList'] });
} }
return data?.retcode;
return data?.code;
}, },
}); });


doc_id: string; doc_id: string;
}) => { }) => {
const { data } = await kbService.switch_chunk(params); const { data } = await kbService.switch_chunk(params);
if (data.retcode === 0) {
if (data.code === 0) {
message.success(t('message.modified')); message.success(t('message.modified'));
queryClient.invalidateQueries({ queryKey: ['fetchChunkList'] }); queryClient.invalidateQueries({ queryKey: ['fetchChunkList'] });
} }
return data?.retcode;
return data?.code;
}, },
}); });


service = kbService.set_chunk; service = kbService.set_chunk;
} }
const { data } = await service(payload); const { data } = await service(payload);
if (data.retcode === 0) {
if (data.code === 0) {
message.success(t('message.created')); message.success(t('message.created'));
queryClient.invalidateQueries({ queryKey: ['fetchChunkList'] }); queryClient.invalidateQueries({ queryKey: ['fetchChunkList'] });
} }
return data?.retcode;
return data?.code;
}, },
}); });



+ 22
- 22
web/src/hooks/document-hooks.ts 查看文件

page_size: pagination.pageSize, page_size: pagination.pageSize,
page: pagination.current, page: pagination.current,
}); });
if (ret.data.retcode === 0) {
if (ret.data.code === 0) {
return ret.data.data; return ret.data.data;
} }


doc_id: documentId, doc_id: documentId,
status: Number(status), status: Number(status),
}); });
if (data.retcode === 0) {
if (data.code === 0) {
message.success(i18n.t('message.modified')); message.success(i18n.t('message.modified'));
queryClient.invalidateQueries({ queryKey: ['fetchDocumentList'] }); queryClient.invalidateQueries({ queryKey: ['fetchDocumentList'] });
} }
doc_id: documentId, doc_id: documentId,
name: name, name: name,
}); });
if (data.retcode === 0) {
if (data.code === 0) {
message.success(i18n.t('message.renamed')); message.success(i18n.t('message.renamed'));
queryClient.invalidateQueries({ queryKey: ['fetchDocumentList'] }); queryClient.invalidateQueries({ queryKey: ['fetchDocumentList'] });
} }
return data.retcode;
return data.code;
}, },
}); });


name, name,
kb_id: knowledgeId, kb_id: knowledgeId,
}); });
if (data.retcode === 0) {
if (data.code === 0) {
if (page === 1) { if (page === 1) {
queryClient.invalidateQueries({ queryKey: ['fetchDocumentList'] }); queryClient.invalidateQueries({ queryKey: ['fetchDocumentList'] });
} else { } else {


message.success(i18n.t('message.created')); message.success(i18n.t('message.created'));
} }
return data.retcode;
return data.code;
}, },
}); });


doc_id: documentId, doc_id: documentId,
parser_config: parserConfig, parser_config: parserConfig,
}); });
if (data.retcode === 0) {
if (data.code === 0) {
queryClient.invalidateQueries({ queryKey: ['fetchDocumentList'] }); queryClient.invalidateQueries({ queryKey: ['fetchDocumentList'] });


message.success(i18n.t('message.modified')); message.success(i18n.t('message.modified'));
} }
return data.retcode;
return data.code;
}, },
}); });




try { try {
const ret = await kbService.document_upload(formData); const ret = await kbService.document_upload(formData);
const retcode = get(ret, 'data.retcode');
if (retcode === 0) {
const code = get(ret, 'data.code');
if (code === 0) {
message.success(i18n.t('message.uploaded')); message.success(i18n.t('message.uploaded'));
} }


if (retcode === 0 || retcode === 500) {
if (code === 0 || code === 500) {
queryClient.invalidateQueries({ queryKey: ['fetchDocumentList'] }); queryClient.invalidateQueries({ queryKey: ['fetchDocumentList'] });
} }
return ret?.data; return ret?.data;
formData.append('kb_id', knowledgeId); formData.append('kb_id', knowledgeId);


const ret = await kbService.web_crawl(formData); const ret = await kbService.web_crawl(formData);
const retcode = get(ret, 'data.retcode');
if (retcode === 0) {
const code = get(ret, 'data.code');
if (code === 0) {
message.success(i18n.t('message.uploaded')); message.success(i18n.t('message.uploaded'));
} }


return retcode;
return code;
}, },
}); });


doc_ids: documentIds, doc_ids: documentIds,
run, run,
}); });
const retcode = get(ret, 'data.retcode');
if (retcode === 0) {
const code = get(ret, 'data.code');
if (code === 0) {
queryClient.invalidateQueries({ queryKey: ['fetchDocumentList'] }); queryClient.invalidateQueries({ queryKey: ['fetchDocumentList'] });
message.success(i18n.t('message.operated')); message.success(i18n.t('message.operated'));
} }


return retcode;
return code;
}, },
}); });


initialData: [], initialData: [],
queryFn: async () => { queryFn: async () => {
const { data } = await kbService.document_infos({ doc_ids: ids }); const { data } = await kbService.document_infos({ doc_ids: ids });
if (data.retcode === 0) {
if (data.code === 0) {
return data.data; return data.data;
} }


initialData: {}, initialData: {},
queryFn: async () => { queryFn: async () => {
const { data } = await kbService.document_thumbnails({ doc_ids: ids }); const { data } = await kbService.document_thumbnails({ doc_ids: ids });
if (data.retcode === 0) {
if (data.code === 0) {
return data.data; return data.data;
} }
return {}; return {};
mutationKey: ['removeDocument'], mutationKey: ['removeDocument'],
mutationFn: async (documentIds: string | string[]) => { mutationFn: async (documentIds: string | string[]) => {
const { data } = await kbService.document_rm({ doc_id: documentIds }); const { data } = await kbService.document_rm({ doc_id: documentIds });
if (data.retcode === 0) {
if (data.code === 0) {
message.success(i18n.t('message.deleted')); message.success(i18n.t('message.deleted'));
queryClient.invalidateQueries({ queryKey: ['fetchDocumentList'] }); queryClient.invalidateQueries({ queryKey: ['fetchDocumentList'] });
} }
return data.retcode;
return data.code;
}, },
}); });


mutationKey: ['deleteDocument'], mutationKey: ['deleteDocument'],
mutationFn: async (documentIds: string[]) => { mutationFn: async (documentIds: string[]) => {
const data = await kbService.document_delete({ doc_ids: documentIds }); const data = await kbService.document_delete({ doc_ids: documentIds });
// if (data.retcode === 0) {
// if (data.code === 0) {
// queryClient.invalidateQueries({ queryKey: ['fetchFlowList'] }); // queryClient.invalidateQueries({ queryKey: ['fetchFlowList'] });
// } // }
return data; return data;

+ 12
- 12
web/src/hooks/file-manager-hooks.ts 查看文件

mutationKey: ['deleteFile'], mutationKey: ['deleteFile'],
mutationFn: async (params: { fileIds: string[]; parentId: string }) => { mutationFn: async (params: { fileIds: string[]; parentId: string }) => {
const { data } = await fileManagerService.removeFile(params); const { data } = await fileManagerService.removeFile(params);
if (data.retcode === 0) {
if (data.code === 0) {
setPaginationParams(1); // TODO: There should be a better way to paginate the request list setPaginationParams(1); // TODO: There should be a better way to paginate the request list
queryClient.invalidateQueries({ queryKey: ['fetchFileList'] }); queryClient.invalidateQueries({ queryKey: ['fetchFileList'] });
} }
return data.retcode;
return data.code;
}, },
}); });


mutationKey: ['renameFile'], mutationKey: ['renameFile'],
mutationFn: async (params: { fileId: string; name: string }) => { mutationFn: async (params: { fileId: string; name: string }) => {
const { data } = await fileManagerService.renameFile(params); const { data } = await fileManagerService.renameFile(params);
if (data.retcode === 0) {
if (data.code === 0) {
message.success(t('message.renamed')); message.success(t('message.renamed'));
queryClient.invalidateQueries({ queryKey: ['fetchFileList'] }); queryClient.invalidateQueries({ queryKey: ['fetchFileList'] });
} }
return data.retcode;
return data.code;
}, },
}); });


...params, ...params,
type: 'folder', type: 'folder',
}); });
if (data.retcode === 0) {
if (data.code === 0) {
message.success(t('message.created')); message.success(t('message.created'));
setPaginationParams(1); setPaginationParams(1);
queryClient.invalidateQueries({ queryKey: ['fetchFileList'] }); queryClient.invalidateQueries({ queryKey: ['fetchFileList'] });
} }
return data.retcode;
return data.code;
}, },
}); });


}); });
try { try {
const ret = await fileManagerService.uploadFile(formData); const ret = await fileManagerService.uploadFile(formData);
if (ret?.data.retcode === 0) {
if (ret?.data.code === 0) {
message.success(t('message.uploaded')); message.success(t('message.uploaded'));
setPaginationParams(1); setPaginationParams(1);
queryClient.invalidateQueries({ queryKey: ['fetchFileList'] }); queryClient.invalidateQueries({ queryKey: ['fetchFileList'] });
} }
return ret?.data?.retcode;
return ret?.data?.code;
} catch (error) { } catch (error) {
console.log('🚀 ~ useUploadFile ~ error:', error); console.log('🚀 ~ useUploadFile ~ error:', error);
} }
mutationKey: ['connectFileToKnowledge'], mutationKey: ['connectFileToKnowledge'],
mutationFn: async (params: IConnectRequestBody) => { mutationFn: async (params: IConnectRequestBody) => {
const { data } = await fileManagerService.connectFileToKnowledge(params); const { data } = await fileManagerService.connectFileToKnowledge(params);
if (data.retcode === 0) {
if (data.code === 0) {
message.success(t('message.operated')); message.success(t('message.operated'));
queryClient.invalidateQueries({ queryKey: ['fetchFileList'] }); queryClient.invalidateQueries({ queryKey: ['fetchFileList'] });
} }
return data.retcode;
return data.code;
}, },
}); });


mutationKey: ['moveFile'], mutationKey: ['moveFile'],
mutationFn: async (params: IMoveFileBody) => { mutationFn: async (params: IMoveFileBody) => {
const { data } = await fileManagerService.moveFile(params); const { data } = await fileManagerService.moveFile(params);
if (data.retcode === 0) {
if (data.code === 0) {
message.success(t('message.operated')); message.success(t('message.operated'));
queryClient.invalidateQueries({ queryKey: ['fetchFileList'] }); queryClient.invalidateQueries({ queryKey: ['fetchFileList'] });
} }
return data.retcode;
return data.code;
}, },
}); });



+ 4
- 4
web/src/hooks/flow-hooks.ts 查看文件

avatar?: string; avatar?: string;
}) => { }) => {
const { data = {} } = await flowService.setCanvas(params); const { data = {} } = await flowService.setCanvas(params);
if (data.retcode === 0) {
if (data.code === 0) {
message.success( message.success(
i18n.t(`message.${params?.id ? 'modified' : 'created'}`), i18n.t(`message.${params?.id ? 'modified' : 'created'}`),
); );
mutationKey: ['deleteFlow'], mutationKey: ['deleteFlow'],
mutationFn: async (canvasIds: string[]) => { mutationFn: async (canvasIds: string[]) => {
const { data } = await flowService.removeCanvas({ canvasIds }); const { data } = await flowService.removeCanvas({ canvasIds });
if (data.retcode === 0) {
if (data.code === 0) {
queryClient.invalidateQueries({ queryKey: ['fetchFlowList'] }); queryClient.invalidateQueries({ queryKey: ['fetchFlowList'] });
} }
return data?.data ?? []; return data?.data ?? [];
mutationKey: ['runFlow'], mutationKey: ['runFlow'],
mutationFn: async (params: { id: string; dsl: DSL }) => { mutationFn: async (params: { id: string; dsl: DSL }) => {
const { data } = await flowService.runCanvas(params); const { data } = await flowService.runCanvas(params);
if (data.retcode === 0) {
if (data.code === 0) {
message.success(i18n.t(`message.modified`)); message.success(i18n.t(`message.modified`));
} }
return data?.data ?? {}; return data?.data ?? {};
mutationKey: ['testDbConnect'], mutationKey: ['testDbConnect'],
mutationFn: async (params: any) => { mutationFn: async (params: any) => {
const ret = await flowService.testDbConnect(params); const ret = await flowService.testDbConnect(params);
if (ret?.data?.retcode === 0) {
if (ret?.data?.code === 0) {
message.success(ret?.data?.data); message.success(ret?.data?.data);
} else { } else {
message.error(ret?.data?.data); message.error(ret?.data?.data);

+ 4
- 4
web/src/hooks/knowledge-hooks.ts 查看文件

mutationKey: ['createKnowledge'], mutationKey: ['createKnowledge'],
mutationFn: async (params: { id?: string; name: string }) => { mutationFn: async (params: { id?: string; name: string }) => {
const { data = {} } = await kbService.createKb(params); const { data = {} } = await kbService.createKb(params);
if (data.retcode === 0) {
if (data.code === 0) {
message.success( message.success(
i18n.t(`message.${params?.id ? 'modified' : 'created'}`), i18n.t(`message.${params?.id ? 'modified' : 'created'}`),
); );
mutationKey: ['deleteKnowledge'], mutationKey: ['deleteKnowledge'],
mutationFn: async (id: string) => { mutationFn: async (id: string) => {
const { data } = await kbService.rmKb({ kb_id: id }); const { data } = await kbService.rmKb({ kb_id: id });
if (data.retcode === 0) {
if (data.code === 0) {
message.success(i18n.t(`message.deleted`)); message.success(i18n.t(`message.deleted`));
queryClient.invalidateQueries({ queryKey: ['fetchKnowledgeList'] }); queryClient.invalidateQueries({ queryKey: ['fetchKnowledgeList'] });
} }
kb_id: knowledgeBaseId, kb_id: knowledgeBaseId,
...params, ...params,
}); });
if (data.retcode === 0) {
if (data.code === 0) {
message.success(i18n.t(`message.updated`)); message.success(i18n.t(`message.updated`));
queryClient.invalidateQueries({ queryKey: ['fetchKnowledgeDetail'] }); queryClient.invalidateQueries({ queryKey: ['fetchKnowledgeDetail'] });
} }
page, page,
size: pageSize, size: pageSize,
}); });
if (data.retcode === 0) {
if (data.code === 0) {
const res = data.data; const res = data.data;
return { return {
chunks: res.chunks, chunks: res.chunks,

+ 10
- 10
web/src/hooks/llm-hooks.tsx 查看文件

mutationKey: ['saveApiKey'], mutationKey: ['saveApiKey'],
mutationFn: async (params: IApiKeySavingParams) => { mutationFn: async (params: IApiKeySavingParams) => {
const { data } = await userService.set_api_key(params); const { data } = await userService.set_api_key(params);
if (data.retcode === 0) {
if (data.code === 0) {
message.success(t('message.modified')); message.success(t('message.modified'));
queryClient.invalidateQueries({ queryKey: ['myLlmList'] }); queryClient.invalidateQueries({ queryKey: ['myLlmList'] });
queryClient.invalidateQueries({ queryKey: ['factoryList'] }); queryClient.invalidateQueries({ queryKey: ['factoryList'] });
} }
return data.retcode;
return data.code;
}, },
}); });


mutationKey: ['saveTenantInfo'], mutationKey: ['saveTenantInfo'],
mutationFn: async (params: ISystemModelSettingSavingParams) => { mutationFn: async (params: ISystemModelSettingSavingParams) => {
const { data } = await userService.set_tenant_info(params); const { data } = await userService.set_tenant_info(params);
if (data.retcode === 0) {
if (data.code === 0) {
message.success(t('message.modified')); message.success(t('message.modified'));
} }
return data.retcode;
return data.code;
}, },
}); });


mutationKey: ['addLlm'], mutationKey: ['addLlm'],
mutationFn: async (params: IAddLlmRequestBody) => { mutationFn: async (params: IAddLlmRequestBody) => {
const { data } = await userService.add_llm(params); const { data } = await userService.add_llm(params);
if (data.retcode === 0) {
if (data.code === 0) {
queryClient.invalidateQueries({ queryKey: ['myLlmList'] }); queryClient.invalidateQueries({ queryKey: ['myLlmList'] });
queryClient.invalidateQueries({ queryKey: ['factoryList'] }); queryClient.invalidateQueries({ queryKey: ['factoryList'] });
message.success(t('message.modified')); message.success(t('message.modified'));
} }
return data.retcode;
return data.code;
}, },
}); });


mutationKey: ['deleteLlm'], mutationKey: ['deleteLlm'],
mutationFn: async (params: IDeleteLlmRequestBody) => { mutationFn: async (params: IDeleteLlmRequestBody) => {
const { data } = await userService.delete_llm(params); const { data } = await userService.delete_llm(params);
if (data.retcode === 0) {
if (data.code === 0) {
queryClient.invalidateQueries({ queryKey: ['myLlmList'] }); queryClient.invalidateQueries({ queryKey: ['myLlmList'] });
queryClient.invalidateQueries({ queryKey: ['factoryList'] }); queryClient.invalidateQueries({ queryKey: ['factoryList'] });
message.success(t('message.deleted')); message.success(t('message.deleted'));
} }
return data.retcode;
return data.code;
}, },
}); });


mutationKey: ['deleteFactory'], mutationKey: ['deleteFactory'],
mutationFn: async (params: IDeleteLlmRequestBody) => { mutationFn: async (params: IDeleteLlmRequestBody) => {
const { data } = await userService.deleteFactory(params); const { data } = await userService.deleteFactory(params);
if (data.retcode === 0) {
if (data.code === 0) {
queryClient.invalidateQueries({ queryKey: ['myLlmList'] }); queryClient.invalidateQueries({ queryKey: ['myLlmList'] });
queryClient.invalidateQueries({ queryKey: ['factoryList'] }); queryClient.invalidateQueries({ queryKey: ['factoryList'] });
message.success(t('message.deleted')); message.success(t('message.deleted'));
} }
return data.retcode;
return data.code;
}, },
}); });



+ 2
- 2
web/src/hooks/logic-hooks.ts 查看文件

}); });
try { try {
const res = await response.clone().json(); const res = await response.clone().json();
if (res?.retcode !== 0) {
message.error(res?.retmsg);
if (res?.code !== 0) {
message.error(res?.message);
} }
} catch (error) { } catch (error) {
console.warn('🚀 ~ error:', error); console.warn('🚀 ~ error:', error);

+ 6
- 6
web/src/hooks/login-hooks.ts 查看文件

mutationKey: ['login'], mutationKey: ['login'],
mutationFn: async (params: { email: string; password: string }) => { mutationFn: async (params: { email: string; password: string }) => {
const { data: res = {}, response } = await userService.login(params); const { data: res = {}, response } = await userService.login(params);
if (res.retcode === 0) {
if (res.code === 0) {
const { data } = res; const { data } = res;
message.success(t('message.logged')); message.success(t('message.logged'));
const authorization = response.headers.get(Authorization); const authorization = response.headers.get(Authorization);
Token: token, Token: token,
}); });
} }
return res.retcode;
return res.code;
}, },
}); });


nickname: string; nickname: string;
}) => { }) => {
const { data = {} } = await userService.register(params); const { data = {} } = await userService.register(params);
if (data.retcode === 0) {
if (data.code === 0) {
message.success(t('message.registered')); message.success(t('message.registered'));
} }
return data.retcode;
return data.code;
}, },
}); });


mutationKey: ['logout'], mutationKey: ['logout'],
mutationFn: async () => { mutationFn: async () => {
const { data = {} } = await userService.logout(); const { data = {} } = await userService.logout();
if (data.retcode === 0) {
if (data.code === 0) {
message.success(t('message.logout')); message.success(t('message.logout'));
authorizationUtil.removeAll(); authorizationUtil.removeAll();
history.push('/login'); history.push('/login');
} }
return data.retcode;
return data.code;
}, },
}); });



+ 12
- 12
web/src/hooks/user-setting-hooks.tsx 查看文件

gcTime: 0, gcTime: 0,
queryFn: async () => { queryFn: async () => {
const { data } = await userService.user_info(); const { data } = await userService.user_info();
if (data.retcode === 0) {
if (data.code === 0) {
i18n.changeLanguage( i18n.changeLanguage(
LanguageTranslationMap[ LanguageTranslationMap[
data.data.language as keyof typeof LanguageTranslationMap data.data.language as keyof typeof LanguageTranslationMap
gcTime: 0, gcTime: 0,
queryFn: async () => { queryFn: async () => {
const { data: res } = await userService.get_tenant_info(); const { data: res } = await userService.get_tenant_info();
if (res.retcode === 0) {
if (res.code === 0) {
// llm_id is chat_id // llm_id is chat_id
// asr_id is speech2txt // asr_id is speech2txt
const { data } = res; const { data } = res;
userInfo: { new_password: string } | Partial<IUserInfo>, userInfo: { new_password: string } | Partial<IUserInfo>,
) => { ) => {
const { data } = await userService.setting(userInfo); const { data } = await userService.setting(userInfo);
if (data.retcode === 0) {
if (data.code === 0) {
message.success(t('message.modified')); message.success(t('message.modified'));
queryClient.invalidateQueries({ queryKey: ['userInfo'] }); queryClient.invalidateQueries({ queryKey: ['userInfo'] });
} }
return data?.retcode;
return data?.code;
}, },
}); });


try { try {
setLoading(true); setLoading(true);
const { data } = await userService.getSystemVersion(); const { data } = await userService.getSystemVersion();
if (data.retcode === 0) {
if (data.code === 0) {
setVersion(data.data); setVersion(data.data);
setLoading(false); setLoading(false);
} }
const fetchSystemStatus = useCallback(async () => { const fetchSystemStatus = useCallback(async () => {
setLoading(true); setLoading(true);
const { data } = await userService.getSystemStatus(); const { data } = await userService.getSystemStatus();
if (data.retcode === 0) {
if (data.code === 0) {
setSystemStatus(data.data); setSystemStatus(data.data);
setLoading(false); setLoading(false);
} }
mutationKey: ['removeSystemToken'], mutationKey: ['removeSystemToken'],
mutationFn: async (token: string) => { mutationFn: async (token: string) => {
const { data } = await userService.removeToken({}, token); const { data } = await userService.removeToken({}, token);
if (data.retcode === 0) {
if (data.code === 0) {
message.success(t('message.deleted')); message.success(t('message.deleted'));
queryClient.invalidateQueries({ queryKey: ['fetchSystemTokenList'] }); queryClient.invalidateQueries({ queryKey: ['fetchSystemTokenList'] });
} }
mutationKey: ['createSystemToken'], mutationKey: ['createSystemToken'],
mutationFn: async (params: Record<string, any>) => { mutationFn: async (params: Record<string, any>) => {
const { data } = await userService.createToken(params); const { data } = await userService.createToken(params);
if (data.retcode === 0) {
if (data.code === 0) {
queryClient.invalidateQueries({ queryKey: ['fetchSystemTokenList'] }); queryClient.invalidateQueries({ queryKey: ['fetchSystemTokenList'] });
} }
return data?.data ?? []; return data?.data ?? [];
mutationKey: ['addTenantUser'], mutationKey: ['addTenantUser'],
mutationFn: async (email: string) => { mutationFn: async (email: string) => {
const { data } = await addTenantUser(tenantInfo.tenant_id, email); const { data } = await addTenantUser(tenantInfo.tenant_id, email);
if (data.retcode === 0) {
if (data.code === 0) {
queryClient.invalidateQueries({ queryKey: ['listTenantUser'] }); queryClient.invalidateQueries({ queryKey: ['listTenantUser'] });
} }
return data?.retcode;
return data?.code;
}, },
}); });


tenantId: tenantId ?? tenantInfo.tenant_id, tenantId: tenantId ?? tenantInfo.tenant_id,
userId, userId,
}); });
if (data.retcode === 0) {
if (data.code === 0) {
message.success(t('message.deleted')); message.success(t('message.deleted'));
queryClient.invalidateQueries({ queryKey: ['listTenantUser'] }); queryClient.invalidateQueries({ queryKey: ['listTenantUser'] });
queryClient.invalidateQueries({ queryKey: ['listTenant'] }); queryClient.invalidateQueries({ queryKey: ['listTenant'] });
mutationKey: ['agreeTenant'], mutationKey: ['agreeTenant'],
mutationFn: async (tenantId: string) => { mutationFn: async (tenantId: string) => {
const { data } = await agreeTenant(tenantId); const { data } = await agreeTenant(tenantId);
if (data.retcode === 0) {
if (data.code === 0) {
message.success(t('message.operated')); message.success(t('message.operated'));
queryClient.invalidateQueries({ queryKey: ['listTenant'] }); queryClient.invalidateQueries({ queryKey: ['listTenant'] });
} }

+ 2
- 2
web/src/interfaces/database/base.ts 查看文件

export interface ResponseType<T = any> { export interface ResponseType<T = any> {
retcode: number;
code: number;
data: T; data: T;
retmsg: string;
message: string;
status: number; status: number;
} }



+ 1
- 1
web/src/pages/add-knowledge/components/knowledge-chunk/components/chunk-creating-modal/index.tsx 查看文件

const { t } = useTranslation(); const { t } = useTranslation();


useEffect(() => { useEffect(() => {
if (data?.retcode === 0) {
if (data?.code === 0) {
const { content_with_weight, important_kwd = [] } = data.data; const { content_with_weight, important_kwd = [] } = data.data;
form.setFieldsValue({ content: content_with_weight }); form.setFieldsValue({ content: content_with_weight });
setKeywords(important_kwd); setKeywords(important_kwd);

+ 2
- 2
web/src/pages/add-knowledge/components/knowledge-chunk/hooks.ts 查看文件



const onChunkUpdatingOk = useCallback( const onChunkUpdatingOk = useCallback(
async ({ content, keywords }: { content: string; keywords: string }) => { async ({ content, keywords }: { content: string; keywords: string }) => {
const retcode = await createChunk({
const code = await createChunk({
content_with_weight: content, content_with_weight: content,
doc_id: documentId, doc_id: documentId,
chunk_id: chunkId, chunk_id: chunkId,
important_kwd: keywords, // keywords important_kwd: keywords, // keywords
}); });


if (retcode === 0) {
if (code === 0) {
hideChunkUpdatingModal(); hideChunkUpdatingModal();
} }
}, },

+ 7
- 7
web/src/pages/add-knowledge/components/knowledge-file/hooks.ts 查看文件

async (fileList: UploadFile[]): Promise<number | undefined> => { async (fileList: UploadFile[]): Promise<number | undefined> => {
if (fileList.length > 0) { if (fileList.length > 0) {
const ret: any = await uploadDocument(fileList); const ret: any = await uploadDocument(fileList);
if (typeof ret?.retmsg !== 'string') {
if (typeof ret?.message !== 'string') {
return; return;
} }
const count = getUnSupportedFilesCount(ret?.retmsg);
const count = getUnSupportedFilesCount(ret?.message);
/// 500 error code indicates that some file types are not supported /// 500 error code indicates that some file types are not supported
let retcode = ret?.retcode;
let code = ret?.code;
if ( if (
ret?.retcode === 0 ||
(ret?.retcode === 500 && count !== fileList.length) // Some files were not uploaded successfully, but some were uploaded successfully.
ret?.code === 0 ||
(ret?.code === 500 && count !== fileList.length) // Some files were not uploaded successfully, but some were uploaded successfully.
) { ) {
retcode = 0;
code = 0;
hideDocumentUploadModal(); hideDocumentUploadModal();
} }
return retcode;
return code;
} }
}, },
[uploadDocument, hideDocumentUploadModal], [uploadDocument, hideDocumentUploadModal],

+ 5
- 5
web/src/pages/chat/hooks.ts 查看文件

async (dialogId?: string) => { async (dialogId?: string) => {
if (dialogId) { if (dialogId) {
const ret = await fetchDialog(dialogId); const ret = await fetchDialog(dialogId);
if (ret.retcode === 0) {
if (ret.code === 0) {
setDialog(ret.data); setDialog(ret.data);
} }
} }
controller, controller,
); );


if (res && (res?.response.status !== 200 || res?.data?.retcode !== 0)) {
if (res && (res?.response.status !== 200 || res?.data?.code !== 0)) {
// cancel loading // cancel loading
setValue(message.content); setValue(message.content);
console.info('removeLatestMessage111'); console.info('removeLatestMessage111');
true, true,
conversationId, conversationId,
); );
if (data.retcode === 0) {
if (data.code === 0) {
setConversationIsNew(''); setConversationIsNew('');
const id = data.data.id; const id = data.data.id;
// currentConversationIdRef.current = id; // currentConversationIdRef.current = id;
is_new: false, is_new: false,
}); });


if (ret.retcode === 0) {
if (ret.code === 0) {
hideConversationRenameModal(); hideConversationRenameModal();
} }
}, },
const handleShowConversationRenameModal = useCallback( const handleShowConversationRenameModal = useCallback(
async (conversationId: string) => { async (conversationId: string) => {
const ret = await fetchConversation(conversationId); const ret = await fetchConversation(conversationId);
if (ret.retcode === 0) {
if (ret.code === 0) {
setConversation(ret.data); setConversation(ret.data);
} }
showConversationRenameModal(); showConversationRenameModal();

+ 2
- 2
web/src/pages/chat/shared-hooks.ts 查看文件

messages: [...(derivedMessages ?? []), message], messages: [...(derivedMessages ?? []), message],
}); });


if (res && (res?.response.status !== 200 || res?.data?.retcode !== 0)) {
if (res && (res?.response.status !== 200 || res?.data?.code !== 0)) {
// cancel loading // cancel loading
setValue(message.content); setValue(message.content);
removeLatestMessage(); removeLatestMessage();
sendMessage(message); sendMessage(message);
} else { } else {
const data = await setConversation('user id'); const data = await setConversation('user id');
if (data.retcode === 0) {
if (data.code === 0) {
const id = data.data.id; const id = data.data.id;
sendMessage(message, id); sendMessage(message, id);
} }

+ 2
- 2
web/src/pages/document-viewer/hooks.ts 查看文件

const fetchDocument = useCallback(async () => { const fetchDocument = useCallback(async () => {
const ret = await axios.get(api); const ret = await axios.get(api);
const { data } = ret; const { data } = ret;
if (!(data instanceof ArrayBuffer) && data.retcode !== 0) {
setError(data.retmsg);
if (!(data instanceof ArrayBuffer) && data.code !== 0) {
setError(data.message);
} }
return ret; return ret;
}, [api]); }, [api]);

+ 2
- 2
web/src/pages/file-manager/hooks.ts 查看文件

const handleRemoveFile = () => { const handleRemoveFile = () => {
showDeleteConfirm({ showDeleteConfirm({
onOk: async () => { onOk: async () => {
const retcode = await removeDocument({ fileIds, parentId });
if (retcode === 0) {
const code = await removeDocument({ fileIds, parentId });
if (code === 0) {
setSelectedRowKeys([]); setSelectedRowKeys([]);
} }
return; return;

+ 1
- 1
web/src/pages/file-manager/move-file-modal/async-tree-select.tsx 查看文件

const onLoadData: TreeSelectProps['loadData'] = useCallback( const onLoadData: TreeSelectProps['loadData'] = useCallback(
async ({ id }) => { async ({ id }) => {
const ret = await fetchList(id); const ret = await fetchList(id);
if (ret.retcode === 0) {
if (ret.code === 0) {
setTreeData((tree) => { setTreeData((tree) => {
return tree.concat( return tree.concat(
ret.data.files ret.data.files

+ 2
- 2
web/src/pages/flow/chat/hooks.ts 查看文件

const res = await send(params); const res = await send(params);


if (receiveMessageError(res)) { if (receiveMessageError(res)) {
antMessage.error(res?.data?.retmsg);
antMessage.error(res?.data?.message);


// cancel loading // cancel loading
setValue(message.content); setValue(message.content);
const res = await send(params); const res = await send(params);


if (receiveMessageError(res)) { if (receiveMessageError(res)) {
antMessage.error(res?.data?.retmsg);
antMessage.error(res?.data?.message);


// cancel loading // cancel loading
setValue(message.content); setValue(message.content);

+ 3
- 3
web/src/pages/flow/hooks.ts 查看文件

const { send } = useSendMessageWithSse(api.runCanvas); const { send } = useSendMessageWithSse(api.runCanvas);
const handleRun = useCallback(async () => { const handleRun = useCallback(async () => {
const saveRet = await saveGraph(); const saveRet = await saveGraph();
if (saveRet?.retcode === 0) {
if (saveRet?.code === 0) {
// Call the reset api before opening the run drawer each time // Call the reset api before opening the run drawer each time
const resetRet = await resetFlow(); const resetRet = await resetFlow();
// After resetting, all previous messages will be cleared. // After resetting, all previous messages will be cleared.
if (resetRet?.retcode === 0) {
if (resetRet?.code === 0) {
// fetch prologue // fetch prologue
const sendRet = await send({ id }); const sendRet = await send({ id });
if (receiveMessageError(sendRet)) { if (receiveMessageError(sendRet)) {
message.error(sendRet?.data?.retmsg);
message.error(sendRet?.data?.message);
} else { } else {
refetch(); refetch();
show(); show();

+ 1
- 1
web/src/pages/flow/list/hooks.ts 查看文件

// }, // },
}); });


if (ret?.retcode === 0) {
if (ret?.code === 0) {
hideFlowSettingModal(); hideFlowSettingModal();
navigate(`/flow/${ret.data.id}`); navigate(`/flow/${ret.data.id}`);
} }

+ 1
- 1
web/src/pages/flow/utils.ts 查看文件

}; };


export const receiveMessageError = (res: any) => export const receiveMessageError = (res: any) =>
res && (res?.response.status !== 200 || res?.data?.retcode !== 0);
res && (res?.response.status !== 200 || res?.data?.code !== 0);


// Replace the id in the object with text // Replace the id in the object with text
export const replaceIdWithText = ( export const replaceIdWithText = (

+ 1
- 1
web/src/pages/knowledge/hooks.ts 查看文件

name, name,
}); });


if (ret?.retcode === 0) {
if (ret?.code === 0) {
hideModal(); hideModal();
navigate( navigate(
`/knowledge/${KnowledgeRouteKey.Configuration}?id=${ret.data.kb_id}`, `/knowledge/${KnowledgeRouteKey.Configuration}?id=${ret.data.kb_id}`,

+ 4
- 4
web/src/pages/login/index.tsx 查看文件

const rsaPassWord = rsaPsw(params.password) as string; const rsaPassWord = rsaPsw(params.password) as string;


if (title === 'login') { if (title === 'login') {
const retcode = await login({
const code = await login({
email: params.email, email: params.email,
password: rsaPassWord, password: rsaPassWord,
}); });
if (retcode === 0) {
if (code === 0) {
navigate('/knowledge'); navigate('/knowledge');
} }
} else { } else {
const retcode = await register({
const code = await register({
nickname: params.nickname, nickname: params.nickname,
email: params.email, email: params.email,
password: rsaPassWord, password: rsaPassWord,
}); });
if (retcode === 0) {
if (code === 0) {
setTitle('login'); setTitle('login');
} }
} }

+ 4
- 4
web/src/pages/user-setting/setting-team/hooks.ts 查看文件



const handleAddUserOk = useCallback( const handleAddUserOk = useCallback(
async (email: string) => { async (email: string) => {
const retcode = await addTenantUser(email);
if (retcode === 0) {
const code = await addTenantUser(email);
if (code === 0) {
hideAddingTenantModal(); hideAddingTenantModal();
} }
}, },
const handleDeleteTenantUser = (userId: string) => () => { const handleDeleteTenantUser = (userId: string) => () => {
showDeleteConfirm({ showDeleteConfirm({
onOk: async () => { onOk: async () => {
const retcode = await deleteTenantUser({ userId });
if (retcode === 0) {
const code = await deleteTenantUser({ userId });
if (code === 0) {
} }
return; return;
}, },

+ 8
- 8
web/src/utils/request.ts 查看文件



const data: ResponseType = await response.clone().json(); const data: ResponseType = await response.clone().json();


if (data.retcode === 401 || data.retcode === 401) {
if (data.code === 401 || data.code === 401) {
notification.error({ notification.error({
message: data.retmsg,
description: data.retmsg,
message: data.message,
description: data.message,
duration: 3, duration: 3,
}); });
authorizationUtil.removeAll(); authorizationUtil.removeAll();
history.push('/login'); // Will not jump to the login page history.push('/login'); // Will not jump to the login page
} else if (data.retcode !== 0) {
if (data.retcode === 100) {
message.error(data.retmsg);
} else if (data.code !== 0) {
if (data.code === 100) {
message.error(data.message);
} else { } else {
notification.error({ notification.error({
message: `${i18n.t('message.hint')} : ${data.retcode}`,
description: data.retmsg,
message: `${i18n.t('message.hint')} : ${data.code}`,
description: data.message,
duration: 3, duration: 3,
}); });
} }

Loading…
取消
儲存