chore: merge main

This commit is contained in:
Joel 2024-02-19 15:52:51 +08:00
commit c6f1900a93
525 changed files with 7810 additions and 3203 deletions

30
.github/pull_request_template.md vendored Normal file
View File

@ -0,0 +1,30 @@
# Description
Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. List any dependencies that are required for this change.
Fixes # (issue)
## Type of Change
Please delete options that are not relevant.
- [ ] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
- [ ] This change requires a documentation update, included: [Dify Document](https://github.com/langgenius/dify-docs)
# How Has This Been Tested?
Please describe the tests that you ran to verify your changes. Provide instructions so we can reproduce. Please also list any relevant details for your test configuration
- [ ] TODO
# Suggested Checklist:
- [ ] I have performed a self-review of my own code
- [ ] I have commented my code, particularly in hard-to-understand areas
- [ ] My changes generate no new warnings
- [ ] I ran `dev/reformat`(backend) and `cd web && npx lint-staged`(frontend) to appease the lint gods
- [ ] `optional` I have made corresponding changes to the documentation
- [ ] `optional` I have added tests that prove my fix is effective or that my feature works
- [ ] `optional` New and existing unit tests pass locally with my changes

View File

@ -10,9 +10,33 @@ concurrency:
cancel-in-progress: true cancel-in-progress: true
jobs: jobs:
python-style:
name: Python Style
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.10'
- name: Python dependencies
run: pip install ruff
- name: Ruff check
run: ruff check ./api
- name: Lint hints
if: failure()
run: echo "Please run 'dev/reformat' to fix the fixable linting errors."
test: test:
name: ESLint and SuperLinter name: ESLint and SuperLinter
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: python-style
steps: steps:
- name: Checkout code - name: Checkout code

34
.github/workflows/tool-test-sdks.yaml vendored Normal file
View File

@ -0,0 +1,34 @@
name: Run Unit Test For SDKs
on:
pull_request:
branches:
- main
jobs:
build:
name: unit test for Node.js SDK
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [16, 18, 20]
defaults:
run:
working-directory: sdks/nodejs-client
steps:
- uses: actions/checkout@v4
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: ''
cache-dependency-path: 'yarn.lock'
- name: Install Dependencies
run: yarn install
- name: Test
run: yarn test

View File

@ -81,11 +81,17 @@ UPLOAD_IMAGE_FILE_SIZE_LIMIT=10
# Model Configuration # Model Configuration
MULTIMODAL_SEND_IMAGE_FORMAT=base64 MULTIMODAL_SEND_IMAGE_FORMAT=base64
# Mail configuration, support: resend # Mail configuration, support: resend, smtp
MAIL_TYPE= MAIL_TYPE=resend
MAIL_DEFAULT_SEND_FROM=no-reply <no-reply@dify.ai> MAIL_DEFAULT_SEND_FROM=no-reply <no-reply@dify.ai>
RESEND_API_KEY= RESEND_API_KEY=
RESEND_API_URL=https://api.resend.com RESEND_API_URL=https://api.resend.com
# smtp configuration
SMTP_SERVER=smtp.gmail.com
SMTP_PORT=587
SMTP_USERNAME=123
SMTP_PASSWORD=abc
SMTP_USE_TLS=false
# Sentry configuration # Sentry configuration
SENTRY_DSN= SENTRY_DSN=
@ -120,4 +126,7 @@ HOSTED_ANTHROPIC_QUOTA_LIMIT=600000
HOSTED_ANTHROPIC_PAID_ENABLED=false HOSTED_ANTHROPIC_PAID_ENABLED=false
ETL_TYPE=dify ETL_TYPE=dify
UNSTRUCTURED_API_URL= UNSTRUCTURED_API_URL=
SSRF_PROXY_HTTP_URL=
SSRF_PROXY_HTTPS_URL=

View File

@ -1,4 +1,3 @@
# -*- coding:utf-8 -*-
import os import os
from werkzeug.exceptions import Unauthorized from werkzeug.exceptions import Unauthorized
@ -19,18 +18,28 @@ import threading
import time import time
import warnings import warnings
from commands import register_commands
from config import CloudEditionConfig, Config
from events import event_handlers
from extensions import (ext_celery, ext_code_based_extension, ext_database, ext_hosting_provider, ext_login, ext_mail,
ext_migrate, ext_redis, ext_sentry, ext_storage)
from extensions.ext_database import db
from extensions.ext_login import login_manager
from flask import Flask, Response, request from flask import Flask, Response, request
from flask_cors import CORS from flask_cors import CORS
from commands import register_commands
from config import CloudEditionConfig, Config
from extensions import (
ext_celery,
ext_code_based_extension,
ext_database,
ext_hosting_provider,
ext_login,
ext_mail,
ext_migrate,
ext_redis,
ext_sentry,
ext_storage,
)
from extensions.ext_database import db
from extensions.ext_login import login_manager
from libs.passport import PassportService from libs.passport import PassportService
# DO NOT REMOVE BELOW # DO NOT REMOVE BELOW
from models import account, dataset, model, source, task, tool, tools, web
from services.account_service import AccountService from services.account_service import AccountService
# DO NOT REMOVE ABOVE # DO NOT REMOVE ABOVE

View File

@ -3,11 +3,13 @@ import json
import secrets import secrets
import click import click
from flask import current_app
from werkzeug.exceptions import NotFound
from core.embedding.cached_embedding import CacheEmbedding from core.embedding.cached_embedding import CacheEmbedding
from core.model_manager import ModelManager from core.model_manager import ModelManager
from core.model_runtime.entities.model_entities import ModelType from core.model_runtime.entities.model_entities import ModelType
from extensions.ext_database import db from extensions.ext_database import db
from flask import current_app
from libs.helper import email as email_validate from libs.helper import email as email_validate
from libs.password import hash_password, password_pattern, valid_password from libs.password import hash_password, password_pattern, valid_password
from libs.rsa import generate_key_pair from libs.rsa import generate_key_pair
@ -15,7 +17,6 @@ from models.account import Tenant
from models.dataset import Dataset from models.dataset import Dataset
from models.model import Account from models.model import Account
from models.provider import Provider, ProviderModel from models.provider import Provider, ProviderModel
from werkzeug.exceptions import NotFound
@click.command('reset-password', help='Reset the account password.') @click.command('reset-password', help='Reset the account password.')

View File

@ -1,4 +1,3 @@
# -*- coding:utf-8 -*-
import os import os
import dotenv import dotenv
@ -87,7 +86,7 @@ class Config:
# ------------------------ # ------------------------
# General Configurations. # General Configurations.
# ------------------------ # ------------------------
self.CURRENT_VERSION = "0.5.3" self.CURRENT_VERSION = "0.5.5"
self.COMMIT_SHA = get_env('COMMIT_SHA') self.COMMIT_SHA = get_env('COMMIT_SHA')
self.EDITION = "SELF_HOSTED" self.EDITION = "SELF_HOSTED"
self.DEPLOY_ENV = get_env('DEPLOY_ENV') self.DEPLOY_ENV = get_env('DEPLOY_ENV')
@ -209,6 +208,12 @@ class Config:
self.MAIL_DEFAULT_SEND_FROM = get_env('MAIL_DEFAULT_SEND_FROM') self.MAIL_DEFAULT_SEND_FROM = get_env('MAIL_DEFAULT_SEND_FROM')
self.RESEND_API_KEY = get_env('RESEND_API_KEY') self.RESEND_API_KEY = get_env('RESEND_API_KEY')
self.RESEND_API_URL = get_env('RESEND_API_URL') self.RESEND_API_URL = get_env('RESEND_API_URL')
# SMTP settings
self.SMTP_SERVER = get_env('SMTP_SERVER')
self.SMTP_PORT = get_env('SMTP_PORT')
self.SMTP_USERNAME = get_env('SMTP_USERNAME')
self.SMTP_PASSWORD = get_env('SMTP_PASSWORD')
self.SMTP_USE_TLS = get_bool_env('SMTP_USE_TLS')
# ------------------------ # ------------------------
# Workpace Configurations. # Workpace Configurations.

View File

@ -1,9 +1,8 @@
import json import json
from models.model import AppModelConfig from models.model import AppModelConfig
languages = ['en-US', 'zh-Hans', 'pt-BR', 'es-ES', 'fr-FR', 'de-DE', 'ja-JP', 'ko-KR', 'ru-RU', 'it-IT'] languages = ['en-US', 'zh-Hans', 'pt-BR', 'es-ES', 'fr-FR', 'de-DE', 'ja-JP', 'ko-KR', 'ru-RU', 'it-IT', 'uk-UA']
language_timezone_mapping = { language_timezone_mapping = {
'en-US': 'America/New_York', 'en-US': 'America/New_York',
@ -16,8 +15,10 @@ language_timezone_mapping = {
'ko-KR': 'Asia/Seoul', 'ko-KR': 'Asia/Seoul',
'ru-RU': 'Europe/Moscow', 'ru-RU': 'Europe/Moscow',
'it-IT': 'Europe/Rome', 'it-IT': 'Europe/Rome',
'uk-UA': 'Europe/Kyiv',
} }
def supported_language(lang): def supported_language(lang):
if lang in languages: if lang in languages:
return lang return lang
@ -26,6 +27,7 @@ def supported_language(lang):
.format(lang=lang)) .format(lang=lang))
raise ValueError(error) raise ValueError(error)
user_input_form_template = { user_input_form_template = {
"en-US": [ "en-US": [
{ {
@ -67,6 +69,16 @@ user_input_form_template = {
} }
} }
], ],
"ua-UK": [
{
"paragraph": {
"label": "Запит",
"variable": "default_input",
"required": False,
"default": ""
}
}
],
} }
demo_model_templates = { demo_model_templates = {
@ -145,7 +157,7 @@ demo_model_templates = {
'Italian', 'Italian',
] ]
} }
},{ }, {
"paragraph": { "paragraph": {
"label": "Query", "label": "Query",
"variable": "query", "variable": "query",
@ -272,7 +284,7 @@ demo_model_templates = {
"意大利语", "意大利语",
] ]
} }
},{ }, {
"paragraph": { "paragraph": {
"label": "文本内容", "label": "文本内容",
"variable": "query", "variable": "query",
@ -323,5 +335,130 @@ demo_model_templates = {
) )
} }
], ],
'uk-UA': [{
"name": "Помічник перекладу",
"icon": "",
"icon_background": "",
"description": "Багатомовний перекладач, який надає можливості перекладу різними мовами, перекладаючи введені користувачем дані на потрібну мову.",
"mode": "completion",
"model_config": AppModelConfig(
provider="openai",
model_id="gpt-3.5-turbo-instruct",
configs={
"prompt_template": "Будь ласка, перекладіть наступний текст на {{target_language}}:\n",
"prompt_variables": [
{
"key": "target_language",
"name": "Цільова мова",
"description": "Мова, на яку ви хочете перекласти.",
"type": "select",
"default": "Ukrainian",
"options": [
"Chinese",
"English",
"Japanese",
"French",
"Russian",
"German",
"Spanish",
"Korean",
"Italian",
],
},
],
"completion_params": {
"max_token": 1000,
"temperature": 0,
"top_p": 0,
"presence_penalty": 0.1,
"frequency_penalty": 0.1,
},
},
opening_statement="",
suggested_questions=None,
pre_prompt="Будь ласка, перекладіть наступний текст на {{target_language}}:\n{{query}}\ntranslate:",
model=json.dumps({
"provider": "openai",
"name": "gpt-3.5-turbo-instruct",
"mode": "completion",
"completion_params": {
"max_tokens": 1000,
"temperature": 0,
"top_p": 0,
"presence_penalty": 0.1,
"frequency_penalty": 0.1,
},
}),
user_input_form=json.dumps([
{
"select": {
"label": "Цільова мова",
"variable": "target_language",
"description": "Мова, на яку ви хочете перекласти.",
"default": "Chinese",
"required": True,
'options': [
'Chinese',
'English',
'Japanese',
'French',
'Russian',
'German',
'Spanish',
'Korean',
'Italian',
]
}
}, {
"paragraph": {
"label": "Запит",
"variable": "query",
"required": True,
"default": ""
}
}
])
)
},
{
"name": "AI інтерв’юер фронтенду",
"icon": "",
"icon_background": "",
"description": "Симульований інтерв’юер фронтенду, який перевіряє рівень кваліфікації у розробці фронтенду через опитування.",
"mode": "chat",
"model_config": AppModelConfig(
provider="openai",
model_id="gpt-3.5-turbo",
configs={
"introduction": "Привіт, ласкаво просимо на наше співбесіду. Я інтерв'юер цієї технологічної компанії, і я перевірю ваші навички веб-розробки фронтенду. Далі я поставлю вам декілька технічних запитань. Будь ласка, відповідайте якомога ретельніше. ",
"prompt_template": "Ви будете грати роль інтерв'юера технологічної компанії, перевіряючи навички розробки фронтенду користувача та ставлячи 5-10 чітких технічних питань.\n\nЗверніть увагу:\n- Ставте лише одне запитання за раз.\n- Після того, як користувач відповість на запитання, ставте наступне запитання безпосередньо, не намагаючись виправити будь-які помилки, допущені кандидатом.\n- Якщо ви вважаєте, що користувач не відповів правильно на кілька питань поспіль, задайте менше запитань.\n- Після того, як ви задали останнє запитання, ви можете поставити таке запитання: Чому ви залишили свою попередню роботу? Після того, як користувач відповість на це питання, висловіть своє розуміння та підтримку.\n",
"prompt_variables": [],
"completion_params": {
"max_token": 300,
"temperature": 0.8,
"top_p": 0.9,
"presence_penalty": 0.1,
"frequency_penalty": 0.1,
},
},
opening_statement="Привіт, ласкаво просимо на наше співбесіду. Я інтерв'юер цієї технологічної компанії, і я перевірю ваші навички веб-розробки фронтенду. Далі я поставлю вам декілька технічних запитань. Будь ласка, відповідайте якомога ретельніше. ",
suggested_questions=None,
pre_prompt="Ви будете грати роль інтерв'юера технологічної компанії, перевіряючи навички розробки фронтенду користувача та ставлячи 5-10 чітких технічних питань.\n\nЗверніть увагу:\n- Ставте лише одне запитання за раз.\n- Після того, як користувач відповість на запитання, ставте наступне запитання безпосередньо, не намагаючись виправити будь-які помилки, допущені кандидатом.\n- Якщо ви вважаєте, що користувач не відповів правильно на кілька питань поспіль, задайте менше запитань.\n- Після того, як ви задали останнє запитання, ви можете поставити таке запитання: Чому ви залишили свою попередню роботу? Після того, як користувач відповість на це питання, висловіть своє розуміння та підтримку.\n",
model=json.dumps({
"provider": "openai",
"name": "gpt-3.5-turbo",
"mode": "chat",
"completion_params": {
"max_tokens": 300,
"temperature": 0.8,
"top_p": 0.9,
"presence_penalty": 0.1,
"frequency_penalty": 0.1,
},
}),
user_input_form=None
),
}
],
} }

View File

@ -1,7 +1,5 @@
import json import json
from models.model import App, AppModelConfig
model_templates = { model_templates = {
# completion default mode # completion default mode
'completion_default': { 'completion_default': {

View File

@ -1,14 +1,15 @@
import os import os
from functools import wraps from functools import wraps
from flask import request
from flask_restful import Resource, reqparse
from werkzeug.exceptions import NotFound, Unauthorized
from constants.languages import supported_language from constants.languages import supported_language
from controllers.console import api from controllers.console import api
from controllers.console.wraps import only_edition_cloud from controllers.console.wraps import only_edition_cloud
from extensions.ext_database import db from extensions.ext_database import db
from flask import request
from flask_restful import Resource, reqparse
from models.model import App, InstalledApp, RecommendedApp from models.model import App, InstalledApp, RecommendedApp
from werkzeug.exceptions import NotFound, Unauthorized
def admin_required(view): def admin_required(view):

View File

@ -1,12 +1,13 @@
import flask_restful import flask_restful
from extensions.ext_database import db
from flask_login import current_user from flask_login import current_user
from flask_restful import Resource, fields, marshal_with from flask_restful import Resource, fields, marshal_with
from werkzeug.exceptions import Forbidden
from extensions.ext_database import db
from libs.helper import TimestampField from libs.helper import TimestampField
from libs.login import login_required from libs.login import login_required
from models.dataset import Dataset from models.dataset import Dataset
from models.model import ApiToken, App from models.model import ApiToken, App
from werkzeug.exceptions import Forbidden
from . import api from . import api
from .setup import setup_required from .setup import setup_required

View File

@ -1,7 +1,8 @@
from flask_restful import Resource, reqparse
from controllers.console import api from controllers.console import api
from controllers.console.setup import setup_required from controllers.console.setup import setup_required
from controllers.console.wraps import account_initialization_required from controllers.console.wraps import account_initialization_required
from flask_restful import Resource, reqparse
from libs.login import login_required from libs.login import login_required
from services.advanced_prompt_template_service import AdvancedPromptTemplateService from services.advanced_prompt_template_service import AdvancedPromptTemplateService

View File

@ -1,17 +1,20 @@
from flask import request
from flask_login import current_user
from flask_restful import Resource, marshal, marshal_with, reqparse
from werkzeug.exceptions import Forbidden
from controllers.console import api from controllers.console import api
from controllers.console.app.error import NoFileUploadedError from controllers.console.app.error import NoFileUploadedError
from controllers.console.datasets.error import TooManyFilesError from controllers.console.datasets.error import TooManyFilesError
from controllers.console.setup import setup_required from controllers.console.setup import setup_required
from controllers.console.wraps import account_initialization_required, cloud_edition_billing_resource_check from controllers.console.wraps import account_initialization_required, cloud_edition_billing_resource_check
from extensions.ext_redis import redis_client from extensions.ext_redis import redis_client
from fields.annotation_fields import (annotation_fields, annotation_hit_history_fields, from fields.annotation_fields import (
annotation_hit_history_list_fields, annotation_list_fields) annotation_fields,
from flask import request annotation_hit_history_fields,
from flask_login import current_user )
from flask_restful import Resource, marshal, marshal_with, reqparse
from libs.login import login_required from libs.login import login_required
from services.annotation_service import AppAnnotationService from services.annotation_service import AppAnnotationService
from werkzeug.exceptions import Forbidden
class AnnotationReplyActionApi(Resource): class AnnotationReplyActionApi(Resource):

View File

@ -1,8 +1,11 @@
# -*- coding:utf-8 -*-
import json import json
import logging import logging
from datetime import datetime from datetime import datetime
from flask_login import current_user
from flask_restful import Resource, abort, inputs, marshal_with, reqparse
from werkzeug.exceptions import Forbidden
from constants.languages import demo_model_templates, languages from constants.languages import demo_model_templates, languages
from constants.model_template import model_templates from constants.model_template import model_templates
from controllers.console import api from controllers.console import api
@ -15,16 +18,15 @@ from core.model_runtime.entities.model_entities import ModelType
from core.provider_manager import ProviderManager from core.provider_manager import ProviderManager
from events.app_event import app_was_created, app_was_deleted from events.app_event import app_was_created, app_was_deleted
from extensions.ext_database import db from extensions.ext_database import db
from fields.app_fields import (app_detail_fields, app_detail_fields_with_site, app_pagination_fields, from fields.app_fields import (
template_list_fields) app_detail_fields,
from flask import current_app app_detail_fields_with_site,
from flask_login import current_user app_pagination_fields,
from flask_restful import Resource, abort, inputs, marshal_with, reqparse template_list_fields,
)
from libs.login import login_required from libs.login import login_required
from models.model import App, AppModelConfig, Site from models.model import App, AppModelConfig, Site
from models.tools import ApiToolProvider
from services.app_model_config_service import AppModelConfigService from services.app_model_config_service import AppModelConfigService
from werkzeug.exceptions import Forbidden
def _get_app(app_id, tenant_id): def _get_app(app_id, tenant_id):
@ -130,8 +132,8 @@ class AppListApi(Resource):
if not model_instance: if not model_instance:
raise ProviderNotInitializeError( raise ProviderNotInitializeError(
f"No Default System Reasoning Model available. Please configure " "No Default System Reasoning Model available. Please configure "
f"in the Settings -> Model Provider.") "in the Settings -> Model Provider.")
else: else:
model_config_dict["model"]["provider"] = model_instance.provider model_config_dict["model"]["provider"] = model_instance.provider
model_config_dict["model"]["name"] = model_instance.model model_config_dict["model"]["name"] = model_instance.model

View File

@ -1,24 +1,35 @@
# -*- coding:utf-8 -*-
import logging import logging
from flask import request
from flask_restful import Resource, reqparse
from werkzeug.exceptions import InternalServerError
import services import services
from controllers.console import api from controllers.console import api
from controllers.console.app import _get_app from controllers.console.app import _get_app
from controllers.console.app.error import (AppUnavailableError, AudioTooLargeError, CompletionRequestError, from controllers.console.app.error import (
NoAudioUploadedError, ProviderModelCurrentlyNotSupportError, AppUnavailableError,
ProviderNotInitializeError, ProviderNotSupportSpeechToTextError, AudioTooLargeError,
ProviderQuotaExceededError, UnsupportedAudioTypeError) CompletionRequestError,
NoAudioUploadedError,
ProviderModelCurrentlyNotSupportError,
ProviderNotInitializeError,
ProviderNotSupportSpeechToTextError,
ProviderQuotaExceededError,
UnsupportedAudioTypeError,
)
from controllers.console.setup import setup_required from controllers.console.setup import setup_required
from controllers.console.wraps import account_initialization_required from controllers.console.wraps import account_initialization_required
from core.errors.error import ModelCurrentlyNotSupportError, ProviderTokenNotInitError, QuotaExceededError from core.errors.error import ModelCurrentlyNotSupportError, ProviderTokenNotInitError, QuotaExceededError
from core.model_runtime.errors.invoke import InvokeError from core.model_runtime.errors.invoke import InvokeError
from flask import request
from flask_restful import Resource
from libs.login import login_required from libs.login import login_required
from services.audio_service import AudioService from services.audio_service import AudioService
from services.errors.audio import (AudioTooLargeServiceError, NoAudioUploadedServiceError, from services.errors.audio import (
ProviderNotSupportSpeechToTextServiceError, UnsupportedAudioTypeServiceError) AudioTooLargeServiceError,
from werkzeug.exceptions import InternalServerError NoAudioUploadedServiceError,
ProviderNotSupportSpeechToTextServiceError,
UnsupportedAudioTypeServiceError,
)
class ChatMessageAudioApi(Resource): class ChatMessageAudioApi(Resource):
@ -34,7 +45,9 @@ class ChatMessageAudioApi(Resource):
try: try:
response = AudioService.transcript_asr( response = AudioService.transcript_asr(
tenant_id=app_model.tenant_id, tenant_id=app_model.tenant_id,
file=file file=file,
end_user=None,
promot=app_model.app_model_config.pre_prompt
) )
return response return response
@ -60,7 +73,7 @@ class ChatMessageAudioApi(Resource):
except ValueError as e: except ValueError as e:
raise e raise e
except Exception as e: except Exception as e:
logging.exception("internal server error.") logging.exception(f"internal server error, {str(e)}.")
raise InternalServerError() raise InternalServerError()
@ -71,10 +84,12 @@ class ChatMessageTextApi(Resource):
def post(self, app_id): def post(self, app_id):
app_id = str(app_id) app_id = str(app_id)
app_model = _get_app(app_id, None) app_model = _get_app(app_id, None)
try: try:
response = AudioService.transcript_tts( response = AudioService.transcript_tts(
tenant_id=app_model.tenant_id, tenant_id=app_model.tenant_id,
text=request.form['text'], text=request.form['text'],
voice=app_model.app_model_config.text_to_speech_dict.get('voice'),
streaming=False streaming=False
) )
@ -101,9 +116,50 @@ class ChatMessageTextApi(Resource):
except ValueError as e: except ValueError as e:
raise e raise e
except Exception as e: except Exception as e:
logging.exception("internal server error.") logging.exception(f"internal server error, {str(e)}.")
raise InternalServerError()
class TextModesApi(Resource):
def get(self, app_id: str):
app_model = _get_app(str(app_id))
try:
parser = reqparse.RequestParser()
parser.add_argument('language', type=str, required=True, location='args')
args = parser.parse_args()
response = AudioService.transcript_tts_voices(
tenant_id=app_model.tenant_id,
language=args['language'],
)
return response
except services.errors.audio.ProviderNotSupportTextToSpeechLanageServiceError:
raise AppUnavailableError("Text to audio voices language parameter loss.")
except NoAudioUploadedServiceError:
raise NoAudioUploadedError()
except AudioTooLargeServiceError as e:
raise AudioTooLargeError(str(e))
except UnsupportedAudioTypeServiceError:
raise UnsupportedAudioTypeError()
except ProviderNotSupportSpeechToTextServiceError:
raise ProviderNotSupportSpeechToTextError()
except ProviderTokenNotInitError as ex:
raise ProviderNotInitializeError(ex.description)
except QuotaExceededError:
raise ProviderQuotaExceededError()
except ModelCurrentlyNotSupportError:
raise ProviderModelCurrentlyNotSupportError()
except InvokeError as e:
raise CompletionRequestError(e.description)
except ValueError as e:
raise e
except Exception as e:
logging.exception(f"internal server error, {str(e)}.")
raise InternalServerError() raise InternalServerError()
api.add_resource(ChatMessageAudioApi, '/apps/<uuid:app_id>/audio-to-text') api.add_resource(ChatMessageAudioApi, '/apps/<uuid:app_id>/audio-to-text')
api.add_resource(ChatMessageTextApi, '/apps/<uuid:app_id>/text-to-audio') api.add_resource(ChatMessageTextApi, '/apps/<uuid:app_id>/text-to-audio')
api.add_resource(TextModesApi, '/apps/<uuid:app_id>/text-to-audio/voices')

View File

@ -1,27 +1,33 @@
# -*- coding:utf-8 -*-
import json import json
import logging import logging
from typing import Generator, Union from collections.abc import Generator
from typing import Union
import flask_login import flask_login
from flask import Response, stream_with_context
from flask_restful import Resource, reqparse
from werkzeug.exceptions import InternalServerError, NotFound
import services import services
from controllers.console import api from controllers.console import api
from controllers.console.app import _get_app from controllers.console.app import _get_app
from controllers.console.app.error import (AppUnavailableError, CompletionRequestError, ConversationCompletedError, from controllers.console.app.error import (
ProviderModelCurrentlyNotSupportError, ProviderNotInitializeError, AppUnavailableError,
ProviderQuotaExceededError) CompletionRequestError,
ConversationCompletedError,
ProviderModelCurrentlyNotSupportError,
ProviderNotInitializeError,
ProviderQuotaExceededError,
)
from controllers.console.setup import setup_required from controllers.console.setup import setup_required
from controllers.console.wraps import account_initialization_required from controllers.console.wraps import account_initialization_required
from core.application_queue_manager import ApplicationQueueManager from core.application_queue_manager import ApplicationQueueManager
from core.entities.application_entities import InvokeFrom from core.entities.application_entities import InvokeFrom
from core.errors.error import ModelCurrentlyNotSupportError, ProviderTokenNotInitError, QuotaExceededError from core.errors.error import ModelCurrentlyNotSupportError, ProviderTokenNotInitError, QuotaExceededError
from core.model_runtime.errors.invoke import InvokeError from core.model_runtime.errors.invoke import InvokeError
from flask import Response, stream_with_context
from flask_restful import Resource, reqparse
from libs.helper import uuid_value from libs.helper import uuid_value
from libs.login import login_required from libs.login import login_required
from services.completion_service import CompletionService from services.completion_service import CompletionService
from werkzeug.exceptions import InternalServerError, NotFound
# define completion message api for user # define completion message api for user
@ -163,8 +169,7 @@ def compact_response(response: Union[dict, Generator]) -> Response:
return Response(response=json.dumps(response), status=200, mimetype='application/json') return Response(response=json.dumps(response), status=200, mimetype='application/json')
else: else:
def generate() -> Generator: def generate() -> Generator:
for chunk in response: yield from response
yield chunk
return Response(stream_with_context(generate()), status=200, return Response(stream_with_context(generate()), status=200,
mimetype='text/event-stream') mimetype='text/event-stream')

View File

@ -1,22 +1,27 @@
from datetime import datetime from datetime import datetime
import pytz import pytz
from flask_login import current_user
from flask_restful import Resource, marshal_with, reqparse
from flask_restful.inputs import int_range
from sqlalchemy import func, or_
from sqlalchemy.orm import joinedload
from werkzeug.exceptions import NotFound
from controllers.console import api from controllers.console import api
from controllers.console.app import _get_app from controllers.console.app import _get_app
from controllers.console.setup import setup_required from controllers.console.setup import setup_required
from controllers.console.wraps import account_initialization_required from controllers.console.wraps import account_initialization_required
from extensions.ext_database import db from extensions.ext_database import db
from fields.conversation_fields import (conversation_detail_fields, conversation_message_detail_fields, from fields.conversation_fields import (
conversation_pagination_fields, conversation_with_summary_pagination_fields) conversation_detail_fields,
from flask_login import current_user conversation_message_detail_fields,
from flask_restful import Resource, marshal_with, reqparse conversation_pagination_fields,
from flask_restful.inputs import int_range conversation_with_summary_pagination_fields,
)
from libs.helper import datetime_string from libs.helper import datetime_string
from libs.login import login_required from libs.login import login_required
from models.model import Conversation, Message, MessageAnnotation from models.model import Conversation, Message, MessageAnnotation
from sqlalchemy import func, or_
from sqlalchemy.orm import joinedload
from werkzeug.exceptions import NotFound
class CompletionConversationApi(Resource): class CompletionConversationApi(Resource):

View File

@ -1,13 +1,18 @@
from flask_login import current_user
from flask_restful import Resource, reqparse
from controllers.console import api from controllers.console import api
from controllers.console.app.error import (CompletionRequestError, ProviderModelCurrentlyNotSupportError, from controllers.console.app.error import (
ProviderNotInitializeError, ProviderQuotaExceededError) CompletionRequestError,
ProviderModelCurrentlyNotSupportError,
ProviderNotInitializeError,
ProviderQuotaExceededError,
)
from controllers.console.setup import setup_required from controllers.console.setup import setup_required
from controllers.console.wraps import account_initialization_required from controllers.console.wraps import account_initialization_required
from core.errors.error import ModelCurrentlyNotSupportError, ProviderTokenNotInitError, QuotaExceededError from core.errors.error import ModelCurrentlyNotSupportError, ProviderTokenNotInitError, QuotaExceededError
from core.generator.llm_generator import LLMGenerator from core.generator.llm_generator import LLMGenerator
from core.model_runtime.errors.invoke import InvokeError from core.model_runtime.errors.invoke import InvokeError
from flask_login import current_user
from flask_restful import Resource, reqparse
from libs.login import login_required from libs.login import login_required

View File

@ -1,12 +1,23 @@
import json import json
import logging import logging
from typing import Generator, Union from collections.abc import Generator
from typing import Union
from flask import Response, stream_with_context
from flask_login import current_user
from flask_restful import Resource, fields, marshal_with, reqparse
from flask_restful.inputs import int_range
from werkzeug.exceptions import Forbidden, InternalServerError, NotFound
from controllers.console import api from controllers.console import api
from controllers.console.app import _get_app from controllers.console.app import _get_app
from controllers.console.app.error import (AppMoreLikeThisDisabledError, CompletionRequestError, from controllers.console.app.error import (
ProviderModelCurrentlyNotSupportError, ProviderNotInitializeError, AppMoreLikeThisDisabledError,
ProviderQuotaExceededError) CompletionRequestError,
ProviderModelCurrentlyNotSupportError,
ProviderNotInitializeError,
ProviderQuotaExceededError,
)
from controllers.console.setup import setup_required from controllers.console.setup import setup_required
from controllers.console.wraps import account_initialization_required, cloud_edition_billing_resource_check from controllers.console.wraps import account_initialization_required, cloud_edition_billing_resource_check
from core.entities.application_entities import InvokeFrom from core.entities.application_entities import InvokeFrom
@ -14,10 +25,6 @@ from core.errors.error import ModelCurrentlyNotSupportError, ProviderTokenNotIni
from core.model_runtime.errors.invoke import InvokeError from core.model_runtime.errors.invoke import InvokeError
from extensions.ext_database import db from extensions.ext_database import db
from fields.conversation_fields import annotation_fields, message_detail_fields from fields.conversation_fields import annotation_fields, message_detail_fields
from flask import Response, stream_with_context
from flask_login import current_user
from flask_restful import Resource, fields, marshal_with, reqparse
from flask_restful.inputs import int_range
from libs.helper import uuid_value from libs.helper import uuid_value
from libs.infinite_scroll_pagination import InfiniteScrollPagination from libs.infinite_scroll_pagination import InfiniteScrollPagination
from libs.login import login_required from libs.login import login_required
@ -28,7 +35,6 @@ from services.errors.app import MoreLikeThisDisabledError
from services.errors.conversation import ConversationNotExistsError from services.errors.conversation import ConversationNotExistsError
from services.errors.message import MessageNotExistsError from services.errors.message import MessageNotExistsError
from services.message_service import MessageService from services.message_service import MessageService
from werkzeug.exceptions import Forbidden, InternalServerError, NotFound
class ChatMessageListApi(Resource): class ChatMessageListApi(Resource):
@ -241,8 +247,7 @@ def compact_response(response: Union[dict, Generator]) -> Response:
return Response(response=json.dumps(response), status=200, mimetype='application/json') return Response(response=json.dumps(response), status=200, mimetype='application/json')
else: else:
def generate() -> Generator: def generate() -> Generator:
for chunk in response: yield from response
yield chunk
return Response(stream_with_context(generate()), status=200, return Response(stream_with_context(generate()), status=200,
mimetype='text/event-stream') mimetype='text/event-stream')

View File

@ -1,4 +1,7 @@
# -*- coding:utf-8 -*-
from flask import request
from flask_login import current_user
from flask_restful import Resource
from controllers.console import api from controllers.console import api
from controllers.console.app import _get_app from controllers.console.app import _get_app
@ -6,9 +9,6 @@ from controllers.console.setup import setup_required
from controllers.console.wraps import account_initialization_required from controllers.console.wraps import account_initialization_required
from events.app_event import app_model_config_was_updated from events.app_event import app_model_config_was_updated
from extensions.ext_database import db from extensions.ext_database import db
from flask import request
from flask_login import current_user
from flask_restful import Resource
from libs.login import login_required from libs.login import login_required
from models.model import AppModelConfig from models.model import AppModelConfig
from services.app_model_config_service import AppModelConfigService from services.app_model_config_service import AppModelConfigService

View File

@ -1,4 +1,7 @@
# -*- coding:utf-8 -*- from flask_login import current_user
from flask_restful import Resource, marshal_with, reqparse
from werkzeug.exceptions import Forbidden, NotFound
from constants.languages import supported_language from constants.languages import supported_language
from controllers.console import api from controllers.console import api
from controllers.console.app import _get_app from controllers.console.app import _get_app
@ -6,11 +9,8 @@ from controllers.console.setup import setup_required
from controllers.console.wraps import account_initialization_required from controllers.console.wraps import account_initialization_required
from extensions.ext_database import db from extensions.ext_database import db
from fields.app_fields import app_site_fields from fields.app_fields import app_site_fields
from flask_login import current_user
from flask_restful import Resource, marshal_with, reqparse
from libs.login import login_required from libs.login import login_required
from models.model import Site from models.model import Site
from werkzeug.exceptions import Forbidden, NotFound
def parse_app_site_args(): def parse_app_site_args():

View File

@ -1,16 +1,16 @@
# -*- coding:utf-8 -*-
from datetime import datetime from datetime import datetime
from decimal import Decimal from decimal import Decimal
import pytz import pytz
from flask import jsonify
from flask_login import current_user
from flask_restful import Resource, reqparse
from controllers.console import api from controllers.console import api
from controllers.console.app import _get_app from controllers.console.app import _get_app
from controllers.console.setup import setup_required from controllers.console.setup import setup_required
from controllers.console.wraps import account_initialization_required from controllers.console.wraps import account_initialization_required
from extensions.ext_database import db from extensions.ext_database import db
from flask import jsonify
from flask_login import current_user
from flask_restful import Resource, reqparse
from libs.helper import datetime_string from libs.helper import datetime_string
from libs.login import login_required from libs.login import login_required

View File

@ -2,14 +2,15 @@ import base64
import secrets import secrets
from datetime import datetime from datetime import datetime
from flask_restful import Resource, reqparse
from constants.languages import supported_language from constants.languages import supported_language
from controllers.console import api from controllers.console import api
from controllers.console.error import AlreadyActivateError from controllers.console.error import AlreadyActivateError
from extensions.ext_database import db from extensions.ext_database import db
from flask_restful import Resource, reqparse
from libs.helper import email, str_len, timezone from libs.helper import email, str_len, timezone
from libs.password import hash_password, valid_password from libs.password import hash_password, valid_password
from models.account import AccountStatus, Tenant from models.account import AccountStatus
from services.account_service import RegisterService from services.account_service import RegisterService

View File

@ -1,13 +1,14 @@
import logging import logging
import requests import requests
from controllers.console import api
from flask import current_app, redirect, request from flask import current_app, redirect, request
from flask_login import current_user from flask_login import current_user
from flask_restful import Resource from flask_restful import Resource
from werkzeug.exceptions import Forbidden
from controllers.console import api
from libs.login import login_required from libs.login import login_required
from libs.oauth_data_source import NotionOAuth from libs.oauth_data_source import NotionOAuth
from werkzeug.exceptions import Forbidden
from ..setup import setup_required from ..setup import setup_required
from ..wraps import account_initialization_required from ..wraps import account_initialization_required

View File

@ -1,14 +1,13 @@
# -*- coding:utf-8 -*-
import flask
import flask_login import flask_login
from flask import current_app, request
from flask_restful import Resource, reqparse
import services import services
from controllers.console import api from controllers.console import api
from controllers.console.setup import setup_required from controllers.console.setup import setup_required
from flask import current_app, request
from flask_restful import Resource, reqparse
from libs.helper import email from libs.helper import email
from libs.password import valid_password from libs.password import valid_password
from services.account_service import AccountService from services.account_service import AccountService, TenantService
class LoginApi(Resource): class LoginApi(Resource):
@ -30,6 +29,8 @@ class LoginApi(Resource):
except services.errors.account.AccountLoginError: except services.errors.account.AccountLoginError:
return {'code': 'unauthorized', 'message': 'Invalid email or password'}, 401 return {'code': 'unauthorized', 'message': 'Invalid email or password'}, 401
TenantService.create_owner_tenant_if_not_exist(account)
AccountService.update_last_login(account, request) AccountService.update_last_login(account, request)
# todo: return the user info # todo: return the user info

View File

@ -3,13 +3,14 @@ from datetime import datetime
from typing import Optional from typing import Optional
import requests import requests
from constants.languages import languages
from extensions.ext_database import db
from flask import current_app, redirect, request from flask import current_app, redirect, request
from flask_restful import Resource from flask_restful import Resource
from constants.languages import languages
from extensions.ext_database import db
from libs.oauth import GitHubOAuth, GoogleOAuth, OAuthUserInfo from libs.oauth import GitHubOAuth, GoogleOAuth, OAuthUserInfo
from models.account import Account, AccountStatus from models.account import Account, AccountStatus
from services.account_service import AccountService, RegisterService from services.account_service import AccountService, RegisterService, TenantService
from .. import api from .. import api
@ -75,6 +76,8 @@ class OAuthCallback(Resource):
account.initialized_at = datetime.utcnow() account.initialized_at = datetime.utcnow()
db.session.commit() db.session.commit()
TenantService.create_owner_tenant_if_not_exist(account)
AccountService.update_last_login(account, request) AccountService.update_last_login(account, request)
token = AccountService.get_account_jwt_token(account) token = AccountService.get_account_jwt_token(account)

View File

@ -1,8 +1,9 @@
from flask_login import current_user
from flask_restful import Resource, reqparse
from controllers.console import api from controllers.console import api
from controllers.console.setup import setup_required from controllers.console.setup import setup_required
from controllers.console.wraps import account_initialization_required, only_edition_cloud from controllers.console.wraps import account_initialization_required, only_edition_cloud
from flask_login import current_user
from flask_restful import Resource, reqparse
from libs.login import login_required from libs.login import login_required
from services.billing_service import BillingService from services.billing_service import BillingService

View File

@ -1,6 +1,11 @@
import datetime import datetime
import json import json
from flask import request
from flask_login import current_user
from flask_restful import Resource, marshal_with, reqparse
from werkzeug.exceptions import NotFound
from controllers.console import api from controllers.console import api
from controllers.console.setup import setup_required from controllers.console.setup import setup_required
from controllers.console.wraps import account_initialization_required from controllers.console.wraps import account_initialization_required
@ -8,15 +13,11 @@ from core.data_loader.loader.notion import NotionLoader
from core.indexing_runner import IndexingRunner from core.indexing_runner import IndexingRunner
from extensions.ext_database import db from extensions.ext_database import db
from fields.data_source_fields import integrate_list_fields, integrate_notion_info_list_fields from fields.data_source_fields import integrate_list_fields, integrate_notion_info_list_fields
from flask import request
from flask_login import current_user
from flask_restful import Resource, marshal_with, reqparse
from libs.login import login_required from libs.login import login_required
from models.dataset import Document from models.dataset import Document
from models.source import DataSourceBinding from models.source import DataSourceBinding
from services.dataset_service import DatasetService, DocumentService from services.dataset_service import DatasetService, DocumentService
from tasks.document_indexing_sync_task import document_indexing_sync_task from tasks.document_indexing_sync_task import document_indexing_sync_task
from werkzeug.exceptions import NotFound
class DataSourceApi(Resource): class DataSourceApi(Resource):

View File

@ -1,5 +1,9 @@
# -*- coding:utf-8 -*-
import flask_restful import flask_restful
from flask import current_app, request
from flask_login import current_user
from flask_restful import Resource, marshal, marshal_with, reqparse
from werkzeug.exceptions import Forbidden, NotFound
import services import services
from controllers.console import api from controllers.console import api
from controllers.console.apikey import api_key_fields, api_key_list from controllers.console.apikey import api_key_fields, api_key_list
@ -15,14 +19,10 @@ from extensions.ext_database import db
from fields.app_fields import related_app_list from fields.app_fields import related_app_list
from fields.dataset_fields import dataset_detail_fields, dataset_query_detail_fields from fields.dataset_fields import dataset_detail_fields, dataset_query_detail_fields
from fields.document_fields import document_status_fields from fields.document_fields import document_status_fields
from flask import current_app, request
from flask_login import current_user
from flask_restful import Resource, marshal, marshal_with, reqparse
from libs.login import login_required from libs.login import login_required
from models.dataset import Dataset, Document, DocumentSegment from models.dataset import Dataset, Document, DocumentSegment
from models.model import ApiToken, UploadFile from models.model import ApiToken, UploadFile
from services.dataset_service import DatasetService, DocumentService from services.dataset_service import DatasetService, DocumentService
from werkzeug.exceptions import Forbidden, NotFound
def _validate_name(name): def _validate_name(name):
@ -287,8 +287,8 @@ class DatasetIndexingEstimateApi(Resource):
args['indexing_technique']) args['indexing_technique'])
except LLMBadRequestError: except LLMBadRequestError:
raise ProviderNotInitializeError( raise ProviderNotInitializeError(
f"No Embedding Model available. Please configure a valid provider " "No Embedding Model available. Please configure a valid provider "
f"in the Settings -> Model Provider.") "in the Settings -> Model Provider.")
except ProviderTokenNotInitError as ex: except ProviderTokenNotInitError as ex:
raise ProviderNotInitializeError(ex.description) raise ProviderNotInitializeError(ex.description)
elif args['info_list']['data_source_type'] == 'notion_import': elif args['info_list']['data_source_type'] == 'notion_import':
@ -303,8 +303,8 @@ class DatasetIndexingEstimateApi(Resource):
args['indexing_technique']) args['indexing_technique'])
except LLMBadRequestError: except LLMBadRequestError:
raise ProviderNotInitializeError( raise ProviderNotInitializeError(
f"No Embedding Model available. Please configure a valid provider " "No Embedding Model available. Please configure a valid provider "
f"in the Settings -> Model Provider.") "in the Settings -> Model Provider.")
except ProviderTokenNotInitError as ex: except ProviderTokenNotInitError as ex:
raise ProviderNotInitializeError(ex.description) raise ProviderNotInitializeError(ex.description)
else: else:

View File

@ -1,36 +1,51 @@
# -*- coding:utf-8 -*-
from datetime import datetime from datetime import datetime
from typing import List
from flask import request
from flask_login import current_user
from flask_restful import Resource, fields, marshal, marshal_with, reqparse
from sqlalchemy import asc, desc
from werkzeug.exceptions import Forbidden, NotFound
import services import services
from controllers.console import api from controllers.console import api
from controllers.console.app.error import (ProviderModelCurrentlyNotSupportError, ProviderNotInitializeError, from controllers.console.app.error import (
ProviderQuotaExceededError) ProviderModelCurrentlyNotSupportError,
from controllers.console.datasets.error import (ArchivedDocumentImmutableError, DocumentAlreadyFinishedError, ProviderNotInitializeError,
DocumentIndexingError, InvalidActionError, InvalidMetadataError) ProviderQuotaExceededError,
)
from controllers.console.datasets.error import (
ArchivedDocumentImmutableError,
DocumentAlreadyFinishedError,
DocumentIndexingError,
InvalidActionError,
InvalidMetadataError,
)
from controllers.console.setup import setup_required from controllers.console.setup import setup_required
from controllers.console.wraps import account_initialization_required, cloud_edition_billing_resource_check from controllers.console.wraps import account_initialization_required, cloud_edition_billing_resource_check
from core.errors.error import (LLMBadRequestError, ModelCurrentlyNotSupportError, ProviderTokenNotInitError, from core.errors.error import (
QuotaExceededError) LLMBadRequestError,
ModelCurrentlyNotSupportError,
ProviderTokenNotInitError,
QuotaExceededError,
)
from core.indexing_runner import IndexingRunner from core.indexing_runner import IndexingRunner
from core.model_manager import ModelManager from core.model_manager import ModelManager
from core.model_runtime.entities.model_entities import ModelType from core.model_runtime.entities.model_entities import ModelType
from core.model_runtime.errors.invoke import InvokeAuthorizationError from core.model_runtime.errors.invoke import InvokeAuthorizationError
from extensions.ext_database import db from extensions.ext_database import db
from extensions.ext_redis import redis_client from extensions.ext_redis import redis_client
from fields.document_fields import (dataset_and_document_fields, document_fields, document_status_fields, from fields.document_fields import (
document_with_segments_fields) dataset_and_document_fields,
from flask import request document_fields,
from flask_login import current_user document_status_fields,
from flask_restful import Resource, fields, marshal, marshal_with, reqparse document_with_segments_fields,
)
from libs.login import login_required from libs.login import login_required
from models.dataset import Dataset, DatasetProcessRule, Document, DocumentSegment from models.dataset import Dataset, DatasetProcessRule, Document, DocumentSegment
from models.model import UploadFile from models.model import UploadFile
from services.dataset_service import DatasetService, DocumentService from services.dataset_service import DatasetService, DocumentService
from sqlalchemy import asc, desc
from tasks.add_document_to_index_task import add_document_to_index_task from tasks.add_document_to_index_task import add_document_to_index_task
from tasks.remove_document_from_index_task import remove_document_from_index_task from tasks.remove_document_from_index_task import remove_document_from_index_task
from werkzeug.exceptions import Forbidden, NotFound
class DocumentResource(Resource): class DocumentResource(Resource):
@ -54,7 +69,7 @@ class DocumentResource(Resource):
return document return document
def get_batch_documents(self, dataset_id: str, batch: str) -> List[Document]: def get_batch_documents(self, dataset_id: str, batch: str) -> list[Document]:
dataset = DatasetService.get_dataset(dataset_id) dataset = DatasetService.get_dataset(dataset_id)
if not dataset: if not dataset:
raise NotFound('Dataset not found.') raise NotFound('Dataset not found.')
@ -279,8 +294,8 @@ class DatasetInitApi(Resource):
) )
except InvokeAuthorizationError: except InvokeAuthorizationError:
raise ProviderNotInitializeError( raise ProviderNotInitializeError(
f"No Embedding Model available. Please configure a valid provider " "No Embedding Model available. Please configure a valid provider "
f"in the Settings -> Model Provider.") "in the Settings -> Model Provider.")
except ProviderTokenNotInitError as ex: except ProviderTokenNotInitError as ex:
raise ProviderNotInitializeError(ex.description) raise ProviderNotInitializeError(ex.description)
@ -355,8 +370,8 @@ class DocumentIndexingEstimateApi(DocumentResource):
'English', dataset_id) 'English', dataset_id)
except LLMBadRequestError: except LLMBadRequestError:
raise ProviderNotInitializeError( raise ProviderNotInitializeError(
f"No Embedding Model available. Please configure a valid provider " "No Embedding Model available. Please configure a valid provider "
f"in the Settings -> Model Provider.") "in the Settings -> Model Provider.")
except ProviderTokenNotInitError as ex: except ProviderTokenNotInitError as ex:
raise ProviderNotInitializeError(ex.description) raise ProviderNotInitializeError(ex.description)
@ -425,8 +440,8 @@ class DocumentBatchIndexingEstimateApi(DocumentResource):
'English', dataset_id) 'English', dataset_id)
except LLMBadRequestError: except LLMBadRequestError:
raise ProviderNotInitializeError( raise ProviderNotInitializeError(
f"No Embedding Model available. Please configure a valid provider " "No Embedding Model available. Please configure a valid provider "
f"in the Settings -> Model Provider.") "in the Settings -> Model Provider.")
except ProviderTokenNotInitError as ex: except ProviderTokenNotInitError as ex:
raise ProviderNotInitializeError(ex.description) raise ProviderNotInitializeError(ex.description)
elif dataset.data_source_type == 'notion_import': elif dataset.data_source_type == 'notion_import':
@ -439,8 +454,8 @@ class DocumentBatchIndexingEstimateApi(DocumentResource):
None, 'English', dataset_id) None, 'English', dataset_id)
except LLMBadRequestError: except LLMBadRequestError:
raise ProviderNotInitializeError( raise ProviderNotInitializeError(
f"No Embedding Model available. Please configure a valid provider " "No Embedding Model available. Please configure a valid provider "
f"in the Settings -> Model Provider.") "in the Settings -> Model Provider.")
except ProviderTokenNotInitError as ex: except ProviderTokenNotInitError as ex:
raise ProviderNotInitializeError(ex.description) raise ProviderNotInitializeError(ex.description)
else: else:

View File

@ -1,8 +1,12 @@
# -*- coding:utf-8 -*-
import uuid import uuid
from datetime import datetime from datetime import datetime
import pandas as pd import pandas as pd
from flask import request
from flask_login import current_user
from flask_restful import Resource, marshal, reqparse
from werkzeug.exceptions import Forbidden, NotFound
import services import services
from controllers.console import api from controllers.console import api
from controllers.console.app.error import ProviderNotInitializeError from controllers.console.app.error import ProviderNotInitializeError
@ -15,16 +19,12 @@ from core.model_runtime.entities.model_entities import ModelType
from extensions.ext_database import db from extensions.ext_database import db
from extensions.ext_redis import redis_client from extensions.ext_redis import redis_client
from fields.segment_fields import segment_fields from fields.segment_fields import segment_fields
from flask import request
from flask_login import current_user
from flask_restful import Resource, marshal, reqparse
from libs.login import login_required from libs.login import login_required
from models.dataset import DocumentSegment from models.dataset import DocumentSegment
from services.dataset_service import DatasetService, DocumentService, SegmentService from services.dataset_service import DatasetService, DocumentService, SegmentService
from tasks.batch_create_segment_to_index_task import batch_create_segment_to_index_task from tasks.batch_create_segment_to_index_task import batch_create_segment_to_index_task
from tasks.disable_segment_from_index_task import disable_segment_from_index_task from tasks.disable_segment_from_index_task import disable_segment_from_index_task
from tasks.enable_segment_to_index_task import enable_segment_to_index_task from tasks.enable_segment_to_index_task import enable_segment_to_index_task
from werkzeug.exceptions import Forbidden, NotFound
class DatasetDocumentSegmentListApi(Resource): class DatasetDocumentSegmentListApi(Resource):
@ -142,8 +142,8 @@ class DatasetDocumentSegmentApi(Resource):
) )
except LLMBadRequestError: except LLMBadRequestError:
raise ProviderNotInitializeError( raise ProviderNotInitializeError(
f"No Embedding Model available. Please configure a valid provider " "No Embedding Model available. Please configure a valid provider "
f"in the Settings -> Model Provider.") "in the Settings -> Model Provider.")
except ProviderTokenNotInitError as ex: except ProviderTokenNotInitError as ex:
raise ProviderNotInitializeError(ex.description) raise ProviderNotInitializeError(ex.description)
@ -233,8 +233,8 @@ class DatasetDocumentSegmentAddApi(Resource):
) )
except LLMBadRequestError: except LLMBadRequestError:
raise ProviderNotInitializeError( raise ProviderNotInitializeError(
f"No Embedding Model available. Please configure a valid provider " "No Embedding Model available. Please configure a valid provider "
f"in the Settings -> Model Provider.") "in the Settings -> Model Provider.")
except ProviderTokenNotInitError as ex: except ProviderTokenNotInitError as ex:
raise ProviderNotInitializeError(ex.description) raise ProviderNotInitializeError(ex.description)
try: try:
@ -285,8 +285,8 @@ class DatasetDocumentSegmentUpdateApi(Resource):
) )
except LLMBadRequestError: except LLMBadRequestError:
raise ProviderNotInitializeError( raise ProviderNotInitializeError(
f"No Embedding Model available. Please configure a valid provider " "No Embedding Model available. Please configure a valid provider "
f"in the Settings -> Model Provider.") "in the Settings -> Model Provider.")
except ProviderTokenNotInitError as ex: except ProviderTokenNotInitError as ex:
raise ProviderNotInitializeError(ex.description) raise ProviderNotInitializeError(ex.description)
# check segment # check segment

View File

@ -1,13 +1,18 @@
import services
from controllers.console import api
from controllers.console.datasets.error import (FileTooLargeError, NoFileUploadedError, TooManyFilesError,
UnsupportedFileTypeError)
from controllers.console.setup import setup_required
from controllers.console.wraps import account_initialization_required
from fields.file_fields import file_fields, upload_config_fields
from flask import current_app, request from flask import current_app, request
from flask_login import current_user from flask_login import current_user
from flask_restful import Resource, marshal_with from flask_restful import Resource, marshal_with
import services
from controllers.console import api
from controllers.console.datasets.error import (
FileTooLargeError,
NoFileUploadedError,
TooManyFilesError,
UnsupportedFileTypeError,
)
from controllers.console.setup import setup_required
from controllers.console.wraps import account_initialization_required
from fields.file_fields import file_fields, upload_config_fields
from libs.login import login_required from libs.login import login_required
from services.file_service import ALLOWED_EXTENSIONS, UNSTRUSTURED_ALLOWED_EXTENSIONS, FileService from services.file_service import ALLOWED_EXTENSIONS, UNSTRUSTURED_ALLOWED_EXTENSIONS, FileService

View File

@ -1,22 +1,31 @@
import logging import logging
from flask_login import current_user
from flask_restful import Resource, marshal, reqparse
from werkzeug.exceptions import Forbidden, InternalServerError, NotFound
import services import services
from controllers.console import api from controllers.console import api
from controllers.console.app.error import (CompletionRequestError, ProviderModelCurrentlyNotSupportError, from controllers.console.app.error import (
ProviderNotInitializeError, ProviderQuotaExceededError) CompletionRequestError,
ProviderModelCurrentlyNotSupportError,
ProviderNotInitializeError,
ProviderQuotaExceededError,
)
from controllers.console.datasets.error import DatasetNotInitializedError, HighQualityDatasetOnlyError from controllers.console.datasets.error import DatasetNotInitializedError, HighQualityDatasetOnlyError
from controllers.console.setup import setup_required from controllers.console.setup import setup_required
from controllers.console.wraps import account_initialization_required from controllers.console.wraps import account_initialization_required
from core.errors.error import (LLMBadRequestError, ModelCurrentlyNotSupportError, ProviderTokenNotInitError, from core.errors.error import (
QuotaExceededError) LLMBadRequestError,
ModelCurrentlyNotSupportError,
ProviderTokenNotInitError,
QuotaExceededError,
)
from core.model_runtime.errors.invoke import InvokeError from core.model_runtime.errors.invoke import InvokeError
from fields.hit_testing_fields import hit_testing_record_fields from fields.hit_testing_fields import hit_testing_record_fields
from flask_login import current_user
from flask_restful import Resource, marshal, reqparse
from libs.login import login_required from libs.login import login_required
from services.dataset_service import DatasetService from services.dataset_service import DatasetService
from services.hit_testing_service import HitTestingService from services.hit_testing_service import HitTestingService
from werkzeug.exceptions import Forbidden, InternalServerError, NotFound
class HitTestingApi(Resource): class HitTestingApi(Resource):
@ -67,8 +76,8 @@ class HitTestingApi(Resource):
raise ProviderModelCurrentlyNotSupportError() raise ProviderModelCurrentlyNotSupportError()
except LLMBadRequestError: except LLMBadRequestError:
raise ProviderNotInitializeError( raise ProviderNotInitializeError(
f"No Embedding Model or Reranking Model available. Please configure a valid provider " "No Embedding Model or Reranking Model available. Please configure a valid provider "
f"in the Settings -> Model Provider.") "in the Settings -> Model Provider.")
except InvokeError as e: except InvokeError as e:
raise CompletionRequestError(e.description) raise CompletionRequestError(e.description)
except ValueError as e: except ValueError as e:

View File

@ -1,21 +1,32 @@
# -*- coding:utf-8 -*-
import logging import logging
from flask import request
from werkzeug.exceptions import InternalServerError
import services import services
from controllers.console import api from controllers.console import api
from controllers.console.app.error import (AppUnavailableError, AudioTooLargeError, CompletionRequestError, from controllers.console.app.error import (
NoAudioUploadedError, ProviderModelCurrentlyNotSupportError, AppUnavailableError,
ProviderNotInitializeError, ProviderNotSupportSpeechToTextError, AudioTooLargeError,
ProviderQuotaExceededError, UnsupportedAudioTypeError) CompletionRequestError,
NoAudioUploadedError,
ProviderModelCurrentlyNotSupportError,
ProviderNotInitializeError,
ProviderNotSupportSpeechToTextError,
ProviderQuotaExceededError,
UnsupportedAudioTypeError,
)
from controllers.console.explore.wraps import InstalledAppResource from controllers.console.explore.wraps import InstalledAppResource
from core.errors.error import ModelCurrentlyNotSupportError, ProviderTokenNotInitError, QuotaExceededError from core.errors.error import ModelCurrentlyNotSupportError, ProviderTokenNotInitError, QuotaExceededError
from core.model_runtime.errors.invoke import InvokeError from core.model_runtime.errors.invoke import InvokeError
from flask import request
from models.model import AppModelConfig from models.model import AppModelConfig
from services.audio_service import AudioService from services.audio_service import AudioService
from services.errors.audio import (AudioTooLargeServiceError, NoAudioUploadedServiceError, from services.errors.audio import (
ProviderNotSupportSpeechToTextServiceError, UnsupportedAudioTypeServiceError) AudioTooLargeServiceError,
from werkzeug.exceptions import InternalServerError NoAudioUploadedServiceError,
ProviderNotSupportSpeechToTextServiceError,
UnsupportedAudioTypeServiceError,
)
class ChatAudioApi(InstalledAppResource): class ChatAudioApi(InstalledAppResource):
@ -74,6 +85,7 @@ class ChatTextApi(InstalledAppResource):
response = AudioService.transcript_tts( response = AudioService.transcript_tts(
tenant_id=app_model.tenant_id, tenant_id=app_model.tenant_id,
text=request.form['text'], text=request.form['text'],
voice=app_model.app_model_config.text_to_speech_dict.get('voice'),
streaming=False streaming=False
) )
return {'data': response.data.decode('latin1')} return {'data': response.data.decode('latin1')}

View File

@ -1,14 +1,24 @@
# -*- coding:utf-8 -*-
import json import json
import logging import logging
from collections.abc import Generator
from datetime import datetime from datetime import datetime
from typing import Generator, Union from typing import Union
from flask import Response, stream_with_context
from flask_login import current_user
from flask_restful import reqparse
from werkzeug.exceptions import InternalServerError, NotFound
import services import services
from controllers.console import api from controllers.console import api
from controllers.console.app.error import (AppUnavailableError, CompletionRequestError, ConversationCompletedError, from controllers.console.app.error import (
ProviderModelCurrentlyNotSupportError, ProviderNotInitializeError, AppUnavailableError,
ProviderQuotaExceededError) CompletionRequestError,
ConversationCompletedError,
ProviderModelCurrentlyNotSupportError,
ProviderNotInitializeError,
ProviderQuotaExceededError,
)
from controllers.console.explore.error import NotChatAppError, NotCompletionAppError from controllers.console.explore.error import NotChatAppError, NotCompletionAppError
from controllers.console.explore.wraps import InstalledAppResource from controllers.console.explore.wraps import InstalledAppResource
from core.application_queue_manager import ApplicationQueueManager from core.application_queue_manager import ApplicationQueueManager
@ -16,12 +26,8 @@ from core.entities.application_entities import InvokeFrom
from core.errors.error import ModelCurrentlyNotSupportError, ProviderTokenNotInitError, QuotaExceededError from core.errors.error import ModelCurrentlyNotSupportError, ProviderTokenNotInitError, QuotaExceededError
from core.model_runtime.errors.invoke import InvokeError from core.model_runtime.errors.invoke import InvokeError
from extensions.ext_database import db from extensions.ext_database import db
from flask import Response, stream_with_context
from flask_login import current_user
from flask_restful import reqparse
from libs.helper import uuid_value from libs.helper import uuid_value
from services.completion_service import CompletionService from services.completion_service import CompletionService
from werkzeug.exceptions import InternalServerError, NotFound
# define completion api for user # define completion api for user
@ -158,8 +164,7 @@ def compact_response(response: Union[dict, Generator]) -> Response:
return Response(response=json.dumps(response), status=200, mimetype='application/json') return Response(response=json.dumps(response), status=200, mimetype='application/json')
else: else:
def generate() -> Generator: def generate() -> Generator:
for chunk in response: yield from response
yield chunk
return Response(stream_with_context(generate()), status=200, return Response(stream_with_context(generate()), status=200,
mimetype='text/event-stream') mimetype='text/event-stream')

View File

@ -1,16 +1,16 @@
# -*- coding:utf-8 -*- from flask_login import current_user
from flask_restful import marshal_with, reqparse
from flask_restful.inputs import int_range
from werkzeug.exceptions import NotFound
from controllers.console import api from controllers.console import api
from controllers.console.explore.error import NotChatAppError from controllers.console.explore.error import NotChatAppError
from controllers.console.explore.wraps import InstalledAppResource from controllers.console.explore.wraps import InstalledAppResource
from fields.conversation_fields import conversation_infinite_scroll_pagination_fields, simple_conversation_fields from fields.conversation_fields import conversation_infinite_scroll_pagination_fields, simple_conversation_fields
from flask_login import current_user from libs.helper import uuid_value
from flask_restful import fields, marshal_with, reqparse
from flask_restful.inputs import int_range
from libs.helper import TimestampField, uuid_value
from services.conversation_service import ConversationService from services.conversation_service import ConversationService
from services.errors.conversation import ConversationNotExistsError, LastConversationNotExistsError from services.errors.conversation import ConversationNotExistsError, LastConversationNotExistsError
from services.web_conversation_service import WebConversationService from services.web_conversation_service import WebConversationService
from werkzeug.exceptions import NotFound
class ConversationListApi(InstalledAppResource): class ConversationListApi(InstalledAppResource):

View File

@ -1,4 +1,3 @@
# -*- coding:utf-8 -*-
from libs.exception import BaseHTTPException from libs.exception import BaseHTTPException

View File

@ -1,18 +1,18 @@
# -*- coding:utf-8 -*-
from datetime import datetime from datetime import datetime
from flask_login import current_user
from flask_restful import Resource, inputs, marshal_with, reqparse
from sqlalchemy import and_
from werkzeug.exceptions import BadRequest, Forbidden, NotFound
from controllers.console import api from controllers.console import api
from controllers.console.explore.wraps import InstalledAppResource from controllers.console.explore.wraps import InstalledAppResource
from controllers.console.wraps import account_initialization_required, cloud_edition_billing_resource_check from controllers.console.wraps import account_initialization_required, cloud_edition_billing_resource_check
from extensions.ext_database import db from extensions.ext_database import db
from fields.installed_app_fields import installed_app_list_fields from fields.installed_app_fields import installed_app_list_fields
from flask_login import current_user
from flask_restful import Resource, inputs, marshal_with, reqparse
from libs.login import login_required from libs.login import login_required
from models.model import App, InstalledApp, RecommendedApp from models.model import App, InstalledApp, RecommendedApp
from services.account_service import TenantService from services.account_service import TenantService
from sqlalchemy import and_
from werkzeug.exceptions import BadRequest, Forbidden, NotFound
class InstalledAppsListApi(Resource): class InstalledAppsListApi(Resource):

View File

@ -1,31 +1,39 @@
# -*- coding:utf-8 -*-
import json import json
import logging import logging
from typing import Generator, Union from collections.abc import Generator
from typing import Union
from flask import Response, stream_with_context
from flask_login import current_user
from flask_restful import marshal_with, reqparse
from flask_restful.inputs import int_range
from werkzeug.exceptions import InternalServerError, NotFound
import services import services
from controllers.console import api from controllers.console import api
from controllers.console.app.error import (AppMoreLikeThisDisabledError, CompletionRequestError, from controllers.console.app.error import (
ProviderModelCurrentlyNotSupportError, ProviderNotInitializeError, AppMoreLikeThisDisabledError,
ProviderQuotaExceededError) CompletionRequestError,
from controllers.console.explore.error import (AppSuggestedQuestionsAfterAnswerDisabledError, NotChatAppError, ProviderModelCurrentlyNotSupportError,
NotCompletionAppError) ProviderNotInitializeError,
ProviderQuotaExceededError,
)
from controllers.console.explore.error import (
AppSuggestedQuestionsAfterAnswerDisabledError,
NotChatAppError,
NotCompletionAppError,
)
from controllers.console.explore.wraps import InstalledAppResource from controllers.console.explore.wraps import InstalledAppResource
from core.entities.application_entities import InvokeFrom from core.entities.application_entities import InvokeFrom
from core.errors.error import ModelCurrentlyNotSupportError, ProviderTokenNotInitError, QuotaExceededError from core.errors.error import ModelCurrentlyNotSupportError, ProviderTokenNotInitError, QuotaExceededError
from core.model_runtime.errors.invoke import InvokeError from core.model_runtime.errors.invoke import InvokeError
from fields.message_fields import message_infinite_scroll_pagination_fields from fields.message_fields import message_infinite_scroll_pagination_fields
from flask import Response, stream_with_context from libs.helper import uuid_value
from flask_login import current_user
from flask_restful import fields, marshal_with, reqparse
from flask_restful.inputs import int_range
from libs.helper import TimestampField, uuid_value
from services.completion_service import CompletionService from services.completion_service import CompletionService
from services.errors.app import MoreLikeThisDisabledError from services.errors.app import MoreLikeThisDisabledError
from services.errors.conversation import ConversationNotExistsError from services.errors.conversation import ConversationNotExistsError
from services.errors.message import MessageNotExistsError, SuggestedQuestionsAfterAnswerDisabledError from services.errors.message import MessageNotExistsError, SuggestedQuestionsAfterAnswerDisabledError
from services.message_service import MessageService from services.message_service import MessageService
from werkzeug.exceptions import InternalServerError, NotFound
class MessageListApi(InstalledAppResource): class MessageListApi(InstalledAppResource):
@ -115,8 +123,7 @@ def compact_response(response: Union[dict, Generator]) -> Response:
return Response(response=json.dumps(response), status=200, mimetype='application/json') return Response(response=json.dumps(response), status=200, mimetype='application/json')
else: else:
def generate() -> Generator: def generate() -> Generator:
for chunk in response: yield from response
yield chunk
return Response(stream_with_context(generate()), status=200, return Response(stream_with_context(generate()), status=200,
mimetype='text/event-stream') mimetype='text/event-stream')

View File

@ -1,11 +1,11 @@
# -*- coding:utf-8 -*-
import json import json
from flask import current_app
from flask_restful import fields, marshal_with
from controllers.console import api from controllers.console import api
from controllers.console.explore.wraps import InstalledAppResource from controllers.console.explore.wraps import InstalledAppResource
from extensions.ext_database import db from extensions.ext_database import db
from flask import current_app
from flask_restful import fields, marshal_with
from models.model import AppModelConfig, InstalledApp from models.model import AppModelConfig, InstalledApp
from models.tools import ApiToolProvider from models.tools import ApiToolProvider
@ -77,7 +77,7 @@ class ExploreAppMetaApi(InstalledAppResource):
# get all tools # get all tools
tools = agent_config.get('tools', []) tools = agent_config.get('tools', [])
url_prefix = (current_app.config.get("CONSOLE_API_URL") url_prefix = (current_app.config.get("CONSOLE_API_URL")
+ f"/console/api/workspaces/current/tool-provider/builtin/") + "/console/api/workspaces/current/tool-provider/builtin/")
for tool in tools: for tool in tools:
keys = list(tool.keys()) keys = list(tool.keys())
if len(keys) >= 4: if len(keys) >= 4:

View File

@ -1,15 +1,15 @@
# -*- coding:utf-8 -*- from flask_login import current_user
from flask_restful import Resource, fields, marshal_with
from sqlalchemy import and_
from constants.languages import languages from constants.languages import languages
from controllers.console import api from controllers.console import api
from controllers.console.app.error import AppNotFoundError from controllers.console.app.error import AppNotFoundError
from controllers.console.wraps import account_initialization_required from controllers.console.wraps import account_initialization_required
from extensions.ext_database import db from extensions.ext_database import db
from flask_login import current_user
from flask_restful import Resource, fields, marshal_with
from libs.login import login_required from libs.login import login_required
from models.model import App, InstalledApp, RecommendedApp from models.model import App, InstalledApp, RecommendedApp
from services.account_service import TenantService from services.account_service import TenantService
from sqlalchemy import and_
app_fields = { app_fields = {
'id': fields.String, 'id': fields.String,

View File

@ -1,14 +1,15 @@
from flask_login import current_user
from flask_restful import fields, marshal_with, reqparse
from flask_restful.inputs import int_range
from werkzeug.exceptions import NotFound
from controllers.console import api from controllers.console import api
from controllers.console.explore.error import NotCompletionAppError from controllers.console.explore.error import NotCompletionAppError
from controllers.console.explore.wraps import InstalledAppResource from controllers.console.explore.wraps import InstalledAppResource
from fields.conversation_fields import message_file_fields from fields.conversation_fields import message_file_fields
from flask_login import current_user
from flask_restful import fields, marshal_with, reqparse
from flask_restful.inputs import int_range
from libs.helper import TimestampField, uuid_value from libs.helper import TimestampField, uuid_value
from services.errors.message import MessageNotExistsError from services.errors.message import MessageNotExistsError
from services.saved_message_service import SavedMessageService from services.saved_message_service import SavedMessageService
from werkzeug.exceptions import NotFound
feedback_fields = { feedback_fields = {
'rating': fields.String 'rating': fields.String

View File

@ -1,12 +1,13 @@
from functools import wraps from functools import wraps
from flask_login import current_user
from flask_restful import Resource
from werkzeug.exceptions import NotFound
from controllers.console.wraps import account_initialization_required from controllers.console.wraps import account_initialization_required
from extensions.ext_database import db from extensions.ext_database import db
from flask_login import current_user
from flask_restful import Resource
from libs.login import login_required from libs.login import login_required
from models.model import InstalledApp from models.model import InstalledApp
from werkzeug.exceptions import NotFound
def installed_app_required(view=None): def installed_app_required(view=None):

View File

@ -1,9 +1,10 @@
from flask_login import current_user
from flask_restful import Resource, marshal_with, reqparse
from controllers.console import api from controllers.console import api
from controllers.console.setup import setup_required from controllers.console.setup import setup_required
from controllers.console.wraps import account_initialization_required from controllers.console.wraps import account_initialization_required
from fields.api_based_extension_fields import api_based_extension_fields from fields.api_based_extension_fields import api_based_extension_fields
from flask_login import current_user
from flask_restful import Resource, marshal_with, reqparse
from libs.login import login_required from libs.login import login_required
from models.api_based_extension import APIBasedExtension from models.api_based_extension import APIBasedExtension
from services.api_based_extension_service import APIBasedExtensionService from services.api_based_extension_service import APIBasedExtensionService

View File

@ -1,5 +1,6 @@
from flask_login import current_user from flask_login import current_user
from flask_restful import Resource from flask_restful import Resource
from services.feature_service import FeatureService from services.feature_service import FeatureService
from . import api from . import api

View File

@ -2,6 +2,7 @@ import os
from flask import current_app, session from flask import current_app, session
from flask_restful import Resource, reqparse from flask_restful import Resource, reqparse
from libs.helper import str_len from libs.helper import str_len
from models.model import DifySetup from models.model import DifySetup
from services.account_service import TenantService from services.account_service import TenantService

View File

@ -1,9 +1,9 @@
# -*- coding:utf-8 -*-
from functools import wraps from functools import wraps
from extensions.ext_database import db
from flask import current_app, request from flask import current_app, request
from flask_restful import Resource, reqparse from flask_restful import Resource, reqparse
from extensions.ext_database import db
from libs.helper import email, str_len from libs.helper import email, str_len
from libs.password import valid_password from libs.password import valid_password
from models.model import DifySetup from models.model import DifySetup

View File

@ -1,4 +1,3 @@
# -*- coding:utf-8 -*-
import json import json
import logging import logging
@ -6,7 +5,6 @@ import logging
import requests import requests
from flask import current_app from flask import current_app
from flask_restful import Resource, reqparse from flask_restful import Resource, reqparse
from werkzeug.exceptions import InternalServerError
from . import api from . import api

View File

@ -1,17 +1,21 @@
# -*- coding:utf-8 -*-
from datetime import datetime from datetime import datetime
import pytz import pytz
from constants.languages import supported_language
from controllers.console import api
from controllers.console.setup import setup_required
from controllers.console.workspace.error import (AccountAlreadyInitedError, CurrentPasswordIncorrectError,
InvalidInvitationCodeError, RepeatPasswordNotMatchError)
from controllers.console.wraps import account_initialization_required
from extensions.ext_database import db
from flask import current_app, request from flask import current_app, request
from flask_login import current_user from flask_login import current_user
from flask_restful import Resource, fields, marshal_with, reqparse from flask_restful import Resource, fields, marshal_with, reqparse
from constants.languages import supported_language
from controllers.console import api
from controllers.console.setup import setup_required
from controllers.console.workspace.error import (
AccountAlreadyInitedError,
CurrentPasswordIncorrectError,
InvalidInvitationCodeError,
RepeatPasswordNotMatchError,
)
from controllers.console.wraps import account_initialization_required
from extensions.ext_database import db
from libs.helper import TimestampField, timezone from libs.helper import TimestampField, timezone
from libs.login import login_required from libs.login import login_required
from models.account import AccountIntegrate, InvitationCode from models.account import AccountIntegrate, InvitationCode

View File

@ -1,16 +1,17 @@
# -*- coding:utf-8 -*- from flask import current_app
from flask_login import current_user
from flask_restful import Resource, abort, fields, marshal_with, reqparse
import services import services
from controllers.console import api from controllers.console import api
from controllers.console.setup import setup_required from controllers.console.setup import setup_required
from controllers.console.wraps import account_initialization_required, cloud_edition_billing_resource_check from controllers.console.wraps import account_initialization_required, cloud_edition_billing_resource_check
from extensions.ext_database import db from extensions.ext_database import db
from flask import current_app
from flask_login import current_user
from flask_restful import Resource, abort, fields, marshal_with, reqparse
from libs.helper import TimestampField from libs.helper import TimestampField
from libs.login import login_required from libs.login import login_required
from models.account import Account from models.account import Account
from services.account_service import RegisterService, TenantService from services.account_service import RegisterService, TenantService
from services.errors.account import AccountAlreadyInTenantError
account_fields = { account_fields = {
'id': fields.String, 'id': fields.String,
@ -71,6 +72,13 @@ class MemberInviteEmailApi(Resource):
'email': invitee_email, 'email': invitee_email,
'url': f'{console_web_url}/activate?email={invitee_email}&token={token}' 'url': f'{console_web_url}/activate?email={invitee_email}&token={token}'
}) })
except AccountAlreadyInTenantError:
invitation_results.append({
'status': 'success',
'email': invitee_email,
'url': f'{console_web_url}/signin'
})
break
except Exception as e: except Exception as e:
invitation_results.append({ invitation_results.append({
'status': 'failed', 'status': 'failed',

View File

@ -1,18 +1,19 @@
import io import io
from flask import send_file
from flask_login import current_user
from flask_restful import Resource, reqparse
from werkzeug.exceptions import Forbidden
from controllers.console import api from controllers.console import api
from controllers.console.setup import setup_required from controllers.console.setup import setup_required
from controllers.console.wraps import account_initialization_required from controllers.console.wraps import account_initialization_required
from core.model_runtime.entities.model_entities import ModelType from core.model_runtime.entities.model_entities import ModelType
from core.model_runtime.errors.validate import CredentialsValidateFailedError from core.model_runtime.errors.validate import CredentialsValidateFailedError
from core.model_runtime.utils.encoders import jsonable_encoder from core.model_runtime.utils.encoders import jsonable_encoder
from flask import send_file
from flask_login import current_user
from flask_restful import Resource, reqparse
from libs.login import login_required from libs.login import login_required
from services.billing_service import BillingService from services.billing_service import BillingService
from services.model_provider_service import ModelProviderService from services.model_provider_service import ModelProviderService
from werkzeug.exceptions import Forbidden
class ModelProviderListApi(Resource): class ModelProviderListApi(Resource):

View File

@ -1,16 +1,17 @@
import logging import logging
from flask_login import current_user
from flask_restful import Resource, reqparse
from werkzeug.exceptions import Forbidden
from controllers.console import api from controllers.console import api
from controllers.console.setup import setup_required from controllers.console.setup import setup_required
from controllers.console.wraps import account_initialization_required from controllers.console.wraps import account_initialization_required
from core.model_runtime.entities.model_entities import ModelType from core.model_runtime.entities.model_entities import ModelType
from core.model_runtime.errors.validate import CredentialsValidateFailedError from core.model_runtime.errors.validate import CredentialsValidateFailedError
from core.model_runtime.utils.encoders import jsonable_encoder from core.model_runtime.utils.encoders import jsonable_encoder
from flask_login import current_user
from flask_restful import Resource, reqparse
from libs.login import login_required from libs.login import login_required
from services.model_provider_service import ModelProviderService from services.model_provider_service import ModelProviderService
from werkzeug.exceptions import Forbidden
class DefaultModelApi(Resource): class DefaultModelApi(Resource):

View File

@ -1,15 +1,15 @@
import io import io
import json
from flask import send_file
from flask_login import current_user
from flask_restful import Resource, reqparse
from werkzeug.exceptions import Forbidden
from controllers.console import api from controllers.console import api
from controllers.console.setup import setup_required from controllers.console.setup import setup_required
from controllers.console.wraps import account_initialization_required from controllers.console.wraps import account_initialization_required
from flask import send_file
from flask_login import current_user
from flask_restful import Resource, reqparse
from libs.login import login_required from libs.login import login_required
from services.tools_manage_service import ToolManageService from services.tools_manage_service import ToolManageService
from werkzeug.exceptions import Forbidden
class ToolProviderListApi(Resource): class ToolProviderListApi(Resource):

View File

@ -1,18 +1,22 @@
# -*- coding:utf-8 -*-
import logging import logging
from flask import request
from flask_login import current_user
from flask_restful import Resource, fields, inputs, marshal, marshal_with, reqparse
import services import services
from controllers.console import api from controllers.console import api
from controllers.console.admin import admin_required from controllers.console.admin import admin_required
from controllers.console.datasets.error import (FileTooLargeError, NoFileUploadedError, TooManyFilesError, from controllers.console.datasets.error import (
UnsupportedFileTypeError) FileTooLargeError,
NoFileUploadedError,
TooManyFilesError,
UnsupportedFileTypeError,
)
from controllers.console.error import AccountNotLinkTenantError from controllers.console.error import AccountNotLinkTenantError
from controllers.console.setup import setup_required from controllers.console.setup import setup_required
from controllers.console.wraps import account_initialization_required, cloud_edition_billing_resource_check from controllers.console.wraps import account_initialization_required, cloud_edition_billing_resource_check
from extensions.ext_database import db from extensions.ext_database import db
from flask import request
from flask_login import current_user
from flask_restful import Resource, fields, inputs, marshal, marshal_with, reqparse
from libs.helper import TimestampField from libs.helper import TimestampField
from libs.login import login_required from libs.login import login_required
from models.account import Tenant from models.account import Tenant

View File

@ -1,10 +1,10 @@
# -*- coding:utf-8 -*-
import json import json
from functools import wraps from functools import wraps
from controllers.console.workspace.error import AccountNotInitializedError
from flask import abort, current_app, request from flask import abort, current_app, request
from flask_login import current_user from flask_login import current_user
from controllers.console.workspace.error import AccountNotInitializedError
from services.feature_service import FeatureService from services.feature_service import FeatureService
from services.operation_service import OperationService from services.operation_service import OperationService

View File

@ -1,11 +1,12 @@
import services
from controllers.files import api
from flask import Response, request from flask import Response, request
from flask_restful import Resource from flask_restful import Resource
from werkzeug.exceptions import NotFound
import services
from controllers.files import api
from libs.exception import BaseHTTPException from libs.exception import BaseHTTPException
from services.account_service import TenantService from services.account_service import TenantService
from services.file_service import FileService from services.file_service import FileService
from werkzeug.exceptions import NotFound
class ImagePreviewApi(Resource): class ImagePreviewApi(Resource):
@ -40,7 +41,7 @@ class WorkspaceWebappLogoApi(Resource):
webapp_logo_file_id = custom_config.get('replace_webapp_logo') if custom_config is not None else None webapp_logo_file_id = custom_config.get('replace_webapp_logo') if custom_config is not None else None
if not webapp_logo_file_id: if not webapp_logo_file_id:
raise NotFound(f'webapp logo is not found') raise NotFound('webapp logo is not found')
try: try:
generator, mimetype = FileService.get_public_image_preview( generator, mimetype = FileService.get_public_image_preview(

View File

@ -1,10 +1,11 @@
from controllers.files import api
from core.tools.tool_file_manager import ToolFileManager
from flask import Response from flask import Response
from flask_restful import Resource, reqparse from flask_restful import Resource, reqparse
from libs.exception import BaseHTTPException
from werkzeug.exceptions import Forbidden, NotFound from werkzeug.exceptions import Forbidden, NotFound
from controllers.files import api
from core.tools.tool_file_manager import ToolFileManager
from libs.exception import BaseHTTPException
class ToolFilePreviewApi(Resource): class ToolFilePreviewApi(Resource):
def get(self, file_id, extension): def get(self, file_id, extension):
@ -31,7 +32,7 @@ class ToolFilePreviewApi(Resource):
) )
if not result: if not result:
raise NotFound(f'file is not found') raise NotFound('file is not found')
generator, mimetype = result generator, mimetype = result
except Exception: except Exception:

View File

@ -1,11 +1,11 @@
# -*- coding:utf-8 -*-
import json import json
from flask import current_app
from flask_restful import fields, marshal_with
from controllers.service_api import api from controllers.service_api import api
from controllers.service_api.wraps import AppApiResource from controllers.service_api.wraps import AppApiResource
from extensions.ext_database import db from extensions.ext_database import db
from flask import current_app
from flask_restful import fields, marshal_with
from models.model import App, AppModelConfig from models.model import App, AppModelConfig
from models.tools import ApiToolProvider from models.tools import ApiToolProvider
@ -77,7 +77,7 @@ class AppMetaApi(AppApiResource):
# get all tools # get all tools
tools = agent_config.get('tools', []) tools = agent_config.get('tools', [])
url_prefix = (current_app.config.get("CONSOLE_API_URL") url_prefix = (current_app.config.get("CONSOLE_API_URL")
+ f"/console/api/workspaces/current/tool-provider/builtin/") + "/console/api/workspaces/current/tool-provider/builtin/")
for tool in tools: for tool in tools:
keys = list(tool.keys()) keys = list(tool.keys())
if len(keys) >= 4: if len(keys) >= 4:

View File

@ -1,21 +1,33 @@
import logging import logging
from flask import request
from flask_restful import reqparse
from werkzeug.exceptions import InternalServerError
import services import services
from controllers.service_api import api from controllers.service_api import api
from controllers.service_api.app.error import (AppUnavailableError, AudioTooLargeError, CompletionRequestError, from controllers.service_api.app.error import (
NoAudioUploadedError, ProviderModelCurrentlyNotSupportError, AppUnavailableError,
ProviderNotInitializeError, ProviderNotSupportSpeechToTextError, AudioTooLargeError,
ProviderQuotaExceededError, UnsupportedAudioTypeError) CompletionRequestError,
NoAudioUploadedError,
ProviderModelCurrentlyNotSupportError,
ProviderNotInitializeError,
ProviderNotSupportSpeechToTextError,
ProviderQuotaExceededError,
UnsupportedAudioTypeError,
)
from controllers.service_api.wraps import AppApiResource from controllers.service_api.wraps import AppApiResource
from core.errors.error import ModelCurrentlyNotSupportError, ProviderTokenNotInitError, QuotaExceededError from core.errors.error import ModelCurrentlyNotSupportError, ProviderTokenNotInitError, QuotaExceededError
from core.model_runtime.errors.invoke import InvokeError from core.model_runtime.errors.invoke import InvokeError
from flask import request
from flask_restful import reqparse
from models.model import App, AppModelConfig from models.model import App, AppModelConfig
from services.audio_service import AudioService from services.audio_service import AudioService
from services.errors.audio import (AudioTooLargeServiceError, NoAudioUploadedServiceError, from services.errors.audio import (
ProviderNotSupportSpeechToTextServiceError, UnsupportedAudioTypeServiceError) AudioTooLargeServiceError,
from werkzeug.exceptions import InternalServerError NoAudioUploadedServiceError,
ProviderNotSupportSpeechToTextServiceError,
UnsupportedAudioTypeServiceError,
)
class AudioApi(AppApiResource): class AudioApi(AppApiResource):
@ -74,6 +86,7 @@ class TextApi(AppApiResource):
tenant_id=app_model.tenant_id, tenant_id=app_model.tenant_id,
text=args['text'], text=args['text'],
end_user=args['user'], end_user=args['user'],
voice=app_model.app_model_config.text_to_speech_dict.get('voice'),
streaming=args['streaming'] streaming=args['streaming']
) )

View File

@ -1,23 +1,31 @@
import json import json
import logging import logging
from typing import Generator, Union from collections.abc import Generator
from typing import Union
from flask import Response, stream_with_context
from flask_restful import reqparse
from werkzeug.exceptions import InternalServerError, NotFound
import services import services
from controllers.service_api import api from controllers.service_api import api
from controllers.service_api.app import create_or_update_end_user_for_user_id from controllers.service_api.app import create_or_update_end_user_for_user_id
from controllers.service_api.app.error import (AppUnavailableError, CompletionRequestError, ConversationCompletedError, from controllers.service_api.app.error import (
NotChatAppError, ProviderModelCurrentlyNotSupportError, AppUnavailableError,
ProviderNotInitializeError, ProviderQuotaExceededError) CompletionRequestError,
ConversationCompletedError,
NotChatAppError,
ProviderModelCurrentlyNotSupportError,
ProviderNotInitializeError,
ProviderQuotaExceededError,
)
from controllers.service_api.wraps import AppApiResource from controllers.service_api.wraps import AppApiResource
from core.application_queue_manager import ApplicationQueueManager from core.application_queue_manager import ApplicationQueueManager
from core.entities.application_entities import InvokeFrom from core.entities.application_entities import InvokeFrom
from core.errors.error import ModelCurrentlyNotSupportError, ProviderTokenNotInitError, QuotaExceededError from core.errors.error import ModelCurrentlyNotSupportError, ProviderTokenNotInitError, QuotaExceededError
from core.model_runtime.errors.invoke import InvokeError from core.model_runtime.errors.invoke import InvokeError
from flask import Response, stream_with_context
from flask_restful import reqparse
from libs.helper import uuid_value from libs.helper import uuid_value
from services.completion_service import CompletionService from services.completion_service import CompletionService
from werkzeug.exceptions import InternalServerError, NotFound
class CompletionApi(AppApiResource): class CompletionApi(AppApiResource):
@ -175,8 +183,7 @@ def compact_response(response: Union[dict, Generator]) -> Response:
return Response(response=json.dumps(response), status=200, mimetype='application/json') return Response(response=json.dumps(response), status=200, mimetype='application/json')
else: else:
def generate() -> Generator: def generate() -> Generator:
for chunk in response: yield from response
yield chunk
return Response(stream_with_context(generate()), status=200, return Response(stream_with_context(generate()), status=200,
mimetype='text/event-stream') mimetype='text/event-stream')

View File

@ -1,16 +1,16 @@
# -*- coding:utf-8 -*- from flask import request
from flask_restful import marshal_with, reqparse
from flask_restful.inputs import int_range
from werkzeug.exceptions import NotFound
import services import services
from controllers.service_api import api from controllers.service_api import api
from controllers.service_api.app import create_or_update_end_user_for_user_id from controllers.service_api.app import create_or_update_end_user_for_user_id
from controllers.service_api.app.error import NotChatAppError from controllers.service_api.app.error import NotChatAppError
from controllers.service_api.wraps import AppApiResource from controllers.service_api.wraps import AppApiResource
from fields.conversation_fields import conversation_infinite_scroll_pagination_fields, simple_conversation_fields from fields.conversation_fields import conversation_infinite_scroll_pagination_fields, simple_conversation_fields
from flask import request from libs.helper import uuid_value
from flask_restful import fields, marshal_with, reqparse
from flask_restful.inputs import int_range
from libs.helper import TimestampField, uuid_value
from services.conversation_service import ConversationService from services.conversation_service import ConversationService
from werkzeug.exceptions import NotFound
class ConversationApi(AppApiResource): class ConversationApi(AppApiResource):

View File

@ -1,4 +1,3 @@
# -*- coding:utf-8 -*-
from libs.exception import BaseHTTPException from libs.exception import BaseHTTPException

View File

@ -1,12 +1,17 @@
from flask import request
from flask_restful import marshal_with
import services import services
from controllers.service_api import api from controllers.service_api import api
from controllers.service_api.app import create_or_update_end_user_for_user_id from controllers.service_api.app import create_or_update_end_user_for_user_id
from controllers.service_api.app.error import (FileTooLargeError, NoFileUploadedError, TooManyFilesError, from controllers.service_api.app.error import (
UnsupportedFileTypeError) FileTooLargeError,
NoFileUploadedError,
TooManyFilesError,
UnsupportedFileTypeError,
)
from controllers.service_api.wraps import AppApiResource from controllers.service_api.wraps import AppApiResource
from fields.file_fields import file_fields from fields.file_fields import file_fields
from flask import request
from flask_restful import marshal_with
from services.file_service import FileService from services.file_service import FileService

View File

@ -1,4 +1,7 @@
# -*- coding:utf-8 -*- from flask_restful import fields, marshal_with, reqparse
from flask_restful.inputs import int_range
from werkzeug.exceptions import NotFound
import services import services
from controllers.service_api import api from controllers.service_api import api
from controllers.service_api.app import create_or_update_end_user_for_user_id from controllers.service_api.app import create_or_update_end_user_for_user_id
@ -6,12 +9,9 @@ from controllers.service_api.app.error import NotChatAppError
from controllers.service_api.wraps import AppApiResource from controllers.service_api.wraps import AppApiResource
from extensions.ext_database import db from extensions.ext_database import db
from fields.conversation_fields import message_file_fields from fields.conversation_fields import message_file_fields
from flask_restful import fields, marshal_with, reqparse
from flask_restful.inputs import int_range
from libs.helper import TimestampField, uuid_value from libs.helper import TimestampField, uuid_value
from models.model import EndUser, Message from models.model import EndUser, Message
from services.message_service import MessageService from services.message_service import MessageService
from werkzeug.exceptions import NotFound
class MessageListApi(AppApiResource): class MessageListApi(AppApiResource):

View File

@ -1,3 +1,6 @@
from flask import request
from flask_restful import marshal, reqparse
import services.dataset_service import services.dataset_service
from controllers.service_api import api from controllers.service_api import api
from controllers.service_api.dataset.error import DatasetNameDuplicateError from controllers.service_api.dataset.error import DatasetNameDuplicateError
@ -5,8 +8,6 @@ from controllers.service_api.wraps import DatasetApiResource
from core.model_runtime.entities.model_entities import ModelType from core.model_runtime.entities.model_entities import ModelType
from core.provider_manager import ProviderManager from core.provider_manager import ProviderManager
from fields.dataset_fields import dataset_detail_fields from fields.dataset_fields import dataset_detail_fields
from flask import request
from flask_restful import marshal, reqparse
from libs.login import current_user from libs.login import current_user
from models.dataset import Dataset from models.dataset import Dataset
from services.dataset_service import DatasetService from services.dataset_service import DatasetService

View File

@ -1,23 +1,27 @@
import json import json
from flask import request
from flask_restful import marshal, reqparse
from sqlalchemy import desc
from werkzeug.exceptions import NotFound
import services.dataset_service import services.dataset_service
from controllers.service_api import api from controllers.service_api import api
from controllers.service_api.app.error import ProviderNotInitializeError from controllers.service_api.app.error import ProviderNotInitializeError
from controllers.service_api.dataset.error import (ArchivedDocumentImmutableError, DocumentIndexingError, from controllers.service_api.dataset.error import (
NoFileUploadedError, TooManyFilesError) ArchivedDocumentImmutableError,
DocumentIndexingError,
NoFileUploadedError,
TooManyFilesError,
)
from controllers.service_api.wraps import DatasetApiResource, cloud_edition_billing_resource_check from controllers.service_api.wraps import DatasetApiResource, cloud_edition_billing_resource_check
from core.errors.error import ProviderTokenNotInitError from core.errors.error import ProviderTokenNotInitError
from extensions.ext_database import db from extensions.ext_database import db
from fields.document_fields import document_fields, document_status_fields from fields.document_fields import document_fields, document_status_fields
from flask import request
from flask_login import current_user
from flask_restful import marshal, reqparse
from libs.login import current_user from libs.login import current_user
from models.dataset import Dataset, Document, DocumentSegment from models.dataset import Dataset, Document, DocumentSegment
from services.dataset_service import DocumentService from services.dataset_service import DocumentService
from services.file_service import FileService from services.file_service import FileService
from sqlalchemy import desc
from werkzeug.exceptions import NotFound
class DocumentAddByTextApi(DatasetApiResource): class DocumentAddByTextApi(DatasetApiResource):

View File

@ -1,3 +1,7 @@
from flask_login import current_user
from flask_restful import marshal, reqparse
from werkzeug.exceptions import NotFound
from controllers.service_api import api from controllers.service_api import api
from controllers.service_api.app.error import ProviderNotInitializeError from controllers.service_api.app.error import ProviderNotInitializeError
from controllers.service_api.wraps import DatasetApiResource, cloud_edition_billing_resource_check from controllers.service_api.wraps import DatasetApiResource, cloud_edition_billing_resource_check
@ -6,11 +10,8 @@ from core.model_manager import ModelManager
from core.model_runtime.entities.model_entities import ModelType from core.model_runtime.entities.model_entities import ModelType
from extensions.ext_database import db from extensions.ext_database import db
from fields.segment_fields import segment_fields from fields.segment_fields import segment_fields
from flask_login import current_user
from flask_restful import marshal, reqparse
from models.dataset import Dataset, DocumentSegment from models.dataset import Dataset, DocumentSegment
from services.dataset_service import DatasetService, DocumentService, SegmentService from services.dataset_service import DatasetService, DocumentService, SegmentService
from werkzeug.exceptions import NotFound
class SegmentApi(DatasetApiResource): class SegmentApi(DatasetApiResource):
@ -45,8 +46,8 @@ class SegmentApi(DatasetApiResource):
) )
except LLMBadRequestError: except LLMBadRequestError:
raise ProviderNotInitializeError( raise ProviderNotInitializeError(
f"No Embedding Model available. Please configure a valid provider " "No Embedding Model available. Please configure a valid provider "
f"in the Settings -> Model Provider.") "in the Settings -> Model Provider.")
except ProviderTokenNotInitError as ex: except ProviderTokenNotInitError as ex:
raise ProviderNotInitializeError(ex.description) raise ProviderNotInitializeError(ex.description)
# validate args # validate args
@ -89,8 +90,8 @@ class SegmentApi(DatasetApiResource):
) )
except LLMBadRequestError: except LLMBadRequestError:
raise ProviderNotInitializeError( raise ProviderNotInitializeError(
f"No Embedding Model available. Please configure a valid provider " "No Embedding Model available. Please configure a valid provider "
f"in the Settings -> Model Provider.") "in the Settings -> Model Provider.")
except ProviderTokenNotInitError as ex: except ProviderTokenNotInitError as ex:
raise ProviderNotInitializeError(ex.description) raise ProviderNotInitializeError(ex.description)
@ -181,8 +182,8 @@ class DatasetSegmentApi(DatasetApiResource):
) )
except LLMBadRequestError: except LLMBadRequestError:
raise ProviderNotInitializeError( raise ProviderNotInitializeError(
f"No Embedding Model available. Please configure a valid provider " "No Embedding Model available. Please configure a valid provider "
f"in the Settings -> Model Provider.") "in the Settings -> Model Provider.")
except ProviderTokenNotInitError as ex: except ProviderTokenNotInitError as ex:
raise ProviderNotInitializeError(ex.description) raise ProviderNotInitializeError(ex.description)
# check segment # check segment

View File

@ -1,7 +1,8 @@
from controllers.service_api import api
from flask import current_app from flask import current_app
from flask_restful import Resource from flask_restful import Resource
from controllers.service_api import api
class IndexApi(Resource): class IndexApi(Resource):
def get(self): def get(self):

View File

@ -1,16 +1,16 @@
# -*- coding:utf-8 -*-
from datetime import datetime from datetime import datetime
from functools import wraps from functools import wraps
from extensions.ext_database import db
from flask import current_app, request from flask import current_app, request
from flask_login import user_logged_in from flask_login import user_logged_in
from flask_restful import Resource from flask_restful import Resource
from werkzeug.exceptions import NotFound, Unauthorized
from extensions.ext_database import db
from libs.login import _get_user from libs.login import _get_user
from models.account import Account, Tenant, TenantAccountJoin from models.account import Account, Tenant, TenantAccountJoin
from models.model import ApiToken, App from models.model import ApiToken, App
from services.feature_service import FeatureService from services.feature_service import FeatureService
from werkzeug.exceptions import NotFound, Unauthorized
def validate_app_token(view=None): def validate_app_token(view=None):

View File

@ -1,11 +1,11 @@
# -*- coding:utf-8 -*-
import json import json
from flask import current_app
from flask_restful import fields, marshal_with
from controllers.web import api from controllers.web import api
from controllers.web.wraps import WebApiResource from controllers.web.wraps import WebApiResource
from extensions.ext_database import db from extensions.ext_database import db
from flask import current_app
from flask_restful import fields, marshal_with
from models.model import App, AppModelConfig from models.model import App, AppModelConfig
from models.tools import ApiToolProvider from models.tools import ApiToolProvider
@ -76,7 +76,7 @@ class AppMeta(WebApiResource):
# get all tools # get all tools
tools = agent_config.get('tools', []) tools = agent_config.get('tools', [])
url_prefix = (current_app.config.get("CONSOLE_API_URL") url_prefix = (current_app.config.get("CONSOLE_API_URL")
+ f"/console/api/workspaces/current/tool-provider/builtin/") + "/console/api/workspaces/current/tool-provider/builtin/")
for tool in tools: for tool in tools:
keys = list(tool.keys()) keys = list(tool.keys())
if len(keys) >= 4: if len(keys) >= 4:

View File

@ -1,21 +1,32 @@
# -*- coding:utf-8 -*-
import logging import logging
from flask import request
from werkzeug.exceptions import InternalServerError
import services import services
from controllers.web import api from controllers.web import api
from controllers.web.error import (AppUnavailableError, AudioTooLargeError, CompletionRequestError, from controllers.web.error import (
NoAudioUploadedError, ProviderModelCurrentlyNotSupportError, AppUnavailableError,
ProviderNotInitializeError, ProviderNotSupportSpeechToTextError, AudioTooLargeError,
ProviderQuotaExceededError, UnsupportedAudioTypeError) CompletionRequestError,
NoAudioUploadedError,
ProviderModelCurrentlyNotSupportError,
ProviderNotInitializeError,
ProviderNotSupportSpeechToTextError,
ProviderQuotaExceededError,
UnsupportedAudioTypeError,
)
from controllers.web.wraps import WebApiResource from controllers.web.wraps import WebApiResource
from core.errors.error import ModelCurrentlyNotSupportError, ProviderTokenNotInitError, QuotaExceededError from core.errors.error import ModelCurrentlyNotSupportError, ProviderTokenNotInitError, QuotaExceededError
from core.model_runtime.errors.invoke import InvokeError from core.model_runtime.errors.invoke import InvokeError
from flask import request
from models.model import App, AppModelConfig from models.model import App, AppModelConfig
from services.audio_service import AudioService from services.audio_service import AudioService
from services.errors.audio import (AudioTooLargeServiceError, NoAudioUploadedServiceError, from services.errors.audio import (
ProviderNotSupportSpeechToTextServiceError, UnsupportedAudioTypeServiceError) AudioTooLargeServiceError,
from werkzeug.exceptions import InternalServerError NoAudioUploadedServiceError,
ProviderNotSupportSpeechToTextServiceError,
UnsupportedAudioTypeServiceError,
)
class AudioApi(WebApiResource): class AudioApi(WebApiResource):
@ -57,17 +68,23 @@ class AudioApi(WebApiResource):
except ValueError as e: except ValueError as e:
raise e raise e
except Exception as e: except Exception as e:
logging.exception("internal server error.") logging.exception(f"internal server error: {str(e)}")
raise InternalServerError() raise InternalServerError()
class TextApi(WebApiResource): class TextApi(WebApiResource):
def post(self, app_model: App, end_user): def post(self, app_model: App, end_user):
app_model_config: AppModelConfig = app_model.app_model_config
if not app_model_config.text_to_speech_dict['enabled']:
raise AppUnavailableError()
try: try:
response = AudioService.transcript_tts( response = AudioService.transcript_tts(
tenant_id=app_model.tenant_id, tenant_id=app_model.tenant_id,
text=request.form['text'], text=request.form['text'],
end_user=end_user.external_user_id, end_user=end_user.external_user_id,
voice=app_model.app_model_config.text_to_speech_dict.get('voice'),
streaming=False streaming=False
) )
@ -94,7 +111,7 @@ class TextApi(WebApiResource):
except ValueError as e: except ValueError as e:
raise e raise e
except Exception as e: except Exception as e:
logging.exception("internal server error.") logging.exception(f"internal server error: {str(e)}")
raise InternalServerError() raise InternalServerError()

View File

@ -1,23 +1,31 @@
# -*- coding:utf-8 -*-
import json import json
import logging import logging
from typing import Generator, Union from collections.abc import Generator
from typing import Union
from flask import Response, stream_with_context
from flask_restful import reqparse
from werkzeug.exceptions import InternalServerError, NotFound
import services import services
from controllers.web import api from controllers.web import api
from controllers.web.error import (AppUnavailableError, CompletionRequestError, ConversationCompletedError, from controllers.web.error import (
NotChatAppError, NotCompletionAppError, ProviderModelCurrentlyNotSupportError, AppUnavailableError,
ProviderNotInitializeError, ProviderQuotaExceededError) CompletionRequestError,
ConversationCompletedError,
NotChatAppError,
NotCompletionAppError,
ProviderModelCurrentlyNotSupportError,
ProviderNotInitializeError,
ProviderQuotaExceededError,
)
from controllers.web.wraps import WebApiResource from controllers.web.wraps import WebApiResource
from core.application_queue_manager import ApplicationQueueManager from core.application_queue_manager import ApplicationQueueManager
from core.entities.application_entities import InvokeFrom from core.entities.application_entities import InvokeFrom
from core.errors.error import ModelCurrentlyNotSupportError, ProviderTokenNotInitError, QuotaExceededError from core.errors.error import ModelCurrentlyNotSupportError, ProviderTokenNotInitError, QuotaExceededError
from core.model_runtime.errors.invoke import InvokeError from core.model_runtime.errors.invoke import InvokeError
from flask import Response, stream_with_context
from flask_restful import reqparse
from libs.helper import uuid_value from libs.helper import uuid_value
from services.completion_service import CompletionService from services.completion_service import CompletionService
from werkzeug.exceptions import InternalServerError, NotFound
# define completion api for user # define completion api for user
@ -146,8 +154,7 @@ def compact_response(response: Union[dict, Generator]) -> Response:
return Response(response=json.dumps(response), status=200, mimetype='application/json') return Response(response=json.dumps(response), status=200, mimetype='application/json')
else: else:
def generate() -> Generator: def generate() -> Generator:
for chunk in response: yield from response
yield chunk
return Response(stream_with_context(generate()), status=200, return Response(stream_with_context(generate()), status=200,
mimetype='text/event-stream') mimetype='text/event-stream')

View File

@ -1,15 +1,15 @@
# -*- coding:utf-8 -*- from flask_restful import marshal_with, reqparse
from flask_restful.inputs import int_range
from werkzeug.exceptions import NotFound
from controllers.web import api from controllers.web import api
from controllers.web.error import NotChatAppError from controllers.web.error import NotChatAppError
from controllers.web.wraps import WebApiResource from controllers.web.wraps import WebApiResource
from fields.conversation_fields import conversation_infinite_scroll_pagination_fields, simple_conversation_fields from fields.conversation_fields import conversation_infinite_scroll_pagination_fields, simple_conversation_fields
from flask_restful import fields, marshal_with, reqparse from libs.helper import uuid_value
from flask_restful.inputs import int_range
from libs.helper import TimestampField, uuid_value
from services.conversation_service import ConversationService from services.conversation_service import ConversationService
from services.errors.conversation import ConversationNotExistsError, LastConversationNotExistsError from services.errors.conversation import ConversationNotExistsError, LastConversationNotExistsError
from services.web_conversation_service import WebConversationService from services.web_conversation_service import WebConversationService
from werkzeug.exceptions import NotFound
class ConversationListApi(WebApiResource): class ConversationListApi(WebApiResource):

View File

@ -1,4 +1,3 @@
# -*- coding:utf-8 -*-
from libs.exception import BaseHTTPException from libs.exception import BaseHTTPException

View File

@ -1,10 +1,11 @@
from flask import request
from flask_restful import marshal_with
import services import services
from controllers.web import api from controllers.web import api
from controllers.web.error import FileTooLargeError, NoFileUploadedError, TooManyFilesError, UnsupportedFileTypeError from controllers.web.error import FileTooLargeError, NoFileUploadedError, TooManyFilesError, UnsupportedFileTypeError
from controllers.web.wraps import WebApiResource from controllers.web.wraps import WebApiResource
from fields.file_fields import file_fields from fields.file_fields import file_fields
from flask import request
from flask_restful import marshal_with
from services.file_service import FileService from services.file_service import FileService

View File

@ -1,30 +1,37 @@
# -*- coding:utf-8 -*-
import json import json
import logging import logging
from typing import Generator, Union from collections.abc import Generator
from typing import Union
from flask import Response, stream_with_context
from flask_restful import fields, marshal_with, reqparse
from flask_restful.inputs import int_range
from werkzeug.exceptions import InternalServerError, NotFound
import services import services
from controllers.web import api from controllers.web import api
from controllers.web.error import (AppMoreLikeThisDisabledError, AppSuggestedQuestionsAfterAnswerDisabledError, from controllers.web.error import (
CompletionRequestError, NotChatAppError, NotCompletionAppError, AppMoreLikeThisDisabledError,
ProviderModelCurrentlyNotSupportError, ProviderNotInitializeError, AppSuggestedQuestionsAfterAnswerDisabledError,
ProviderQuotaExceededError) CompletionRequestError,
NotChatAppError,
NotCompletionAppError,
ProviderModelCurrentlyNotSupportError,
ProviderNotInitializeError,
ProviderQuotaExceededError,
)
from controllers.web.wraps import WebApiResource from controllers.web.wraps import WebApiResource
from core.entities.application_entities import InvokeFrom from core.entities.application_entities import InvokeFrom
from core.errors.error import ModelCurrentlyNotSupportError, ProviderTokenNotInitError, QuotaExceededError from core.errors.error import ModelCurrentlyNotSupportError, ProviderTokenNotInitError, QuotaExceededError
from core.model_runtime.errors.invoke import InvokeError from core.model_runtime.errors.invoke import InvokeError
from fields.conversation_fields import message_file_fields from fields.conversation_fields import message_file_fields
from fields.message_fields import agent_thought_fields from fields.message_fields import agent_thought_fields
from flask import Response, stream_with_context
from flask_restful import fields, marshal_with, reqparse
from flask_restful.inputs import int_range
from libs.helper import TimestampField, uuid_value from libs.helper import TimestampField, uuid_value
from services.completion_service import CompletionService from services.completion_service import CompletionService
from services.errors.app import MoreLikeThisDisabledError from services.errors.app import MoreLikeThisDisabledError
from services.errors.conversation import ConversationNotExistsError from services.errors.conversation import ConversationNotExistsError
from services.errors.message import MessageNotExistsError, SuggestedQuestionsAfterAnswerDisabledError from services.errors.message import MessageNotExistsError, SuggestedQuestionsAfterAnswerDisabledError
from services.message_service import MessageService from services.message_service import MessageService
from werkzeug.exceptions import InternalServerError, NotFound
class MessageListApi(WebApiResource): class MessageListApi(WebApiResource):
@ -153,8 +160,7 @@ def compact_response(response: Union[dict, Generator]) -> Response:
return Response(response=json.dumps(response), status=200, mimetype='application/json') return Response(response=json.dumps(response), status=200, mimetype='application/json')
else: else:
def generate() -> Generator: def generate() -> Generator:
for chunk in response: yield from response
yield chunk
return Response(stream_with_context(generate()), status=200, return Response(stream_with_context(generate()), status=200,
mimetype='text/event-stream') mimetype='text/event-stream')

View File

@ -1,13 +1,13 @@
# -*- coding:utf-8 -*-
import uuid import uuid
from flask import request
from flask_restful import Resource
from werkzeug.exceptions import NotFound, Unauthorized
from controllers.web import api from controllers.web import api
from extensions.ext_database import db from extensions.ext_database import db
from flask import request
from flask_restful import Resource
from libs.passport import PassportService from libs.passport import PassportService
from models.model import App, EndUser, Site from models.model import App, EndUser, Site
from werkzeug.exceptions import NotFound, Unauthorized
class PassportResource(Resource): class PassportResource(Resource):

View File

@ -1,13 +1,14 @@
from flask_restful import fields, marshal_with, reqparse
from flask_restful.inputs import int_range
from werkzeug.exceptions import NotFound
from controllers.web import api from controllers.web import api
from controllers.web.error import NotCompletionAppError from controllers.web.error import NotCompletionAppError
from controllers.web.wraps import WebApiResource from controllers.web.wraps import WebApiResource
from fields.conversation_fields import message_file_fields from fields.conversation_fields import message_file_fields
from flask_restful import fields, marshal_with, reqparse
from flask_restful.inputs import int_range
from libs.helper import TimestampField, uuid_value from libs.helper import TimestampField, uuid_value
from services.errors.message import MessageNotExistsError from services.errors.message import MessageNotExistsError
from services.saved_message_service import SavedMessageService from services.saved_message_service import SavedMessageService
from werkzeug.exceptions import NotFound
feedback_fields = { feedback_fields = {
'rating': fields.String 'rating': fields.String

View File

@ -1,14 +1,13 @@
# -*- coding:utf-8 -*-
import os from flask import current_app
from flask_restful import fields, marshal_with
from werkzeug.exceptions import Forbidden
from controllers.web import api from controllers.web import api
from controllers.web.wraps import WebApiResource from controllers.web.wraps import WebApiResource
from extensions.ext_database import db from extensions.ext_database import db
from flask import current_app
from flask_restful import fields, marshal_with
from models.model import Site from models.model import Site
from services.feature_service import FeatureService from services.feature_service import FeatureService
from werkzeug.exceptions import Forbidden
class AppSiteApi(WebApiResource): class AppSiteApi(WebApiResource):

View File

@ -1,12 +1,12 @@
# -*- coding:utf-8 -*-
from functools import wraps from functools import wraps
from extensions.ext_database import db
from flask import request from flask import request
from flask_restful import Resource from flask_restful import Resource
from werkzeug.exceptions import NotFound, Unauthorized
from extensions.ext_database import db
from libs.passport import PassportService from libs.passport import PassportService
from models.model import App, EndUser, Site from models.model import App, EndUser, Site
from werkzeug.exceptions import NotFound, Unauthorized
def validate_jwt_token(view=None): def validate_jwt_token(view=None):

View File

@ -1,5 +1,5 @@
import logging import logging
from typing import List, Optional from typing import Optional
from core.callback_handler.agent_loop_gather_callback_handler import AgentLoopGatherCallbackHandler from core.callback_handler.agent_loop_gather_callback_handler import AgentLoopGatherCallbackHandler
from core.model_runtime.callbacks.base_callback import Callback from core.model_runtime.callbacks.base_callback import Callback
@ -17,7 +17,7 @@ class AgentLLMCallback(Callback):
def on_before_invoke(self, llm_instance: AIModel, model: str, credentials: dict, def on_before_invoke(self, llm_instance: AIModel, model: str, credentials: dict,
prompt_messages: list[PromptMessage], model_parameters: dict, prompt_messages: list[PromptMessage], model_parameters: dict,
tools: Optional[list[PromptMessageTool]] = None, stop: Optional[List[str]] = None, tools: Optional[list[PromptMessageTool]] = None, stop: Optional[list[str]] = None,
stream: bool = True, user: Optional[str] = None) -> None: stream: bool = True, user: Optional[str] = None) -> None:
""" """
Before invoke callback Before invoke callback
@ -38,7 +38,7 @@ class AgentLLMCallback(Callback):
def on_new_chunk(self, llm_instance: AIModel, chunk: LLMResultChunk, model: str, credentials: dict, def on_new_chunk(self, llm_instance: AIModel, chunk: LLMResultChunk, model: str, credentials: dict,
prompt_messages: list[PromptMessage], model_parameters: dict, prompt_messages: list[PromptMessage], model_parameters: dict,
tools: Optional[list[PromptMessageTool]] = None, stop: Optional[List[str]] = None, tools: Optional[list[PromptMessageTool]] = None, stop: Optional[list[str]] = None,
stream: bool = True, user: Optional[str] = None): stream: bool = True, user: Optional[str] = None):
""" """
On new chunk callback On new chunk callback
@ -58,7 +58,7 @@ class AgentLLMCallback(Callback):
def on_after_invoke(self, llm_instance: AIModel, result: LLMResult, model: str, credentials: dict, def on_after_invoke(self, llm_instance: AIModel, result: LLMResult, model: str, credentials: dict,
prompt_messages: list[PromptMessage], model_parameters: dict, prompt_messages: list[PromptMessage], model_parameters: dict,
tools: Optional[list[PromptMessageTool]] = None, stop: Optional[List[str]] = None, tools: Optional[list[PromptMessageTool]] = None, stop: Optional[list[str]] = None,
stream: bool = True, user: Optional[str] = None) -> None: stream: bool = True, user: Optional[str] = None) -> None:
""" """
After invoke callback After invoke callback
@ -80,7 +80,7 @@ class AgentLLMCallback(Callback):
def on_invoke_error(self, llm_instance: AIModel, ex: Exception, model: str, credentials: dict, def on_invoke_error(self, llm_instance: AIModel, ex: Exception, model: str, credentials: dict,
prompt_messages: list[PromptMessage], model_parameters: dict, prompt_messages: list[PromptMessage], model_parameters: dict,
tools: Optional[list[PromptMessageTool]] = None, stop: Optional[List[str]] = None, tools: Optional[list[PromptMessageTool]] = None, stop: Optional[list[str]] = None,
stream: bool = True, user: Optional[str] = None) -> None: stream: bool = True, user: Optional[str] = None) -> None:
""" """
Invoke error callback Invoke error callback

View File

@ -1,16 +1,14 @@
from typing import List, cast from typing import cast
from core.entities.application_entities import ModelConfigEntity from core.entities.application_entities import ModelConfigEntity
from core.entities.message_entities import lc_messages_to_prompt_messages
from core.model_runtime.entities.message_entities import PromptMessage from core.model_runtime.entities.message_entities import PromptMessage
from core.model_runtime.entities.model_entities import ModelPropertyKey from core.model_runtime.entities.model_entities import ModelPropertyKey
from core.model_runtime.model_providers.__base.large_language_model import LargeLanguageModel from core.model_runtime.model_providers.__base.large_language_model import LargeLanguageModel
from langchain.schema import BaseMessage
class CalcTokenMixin: class CalcTokenMixin:
def get_message_rest_tokens(self, model_config: ModelConfigEntity, messages: List[PromptMessage], **kwargs) -> int: def get_message_rest_tokens(self, model_config: ModelConfigEntity, messages: list[PromptMessage], **kwargs) -> int:
""" """
Got the rest tokens available for the model after excluding messages tokens and completion max tokens Got the rest tokens available for the model after excluding messages tokens and completion max tokens

View File

@ -1,10 +1,6 @@
from typing import Any, List, Optional, Sequence, Tuple, Union, cast from collections.abc import Sequence
from typing import Any, Optional, Union
from core.entities.application_entities import ModelConfigEntity
from core.entities.message_entities import lc_messages_to_prompt_messages
from core.model_manager import ModelInstance
from core.model_runtime.entities.message_entities import PromptMessageTool
from core.third_party.langchain.llms.fake import FakeLLM
from langchain.agents import BaseSingleActionAgent, OpenAIFunctionsAgent from langchain.agents import BaseSingleActionAgent, OpenAIFunctionsAgent
from langchain.agents.openai_functions_agent.base import _format_intermediate_steps, _parse_ai_message from langchain.agents.openai_functions_agent.base import _format_intermediate_steps, _parse_ai_message
from langchain.callbacks.base import BaseCallbackManager from langchain.callbacks.base import BaseCallbackManager
@ -14,6 +10,12 @@ from langchain.schema import AgentAction, AgentFinish, AIMessage, SystemMessage
from langchain.tools import BaseTool from langchain.tools import BaseTool
from pydantic import root_validator from pydantic import root_validator
from core.entities.application_entities import ModelConfigEntity
from core.entities.message_entities import lc_messages_to_prompt_messages
from core.model_manager import ModelInstance
from core.model_runtime.entities.message_entities import PromptMessageTool
from core.third_party.langchain.llms.fake import FakeLLM
class MultiDatasetRouterAgent(OpenAIFunctionsAgent): class MultiDatasetRouterAgent(OpenAIFunctionsAgent):
""" """
@ -41,7 +43,7 @@ class MultiDatasetRouterAgent(OpenAIFunctionsAgent):
def plan( def plan(
self, self,
intermediate_steps: List[Tuple[AgentAction, str]], intermediate_steps: list[tuple[AgentAction, str]],
callbacks: Callbacks = None, callbacks: Callbacks = None,
**kwargs: Any, **kwargs: Any,
) -> Union[AgentAction, AgentFinish]: ) -> Union[AgentAction, AgentFinish]:
@ -84,7 +86,7 @@ class MultiDatasetRouterAgent(OpenAIFunctionsAgent):
def real_plan( def real_plan(
self, self,
intermediate_steps: List[Tuple[AgentAction, str]], intermediate_steps: list[tuple[AgentAction, str]],
callbacks: Callbacks = None, callbacks: Callbacks = None,
**kwargs: Any, **kwargs: Any,
) -> Union[AgentAction, AgentFinish]: ) -> Union[AgentAction, AgentFinish]:
@ -145,7 +147,7 @@ class MultiDatasetRouterAgent(OpenAIFunctionsAgent):
async def aplan( async def aplan(
self, self,
intermediate_steps: List[Tuple[AgentAction, str]], intermediate_steps: list[tuple[AgentAction, str]],
callbacks: Callbacks = None, callbacks: Callbacks = None,
**kwargs: Any, **kwargs: Any,
) -> Union[AgentAction, AgentFinish]: ) -> Union[AgentAction, AgentFinish]:
@ -157,7 +159,7 @@ class MultiDatasetRouterAgent(OpenAIFunctionsAgent):
model_config: ModelConfigEntity, model_config: ModelConfigEntity,
tools: Sequence[BaseTool], tools: Sequence[BaseTool],
callback_manager: Optional[BaseCallbackManager] = None, callback_manager: Optional[BaseCallbackManager] = None,
extra_prompt_messages: Optional[List[BaseMessagePromptTemplate]] = None, extra_prompt_messages: Optional[list[BaseMessagePromptTemplate]] = None,
system_message: Optional[SystemMessage] = SystemMessage( system_message: Optional[SystemMessage] = SystemMessage(
content="You are a helpful AI assistant." content="You are a helpful AI assistant."
), ),

View File

@ -1,4 +1,24 @@
from typing import Any, List, Optional, Sequence, Tuple, Union, cast from collections.abc import Sequence
from typing import Any, Optional, Union
from langchain.agents import BaseSingleActionAgent, OpenAIFunctionsAgent
from langchain.agents.openai_functions_agent.base import _format_intermediate_steps, _parse_ai_message
from langchain.callbacks.base import BaseCallbackManager
from langchain.callbacks.manager import Callbacks
from langchain.chat_models.openai import _convert_message_to_dict, _import_tiktoken
from langchain.memory.prompt import SUMMARY_PROMPT
from langchain.prompts.chat import BaseMessagePromptTemplate
from langchain.schema import (
AgentAction,
AgentFinish,
AIMessage,
BaseMessage,
HumanMessage,
SystemMessage,
get_buffer_string,
)
from langchain.tools import BaseTool
from pydantic import root_validator
from core.agent.agent.agent_llm_callback import AgentLLMCallback from core.agent.agent.agent_llm_callback import AgentLLMCallback
from core.agent.agent.calc_token_mixin import CalcTokenMixin, ExceededLLMTokensLimitError from core.agent.agent.calc_token_mixin import CalcTokenMixin, ExceededLLMTokensLimitError
@ -7,19 +27,7 @@ from core.entities.application_entities import ModelConfigEntity
from core.entities.message_entities import lc_messages_to_prompt_messages from core.entities.message_entities import lc_messages_to_prompt_messages
from core.model_manager import ModelInstance from core.model_manager import ModelInstance
from core.model_runtime.entities.message_entities import PromptMessage, PromptMessageTool from core.model_runtime.entities.message_entities import PromptMessage, PromptMessageTool
from core.model_runtime.model_providers.__base.large_language_model import LargeLanguageModel
from core.third_party.langchain.llms.fake import FakeLLM from core.third_party.langchain.llms.fake import FakeLLM
from langchain.agents import BaseSingleActionAgent, OpenAIFunctionsAgent
from langchain.agents.openai_functions_agent.base import _format_intermediate_steps, _parse_ai_message
from langchain.callbacks.base import BaseCallbackManager
from langchain.callbacks.manager import Callbacks
from langchain.chat_models.openai import _convert_message_to_dict, _import_tiktoken
from langchain.memory.prompt import SUMMARY_PROMPT
from langchain.prompts.chat import BaseMessagePromptTemplate
from langchain.schema import (AgentAction, AgentFinish, AIMessage, BaseMessage, HumanMessage, SystemMessage,
get_buffer_string)
from langchain.tools import BaseTool
from pydantic import root_validator
class AutoSummarizingOpenAIFunctionCallAgent(OpenAIFunctionsAgent, CalcTokenMixin): class AutoSummarizingOpenAIFunctionCallAgent(OpenAIFunctionsAgent, CalcTokenMixin):
@ -44,7 +52,7 @@ class AutoSummarizingOpenAIFunctionCallAgent(OpenAIFunctionsAgent, CalcTokenMixi
model_config: ModelConfigEntity, model_config: ModelConfigEntity,
tools: Sequence[BaseTool], tools: Sequence[BaseTool],
callback_manager: Optional[BaseCallbackManager] = None, callback_manager: Optional[BaseCallbackManager] = None,
extra_prompt_messages: Optional[List[BaseMessagePromptTemplate]] = None, extra_prompt_messages: Optional[list[BaseMessagePromptTemplate]] = None,
system_message: Optional[SystemMessage] = SystemMessage( system_message: Optional[SystemMessage] = SystemMessage(
content="You are a helpful AI assistant." content="You are a helpful AI assistant."
), ),
@ -118,7 +126,7 @@ class AutoSummarizingOpenAIFunctionCallAgent(OpenAIFunctionsAgent, CalcTokenMixi
def plan( def plan(
self, self,
intermediate_steps: List[Tuple[AgentAction, str]], intermediate_steps: list[tuple[AgentAction, str]],
callbacks: Callbacks = None, callbacks: Callbacks = None,
**kwargs: Any, **kwargs: Any,
) -> Union[AgentAction, AgentFinish]: ) -> Union[AgentAction, AgentFinish]:
@ -200,7 +208,7 @@ class AutoSummarizingOpenAIFunctionCallAgent(OpenAIFunctionsAgent, CalcTokenMixi
def return_stopped_response( def return_stopped_response(
self, self,
early_stopping_method: str, early_stopping_method: str,
intermediate_steps: List[Tuple[AgentAction, str]], intermediate_steps: list[tuple[AgentAction, str]],
**kwargs: Any, **kwargs: Any,
) -> AgentFinish: ) -> AgentFinish:
try: try:
@ -208,7 +216,7 @@ class AutoSummarizingOpenAIFunctionCallAgent(OpenAIFunctionsAgent, CalcTokenMixi
except ValueError: except ValueError:
return AgentFinish({"output": "I'm sorry, I don't know how to respond to that."}, "") return AgentFinish({"output": "I'm sorry, I don't know how to respond to that."}, "")
def summarize_messages_if_needed(self, messages: List[PromptMessage], **kwargs) -> List[PromptMessage]: def summarize_messages_if_needed(self, messages: list[PromptMessage], **kwargs) -> list[PromptMessage]:
# calculate rest tokens and summarize previous function observation messages if rest_tokens < 0 # calculate rest tokens and summarize previous function observation messages if rest_tokens < 0
rest_tokens = self.get_message_rest_tokens( rest_tokens = self.get_message_rest_tokens(
self.model_config, self.model_config,
@ -257,7 +265,7 @@ class AutoSummarizingOpenAIFunctionCallAgent(OpenAIFunctionsAgent, CalcTokenMixi
return new_messages return new_messages
def predict_new_summary( def predict_new_summary(
self, messages: List[BaseMessage], existing_summary: str self, messages: list[BaseMessage], existing_summary: str
) -> str: ) -> str:
new_lines = get_buffer_string( new_lines = get_buffer_string(
messages, messages,
@ -268,7 +276,7 @@ class AutoSummarizingOpenAIFunctionCallAgent(OpenAIFunctionsAgent, CalcTokenMixi
chain = LLMChain(model_config=self.summary_model_config, prompt=SUMMARY_PROMPT) chain = LLMChain(model_config=self.summary_model_config, prompt=SUMMARY_PROMPT)
return chain.predict(summary=existing_summary, new_lines=new_lines) return chain.predict(summary=existing_summary, new_lines=new_lines)
def get_num_tokens_from_messages(self, model_config: ModelConfigEntity, messages: List[BaseMessage], **kwargs) -> int: def get_num_tokens_from_messages(self, model_config: ModelConfigEntity, messages: list[BaseMessage], **kwargs) -> int:
"""Calculate num tokens for gpt-3.5-turbo and gpt-4 with tiktoken package. """Calculate num tokens for gpt-3.5-turbo and gpt-4 with tiktoken package.
Official documentation: https://github.com/openai/openai-cookbook/blob/ Official documentation: https://github.com/openai/openai-cookbook/blob/

View File

@ -1,8 +1,7 @@
import re import re
from typing import Any, List, Optional, Sequence, Tuple, Union, cast from collections.abc import Sequence
from typing import Any, Optional, Union, cast
from core.chain.llm_chain import LLMChain
from core.entities.application_entities import ModelConfigEntity
from langchain import BasePromptTemplate, PromptTemplate from langchain import BasePromptTemplate, PromptTemplate
from langchain.agents import Agent, AgentOutputParser, StructuredChatAgent from langchain.agents import Agent, AgentOutputParser, StructuredChatAgent
from langchain.agents.structured_chat.base import HUMAN_MESSAGE_TEMPLATE from langchain.agents.structured_chat.base import HUMAN_MESSAGE_TEMPLATE
@ -13,6 +12,9 @@ from langchain.prompts import ChatPromptTemplate, HumanMessagePromptTemplate, Sy
from langchain.schema import AgentAction, AgentFinish, OutputParserException from langchain.schema import AgentAction, AgentFinish, OutputParserException
from langchain.tools import BaseTool from langchain.tools import BaseTool
from core.chain.llm_chain import LLMChain
from core.entities.application_entities import ModelConfigEntity
FORMAT_INSTRUCTIONS = """Use a json blob to specify a tool by providing an action key (tool name) and an action_input key (tool input). FORMAT_INSTRUCTIONS = """Use a json blob to specify a tool by providing an action key (tool name) and an action_input key (tool input).
The nouns in the format of "Thought", "Action", "Action Input", "Final Answer" must be expressed in English. The nouns in the format of "Thought", "Action", "Action Input", "Final Answer" must be expressed in English.
Valid "action" values: "Final Answer" or {tool_names} Valid "action" values: "Final Answer" or {tool_names}
@ -67,7 +69,7 @@ class StructuredMultiDatasetRouterAgent(StructuredChatAgent):
def plan( def plan(
self, self,
intermediate_steps: List[Tuple[AgentAction, str]], intermediate_steps: list[tuple[AgentAction, str]],
callbacks: Callbacks = None, callbacks: Callbacks = None,
**kwargs: Any, **kwargs: Any,
) -> Union[AgentAction, AgentFinish]: ) -> Union[AgentAction, AgentFinish]:
@ -124,8 +126,8 @@ class StructuredMultiDatasetRouterAgent(StructuredChatAgent):
suffix: str = SUFFIX, suffix: str = SUFFIX,
human_message_template: str = HUMAN_MESSAGE_TEMPLATE, human_message_template: str = HUMAN_MESSAGE_TEMPLATE,
format_instructions: str = FORMAT_INSTRUCTIONS, format_instructions: str = FORMAT_INSTRUCTIONS,
input_variables: Optional[List[str]] = None, input_variables: Optional[list[str]] = None,
memory_prompts: Optional[List[BasePromptTemplate]] = None, memory_prompts: Optional[list[BasePromptTemplate]] = None,
) -> BasePromptTemplate: ) -> BasePromptTemplate:
tool_strings = [] tool_strings = []
for tool in tools: for tool in tools:
@ -152,7 +154,7 @@ class StructuredMultiDatasetRouterAgent(StructuredChatAgent):
tools: Sequence[BaseTool], tools: Sequence[BaseTool],
prefix: str = PREFIX, prefix: str = PREFIX,
format_instructions: str = FORMAT_INSTRUCTIONS, format_instructions: str = FORMAT_INSTRUCTIONS,
input_variables: Optional[List[str]] = None, input_variables: Optional[list[str]] = None,
) -> PromptTemplate: ) -> PromptTemplate:
"""Create prompt in the style of the zero shot agent. """Create prompt in the style of the zero shot agent.
@ -179,7 +181,7 @@ Thought: {agent_scratchpad}
return PromptTemplate(template=template, input_variables=input_variables) return PromptTemplate(template=template, input_variables=input_variables)
def _construct_scratchpad( def _construct_scratchpad(
self, intermediate_steps: List[Tuple[AgentAction, str]] self, intermediate_steps: list[tuple[AgentAction, str]]
) -> str: ) -> str:
agent_scratchpad = "" agent_scratchpad = ""
for action, observation in intermediate_steps: for action, observation in intermediate_steps:
@ -212,8 +214,8 @@ Thought: {agent_scratchpad}
suffix: str = SUFFIX, suffix: str = SUFFIX,
human_message_template: str = HUMAN_MESSAGE_TEMPLATE, human_message_template: str = HUMAN_MESSAGE_TEMPLATE,
format_instructions: str = FORMAT_INSTRUCTIONS, format_instructions: str = FORMAT_INSTRUCTIONS,
input_variables: Optional[List[str]] = None, input_variables: Optional[list[str]] = None,
memory_prompts: Optional[List[BasePromptTemplate]] = None, memory_prompts: Optional[list[BasePromptTemplate]] = None,
**kwargs: Any, **kwargs: Any,
) -> Agent: ) -> Agent:
"""Construct an agent from an LLM and tools.""" """Construct an agent from an LLM and tools."""

View File

@ -1,11 +1,7 @@
import re import re
from typing import Any, List, Optional, Sequence, Tuple, Union, cast from collections.abc import Sequence
from typing import Any, Optional, Union, cast
from core.agent.agent.agent_llm_callback import AgentLLMCallback
from core.agent.agent.calc_token_mixin import CalcTokenMixin, ExceededLLMTokensLimitError
from core.chain.llm_chain import LLMChain
from core.entities.application_entities import ModelConfigEntity
from core.entities.message_entities import lc_messages_to_prompt_messages
from langchain import BasePromptTemplate, PromptTemplate from langchain import BasePromptTemplate, PromptTemplate
from langchain.agents import Agent, AgentOutputParser, StructuredChatAgent from langchain.agents import Agent, AgentOutputParser, StructuredChatAgent
from langchain.agents.structured_chat.base import HUMAN_MESSAGE_TEMPLATE from langchain.agents.structured_chat.base import HUMAN_MESSAGE_TEMPLATE
@ -14,10 +10,23 @@ from langchain.callbacks.base import BaseCallbackManager
from langchain.callbacks.manager import Callbacks from langchain.callbacks.manager import Callbacks
from langchain.memory.prompt import SUMMARY_PROMPT from langchain.memory.prompt import SUMMARY_PROMPT
from langchain.prompts import ChatPromptTemplate, HumanMessagePromptTemplate, SystemMessagePromptTemplate from langchain.prompts import ChatPromptTemplate, HumanMessagePromptTemplate, SystemMessagePromptTemplate
from langchain.schema import (AgentAction, AgentFinish, AIMessage, BaseMessage, HumanMessage, OutputParserException, from langchain.schema import (
get_buffer_string) AgentAction,
AgentFinish,
AIMessage,
BaseMessage,
HumanMessage,
OutputParserException,
get_buffer_string,
)
from langchain.tools import BaseTool from langchain.tools import BaseTool
from core.agent.agent.agent_llm_callback import AgentLLMCallback
from core.agent.agent.calc_token_mixin import CalcTokenMixin, ExceededLLMTokensLimitError
from core.chain.llm_chain import LLMChain
from core.entities.application_entities import ModelConfigEntity
from core.entities.message_entities import lc_messages_to_prompt_messages
FORMAT_INSTRUCTIONS = """Use a json blob to specify a tool by providing an action key (tool name) and an action_input key (tool input). FORMAT_INSTRUCTIONS = """Use a json blob to specify a tool by providing an action key (tool name) and an action_input key (tool input).
The nouns in the format of "Thought", "Action", "Action Input", "Final Answer" must be expressed in English. The nouns in the format of "Thought", "Action", "Action Input", "Final Answer" must be expressed in English.
Valid "action" values: "Final Answer" or {tool_names} Valid "action" values: "Final Answer" or {tool_names}
@ -74,7 +83,7 @@ class AutoSummarizingStructuredChatAgent(StructuredChatAgent, CalcTokenMixin):
def plan( def plan(
self, self,
intermediate_steps: List[Tuple[AgentAction, str]], intermediate_steps: list[tuple[AgentAction, str]],
callbacks: Callbacks = None, callbacks: Callbacks = None,
**kwargs: Any, **kwargs: Any,
) -> Union[AgentAction, AgentFinish]: ) -> Union[AgentAction, AgentFinish]:
@ -119,7 +128,7 @@ class AutoSummarizingStructuredChatAgent(StructuredChatAgent, CalcTokenMixin):
return AgentFinish({"output": "I'm sorry, the answer of model is invalid, " return AgentFinish({"output": "I'm sorry, the answer of model is invalid, "
"I don't know how to respond to that."}, "") "I don't know how to respond to that."}, "")
def summarize_messages(self, intermediate_steps: List[Tuple[AgentAction, str]], **kwargs): def summarize_messages(self, intermediate_steps: list[tuple[AgentAction, str]], **kwargs):
if len(intermediate_steps) >= 2 and self.summary_model_config: if len(intermediate_steps) >= 2 and self.summary_model_config:
should_summary_intermediate_steps = intermediate_steps[self.moving_summary_index:-1] should_summary_intermediate_steps = intermediate_steps[self.moving_summary_index:-1]
should_summary_messages = [AIMessage(content=observation) should_summary_messages = [AIMessage(content=observation)
@ -146,7 +155,7 @@ class AutoSummarizingStructuredChatAgent(StructuredChatAgent, CalcTokenMixin):
return self.get_full_inputs([intermediate_steps[-1]], **kwargs) return self.get_full_inputs([intermediate_steps[-1]], **kwargs)
def predict_new_summary( def predict_new_summary(
self, messages: List[BaseMessage], existing_summary: str self, messages: list[BaseMessage], existing_summary: str
) -> str: ) -> str:
new_lines = get_buffer_string( new_lines = get_buffer_string(
messages, messages,
@ -165,8 +174,8 @@ class AutoSummarizingStructuredChatAgent(StructuredChatAgent, CalcTokenMixin):
suffix: str = SUFFIX, suffix: str = SUFFIX,
human_message_template: str = HUMAN_MESSAGE_TEMPLATE, human_message_template: str = HUMAN_MESSAGE_TEMPLATE,
format_instructions: str = FORMAT_INSTRUCTIONS, format_instructions: str = FORMAT_INSTRUCTIONS,
input_variables: Optional[List[str]] = None, input_variables: Optional[list[str]] = None,
memory_prompts: Optional[List[BasePromptTemplate]] = None, memory_prompts: Optional[list[BasePromptTemplate]] = None,
) -> BasePromptTemplate: ) -> BasePromptTemplate:
tool_strings = [] tool_strings = []
for tool in tools: for tool in tools:
@ -192,7 +201,7 @@ class AutoSummarizingStructuredChatAgent(StructuredChatAgent, CalcTokenMixin):
tools: Sequence[BaseTool], tools: Sequence[BaseTool],
prefix: str = PREFIX, prefix: str = PREFIX,
format_instructions: str = FORMAT_INSTRUCTIONS, format_instructions: str = FORMAT_INSTRUCTIONS,
input_variables: Optional[List[str]] = None, input_variables: Optional[list[str]] = None,
) -> PromptTemplate: ) -> PromptTemplate:
"""Create prompt in the style of the zero shot agent. """Create prompt in the style of the zero shot agent.
@ -219,7 +228,7 @@ Thought: {agent_scratchpad}
return PromptTemplate(template=template, input_variables=input_variables) return PromptTemplate(template=template, input_variables=input_variables)
def _construct_scratchpad( def _construct_scratchpad(
self, intermediate_steps: List[Tuple[AgentAction, str]] self, intermediate_steps: list[tuple[AgentAction, str]]
) -> str: ) -> str:
agent_scratchpad = "" agent_scratchpad = ""
for action, observation in intermediate_steps: for action, observation in intermediate_steps:
@ -252,8 +261,8 @@ Thought: {agent_scratchpad}
suffix: str = SUFFIX, suffix: str = SUFFIX,
human_message_template: str = HUMAN_MESSAGE_TEMPLATE, human_message_template: str = HUMAN_MESSAGE_TEMPLATE,
format_instructions: str = FORMAT_INSTRUCTIONS, format_instructions: str = FORMAT_INSTRUCTIONS,
input_variables: Optional[List[str]] = None, input_variables: Optional[list[str]] = None,
memory_prompts: Optional[List[BasePromptTemplate]] = None, memory_prompts: Optional[list[BasePromptTemplate]] = None,
agent_llm_callback: Optional[AgentLLMCallback] = None, agent_llm_callback: Optional[AgentLLMCallback] = None,
**kwargs: Any, **kwargs: Any,
) -> Agent: ) -> Agent:

View File

@ -2,6 +2,12 @@ import enum
import logging import logging
from typing import Optional, Union from typing import Optional, Union
from langchain.agents import AgentExecutor as LCAgentExecutor
from langchain.agents import BaseMultiActionAgent, BaseSingleActionAgent
from langchain.callbacks.manager import Callbacks
from langchain.tools import BaseTool
from pydantic import BaseModel, Extra
from core.agent.agent.agent_llm_callback import AgentLLMCallback from core.agent.agent.agent_llm_callback import AgentLLMCallback
from core.agent.agent.multi_dataset_router_agent import MultiDatasetRouterAgent from core.agent.agent.multi_dataset_router_agent import MultiDatasetRouterAgent
from core.agent.agent.openai_function_call import AutoSummarizingOpenAIFunctionCallAgent from core.agent.agent.openai_function_call import AutoSummarizingOpenAIFunctionCallAgent
@ -15,11 +21,6 @@ from core.memory.token_buffer_memory import TokenBufferMemory
from core.model_runtime.errors.invoke import InvokeError from core.model_runtime.errors.invoke import InvokeError
from core.tools.tool.dataset_retriever.dataset_multi_retriever_tool import DatasetMultiRetrieverTool from core.tools.tool.dataset_retriever.dataset_multi_retriever_tool import DatasetMultiRetrieverTool
from core.tools.tool.dataset_retriever.dataset_retriever_tool import DatasetRetrieverTool from core.tools.tool.dataset_retriever.dataset_retriever_tool import DatasetRetrieverTool
from langchain.agents import AgentExecutor as LCAgentExecutor
from langchain.agents import BaseMultiActionAgent, BaseSingleActionAgent
from langchain.callbacks.manager import Callbacks
from langchain.tools import BaseTool
from pydantic import BaseModel, Extra
class PlanningStrategy(str, enum.Enum): class PlanningStrategy(str, enum.Enum):

View File

@ -1,10 +1,16 @@
import time import time
from typing import Generator, List, Optional, Tuple, Union, cast from collections.abc import Generator
from typing import Optional, Union, cast
from core.application_queue_manager import ApplicationQueueManager, PublishFrom from core.application_queue_manager import ApplicationQueueManager, PublishFrom
from core.entities.application_entities import (ApplicationGenerateEntity, AppOrchestrationConfigEntity, from core.entities.application_entities import (
ExternalDataVariableEntity, InvokeFrom, ModelConfigEntity, ApplicationGenerateEntity,
PromptTemplateEntity) AppOrchestrationConfigEntity,
ExternalDataVariableEntity,
InvokeFrom,
ModelConfigEntity,
PromptTemplateEntity,
)
from core.features.annotation_reply import AnnotationReplyFeature from core.features.annotation_reply import AnnotationReplyFeature
from core.features.external_data_fetch import ExternalDataFetchFeature from core.features.external_data_fetch import ExternalDataFetchFeature
from core.features.hosting_moderation import HostingModerationFeature from core.features.hosting_moderation import HostingModerationFeature
@ -79,7 +85,7 @@ class AppRunner:
return rest_tokens return rest_tokens
def recale_llm_max_tokens(self, model_config: ModelConfigEntity, def recale_llm_max_tokens(self, model_config: ModelConfigEntity,
prompt_messages: List[PromptMessage]): prompt_messages: list[PromptMessage]):
# recalc max_tokens if sum(prompt_token + max_tokens) over model token limit # recalc max_tokens if sum(prompt_token + max_tokens) over model token limit
model_type_instance = model_config.provider_model_bundle.model_type_instance model_type_instance = model_config.provider_model_bundle.model_type_instance
model_type_instance = cast(LargeLanguageModel, model_type_instance) model_type_instance = cast(LargeLanguageModel, model_type_instance)
@ -121,7 +127,7 @@ class AppRunner:
query: Optional[str] = None, query: Optional[str] = None,
context: Optional[str] = None, context: Optional[str] = None,
memory: Optional[TokenBufferMemory] = None) \ memory: Optional[TokenBufferMemory] = None) \
-> Tuple[List[PromptMessage], Optional[List[str]]]: -> tuple[list[PromptMessage], Optional[list[str]]]:
""" """
Organize prompt messages Organize prompt messages
:param context: :param context:
@ -290,7 +296,7 @@ class AppRunner:
tenant_id: str, tenant_id: str,
app_orchestration_config_entity: AppOrchestrationConfigEntity, app_orchestration_config_entity: AppOrchestrationConfigEntity,
inputs: dict, inputs: dict,
query: str) -> Tuple[bool, dict, str]: query: str) -> tuple[bool, dict, str]:
""" """
Process sensitive_word_avoidance. Process sensitive_word_avoidance.
:param app_id: app id :param app_id: app id

View File

@ -38,7 +38,7 @@ class AssistantApplicationRunner(AppRunner):
""" """
app_record = db.session.query(App).filter(App.id == application_generate_entity.app_id).first() app_record = db.session.query(App).filter(App.id == application_generate_entity.app_id).first()
if not app_record: if not app_record:
raise ValueError(f"App not found") raise ValueError("App not found")
app_orchestration_config = application_generate_entity.app_orchestration_config_entity app_orchestration_config = application_generate_entity.app_orchestration_config_entity
@ -222,6 +222,7 @@ class AssistantApplicationRunner(AppRunner):
conversation=conversation, conversation=conversation,
message=message, message=message,
query=query, query=query,
inputs=inputs,
) )
elif agent_entity.strategy == AgentEntity.Strategy.FUNCTION_CALLING: elif agent_entity.strategy == AgentEntity.Strategy.FUNCTION_CALLING:
assistant_fc_runner = AssistantFunctionCallApplicationRunner( assistant_fc_runner = AssistantFunctionCallApplicationRunner(

View File

@ -35,7 +35,7 @@ class BasicApplicationRunner(AppRunner):
""" """
app_record = db.session.query(App).filter(App.id == application_generate_entity.app_id).first() app_record = db.session.query(App).filter(App.id == application_generate_entity.app_id).first()
if not app_record: if not app_record:
raise ValueError(f"App not found") raise ValueError("App not found")
app_orchestration_config = application_generate_entity.app_orchestration_config_entity app_orchestration_config = application_generate_entity.app_orchestration_config_entity

View File

@ -1,30 +1,45 @@
import json import json
import logging import logging
import time import time
from typing import Generator, Optional, Union, cast from collections.abc import Generator
from typing import Optional, Union, cast
from pydantic import BaseModel
from core.app_runner.moderation_handler import ModerationRule, OutputModerationHandler from core.app_runner.moderation_handler import ModerationRule, OutputModerationHandler
from core.application_queue_manager import ApplicationQueueManager, PublishFrom from core.application_queue_manager import ApplicationQueueManager, PublishFrom
from core.entities.application_entities import ApplicationGenerateEntity, InvokeFrom from core.entities.application_entities import ApplicationGenerateEntity, InvokeFrom
from core.entities.queue_entities import (AnnotationReplyEvent, QueueAgentMessageEvent, QueueAgentThoughtEvent, from core.entities.queue_entities import (
QueueErrorEvent, QueueMessageEndEvent, QueueMessageEvent, AnnotationReplyEvent,
QueueMessageFileEvent, QueueMessageReplaceEvent, QueuePingEvent, QueueAgentMessageEvent,
QueueRetrieverResourcesEvent, QueueStopEvent) QueueAgentThoughtEvent,
QueueErrorEvent,
QueueMessageEndEvent,
QueueMessageEvent,
QueueMessageFileEvent,
QueueMessageReplaceEvent,
QueuePingEvent,
QueueRetrieverResourcesEvent,
QueueStopEvent,
)
from core.errors.error import ModelCurrentlyNotSupportError, ProviderTokenNotInitError, QuotaExceededError from core.errors.error import ModelCurrentlyNotSupportError, ProviderTokenNotInitError, QuotaExceededError
from core.model_runtime.entities.llm_entities import LLMResult, LLMResultChunk, LLMResultChunkDelta, LLMUsage from core.model_runtime.entities.llm_entities import LLMResult, LLMResultChunk, LLMResultChunkDelta, LLMUsage
from core.model_runtime.entities.message_entities import (AssistantPromptMessage, ImagePromptMessageContent, from core.model_runtime.entities.message_entities import (
PromptMessage, PromptMessageContentType, PromptMessageRole, AssistantPromptMessage,
TextPromptMessageContent) ImagePromptMessageContent,
PromptMessage,
PromptMessageContentType,
PromptMessageRole,
TextPromptMessageContent,
)
from core.model_runtime.errors.invoke import InvokeAuthorizationError, InvokeError from core.model_runtime.errors.invoke import InvokeAuthorizationError, InvokeError
from core.model_runtime.model_providers.__base.large_language_model import LargeLanguageModel from core.model_runtime.model_providers.__base.large_language_model import LargeLanguageModel
from core.model_runtime.utils.encoders import jsonable_encoder from core.model_runtime.utils.encoders import jsonable_encoder
from core.prompt.prompt_template import PromptTemplateParser from core.prompt.prompt_template import PromptTemplateParser
from core.tools.tool_file_manager import ToolFileManager from core.tools.tool_file_manager import ToolFileManager
from core.tools.tool_manager import ToolManager
from events.message_event import message_was_created from events.message_event import message_was_created
from extensions.ext_database import db from extensions.ext_database import db
from models.model import Conversation, Message, MessageAgentThought, MessageFile from models.model import Conversation, Message, MessageAgentThought, MessageFile
from pydantic import BaseModel
from services.annotation_service import AppAnnotationService from services.annotation_service import AppAnnotationService
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -104,7 +119,7 @@ class GenerateTaskPipeline:
} }
self._task_state.llm_result.message.content = annotation.content self._task_state.llm_result.message.content = annotation.content
elif isinstance(event, (QueueStopEvent, QueueMessageEndEvent)): elif isinstance(event, QueueStopEvent | QueueMessageEndEvent):
if isinstance(event, QueueMessageEndEvent): if isinstance(event, QueueMessageEndEvent):
self._task_state.llm_result = event.llm_result self._task_state.llm_result = event.llm_result
else: else:
@ -187,7 +202,7 @@ class GenerateTaskPipeline:
data = self._error_to_stream_response_data(self._handle_error(event)) data = self._error_to_stream_response_data(self._handle_error(event))
yield self._yield_response(data) yield self._yield_response(data)
break break
elif isinstance(event, (QueueStopEvent, QueueMessageEndEvent)): elif isinstance(event, QueueStopEvent | QueueMessageEndEvent):
if isinstance(event, QueueMessageEndEvent): if isinstance(event, QueueMessageEndEvent):
self._task_state.llm_result = event.llm_result self._task_state.llm_result = event.llm_result
else: else:
@ -339,7 +354,7 @@ class GenerateTaskPipeline:
yield self._yield_response(response) yield self._yield_response(response)
elif isinstance(event, (QueueMessageEvent, QueueAgentMessageEvent)): elif isinstance(event, QueueMessageEvent | QueueAgentMessageEvent):
chunk = event.chunk chunk = event.chunk
delta_text = chunk.delta.message.content delta_text = chunk.delta.message.content
if delta_text is None: if delta_text is None:
@ -477,7 +492,11 @@ class GenerateTaskPipeline:
} }
# Determine the response based on the type of exception # Determine the response based on the type of exception
data = error_responses.get(type(e)) data = None
for k, v in error_responses.items():
if isinstance(e, k):
data = v
if data: if data:
data.setdefault('message', getattr(e, 'description', str(e))) data.setdefault('message', getattr(e, 'description', str(e)))
else: else:

View File

@ -1,20 +1,21 @@
import logging import logging
import threading import threading
import time import time
from typing import Any, Dict, Optional from typing import Any, Optional
from flask import Flask, current_app
from pydantic import BaseModel
from core.application_queue_manager import PublishFrom from core.application_queue_manager import PublishFrom
from core.moderation.base import ModerationAction, ModerationOutputsResult from core.moderation.base import ModerationAction, ModerationOutputsResult
from core.moderation.factory import ModerationFactory from core.moderation.factory import ModerationFactory
from flask import Flask, current_app
from pydantic import BaseModel
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class ModerationRule(BaseModel): class ModerationRule(BaseModel):
type: str type: str
config: Dict[str, Any] config: dict[str, Any]
class OutputModerationHandler(BaseModel): class OutputModerationHandler(BaseModel):

View File

@ -2,19 +2,34 @@ import json
import logging import logging
import threading import threading
import uuid import uuid
from typing import Any, Generator, Optional, Tuple, Union, cast from collections.abc import Generator
from typing import Any, Optional, Union, cast
from flask import Flask, current_app
from pydantic import ValidationError
from core.app_runner.assistant_app_runner import AssistantApplicationRunner from core.app_runner.assistant_app_runner import AssistantApplicationRunner
from core.app_runner.basic_app_runner import BasicApplicationRunner from core.app_runner.basic_app_runner import BasicApplicationRunner
from core.app_runner.generate_task_pipeline import GenerateTaskPipeline from core.app_runner.generate_task_pipeline import GenerateTaskPipeline
from core.application_queue_manager import ApplicationQueueManager, ConversationTaskStoppedException, PublishFrom from core.application_queue_manager import ApplicationQueueManager, ConversationTaskStoppedException, PublishFrom
from core.entities.application_entities import (AdvancedChatPromptTemplateEntity, from core.entities.application_entities import (
AdvancedCompletionPromptTemplateEntity, AgentEntity, AgentPromptEntity, AdvancedChatPromptTemplateEntity,
AgentToolEntity, ApplicationGenerateEntity, AdvancedCompletionPromptTemplateEntity,
AppOrchestrationConfigEntity, DatasetEntity, AgentEntity,
DatasetRetrieveConfigEntity, ExternalDataVariableEntity, AgentPromptEntity,
FileUploadEntity, InvokeFrom, ModelConfigEntity, PromptTemplateEntity, AgentToolEntity,
SensitiveWordAvoidanceEntity) ApplicationGenerateEntity,
AppOrchestrationConfigEntity,
DatasetEntity,
DatasetRetrieveConfigEntity,
ExternalDataVariableEntity,
FileUploadEntity,
InvokeFrom,
ModelConfigEntity,
PromptTemplateEntity,
SensitiveWordAvoidanceEntity,
TextToSpeechEntity,
)
from core.entities.model_entities import ModelStatus from core.entities.model_entities import ModelStatus
from core.errors.error import ModelCurrentlyNotSupportError, ProviderTokenNotInitError, QuotaExceededError from core.errors.error import ModelCurrentlyNotSupportError, ProviderTokenNotInitError, QuotaExceededError
from core.file.file_obj import FileObj from core.file.file_obj import FileObj
@ -26,10 +41,8 @@ from core.prompt.prompt_template import PromptTemplateParser
from core.provider_manager import ProviderManager from core.provider_manager import ProviderManager
from core.tools.prompt.template import REACT_PROMPT_TEMPLATES from core.tools.prompt.template import REACT_PROMPT_TEMPLATES
from extensions.ext_database import db from extensions.ext_database import db
from flask import Flask, current_app
from models.account import Account from models.account import Account
from models.model import App, Conversation, EndUser, Message, MessageFile from models.model import App, Conversation, EndUser, Message, MessageFile
from pydantic import ValidationError
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -560,7 +573,11 @@ class ApplicationManager:
text_to_speech_dict = copy_app_model_config_dict.get('text_to_speech') text_to_speech_dict = copy_app_model_config_dict.get('text_to_speech')
if text_to_speech_dict: if text_to_speech_dict:
if 'enabled' in text_to_speech_dict and text_to_speech_dict['enabled']: if 'enabled' in text_to_speech_dict and text_to_speech_dict['enabled']:
properties['text_to_speech'] = True properties['text_to_speech'] = TextToSpeechEntity(
enabled=text_to_speech_dict.get('enabled'),
voice=text_to_speech_dict.get('voice'),
language=text_to_speech_dict.get('language'),
)
# sensitive word avoidance # sensitive word avoidance
sensitive_word_avoidance_dict = copy_app_model_config_dict.get('sensitive_word_avoidance') sensitive_word_avoidance_dict = copy_app_model_config_dict.get('sensitive_word_avoidance')
@ -574,7 +591,7 @@ class ApplicationManager:
return AppOrchestrationConfigEntity(**properties) return AppOrchestrationConfigEntity(**properties)
def _init_generate_records(self, application_generate_entity: ApplicationGenerateEntity) \ def _init_generate_records(self, application_generate_entity: ApplicationGenerateEntity) \
-> Tuple[Conversation, Message]: -> tuple[Conversation, Message]:
""" """
Initialize generate records Initialize generate records
:param application_generate_entity: application generate entity :param application_generate_entity: application generate entity

View File

@ -1,17 +1,30 @@
import queue import queue
import time import time
from collections.abc import Generator
from enum import Enum from enum import Enum
from typing import Any, Generator from typing import Any
from sqlalchemy.orm import DeclarativeMeta
from core.entities.application_entities import InvokeFrom from core.entities.application_entities import InvokeFrom
from core.entities.queue_entities import (AnnotationReplyEvent, AppQueueEvent, QueueAgentMessageEvent, from core.entities.queue_entities import (
QueueAgentThoughtEvent, QueueErrorEvent, QueueMessage, QueueMessageEndEvent, AnnotationReplyEvent,
QueueMessageEvent, QueueMessageFileEvent, QueueMessageReplaceEvent, AppQueueEvent,
QueuePingEvent, QueueRetrieverResourcesEvent, QueueStopEvent) QueueAgentMessageEvent,
QueueAgentThoughtEvent,
QueueErrorEvent,
QueueMessage,
QueueMessageEndEvent,
QueueMessageEvent,
QueueMessageFileEvent,
QueueMessageReplaceEvent,
QueuePingEvent,
QueueRetrieverResourcesEvent,
QueueStopEvent,
)
from core.model_runtime.entities.llm_entities import LLMResult, LLMResultChunk from core.model_runtime.entities.llm_entities import LLMResult, LLMResultChunk
from extensions.ext_redis import redis_client from extensions.ext_redis import redis_client
from models.model import MessageAgentThought, MessageFile from models.model import MessageAgentThought, MessageFile
from sqlalchemy.orm import DeclarativeMeta
class PublishFrom(Enum): class PublishFrom(Enum):

View File

@ -1,7 +1,11 @@
import json import json
import logging import logging
import time import time
from typing import Any, Dict, List, Optional, Union, cast from typing import Any, Optional, Union, cast
from langchain.agents import openai_functions_agent, openai_functions_multi_agent
from langchain.callbacks.base import BaseCallbackHandler
from langchain.schema import AgentAction, AgentFinish, BaseMessage, LLMResult
from core.application_queue_manager import ApplicationQueueManager, PublishFrom from core.application_queue_manager import ApplicationQueueManager, PublishFrom
from core.callback_handler.entity.agent_loop import AgentLoop from core.callback_handler.entity.agent_loop import AgentLoop
@ -10,9 +14,6 @@ from core.model_runtime.entities.llm_entities import LLMResult as RuntimeLLMResu
from core.model_runtime.entities.message_entities import AssistantPromptMessage, PromptMessage, UserPromptMessage from core.model_runtime.entities.message_entities import AssistantPromptMessage, PromptMessage, UserPromptMessage
from core.model_runtime.model_providers.__base.large_language_model import LargeLanguageModel from core.model_runtime.model_providers.__base.large_language_model import LargeLanguageModel
from extensions.ext_database import db from extensions.ext_database import db
from langchain.agents import openai_functions_agent, openai_functions_multi_agent
from langchain.callbacks.base import BaseCallbackHandler
from langchain.schema import AgentAction, AgentFinish, BaseMessage, ChatGeneration, LLMResult
from models.model import Message, MessageAgentThought, MessageChain from models.model import Message, MessageAgentThought, MessageChain
@ -36,7 +37,7 @@ class AgentLoopGatherCallbackHandler(BaseCallbackHandler):
self._message_agent_thought = None self._message_agent_thought = None
@property @property
def agent_loops(self) -> List[AgentLoop]: def agent_loops(self) -> list[AgentLoop]:
return self._agent_loops return self._agent_loops
def clear_agent_loops(self) -> None: def clear_agent_loops(self) -> None:
@ -94,14 +95,14 @@ class AgentLoopGatherCallbackHandler(BaseCallbackHandler):
def on_chat_model_start( def on_chat_model_start(
self, self,
serialized: Dict[str, Any], serialized: dict[str, Any],
messages: List[List[BaseMessage]], messages: list[list[BaseMessage]],
**kwargs: Any **kwargs: Any
) -> Any: ) -> Any:
pass pass
def on_llm_start( def on_llm_start(
self, serialized: Dict[str, Any], prompts: List[str], **kwargs: Any self, serialized: dict[str, Any], prompts: list[str], **kwargs: Any
) -> None: ) -> None:
pass pass
@ -119,7 +120,7 @@ class AgentLoopGatherCallbackHandler(BaseCallbackHandler):
def on_tool_start( def on_tool_start(
self, self,
serialized: Dict[str, Any], serialized: dict[str, Any],
input_str: str, input_str: str,
**kwargs: Any, **kwargs: Any,
) -> None: ) -> None:

View File

@ -1,5 +1,5 @@
import os import os
from typing import Any, Dict, Optional, Union from typing import Any, Optional, Union
from langchain.callbacks.base import BaseCallbackHandler from langchain.callbacks.base import BaseCallbackHandler
from langchain.input import print_text from langchain.input import print_text
@ -21,7 +21,7 @@ class DifyAgentCallbackHandler(BaseCallbackHandler, BaseModel):
def on_tool_start( def on_tool_start(
self, self,
tool_name: str, tool_name: str,
tool_inputs: Dict[str, Any], tool_inputs: dict[str, Any],
) -> None: ) -> None:
"""Do nothing.""" """Do nothing."""
print_text("\n[on_tool_start] ToolCall:" + tool_name + "\n" + str(tool_inputs) + "\n", color=self.color) print_text("\n[on_tool_start] ToolCall:" + tool_name + "\n" + str(tool_inputs) + "\n", color=self.color)
@ -29,7 +29,7 @@ class DifyAgentCallbackHandler(BaseCallbackHandler, BaseModel):
def on_tool_end( def on_tool_end(
self, self,
tool_name: str, tool_name: str,
tool_inputs: Dict[str, Any], tool_inputs: dict[str, Any],
tool_outputs: str, tool_outputs: str,
) -> None: ) -> None:
"""If not the final action, print out observation.""" """If not the final action, print out observation."""

View File

@ -1,9 +1,9 @@
from typing import List, Union
from langchain.schema import Document
from core.application_queue_manager import ApplicationQueueManager, PublishFrom from core.application_queue_manager import ApplicationQueueManager, PublishFrom
from core.entities.application_entities import InvokeFrom from core.entities.application_entities import InvokeFrom
from extensions.ext_database import db from extensions.ext_database import db
from langchain.schema import Document
from models.dataset import DatasetQuery, DocumentSegment from models.dataset import DatasetQuery, DocumentSegment
from models.model import DatasetRetrieverResource from models.model import DatasetRetrieverResource
@ -39,22 +39,26 @@ class DatasetIndexToolCallbackHandler:
db.session.add(dataset_query) db.session.add(dataset_query)
db.session.commit() db.session.commit()
def on_tool_end(self, documents: List[Document]) -> None: def on_tool_end(self, documents: list[Document]) -> None:
"""Handle tool end.""" """Handle tool end."""
for document in documents: for document in documents:
doc_id = document.metadata['doc_id'] query = db.session.query(DocumentSegment).filter(
DocumentSegment.index_node_id == document.metadata['doc_id']
)
# if 'dataset_id' in document.metadata:
if 'dataset_id' in document.metadata:
query = query.filter(DocumentSegment.dataset_id == document.metadata['dataset_id'])
# add hit count to document segment # add hit count to document segment
db.session.query(DocumentSegment).filter( query.update(
DocumentSegment.index_node_id == doc_id
).update(
{DocumentSegment.hit_count: DocumentSegment.hit_count + 1}, {DocumentSegment.hit_count: DocumentSegment.hit_count + 1},
synchronize_session=False synchronize_session=False
) )
db.session.commit() db.session.commit()
def return_retriever_resource_info(self, resource: List): def return_retriever_resource_info(self, resource: list):
"""Handle return_retriever_resource_info.""" """Handle return_retriever_resource_info."""
if resource and len(resource) > 0: if resource and len(resource) > 0:
for item in resource: for item in resource:

View File

@ -1,6 +1,6 @@
import os import os
import sys import sys
from typing import Any, Dict, List, Optional, Union from typing import Any, Optional, Union
from langchain.callbacks.base import BaseCallbackHandler from langchain.callbacks.base import BaseCallbackHandler
from langchain.input import print_text from langchain.input import print_text
@ -16,8 +16,8 @@ class DifyStdOutCallbackHandler(BaseCallbackHandler):
def on_chat_model_start( def on_chat_model_start(
self, self,
serialized: Dict[str, Any], serialized: dict[str, Any],
messages: List[List[BaseMessage]], messages: list[list[BaseMessage]],
**kwargs: Any **kwargs: Any
) -> Any: ) -> Any:
print_text("\n[on_chat_model_start]\n", color='blue') print_text("\n[on_chat_model_start]\n", color='blue')
@ -26,7 +26,7 @@ class DifyStdOutCallbackHandler(BaseCallbackHandler):
print_text(str(sub_message) + "\n", color='blue') print_text(str(sub_message) + "\n", color='blue')
def on_llm_start( def on_llm_start(
self, serialized: Dict[str, Any], prompts: List[str], **kwargs: Any self, serialized: dict[str, Any], prompts: list[str], **kwargs: Any
) -> None: ) -> None:
"""Print out the prompts.""" """Print out the prompts."""
print_text("\n[on_llm_start]\n", color='blue') print_text("\n[on_llm_start]\n", color='blue')
@ -48,13 +48,13 @@ class DifyStdOutCallbackHandler(BaseCallbackHandler):
print_text("\n[on_llm_error]\nError: " + str(error) + "\n", color='blue') print_text("\n[on_llm_error]\nError: " + str(error) + "\n", color='blue')
def on_chain_start( def on_chain_start(
self, serialized: Dict[str, Any], inputs: Dict[str, Any], **kwargs: Any self, serialized: dict[str, Any], inputs: dict[str, Any], **kwargs: Any
) -> None: ) -> None:
"""Print out that we are entering a chain.""" """Print out that we are entering a chain."""
chain_type = serialized['id'][-1] chain_type = serialized['id'][-1]
print_text("\n[on_chain_start]\nChain: " + chain_type + "\nInputs: " + str(inputs) + "\n", color='pink') print_text("\n[on_chain_start]\nChain: " + chain_type + "\nInputs: " + str(inputs) + "\n", color='pink')
def on_chain_end(self, outputs: Dict[str, Any], **kwargs: Any) -> None: def on_chain_end(self, outputs: dict[str, Any], **kwargs: Any) -> None:
"""Print out that we finished a chain.""" """Print out that we finished a chain."""
print_text("\n[on_chain_end]\nOutputs: " + str(outputs) + "\n", color='pink') print_text("\n[on_chain_end]\nOutputs: " + str(outputs) + "\n", color='pink')
@ -66,7 +66,7 @@ class DifyStdOutCallbackHandler(BaseCallbackHandler):
def on_tool_start( def on_tool_start(
self, self,
serialized: Dict[str, Any], serialized: dict[str, Any],
input_str: str, input_str: str,
**kwargs: Any, **kwargs: Any,
) -> None: ) -> None:

View File

@ -1,26 +1,27 @@
from typing import Any, Dict, List, Optional from typing import Any, Optional
from langchain import LLMChain as LCLLMChain
from langchain.callbacks.manager import CallbackManagerForChainRun
from langchain.schema import Generation, LLMResult
from langchain.schema.language_model import BaseLanguageModel
from core.agent.agent.agent_llm_callback import AgentLLMCallback from core.agent.agent.agent_llm_callback import AgentLLMCallback
from core.entities.application_entities import ModelConfigEntity from core.entities.application_entities import ModelConfigEntity
from core.entities.message_entities import lc_messages_to_prompt_messages from core.entities.message_entities import lc_messages_to_prompt_messages
from core.model_manager import ModelInstance from core.model_manager import ModelInstance
from core.third_party.langchain.llms.fake import FakeLLM from core.third_party.langchain.llms.fake import FakeLLM
from langchain import LLMChain as LCLLMChain
from langchain.callbacks.manager import CallbackManagerForChainRun
from langchain.schema import Generation, LLMResult
from langchain.schema.language_model import BaseLanguageModel
class LLMChain(LCLLMChain): class LLMChain(LCLLMChain):
model_config: ModelConfigEntity model_config: ModelConfigEntity
"""The language model instance to use.""" """The language model instance to use."""
llm: BaseLanguageModel = FakeLLM(response="") llm: BaseLanguageModel = FakeLLM(response="")
parameters: Dict[str, Any] = {} parameters: dict[str, Any] = {}
agent_llm_callback: Optional[AgentLLMCallback] = None agent_llm_callback: Optional[AgentLLMCallback] = None
def generate( def generate(
self, self,
input_list: List[Dict[str, Any]], input_list: list[dict[str, Any]],
run_manager: Optional[CallbackManagerForChainRun] = None, run_manager: Optional[CallbackManagerForChainRun] = None,
) -> LLMResult: ) -> LLMResult:
"""Generate LLM result from inputs.""" """Generate LLM result from inputs."""

View File

@ -1,8 +1,12 @@
import tempfile import tempfile
from pathlib import Path from pathlib import Path
from typing import List, Optional, Union from typing import Optional, Union
import requests import requests
from flask import current_app
from langchain.document_loaders import Docx2txtLoader, TextLoader
from langchain.schema import Document
from core.data_loader.loader.csv_loader import CSVLoader from core.data_loader.loader.csv_loader import CSVLoader
from core.data_loader.loader.excel import ExcelLoader from core.data_loader.loader.excel import ExcelLoader
from core.data_loader.loader.html import HTMLLoader from core.data_loader.loader.html import HTMLLoader
@ -16,9 +20,6 @@ from core.data_loader.loader.unstructured.unstructured_pptx import UnstructuredP
from core.data_loader.loader.unstructured.unstructured_text import UnstructuredTextLoader from core.data_loader.loader.unstructured.unstructured_text import UnstructuredTextLoader
from core.data_loader.loader.unstructured.unstructured_xml import UnstructuredXmlLoader from core.data_loader.loader.unstructured.unstructured_xml import UnstructuredXmlLoader
from extensions.ext_storage import storage from extensions.ext_storage import storage
from flask import current_app
from langchain.document_loaders import Docx2txtLoader, TextLoader
from langchain.schema import Document
from models.model import UploadFile from models.model import UploadFile
SUPPORT_URL_CONTENT_TYPES = ['application/pdf', 'text/plain'] SUPPORT_URL_CONTENT_TYPES = ['application/pdf', 'text/plain']
@ -27,7 +28,7 @@ USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTM
class FileExtractor: class FileExtractor:
@classmethod @classmethod
def load(cls, upload_file: UploadFile, return_text: bool = False, is_automatic: bool = False) -> Union[List[Document], str]: def load(cls, upload_file: UploadFile, return_text: bool = False, is_automatic: bool = False) -> Union[list[Document], str]:
with tempfile.TemporaryDirectory() as temp_dir: with tempfile.TemporaryDirectory() as temp_dir:
suffix = Path(upload_file.key).suffix suffix = Path(upload_file.key).suffix
file_path = f"{temp_dir}/{next(tempfile._get_candidate_names())}{suffix}" file_path = f"{temp_dir}/{next(tempfile._get_candidate_names())}{suffix}"
@ -36,7 +37,7 @@ class FileExtractor:
return cls.load_from_file(file_path, return_text, upload_file, is_automatic) return cls.load_from_file(file_path, return_text, upload_file, is_automatic)
@classmethod @classmethod
def load_from_url(cls, url: str, return_text: bool = False) -> Union[List[Document], str]: def load_from_url(cls, url: str, return_text: bool = False) -> Union[list[Document], str]:
response = requests.get(url, headers={ response = requests.get(url, headers={
"User-Agent": USER_AGENT "User-Agent": USER_AGENT
}) })
@ -52,7 +53,7 @@ class FileExtractor:
@classmethod @classmethod
def load_from_file(cls, file_path: str, return_text: bool = False, def load_from_file(cls, file_path: str, return_text: bool = False,
upload_file: Optional[UploadFile] = None, upload_file: Optional[UploadFile] = None,
is_automatic: bool = False) -> Union[List[Document], str]: is_automatic: bool = False) -> Union[list[Document], str]:
input_file = Path(file_path) input_file = Path(file_path)
delimiter = '\n' delimiter = '\n'
file_extension = input_file.suffix.lower() file_extension = input_file.suffix.lower()

Some files were not shown because too many files have changed in this diff Show More