mirror of https://github.com/langgenius/dify.git
Merge remote-tracking branch 'origin/main' into feat/trigger
This commit is contained in:
commit
8315e0c74b
|
|
@ -15,7 +15,11 @@ FROM base AS packages
|
|||
# RUN sed -i 's@deb.debian.org@mirrors.aliyun.com@g' /etc/apt/sources.list.d/debian.sources
|
||||
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y --no-install-recommends gcc g++ libc-dev libffi-dev libgmp-dev libmpfr-dev libmpc-dev
|
||||
&& apt-get install -y --no-install-recommends \
|
||||
# basic environment
|
||||
g++ \
|
||||
# for building gmpy2
|
||||
libmpfr-dev libmpc-dev
|
||||
|
||||
# Install Python dependencies
|
||||
COPY pyproject.toml uv.lock ./
|
||||
|
|
@ -49,7 +53,9 @@ RUN \
|
|||
# Install dependencies
|
||||
&& apt-get install -y --no-install-recommends \
|
||||
# basic environment
|
||||
curl nodejs libgmp-dev libmpfr-dev libmpc-dev \
|
||||
curl nodejs \
|
||||
# for gmpy2 \
|
||||
libgmp-dev libmpfr-dev libmpc-dev \
|
||||
# For Security
|
||||
expat libldap-2.5-0 perl libsqlite3-0 zlib1g \
|
||||
# install fonts to support the use of tools like pypdfium2
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ from flask_restx import Resource, reqparse
|
|||
|
||||
from controllers.console import console_ns
|
||||
from controllers.console.wraps import account_initialization_required, only_edition_cloud, setup_required
|
||||
from enums.cloud_plan import CloudPlan
|
||||
from libs.login import current_account_with_tenant, login_required
|
||||
from services.billing_service import BillingService
|
||||
|
||||
|
|
@ -16,7 +17,13 @@ class Subscription(Resource):
|
|||
current_user, current_tenant_id = current_account_with_tenant()
|
||||
parser = (
|
||||
reqparse.RequestParser()
|
||||
.add_argument("plan", type=str, required=True, location="args", choices=["professional", "team"])
|
||||
.add_argument(
|
||||
"plan",
|
||||
type=str,
|
||||
required=True,
|
||||
location="args",
|
||||
choices=[CloudPlan.PROFESSIONAL, CloudPlan.TEAM],
|
||||
)
|
||||
.add_argument("interval", type=str, required=True, location="args", choices=["month", "year"])
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ from controllers.console.wraps import (
|
|||
cloud_edition_billing_resource_check,
|
||||
setup_required,
|
||||
)
|
||||
from enums.cloud_plan import CloudPlan
|
||||
from extensions.ext_database import db
|
||||
from libs.helper import TimestampField
|
||||
from libs.login import current_account_with_tenant, login_required
|
||||
|
|
@ -83,7 +84,7 @@ class TenantListApi(Resource):
|
|||
"name": tenant.name,
|
||||
"status": tenant.status,
|
||||
"created_at": tenant.created_at,
|
||||
"plan": features.billing.subscription.plan if features.billing.enabled else "sandbox",
|
||||
"plan": features.billing.subscription.plan if features.billing.enabled else CloudPlan.SANDBOX,
|
||||
"current": tenant.id == current_tenant_id if current_tenant_id else False,
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ from flask import abort, request
|
|||
|
||||
from configs import dify_config
|
||||
from controllers.console.workspace.error import AccountNotInitializedError
|
||||
from enums.cloud_plan import CloudPlan
|
||||
from extensions.ext_database import db
|
||||
from extensions.ext_redis import redis_client
|
||||
from libs.login import current_account_with_tenant
|
||||
|
|
@ -133,7 +134,7 @@ def cloud_edition_billing_knowledge_limit_check(resource: str):
|
|||
features = FeatureService.get_features(current_tenant_id)
|
||||
if features.billing.enabled:
|
||||
if resource == "add_segment":
|
||||
if features.billing.subscription.plan == "sandbox":
|
||||
if features.billing.subscription.plan == CloudPlan.SANDBOX:
|
||||
abort(
|
||||
403,
|
||||
"To unlock this feature and elevate your Dify experience, please upgrade to a paid plan.",
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ from sqlalchemy import select, update
|
|||
from sqlalchemy.orm import Session
|
||||
from werkzeug.exceptions import Forbidden, NotFound, Unauthorized
|
||||
|
||||
from enums.cloud_plan import CloudPlan
|
||||
from extensions.ext_database import db
|
||||
from extensions.ext_redis import redis_client
|
||||
from libs.datetime_utils import naive_utc_now
|
||||
|
|
@ -139,7 +140,7 @@ def cloud_edition_billing_knowledge_limit_check(resource: str, api_token_type: s
|
|||
features = FeatureService.get_features(api_token.tenant_id)
|
||||
if features.billing.enabled:
|
||||
if resource == "add_segment":
|
||||
if features.billing.subscription.plan == "sandbox":
|
||||
if features.billing.subscription.plan == CloudPlan.SANDBOX:
|
||||
raise Forbidden(
|
||||
"To unlock this feature and elevate your Dify experience, please upgrade to a paid plan."
|
||||
)
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ from core.workflow.repositories.draft_variable_repository import DraftVariableSa
|
|||
from core.workflow.repositories.workflow_execution_repository import WorkflowExecutionRepository
|
||||
from core.workflow.repositories.workflow_node_execution_repository import WorkflowNodeExecutionRepository
|
||||
from core.workflow.variable_loader import DUMMY_VARIABLE_LOADER, VariableLoader
|
||||
from enums.cloud_plan import CloudPlan
|
||||
from extensions.ext_database import db
|
||||
from extensions.ext_redis import redis_client
|
||||
from libs.flask_utils import preserve_flask_contexts
|
||||
|
|
@ -255,7 +256,7 @@ class PipelineGenerator(BaseAppGenerator):
|
|||
json_text = json.dumps(text)
|
||||
upload_file = FileService(db.engine).upload_text(json_text, name, user.id, dataset.tenant_id)
|
||||
features = FeatureService.get_features(dataset.tenant_id)
|
||||
if features.billing.enabled and features.billing.subscription.plan == "sandbox":
|
||||
if features.billing.enabled and features.billing.subscription.plan == CloudPlan.SANDBOX:
|
||||
tenant_pipeline_task_key = f"tenant_pipeline_task:{dataset.tenant_id}"
|
||||
tenant_self_pipeline_task_queue = f"tenant_self_pipeline_task_queue:{dataset.tenant_id}"
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,15 @@
|
|||
from enum import StrEnum, auto
|
||||
|
||||
|
||||
class CloudPlan(StrEnum):
|
||||
"""
|
||||
Enum representing user plan types in the cloud platform.
|
||||
|
||||
SANDBOX: Free/default plan with limited features
|
||||
PROFESSIONAL: Professional paid plan
|
||||
TEAM: Team collaboration paid plan
|
||||
"""
|
||||
|
||||
SANDBOX = auto()
|
||||
PROFESSIONAL = auto()
|
||||
TEAM = auto()
|
||||
|
|
@ -3,6 +3,7 @@ import re
|
|||
import uuid
|
||||
from collections.abc import Mapping
|
||||
from datetime import datetime
|
||||
from decimal import Decimal
|
||||
from enum import StrEnum, auto
|
||||
from typing import TYPE_CHECKING, Any, Literal, Optional, cast
|
||||
|
||||
|
|
@ -914,34 +915,40 @@ class Message(Base):
|
|||
)
|
||||
|
||||
id: Mapped[str] = mapped_column(StringUUID, server_default=sa.text("uuid_generate_v4()"))
|
||||
app_id = mapped_column(StringUUID, nullable=False)
|
||||
model_provider = mapped_column(String(255), nullable=True)
|
||||
model_id = mapped_column(String(255), nullable=True)
|
||||
override_model_configs = mapped_column(sa.Text)
|
||||
conversation_id = mapped_column(StringUUID, sa.ForeignKey("conversations.id"), nullable=False)
|
||||
app_id: Mapped[str] = mapped_column(StringUUID, nullable=False)
|
||||
model_provider: Mapped[str | None] = mapped_column(String(255), nullable=True)
|
||||
model_id: Mapped[str | None] = mapped_column(String(255), nullable=True)
|
||||
override_model_configs: Mapped[str | None] = mapped_column(sa.Text)
|
||||
conversation_id: Mapped[str] = mapped_column(StringUUID, sa.ForeignKey("conversations.id"), nullable=False)
|
||||
_inputs: Mapped[dict[str, Any]] = mapped_column("inputs", sa.JSON)
|
||||
query: Mapped[str] = mapped_column(sa.Text, nullable=False)
|
||||
message = mapped_column(sa.JSON, nullable=False)
|
||||
message: Mapped[dict[str, Any]] = mapped_column(sa.JSON, nullable=False)
|
||||
message_tokens: Mapped[int] = mapped_column(sa.Integer, nullable=False, server_default=sa.text("0"))
|
||||
message_unit_price = mapped_column(sa.Numeric(10, 4), nullable=False)
|
||||
message_price_unit = mapped_column(sa.Numeric(10, 7), nullable=False, server_default=sa.text("0.001"))
|
||||
message_unit_price: Mapped[Decimal] = mapped_column(sa.Numeric(10, 4), nullable=False)
|
||||
message_price_unit: Mapped[Decimal] = mapped_column(
|
||||
sa.Numeric(10, 7), nullable=False, server_default=sa.text("0.001")
|
||||
)
|
||||
answer: Mapped[str] = mapped_column(sa.Text, nullable=False)
|
||||
answer_tokens: Mapped[int] = mapped_column(sa.Integer, nullable=False, server_default=sa.text("0"))
|
||||
answer_unit_price = mapped_column(sa.Numeric(10, 4), nullable=False)
|
||||
answer_price_unit = mapped_column(sa.Numeric(10, 7), nullable=False, server_default=sa.text("0.001"))
|
||||
parent_message_id = mapped_column(StringUUID, nullable=True)
|
||||
provider_response_latency = mapped_column(sa.Float, nullable=False, server_default=sa.text("0"))
|
||||
total_price = mapped_column(sa.Numeric(10, 7))
|
||||
answer_unit_price: Mapped[Decimal] = mapped_column(sa.Numeric(10, 4), nullable=False)
|
||||
answer_price_unit: Mapped[Decimal] = mapped_column(
|
||||
sa.Numeric(10, 7), nullable=False, server_default=sa.text("0.001")
|
||||
)
|
||||
parent_message_id: Mapped[str | None] = mapped_column(StringUUID, nullable=True)
|
||||
provider_response_latency: Mapped[float] = mapped_column(sa.Float, nullable=False, server_default=sa.text("0"))
|
||||
total_price: Mapped[Decimal | None] = mapped_column(sa.Numeric(10, 7))
|
||||
currency: Mapped[str] = mapped_column(String(255), nullable=False)
|
||||
status = mapped_column(String(255), nullable=False, server_default=sa.text("'normal'::character varying"))
|
||||
error = mapped_column(sa.Text)
|
||||
message_metadata = mapped_column(sa.Text)
|
||||
status: Mapped[str] = mapped_column(
|
||||
String(255), nullable=False, server_default=sa.text("'normal'::character varying")
|
||||
)
|
||||
error: Mapped[str | None] = mapped_column(sa.Text)
|
||||
message_metadata: Mapped[str | None] = mapped_column(sa.Text)
|
||||
invoke_from: Mapped[str | None] = mapped_column(String(255), nullable=True)
|
||||
from_source: Mapped[str] = mapped_column(String(255), nullable=False)
|
||||
from_end_user_id: Mapped[str | None] = mapped_column(StringUUID)
|
||||
from_account_id: Mapped[str | None] = mapped_column(StringUUID)
|
||||
created_at: Mapped[datetime] = mapped_column(sa.DateTime, server_default=func.current_timestamp())
|
||||
updated_at = mapped_column(sa.DateTime, nullable=False, server_default=func.current_timestamp())
|
||||
updated_at: Mapped[datetime] = mapped_column(sa.DateTime, nullable=False, server_default=func.current_timestamp())
|
||||
agent_based: Mapped[bool] = mapped_column(sa.Boolean, nullable=False, server_default=sa.text("false"))
|
||||
workflow_run_id: Mapped[str | None] = mapped_column(StringUUID)
|
||||
app_mode: Mapped[str | None] = mapped_column(String(255), nullable=True)
|
||||
|
|
|
|||
|
|
@ -213,7 +213,7 @@ vdb = [
|
|||
"pymochow==2.2.9",
|
||||
"pyobvector~=0.2.15",
|
||||
"qdrant-client==1.9.0",
|
||||
"tablestore==6.2.0",
|
||||
"tablestore==6.3.7",
|
||||
"tcvectordb~=1.6.4",
|
||||
"tidb-vector==0.0.9",
|
||||
"upstash-vector==0.6.0",
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ from sqlalchemy.exc import SQLAlchemyError
|
|||
|
||||
import app
|
||||
from configs import dify_config
|
||||
from enums.cloud_plan import CloudPlan
|
||||
from extensions.ext_database import db
|
||||
from extensions.ext_redis import redis_client
|
||||
from models.model import (
|
||||
|
|
@ -63,7 +64,7 @@ def clean_messages():
|
|||
plan = features.billing.subscription.plan
|
||||
else:
|
||||
plan = plan_cache.decode()
|
||||
if plan == "sandbox":
|
||||
if plan == CloudPlan.SANDBOX:
|
||||
# clean related message
|
||||
db.session.query(MessageFeedback).where(MessageFeedback.message_id == message.id).delete(
|
||||
synchronize_session=False
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ from sqlalchemy.exc import SQLAlchemyError
|
|||
import app
|
||||
from configs import dify_config
|
||||
from core.rag.index_processor.index_processor_factory import IndexProcessorFactory
|
||||
from enums.cloud_plan import CloudPlan
|
||||
from extensions.ext_database import db
|
||||
from extensions.ext_redis import redis_client
|
||||
from models.dataset import Dataset, DatasetAutoDisableLog, DatasetQuery, Document
|
||||
|
|
@ -35,7 +36,7 @@ def clean_unused_datasets_task():
|
|||
},
|
||||
{
|
||||
"clean_day": datetime.datetime.now() - datetime.timedelta(days=dify_config.PLAN_PRO_CLEAN_DAY_SETTING),
|
||||
"plan_filter": "sandbox",
|
||||
"plan_filter": CloudPlan.SANDBOX,
|
||||
"add_logs": False,
|
||||
},
|
||||
]
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ from sqlalchemy import select
|
|||
|
||||
import app
|
||||
from configs import dify_config
|
||||
from enums.cloud_plan import CloudPlan
|
||||
from extensions.ext_database import db
|
||||
from extensions.ext_mail import mail
|
||||
from libs.email_i18n import EmailType, get_email_i18n_service
|
||||
|
|
@ -45,7 +46,7 @@ def mail_clean_document_notify_task():
|
|||
for tenant_id, tenant_dataset_auto_disable_logs in dataset_auto_disable_logs_map.items():
|
||||
features = FeatureService.get_features(tenant_id)
|
||||
plan = features.billing.subscription.plan
|
||||
if plan != "sandbox":
|
||||
if plan != CloudPlan.SANDBOX:
|
||||
knowledge_details = []
|
||||
# check tenant
|
||||
tenant = db.session.query(Tenant).where(Tenant.id == tenant_id).first()
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ from core.app.apps.completion.app_generator import CompletionAppGenerator
|
|||
from core.app.apps.workflow.app_generator import WorkflowAppGenerator
|
||||
from core.app.entities.app_invoke_entities import InvokeFrom
|
||||
from core.app.features.rate_limiting import RateLimit
|
||||
from enums.cloud_plan import CloudPlan
|
||||
from libs.helper import RateLimiter
|
||||
from models.model import Account, App, AppMode, EndUser
|
||||
from models.workflow import Workflow
|
||||
|
|
@ -45,7 +46,7 @@ class AppGenerateService:
|
|||
if dify_config.BILLING_ENABLED:
|
||||
# check if it's free plan
|
||||
limit_info = BillingService.get_info(app_model.tenant_id)
|
||||
if limit_info["subscription"]["plan"] == "sandbox":
|
||||
if limit_info["subscription"]["plan"] == CloudPlan.SANDBOX:
|
||||
if cls.system_rate_limiter.is_rate_limited(app_model.tenant_id):
|
||||
raise InvokeRateLimitError(
|
||||
"Rate limit exceeded, please upgrade your plan "
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ from typing import Literal
|
|||
import httpx
|
||||
from tenacity import retry, retry_if_exception_type, stop_before_delay, wait_fixed
|
||||
|
||||
from enums.cloud_plan import CloudPlan
|
||||
from extensions.ext_database import db
|
||||
from extensions.ext_redis import redis_client
|
||||
from libs.helper import RateLimiter
|
||||
|
|
@ -31,7 +32,7 @@ class BillingService:
|
|||
|
||||
return {
|
||||
"limit": knowledge_rate_limit.get("limit", 10),
|
||||
"subscription_plan": knowledge_rate_limit.get("subscription_plan", "sandbox"),
|
||||
"subscription_plan": knowledge_rate_limit.get("subscription_plan", CloudPlan.SANDBOX),
|
||||
}
|
||||
|
||||
@classmethod
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ from sqlalchemy.orm import Session, sessionmaker
|
|||
|
||||
from configs import dify_config
|
||||
from core.model_runtime.utils.encoders import jsonable_encoder
|
||||
from enums.cloud_plan import CloudPlan
|
||||
from extensions.ext_database import db
|
||||
from extensions.ext_storage import storage
|
||||
from models.account import Tenant
|
||||
|
|
@ -358,7 +359,7 @@ class ClearFreePlanTenantExpiredLogs:
|
|||
try:
|
||||
if (
|
||||
not dify_config.BILLING_ENABLED
|
||||
or BillingService.get_info(tenant_id)["subscription"]["plan"] == "sandbox"
|
||||
or BillingService.get_info(tenant_id)["subscription"]["plan"] == CloudPlan.SANDBOX
|
||||
):
|
||||
# only process sandbox tenant
|
||||
cls.process_tenant(flask_app, tenant_id, days, batch)
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ from core.model_runtime.entities.model_entities import ModelType
|
|||
from core.rag.index_processor.constant.built_in_field import BuiltInField
|
||||
from core.rag.index_processor.constant.index_type import IndexType
|
||||
from core.rag.retrieval.retrieval_methods import RetrievalMethod
|
||||
from enums.cloud_plan import CloudPlan
|
||||
from events.dataset_event import dataset_was_deleted
|
||||
from events.document_event import document_was_deleted
|
||||
from extensions.ext_database import db
|
||||
|
|
@ -1042,7 +1043,7 @@ class DatasetService:
|
|||
assert isinstance(current_user, Account)
|
||||
assert current_user.current_tenant_id is not None
|
||||
features = FeatureService.get_features(current_user.current_tenant_id)
|
||||
if not features.billing.enabled or features.billing.subscription.plan == "sandbox":
|
||||
if not features.billing.enabled or features.billing.subscription.plan == CloudPlan.SANDBOX:
|
||||
return {
|
||||
"document_ids": [],
|
||||
"count": 0,
|
||||
|
|
@ -1438,7 +1439,7 @@ class DocumentService:
|
|||
count = len(website_info.urls)
|
||||
batch_upload_limit = int(dify_config.BATCH_UPLOAD_LIMIT)
|
||||
|
||||
if features.billing.subscription.plan == "sandbox" and count > 1:
|
||||
if features.billing.subscription.plan == CloudPlan.SANDBOX and count > 1:
|
||||
raise ValueError("Your current plan does not support batch upload, please upgrade your plan.")
|
||||
if count > batch_upload_limit:
|
||||
raise ValueError(f"You have reached the batch upload limit of {batch_upload_limit}.")
|
||||
|
|
@ -1727,7 +1728,7 @@ class DocumentService:
|
|||
# count = len(website_info.urls) # type: ignore
|
||||
# batch_upload_limit = int(dify_config.BATCH_UPLOAD_LIMIT)
|
||||
|
||||
# if features.billing.subscription.plan == "sandbox" and count > 1:
|
||||
# if features.billing.subscription.plan == CloudPlan.SANDBOX and count > 1:
|
||||
# raise ValueError("Your current plan does not support batch upload, please upgrade your plan.")
|
||||
# if count > batch_upload_limit:
|
||||
# raise ValueError(f"You have reached the batch upload limit of {batch_upload_limit}.")
|
||||
|
|
@ -2196,7 +2197,7 @@ class DocumentService:
|
|||
website_info = knowledge_config.data_source.info_list.website_info_list
|
||||
if website_info:
|
||||
count = len(website_info.urls)
|
||||
if features.billing.subscription.plan == "sandbox" and count > 1:
|
||||
if features.billing.subscription.plan == CloudPlan.SANDBOX and count > 1:
|
||||
raise ValueError("Your current plan does not support batch upload, please upgrade your plan.")
|
||||
batch_upload_limit = int(dify_config.BATCH_UPLOAD_LIMIT)
|
||||
if count > batch_upload_limit:
|
||||
|
|
|
|||
|
|
@ -3,12 +3,13 @@ from enum import StrEnum
|
|||
from pydantic import BaseModel, ConfigDict, Field
|
||||
|
||||
from configs import dify_config
|
||||
from enums.cloud_plan import CloudPlan
|
||||
from services.billing_service import BillingService
|
||||
from services.enterprise.enterprise_service import EnterpriseService
|
||||
|
||||
|
||||
class SubscriptionModel(BaseModel):
|
||||
plan: str = "sandbox"
|
||||
plan: str = CloudPlan.SANDBOX
|
||||
interval: str = ""
|
||||
|
||||
|
||||
|
|
@ -186,7 +187,7 @@ class FeatureService:
|
|||
knowledge_rate_limit.enabled = True
|
||||
limit_info = BillingService.get_knowledge_rate_limit(tenant_id)
|
||||
knowledge_rate_limit.limit = limit_info.get("limit", 10)
|
||||
knowledge_rate_limit.subscription_plan = limit_info.get("subscription_plan", "sandbox")
|
||||
knowledge_rate_limit.subscription_plan = limit_info.get("subscription_plan", CloudPlan.SANDBOX)
|
||||
return knowledge_rate_limit
|
||||
|
||||
@classmethod
|
||||
|
|
@ -240,7 +241,7 @@ class FeatureService:
|
|||
features.billing.subscription.interval = billing_info["subscription"]["interval"]
|
||||
features.education.activated = billing_info["subscription"].get("education", False)
|
||||
|
||||
if features.billing.subscription.plan != "sandbox":
|
||||
if features.billing.subscription.plan != CloudPlan.SANDBOX:
|
||||
features.webapp_copyright_enabled = True
|
||||
else:
|
||||
features.is_allow_transfer_workspace = False
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ from celery import shared_task
|
|||
|
||||
from configs import dify_config
|
||||
from core.indexing_runner import DocumentIsPausedError, IndexingRunner
|
||||
from enums.cloud_plan import CloudPlan
|
||||
from extensions.ext_database import db
|
||||
from libs.datetime_utils import naive_utc_now
|
||||
from models.dataset import Dataset, Document
|
||||
|
|
@ -38,7 +39,7 @@ def document_indexing_task(dataset_id: str, document_ids: list):
|
|||
vector_space = features.vector_space
|
||||
count = len(document_ids)
|
||||
batch_upload_limit = int(dify_config.BATCH_UPLOAD_LIMIT)
|
||||
if features.billing.subscription.plan == "sandbox" and count > 1:
|
||||
if features.billing.subscription.plan == CloudPlan.SANDBOX and count > 1:
|
||||
raise ValueError("Your current plan does not support batch upload, please upgrade your plan.")
|
||||
if count > batch_upload_limit:
|
||||
raise ValueError(f"You have reached the batch upload limit of {batch_upload_limit}.")
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ from sqlalchemy import select
|
|||
from configs import dify_config
|
||||
from core.indexing_runner import DocumentIsPausedError, IndexingRunner
|
||||
from core.rag.index_processor.index_processor_factory import IndexProcessorFactory
|
||||
from enums.cloud_plan import CloudPlan
|
||||
from extensions.ext_database import db
|
||||
from libs.datetime_utils import naive_utc_now
|
||||
from models.dataset import Dataset, Document, DocumentSegment
|
||||
|
|
@ -41,7 +42,7 @@ def duplicate_document_indexing_task(dataset_id: str, document_ids: list):
|
|||
if features.billing.enabled:
|
||||
vector_space = features.vector_space
|
||||
count = len(document_ids)
|
||||
if features.billing.subscription.plan == "sandbox" and count > 1:
|
||||
if features.billing.subscription.plan == CloudPlan.SANDBOX and count > 1:
|
||||
raise ValueError("Your current plan does not support batch upload, please upgrade your plan.")
|
||||
batch_upload_limit = int(dify_config.BATCH_UPLOAD_LIMIT)
|
||||
if count > batch_upload_limit:
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import pytest
|
|||
from faker import Faker
|
||||
|
||||
from core.app.entities.app_invoke_entities import InvokeFrom
|
||||
from enums.cloud_plan import CloudPlan
|
||||
from models.model import EndUser
|
||||
from models.workflow import Workflow
|
||||
from services.app_generate_service import AppGenerateService
|
||||
|
|
@ -32,7 +33,7 @@ class TestAppGenerateService:
|
|||
patch("services.app_generate_service.dify_config") as mock_dify_config,
|
||||
):
|
||||
# Setup default mock returns for billing service
|
||||
mock_billing_service.get_info.return_value = {"subscription": {"plan": "sandbox"}}
|
||||
mock_billing_service.get_info.return_value = {"subscription": {"plan": CloudPlan.SANDBOX}}
|
||||
|
||||
# Setup default mock returns for workflow service
|
||||
mock_workflow_service_instance = mock_workflow_service.return_value
|
||||
|
|
@ -430,7 +431,7 @@ class TestAppGenerateService:
|
|||
|
||||
# Setup billing service mock for sandbox plan
|
||||
mock_external_service_dependencies["billing_service"].get_info.return_value = {
|
||||
"subscription": {"plan": "sandbox"}
|
||||
"subscription": {"plan": CloudPlan.SANDBOX}
|
||||
}
|
||||
|
||||
# Set BILLING_ENABLED to True for this test
|
||||
|
|
@ -461,7 +462,7 @@ class TestAppGenerateService:
|
|||
|
||||
# Setup billing service mock for sandbox plan
|
||||
mock_external_service_dependencies["billing_service"].get_info.return_value = {
|
||||
"subscription": {"plan": "sandbox"}
|
||||
"subscription": {"plan": CloudPlan.SANDBOX}
|
||||
}
|
||||
|
||||
# Set BILLING_ENABLED to True for this test
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ from unittest.mock import patch
|
|||
import pytest
|
||||
from faker import Faker
|
||||
|
||||
from enums.cloud_plan import CloudPlan
|
||||
from services.feature_service import FeatureModel, FeatureService, KnowledgeRateLimitModel, SystemFeatureModel
|
||||
|
||||
|
||||
|
|
@ -173,7 +174,7 @@ class TestFeatureService:
|
|||
# Set mock return value inside the patch context
|
||||
mock_external_service_dependencies["billing_service"].get_info.return_value = {
|
||||
"enabled": True,
|
||||
"subscription": {"plan": "sandbox", "interval": "monthly", "education": False},
|
||||
"subscription": {"plan": CloudPlan.SANDBOX, "interval": "monthly", "education": False},
|
||||
"members": {"size": 1, "limit": 3},
|
||||
"apps": {"size": 1, "limit": 5},
|
||||
"vector_space": {"size": 1, "limit": 2},
|
||||
|
|
@ -189,7 +190,7 @@ class TestFeatureService:
|
|||
result = FeatureService.get_features(tenant_id)
|
||||
|
||||
# Assert: Verify sandbox-specific limitations
|
||||
assert result.billing.subscription.plan == "sandbox"
|
||||
assert result.billing.subscription.plan == CloudPlan.SANDBOX
|
||||
assert result.education.activated is False
|
||||
|
||||
# Verify sandbox limitations
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ from unittest.mock import MagicMock, patch
|
|||
import pytest
|
||||
from faker import Faker
|
||||
|
||||
from enums.cloud_plan import CloudPlan
|
||||
from extensions.ext_database import db
|
||||
from models import Account, Tenant, TenantAccountJoin, TenantAccountRole
|
||||
from models.dataset import Dataset, Document
|
||||
|
|
@ -197,7 +198,7 @@ class TestDocumentIndexingTask:
|
|||
# Configure billing features
|
||||
mock_external_service_dependencies["features"].billing.enabled = billing_enabled
|
||||
if billing_enabled:
|
||||
mock_external_service_dependencies["features"].billing.subscription.plan = "sandbox"
|
||||
mock_external_service_dependencies["features"].billing.subscription.plan = CloudPlan.SANDBOX
|
||||
mock_external_service_dependencies["features"].vector_space.limit = 100
|
||||
mock_external_service_dependencies["features"].vector_space.size = 50
|
||||
|
||||
|
|
@ -442,7 +443,7 @@ class TestDocumentIndexingTask:
|
|||
)
|
||||
|
||||
# Configure sandbox plan with batch limit
|
||||
mock_external_service_dependencies["features"].billing.subscription.plan = "sandbox"
|
||||
mock_external_service_dependencies["features"].billing.subscription.plan = CloudPlan.SANDBOX
|
||||
|
||||
# Create more documents than sandbox plan allows (limit is 1)
|
||||
fake = Faker()
|
||||
|
|
|
|||
4646
api/uv.lock
4646
api/uv.lock
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,101 @@
|
|||
# योगदान (CONTRIBUTING)
|
||||
|
||||
तो आप Dify में योगदान देना चाहते हैं — यह शानदार है, हम उत्सुक हैं यह देखने के लिए कि आप क्या बनाते हैं। सीमित टीम और फंडिंग वाले एक स्टार्टअप के रूप में, हमारा बड़ा लक्ष्य LLM एप्लिकेशनों के निर्माण और प्रबंधन के लिए सबसे सहज वर्कफ़्लो डिज़ाइन करना है। समुदाय से मिलने वाली कोई भी मदद वास्तव में मायने रखती है।
|
||||
|
||||
हमारे वर्तमान चरण को देखते हुए हमें तेज़ी से काम करना और डिलीवर करना होता है, लेकिन हम यह भी सुनिश्चित करना चाहते हैं कि आपके जैसे योगदानकर्ताओं के लिए योगदान देने का अनुभव यथासंभव सरल और सुगम हो।\
|
||||
इसी उद्देश्य से हमने यह योगदान गाइड तैयार किया है, ताकि आप कोडबेस से परिचित हो सकें और जान सकें कि हम योगदानकर्ताओं के साथ कैसे काम करते हैं — ताकि आप जल्दी से मज़ेदार हिस्से पर पहुँच सकें।
|
||||
|
||||
यह गाइड, Dify की तरह ही, एक निरंतर विकसित होता दस्तावेज़ है। यदि यह कभी-कभी वास्तविक प्रोजेक्ट से पीछे रह जाए तो हम आपके समझ के लिए आभारी हैं, और सुधार के लिए किसी भी सुझाव का स्वागत करते हैं।
|
||||
|
||||
लाइसेंसिंग के संदर्भ में, कृपया एक मिनट निकालकर हमारा छोटा [License and Contributor Agreement](../../LICENSE) पढ़ें।\
|
||||
समुदाय [code of conduct](https://github.com/langgenius/.github/blob/main/CODE_OF_CONDUCT.md) का भी पालन करता है।
|
||||
|
||||
## शुरू करने से पहले
|
||||
|
||||
कुछ योगदान करने की तलाश में हैं? हमारे [good first issues](https://github.com/langgenius/dify/issues?q=is%3Aissue%20state%3Aopen%20label%3A%22good%20first%20issue%22) ब्राउज़ करें और किसी एक को चुनकर शुरुआत करें!
|
||||
|
||||
कोई नया मॉडल रनटाइम या टूल जोड़ना चाहते हैं? हमारे [plugin repo](https://github.com/langgenius/dify-plugins) में एक PR खोलें और हमें दिखाएँ कि आपने क्या बनाया है।
|
||||
|
||||
किसी मौजूदा मॉडल रनटाइम या टूल को अपडेट करना है, या कुछ बग्स को ठीक करना है? हमारे [official plugin repo](https://github.com/langgenius/dify-official-plugins) पर जाएँ और अपना जादू दिखाएँ!
|
||||
|
||||
मज़े में शामिल हों, योगदान दें, और चलिए मिलकर कुछ शानदार बनाते हैं! 💡✨
|
||||
|
||||
PR के विवरण में मौजूदा issue को लिंक करना या नया issue खोलना न भूलें।
|
||||
|
||||
### बग रिपोर्ट (Bug reports)
|
||||
|
||||
> [!IMPORTANT]\
|
||||
> कृपया बग रिपोर्ट सबमिट करते समय निम्नलिखित जानकारी अवश्य शामिल करें:
|
||||
|
||||
- एक स्पष्ट और वर्णनात्मक शीर्षक
|
||||
- बग का विस्तृत विवरण, जिसमें कोई भी त्रुटि संदेश (error messages) शामिल हो
|
||||
- बग को पुन: उत्पन्न करने के चरण
|
||||
- अपेक्षित व्यवहार
|
||||
- **लॉग्स**, यदि उपलब्ध हों — बैकएंड समस्याओं के लिए यह बहुत महत्वपूर्ण है, आप इन्हें docker-compose logs में पा सकते हैं
|
||||
- स्क्रीनशॉट या वीडियो (यदि लागू हो)
|
||||
|
||||
हम प्राथमिकता कैसे तय करते हैं:
|
||||
|
||||
| समस्या प्रकार (Issue Type) | प्राथमिकता (Priority) |
|
||||
| ------------------------------------------------------------ | --------------- |
|
||||
| मुख्य कार्यों में बग (क्लाउड सेवा, लॉगिन न होना, एप्लिकेशन न चलना, सुरक्षा खामियाँ) | गंभीर (Critical) |
|
||||
| गैर-गंभीर बग, प्रदर्शन सुधार | मध्यम प्राथमिकता (Medium Priority) |
|
||||
| छोटे सुधार (टाइपो, भ्रमित करने वाला लेकिन काम करने वाला UI) | निम्न प्राथमिकता (Low Priority) |
|
||||
|
||||
### फ़ीचर अनुरोध (Feature requests)
|
||||
|
||||
> [!NOTE]\
|
||||
> कृपया फ़ीचर अनुरोध सबमिट करते समय निम्नलिखित जानकारी अवश्य शामिल करें:
|
||||
|
||||
- एक स्पष्ट और वर्णनात्मक शीर्षक
|
||||
- फ़ीचर का विस्तृत विवरण
|
||||
- फ़ीचर के उपयोग का मामला (use case)
|
||||
- फ़ीचर अनुरोध से संबंधित कोई अन्य संदर्भ या स्क्रीनशॉट
|
||||
|
||||
हम प्राथमिकता कैसे तय करते हैं:
|
||||
|
||||
| फ़ीचर प्रकार (Feature Type) | प्राथमिकता (Priority) |
|
||||
| ------------------------------------------------------------ | --------------- |
|
||||
| किसी टीम सदस्य द्वारा उच्च प्राथमिकता (High-Priority) के रूप में चिह्नित फ़ीचर | उच्च प्राथमिकता (High Priority) |
|
||||
| हमारे [community feedback board](https://github.com/langgenius/dify/discussions/categories/feedbacks) से लोकप्रिय फ़ीचर अनुरोध | मध्यम प्राथमिकता (Medium Priority) |
|
||||
| गैर-मुख्य फ़ीचर्स और छोटे सुधार | निम्न प्राथमिकता (Low Priority) |
|
||||
| मूल्यवान लेकिन तात्कालिक नहीं | भविष्य का फ़ीचर (Future-Feature) |
|
||||
|
||||
## अपना PR सबमिट करना (Submitting your PR)
|
||||
|
||||
### पुल रिक्वेस्ट प्रक्रिया (Pull Request Process)
|
||||
|
||||
1. रिपॉज़िटरी को Fork करें
|
||||
1. PR ड्राफ्ट करने से पहले, कृपया अपने बदलावों पर चर्चा करने के लिए एक issue बनाएँ
|
||||
1. अपने परिवर्तनों के लिए एक नई शाखा (branch) बनाएँ
|
||||
1. अपने बदलावों के लिए उपयुक्त टेस्ट जोड़ें
|
||||
1. सुनिश्चित करें कि आपका कोड मौजूदा टेस्ट पास करता है
|
||||
1. PR विवरण में issue लिंक करें, जैसे: `fixes #<issue_number>`
|
||||
1. मर्ज हो जाएँ! 🎉
|
||||
|
||||
### प्रोजेक्ट सेटअप करें (Setup the project)
|
||||
|
||||
#### फ्रंटएंड (Frontend)
|
||||
|
||||
फ्रंटएंड सेवा सेटअप करने के लिए, कृपया हमारी विस्तृत [guide](https://github.com/langgenius/dify/blob/main/web/README.md) देखें जो `web/README.md` फ़ाइल में उपलब्ध है।\
|
||||
यह दस्तावेज़ आपको फ्रंटएंड वातावरण को सही ढंग से सेटअप करने के लिए विस्तृत निर्देश प्रदान करता है।
|
||||
|
||||
#### बैकएंड (Backend)
|
||||
|
||||
बैकएंड सेवा सेटअप करने के लिए, कृपया हमारी विस्तृत [instructions](https://github.com/langgenius/dify/blob/main/api/README.md) देखें जो `api/README.md` फ़ाइल में दी गई हैं।\
|
||||
यह दस्तावेज़ चरण-दर-चरण मार्गदर्शन प्रदान करता है जिससे आप बैकएंड को सुचारू रूप से चला सकें।
|
||||
|
||||
#### अन्य महत्वपूर्ण बातें (Other things to note)
|
||||
|
||||
सेटअप शुरू करने से पहले इस दस्तावेज़ की सावधानीपूर्वक समीक्षा करने की अनुशंसा की जाती है, क्योंकि इसमें निम्नलिखित महत्वपूर्ण जानकारी शामिल है:
|
||||
|
||||
- आवश्यक पूर्व-आवश्यकताएँ और निर्भरताएँ
|
||||
- इंस्टॉलेशन चरण
|
||||
- कॉन्फ़िगरेशन विवरण
|
||||
- सामान्य समस्या निवारण सुझाव
|
||||
|
||||
यदि सेटअप प्रक्रिया के दौरान आपको कोई समस्या आती है, तो बेझिझक हमसे संपर्क करें।
|
||||
|
||||
## सहायता प्राप्त करना (Getting Help)
|
||||
|
||||
यदि योगदान करते समय आप कहीं अटक जाएँ या कोई महत्वपूर्ण प्रश्न हो, तो संबंधित GitHub issue के माध्यम से हमें अपने प्रश्न भेजें, या त्वरित बातचीत के लिए हमारे [Discord](https://discord.gg/8Tpq4AcN9c) पर जुड़ें।
|
||||
|
|
@ -0,0 +1,224 @@
|
|||

|
||||
|
||||
<p align="center">
|
||||
📌 <a href="https://dify.ai/blog/introducing-dify-workflow-file-upload-a-demo-on-ai-podcast">Dify वर्कफ़्लो फ़ाइल अपलोड पेश है: Google NotebookLM पॉडकास्ट को पुनः बनाएँ</a>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://cloud.dify.ai">Dify Cloud</a> ·
|
||||
<a href="https://docs.dify.ai/getting-started/install-self-hosted">स्व-होस्टिंग</a> ·
|
||||
<a href="https://docs.dify.ai">दस्तावेज़ीकरण</a> ·
|
||||
<a href="https://dify.ai/pricing">Dify संस्करण का अवलोकन</a>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://dify.ai" target="_blank">
|
||||
<img alt="Static Badge" src="https://img.shields.io/badge/Product-F04438"></a>
|
||||
<a href="https://dify.ai/pricing" target="_blank">
|
||||
<img alt="Static Badge" src="https://img.shields.io/badge/free-pricing?logo=free&color=%20%23155EEF&label=pricing&labelColor=%20%23528bff"></a>
|
||||
<a href="https://discord.gg/FngNHpbcY7" target="_blank">
|
||||
<img src="https://img.shields.io/discord/1082486657678311454?logo=discord&labelColor=%20%235462eb&logoColor=%20%23f5f5f5&color=%20%235462eb"
|
||||
alt="chat on Discord"></a>
|
||||
<a href="https://reddit.com/r/difyai" target="_blank">
|
||||
<img src="https://img.shields.io/reddit/subreddit-subscribers/difyai?style=plastic&logo=reddit&label=r%2Fdifyai&labelColor=white"
|
||||
alt="join Reddit"></a>
|
||||
<a href="https://twitter.com/intent/follow?screen_name=dify_ai" target="_blank">
|
||||
<img src="https://img.shields.io/twitter/follow/dify_ai?logo=X&color=%20%23f5f5f5"
|
||||
alt="follow on X(Twitter)"></a>
|
||||
<a href="https://www.linkedin.com/company/langgenius/" target="_blank">
|
||||
<img src="https://custom-icon-badges.demolab.com/badge/LinkedIn-0A66C2?logo=linkedin-white&logoColor=fff"
|
||||
alt="follow on LinkedIn"></a>
|
||||
<a href="https://hub.docker.com/u/langgenius" target="_blank">
|
||||
<img alt="Docker Pulls" src="https://img.shields.io/docker/pulls/langgenius/dify-web?labelColor=%20%23FDB062&color=%20%23f79009"></a>
|
||||
<a href="https://github.com/langgenius/dify/graphs/commit-activity" target="_blank">
|
||||
<img alt="Commits last month" src="https://img.shields.io/github/commit-activity/m/langgenius/dify?labelColor=%20%2332b583&color=%20%2312b76a"></a>
|
||||
<a href="https://github.com/langgenius/dify/" target="_blank">
|
||||
<img alt="Issues closed" src="https://img.shields.io/github/issues-search?query=repo%3Alanggenius%2Fdify%20is%3Aclosed&label=issues%20closed&labelColor=%20%237d89b0&color=%20%235d6b98"></a>
|
||||
<a href="https://github.com/langgenius/dify/discussions/" target="_blank">
|
||||
<img alt="Discussion posts" src="https://img.shields.io/github/discussions/langgenius/dify?labelColor=%20%239b8afb&color=%20%237a5af8"></a>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="../../README.md"><img alt="README in English" src="https://img.shields.io/badge/English-d9d9d9"></a>
|
||||
<a href="../zh-TW/README.md"><img alt="繁體中文文件" src="https://img.shields.io/badge/繁體中文-d9d9d9"></a>
|
||||
<a href="../zh-CN/README.md"><img alt="简体中文文件" src="https://img.shields.io/badge/简体中文-d9d9d9"></a>
|
||||
<a href="../ja-JP/README.md"><img alt="日本語のREADME" src="https://img.shields.io/badge/日本語-d9d9d9"></a>
|
||||
<a href="../es-ES/README.md"><img alt="README en Español" src="https://img.shields.io/badge/Español-d9d9d9"></a>
|
||||
<a href="../fr-FR/README.md"><img alt="README en Français" src="https://img.shields.io/badge/Français-d9d9d9"></a>
|
||||
<a href="../tlh/README.md"><img alt="README tlhIngan Hol" src="https://img.shields.io/badge/Klingon-d9d9d9"></a>
|
||||
<a href="../ko-KR/README.md"><img alt="README in Korean" src="https://img.shields.io/badge/한국어-d9d9d9"></a>
|
||||
<a href="../ar-SA/README.md"><img alt="README بالعربية" src="https://img.shields.io/badge/العربية-d9d9d9"></a>
|
||||
<a href="../tr-TR/README.md"><img alt="Türkçe README" src="https://img.shields.io/badge/Türkçe-d9d9d9"></a>
|
||||
<a href="../vi-VN/README.md"><img alt="README Tiếng Việt" src="https://img.shields.io/badge/Ti%E1%BA%BFng%20Vi%E1%BB%87t-d9d9d9"></a>
|
||||
<a href="../de-DE/README.md"><img alt="README in Deutsch" src="https://img.shields.io/badge/German-d9d9d9"></a>
|
||||
<a href="../it-IT/README.md"><img alt="README in Italiano" src="https://img.shields.io/badge/Italiano-d9d9d9"></a>
|
||||
<a href="../bn-BD/README.md"><img alt="README in বাংলা" src="https://img.shields.io/badge/বাংলা-d9d9d9"></a>
|
||||
<a href="../hi-IN/README.md"><img alt="README in हिन्दी" src="https://img.shields.io/badge/Hindi-d9d9d9"></a>
|
||||
</p>
|
||||
|
||||
Dify एक मुक्त-स्रोत प्लेटफ़ॉर्म है जो LLM अनुप्रयोगों (एप्लिकेशनों) के विकास के लिए बनाया गया है। इसका सहज इंटरफ़ेस एजेंटिक एआई वर्कफ़्लो, RAG पाइपलाइनों, एजेंट क्षमताओं, मॉडल प्रबंधन, ऑब्ज़र्वेबिलिटी (निगरानी) सुविधाओं और अन्य को एक साथ जोड़ता है — जिससे आप प्रोटोटाइप से उत्पादन (प्रोडक्शन) तक जल्दी पहुँच सकते हैं।
|
||||
|
||||
## त्वरित प्रारंभ
|
||||
|
||||
> Dify स्थापित करने से पहले, सुनिश्चित करें कि आपकी मशीन निम्नलिखित न्यूनतम सिस्टम आवश्यकताओं को पूरा करती है:
|
||||
>
|
||||
> - CPU >= 2 Core
|
||||
> - RAM >= 4 GiB
|
||||
|
||||
<br/>
|
||||
|
||||
Dify सर्वर शुरू करने का सबसे आसान तरीका [Docker Compose](../..docker/docker-compose.yaml) के माध्यम से है। नीचे दिए गए कमांड्स से Dify चलाने से पहले, सुनिश्चित करें कि आपकी मशीन पर [Docker] (https://docs.docker.com/get-docker/) और [Docker Compose] (https://docs.docker.com/compose/install/) इंस्टॉल हैं।:
|
||||
|
||||
```bash
|
||||
cd dify
|
||||
cd docker
|
||||
cp .env.example .env
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
रन करने के बाद, आप अपने ब्राउज़र में [http://localhost/install](http://localhost/install) पर Dify डैशबोर्ड एक्सेस कर सकते हैं और प्रारंभिक सेटअप प्रक्रिया शुरू कर सकते हैं।
|
||||
|
||||
#### सहायता प्राप्त करना
|
||||
|
||||
यदि आपको Dify सेटअप करते समय कोई समस्या आती है, तो कृपया हमारे [FAQ](https://docs.dify.ai/getting-started/install-self-hosted/faqs) को देखें। यदि फिर भी समस्या बनी रहती है, तो [the community and us](#community--contact) से संपर्क करें।
|
||||
|
||||
> यदि आप Dify में योगदान देना चाहते हैं या अतिरिक्त विकास करना चाहते हैं, तो हमारे [guide to deploying from source code](https://docs.dify.ai/getting-started/install-self-hosted/local-source-code) को देखें।
|
||||
|
||||
## मुख्य विशेषताएँ
|
||||
|
||||
**1. वर्कफ़्लो**:\
|
||||
एक दृश्य कैनवास पर शक्तिशाली एआई वर्कफ़्लो बनाएं और परीक्षण करें, नीचे दी गई सभी सुविधाओं और उससे भी आगे का उपयोग करते हुए।
|
||||
|
||||
**2. व्यापक मॉडल समर्थन**:\
|
||||
कई इन्फ़रेंस प्रदाताओं और स्व-होस्टेड समाधानों से सैकड़ों स्वामित्व / मुक्त-स्रोत LLMs के साथ सहज एकीकरण, जिसमें GPT, Mistral, Llama3, और कोई भी OpenAI API-संगत मॉडल शामिल हैं। समर्थित मॉडल प्रदाताओं की पूरी सूची [here](https://docs.dify.ai/getting-started/readme/model-providers) पर पाई जा सकती है।
|
||||
|
||||

|
||||
|
||||
**3. प्रॉम्प्ट IDE**:\
|
||||
प्रॉम्प्ट बनाने, मॉडल प्रदर्शन की तुलना करने, और चैट-आधारित ऐप में टेक्स्ट-टू-स्पीच जैसी अतिरिक्त सुविधाएँ जोड़ने के लिए सहज इंटरफ़ेस।
|
||||
|
||||
**4. RAG पाइपलाइन**:\
|
||||
विस्तृत RAG क्षमताएँ जो दस्तावेज़ इनजेशन से लेकर रिट्रीवल तक सब कुछ कवर करती हैं, और PDFs, PPTs, तथा अन्य सामान्य दस्तावेज़ प्रारूपों से टेक्स्ट निकालने के लिए आउट-ऑफ़-द-बॉक्स समर्थन प्रदान करती हैं।
|
||||
|
||||
**5. एजेंट क्षमताएँ**:\
|
||||
आप LLM फ़ंक्शन कॉलिंग या ReAct के आधार पर एजेंट परिभाषित कर सकते हैं, और एजेंट के लिए पूर्व-निर्मित या कस्टम टूल जोड़ सकते हैं। Dify एआई एजेंटों के लिए 50+ अंतर्निर्मित टूल प्रदान करता है, जैसे Google Search, DALL·E, Stable Diffusion और WolframAlpha।
|
||||
|
||||
**6. LLMOps**:\
|
||||
समय के साथ एप्लिकेशन लॉग्स और प्रदर्शन की निगरानी और विश्लेषण करें। आप उत्पादन डेटा और एनोटेशनों के आधार पर प्रॉम्प्ट्स, डेटासेट्स और मॉडल्स को निरंतर सुधार सकते हैं।
|
||||
|
||||
**7. Backend-as-a-Service**:\
|
||||
Dify की सभी सेवाएँ संबंधित APIs के साथ आती हैं, जिससे आप Dify को आसानी से अपने व्यावसायिक लॉजिक में एकीकृत कर सकते हैं।
|
||||
|
||||
## Dify का उपयोग करना
|
||||
|
||||
- **Cloud <br/>**\
|
||||
हम [Dify Cloud](https://dify.ai) सेवा प्रदान करते हैं, जिसे कोई भी बिना किसी सेटअप के आज़मा सकता है। यह स्व-परिनियोजित संस्करण की सभी क्षमताएँ प्रदान करता है और सैंडबॉक्स प्लान में 200 निःशुल्क GPT-4 कॉल्स शामिल करता है।
|
||||
|
||||
- **Dify कम्युनिटी संस्करण की स्व-होस्टिंग<br/>**\
|
||||
अपने वातावरण में Dify को जल्दी चलाएँ इस [starter guide](#quick-start) की मदद से।\
|
||||
आगे के संदर्भों और विस्तृत निर्देशों के लिए हमारी [documentation](https://docs.dify.ai) देखें।
|
||||
|
||||
- **उद्यमों / संगठनों के लिए Dify<br/>**\
|
||||
हम अतिरिक्त एंटरप्राइज़-केंद्रित सुविधाएँ प्रदान करते हैं।\
|
||||
[इस चैटबॉट के माध्यम से हमें अपने प्रश्न भेजें](https://udify.app/chat/22L1zSxg6yW1cWQg) या [हमें ईमेल भेजें](mailto:business@dify.ai?subject=%5BGitHub%5DBusiness%20License%20Inquiry) ताकि हम एंटरप्राइज़ आवश्यकताओं पर चर्चा कर सकें। <br/>
|
||||
|
||||
> AWS का उपयोग करने वाले स्टार्टअप्स और छोटे व्यवसायों के लिए, [AWS Marketplace पर Dify Premium](https://aws.amazon.com/marketplace/pp/prodview-t22mebxzwjhu6) देखें और इसे एक क्लिक में अपने AWS VPC पर डिप्लॉय करें। यह एक किफायती AMI ऑफ़रिंग है, जो आपको कस्टम लोगो और ब्रांडिंग के साथ ऐप्स बनाने की अनुमति देती है।
|
||||
|
||||
## आगे बने रहें
|
||||
|
||||
GitHub पर Dify को स्टार करें और नए रिलीज़ की सूचना तुरंत प्राप्त करें।
|
||||
|
||||

|
||||
|
||||
## उन्नत सेटअप
|
||||
|
||||
### कस्टम कॉन्फ़िगरेशन
|
||||
|
||||
यदि आपको कॉन्फ़िगरेशन को कस्टमाइज़ करने की आवश्यकता है, तो कृपया हमारी [.env.example](../../docker/.env.example) फ़ाइल में दिए गए टिप्पणियों (comments) को देखें और अपने `.env` फ़ाइल में संबंधित मानों को अपडेट करें।\
|
||||
इसके अतिरिक्त, आपको अपने विशेष डिप्लॉयमेंट वातावरण और आवश्यकताओं के आधार पर `docker-compose.yaml` फ़ाइल में भी बदलाव करने की आवश्यकता हो सकती है, जैसे इमेज संस्करण, पोर्ट मैपिंग या वॉल्यूम माउंट्स बदलना।\
|
||||
कोई भी बदलाव करने के बाद, कृपया `docker-compose up -d` कमांड को पुनः चलाएँ।\
|
||||
उपलब्ध सभी environment variables की पूरी सूची [here](https://docs.dify.ai/getting-started/install-self-hosted/environments) पर पाई जा सकती है।
|
||||
|
||||
### Grafana के साथ मेट्रिक्स मॉनिटरिंग
|
||||
|
||||
Grafana में Dify के PostgreSQL डेटाबेस को डेटा स्रोत के रूप में उपयोग करते हुए डैशबोर्ड आयात करें, ताकि आप ऐप्स, टेनेंट्स, संदेशों आदि के स्तर पर मेट्रिक्स की निगरानी कर सकें।
|
||||
|
||||
- [Grafana Dashboard by @bowenliang123](https://github.com/bowenliang123/dify-grafana-dashboard)
|
||||
|
||||
### Kubernetes के साथ डिप्लॉयमेंट
|
||||
|
||||
यदि आप उच्च उपलब्धता (high-availability) सेटअप कॉन्फ़िगर करना चाहते हैं, तो समुदाय द्वारा योगदान किए गए [Helm Charts](https://helm.sh/) और YAML फ़ाइलें उपलब्ध हैं जो Dify को Kubernetes पर डिप्लॉय करने की अनुमति देती हैं।
|
||||
|
||||
- [Helm Chart by @LeoQuote](https://github.com/douban/charts/tree/master/charts/dify)
|
||||
- [Helm Chart by @BorisPolonsky](https://github.com/BorisPolonsky/dify-helm)
|
||||
- [Helm Chart by @magicsong](https://github.com/magicsong/ai-charts)
|
||||
- [YAML file by @Winson-030](https://github.com/Winson-030/dify-kubernetes)
|
||||
- [YAML file by @wyy-holding](https://github.com/wyy-holding/dify-k8s)
|
||||
- [🚀 NEW! YAML files (Supports Dify v1.6.0) by @Zhoneym](https://github.com/Zhoneym/DifyAI-Kubernetes)
|
||||
|
||||
#### डिप्लॉयमेंट के लिए Terraform का उपयोग
|
||||
|
||||
[terraform](https://www.terraform.io/) का उपयोग करके एक क्लिक में Dify को क्लाउड प्लेटफ़ॉर्म पर डिप्लॉय करें।
|
||||
|
||||
##### Azure Global
|
||||
|
||||
- [Azure Terraform by @nikawang](https://github.com/nikawang/dify-azure-terraform)
|
||||
|
||||
##### Google Cloud
|
||||
|
||||
- [Google Cloud Terraform by @sotazum](https://github.com/DeNA/dify-google-cloud-terraform)
|
||||
|
||||
#### डिप्लॉयमेंट के लिए AWS CDK का उपयोग
|
||||
|
||||
[CDK](https://aws.amazon.com/cdk/) का उपयोग करके Dify को AWS पर डिप्लॉय करें।
|
||||
|
||||
##### AWS
|
||||
|
||||
- [AWS CDK by @KevinZhao (EKS आधारित)](https://github.com/aws-samples/solution-for-deploying-dify-on-aws)
|
||||
- [AWS CDK by @tmokmss (ECS आधारित)](https://github.com/aws-samples/dify-self-hosted-on-aws)
|
||||
|
||||
#### Alibaba Cloud Computing Nest का उपयोग
|
||||
|
||||
[Alibaba Cloud Computing Nest](https://computenest.console.aliyun.com/service/instance/create/default?type=user&ServiceName=Dify%E7%A4%BE%E5%8C%BA%E7%89%88) के साथ Dify को Alibaba Cloud पर तेज़ी से डिप्लॉय करें।
|
||||
|
||||
#### Alibaba Cloud Data Management का उपयोग
|
||||
|
||||
[Alibaba Cloud Data Management](https://www.alibabacloud.com/help/en/dms/dify-in-invitational-preview/) के साथ एक क्लिक में Dify को Alibaba Cloud पर डिप्लॉय करें।
|
||||
|
||||
#### Azure Devops Pipeline के साथ AKS पर डिप्लॉय करें
|
||||
|
||||
[Azure Devops Pipeline Helm Chart by @LeoZhang](https://github.com/Ruiruiz30/Dify-helm-chart-AKS) के साथ एक क्लिक में Dify को AKS पर डिप्लॉय करें।
|
||||
|
||||
## योगदान (Contributing)
|
||||
|
||||
जो लोग कोड में योगदान देना चाहते हैं, वे हमारे [Contribution Guide](./CONTRIBUTING.md) को देखें।\
|
||||
साथ ही, कृपया Dify को सोशल मीडिया, कार्यक्रमों और सम्मेलनों में साझा करके इसका समर्थन करने पर विचार करें।
|
||||
|
||||
> हम ऐसे योगदानकर्ताओं की तलाश कर रहे हैं जो Dify को मंदारिन या अंग्रेज़ी के अलावा अन्य भाषाओं में अनुवाद करने में मदद कर सकें।\
|
||||
> यदि आप सहायता करने में रुचि रखते हैं, तो अधिक जानकारी के लिए [i18n README](https://github.com/langgenius/dify/blob/main/web/i18n-config/README.md) देखें, और हमारे [Discord Community Server](https://discord.gg/8Tpq4AcN9c) के `global-users` चैनल में हमें संदेश दें।
|
||||
|
||||
## समुदाय और संपर्क (Community & contact)
|
||||
|
||||
- [GitHub Discussion](https://github.com/langgenius/dify/discussions) — सर्वोत्तम उपयोग के लिए: प्रतिक्रिया साझा करने और प्रश्न पूछने हेतु।
|
||||
- [GitHub Issues](https://github.com/langgenius/dify/issues) — सर्वोत्तम उपयोग के लिए: Dify.AI का उपयोग करते समय आने वाली बग्स या फीचर सुझावों के लिए। देखें: [Contribution Guide](../../CONTRIBUTING.md)।
|
||||
- [Discord](https://discord.gg/FngNHpbcY7) — सर्वोत्तम उपयोग के लिए: अपने एप्लिकेशन साझा करने और समुदाय के साथ जुड़ने के लिए।
|
||||
- [X(Twitter)](https://twitter.com/dify_ai) — सर्वोत्तम उपयोग के लिए: अपने एप्लिकेशन साझा करने और समुदाय से जुड़े रहने के लिए।
|
||||
|
||||
**योगदानकर्ता**
|
||||
|
||||
<a href="https://github.com/langgenius/dify/graphs/contributors">
|
||||
<img src="https://contrib.rocks/image?repo=langgenius/dify" />
|
||||
</a>
|
||||
|
||||
## स्टार इतिहास (Star history)
|
||||
|
||||
[](https://star-history.com/#langgenius/dify&Date)
|
||||
|
||||
## सुरक्षा प्रकटीकरण (Security disclosure)
|
||||
|
||||
आपकी गोपनीयता की सुरक्षा के लिए, कृपया GitHub पर सुरक्षा संबंधित समस्याएँ पोस्ट करने से बचें।\
|
||||
इसके बजाय, समस्याओं की रिपोर्ट security@dify.ai पर करें, और हमारी टीम आपको विस्तृत उत्तर के साथ प्रतिक्रिया देगी।
|
||||
|
||||
## लाइसेंस (License)
|
||||
|
||||
यह रिपॉज़िटरी [Dify Open Source License](../../LICENSE) के अंतर्गत लाइसेंस प्राप्त है, जो Apache 2.0 पर आधारित है और इसमें अतिरिक्त शर्तें शामिल हैं।
|
||||
|
|
@ -0,0 +1,213 @@
|
|||

|
||||
|
||||
<p align="center">
|
||||
📌 <a href="https://dify.ai/blog/introducing-dify-workflow-file-upload-a-demo-on-ai-podcast">Introduzione a Dify Workflow File Upload: ricreando il podcast di Google NotebookLM</a>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://cloud.dify.ai">Dify Cloud</a> ·
|
||||
<a href="https://docs.dify.ai/getting-started/install-self-hosted">Self-Hosted</a> ·
|
||||
<a href="https://docs.dify.ai">Documentazione</a> ·
|
||||
<a href="https://dify.ai/pricing">Panoramica dei prodotti Dify</a>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://dify.ai" target="_blank">
|
||||
<img alt="Static Badge" src="https://img.shields.io/badge/Product-F04438"></a>
|
||||
<a href="https://dify.ai/pricing" target="_blank">
|
||||
<img alt="Static Badge" src="https://img.shields.io/badge/free-pricing?logo=free&color=%20%23155EEF&label=pricing&labelColor=%20%23528bff"></a>
|
||||
<a href="https://discord.gg/FngNHpbcY7" target="_blank">
|
||||
<img src="https://img.shields.io/discord/1082486657678311454?logo=discord&labelColor=%20%235462eb&logoColor=%20%23f5f5f5&color=%20%235462eb"
|
||||
alt="chat on Discord"></a>
|
||||
<a href="https://reddit.com/r/difyai" target="_blank">
|
||||
<img src="https://img.shields.io/reddit/subreddit-subscribers/difyai?style=plastic&logo=reddit&label=r%2Fdifyai&labelColor=white"
|
||||
alt="join Reddit"></a>
|
||||
<a href="https://twitter.com/intent/follow?screen_name=dify_ai" target="_blank">
|
||||
<img src="https://img.shields.io/twitter/follow/dify_ai?logo=X&color=%20%23f5f5f5"
|
||||
alt="follow on X(Twitter)"></a>
|
||||
<a href="https://www.linkedin.com/company/langgenius/" target="_blank">
|
||||
<img src="https://custom-icon-badges.demolab.com/badge/LinkedIn-0A66C2?logo=linkedin-white&logoColor=fff"
|
||||
alt="follow on LinkedIn"></a>
|
||||
<a href="https://hub.docker.com/u/langgenius" target="_blank">
|
||||
<img alt="Docker Pulls" src="https://img.shields.io/docker/pulls/langgenius/dify-web?labelColor=%20%23FDB062&color=%20%23f79009"></a>
|
||||
<a href="https://github.com/langgenius/dify/graphs/commit-activity" target="_blank">
|
||||
<img alt="Commits last month" src="https://img.shields.io/github/commit-activity/m/langgenius/dify?labelColor=%20%2332b583&color=%20%2312b76a"></a>
|
||||
<a href="https://github.com/langgenius/dify/" target="_blank">
|
||||
<img alt="Issues closed" src="https://img.shields.io/github/issues-search?query=repo%3Alanggenius%2Fdify%20is%3Aclosed&label=issues%20closed&labelColor=%20%237d89b0&color=%20%235d6b98"></a>
|
||||
<a href="https://github.com/langgenius/dify/discussions/" target="_blank">
|
||||
<img alt="Discussion posts" src="https://img.shields.io/github/discussions/langgenius/dify?labelColor=%20%239b8afb&color=%20%237a5af8"></a>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="../../README.md"><img alt="README in English" src="https://img.shields.io/badge/English-d9d9d9"></a>
|
||||
<a href="../zh-TW/README.md"><img alt="繁體中文文件" src="https://img.shields.io/badge/繁體中文-d9d9d9"></a>
|
||||
<a href="../zh-CN/README.md"><img alt="简体中文文件" src="https://img.shields.io/badge/简体中文-d9d9d9"></a>
|
||||
<a href="../ja-JP/README.md"><img alt="日本語のREADME" src="https://img.shields.io/badge/日本語-d9d9d9"></a>
|
||||
<a href="../es-ES/README.md"><img alt="README en Español" src="https://img.shields.io/badge/Español-d9d9d9"></a>
|
||||
<a href="../fr-FR/README.md"><img alt="README en Français" src="https://img.shields.io/badge/Français-d9d9d9"></a>
|
||||
<a href="../tlh/README.md"><img alt="README tlhIngan Hol" src="https://img.shields.io/badge/Klingon-d9d9d9"></a>
|
||||
<a href="../ko-KR/README.md"><img alt="README in Korean" src="https://img.shields.io/badge/한국어-d9d9d9"></a>
|
||||
<a href="../ar-SA/README.md"><img alt="README بالعربية" src="https://img.shields.io/badge/العربية-d9d9d9"></a>
|
||||
<a href="../tr-TR/README.md"><img alt="Türkçe README" src="https://img.shields.io/badge/Türkçe-d9d9d9"></a>
|
||||
<a href="../vi-VN/README.md"><img alt="README Tiếng Việt" src="https://img.shields.io/badge/Ti%E1%BA%BFng%20Vi%E1%BB%87t-d9d9d9"></a>
|
||||
<a href="../de-DE/README.md"><img alt="README in Deutsch" src="https://img.shields.io/badge/German-d9d9d9"></a>
|
||||
<a href="../it-IT/README.md"><img alt="README in Italiano" src="https://img.shields.io/badge/Italiano-d9d9d9"></a>
|
||||
<a href="../bn-BD/README.md"><img alt="README in বাংলা" src="https://img.shields.io/badge/বাংলা-d9d9d9"></a>
|
||||
</p>
|
||||
|
||||
Dify è una piattaforma open-source per lo sviluppo di applicazioni LLM. La sua interfaccia intuitiva combina flussi di lavoro AI basati su agenti, pipeline RAG, funzionalità di agenti, gestione dei modelli, funzionalità di monitoraggio e altro ancora, permettendovi di passare rapidamente da un prototipo alla produzione.
|
||||
|
||||
## Avvio Rapido
|
||||
|
||||
> Prima di installare Dify, assicuratevi che il vostro sistema soddisfi i seguenti requisiti minimi:
|
||||
>
|
||||
> - CPU >= 2 Core
|
||||
> - RAM >= 4 GiB
|
||||
|
||||
<br/>
|
||||
|
||||
Il modo più semplice per avviare il server Dify è tramite [docker compose](../../docker/docker-compose.yaml). Prima di eseguire Dify con i seguenti comandi, assicuratevi che [Docker](https://docs.docker.com/get-docker/) e [Docker Compose](https://docs.docker.com/compose/install/) siano installati sul vostro sistema:
|
||||
|
||||
```bash
|
||||
cd dify
|
||||
cd docker
|
||||
cp .env.example .env
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
Dopo aver avviato il server, potete accedere al dashboard di Dify tramite il vostro browser all'indirizzo [http://localhost/install](http://localhost/install) e avviare il processo di inizializzazione.
|
||||
|
||||
#### Richiedere Aiuto
|
||||
|
||||
Consultate le nostre [FAQ](https://docs.dify.ai/getting-started/install-self-hosted/faqs) se riscontrate problemi durante la configurazione di Dify. Contattateci [tramite la community](#community--contatti) se continuano a verificarsi difficoltà.
|
||||
|
||||
> Se desiderate contribuire a Dify o effettuare ulteriori sviluppi, consultate la nostra [guida al deployment dal codice sorgente](https://docs.dify.ai/getting-started/install-self-hosted/local-source-code).
|
||||
|
||||
## Caratteristiche Principali
|
||||
|
||||
**1. Workflow**:
|
||||
Create e testate potenti flussi di lavoro AI su un'interfaccia visuale, utilizzando tutte le funzionalità seguenti e oltre.
|
||||
|
||||
**2. Supporto Completo dei Modelli**:
|
||||
Integrazione perfetta con centinaia di LLM proprietari e open-source di decine di provider di inferenza e soluzioni self-hosted, che coprono GPT, Mistral, Llama3 e tutti i modelli compatibili con l'API OpenAI. L'elenco completo dei provider di modelli supportati è disponibile [qui](https://docs.dify.ai/getting-started/readme/model-providers).
|
||||
|
||||

|
||||
|
||||
**3. Prompt IDE**:
|
||||
Interfaccia intuitiva per creare prompt, confrontare le prestazioni dei modelli e aggiungere funzionalità aggiuntive come text-to-speech in un'applicazione basata su chat.
|
||||
|
||||
**4. Pipeline RAG**:
|
||||
Funzionalità RAG complete che coprono tutto, dall'acquisizione dei documenti alla loro interrogazione, con supporto pronto all'uso per l'estrazione di testo da PDF, PPT e altri formati di documenti comuni.
|
||||
|
||||
**5. Capacità degli Agenti**:
|
||||
Potete definire agenti basati su LLM Function Calling o ReAct e aggiungere strumenti predefiniti o personalizzati per l'agente. Dify fornisce oltre 50 strumenti integrati per gli agenti AI, come Google Search, DALL·E, Stable Diffusion e WolframAlpha.
|
||||
|
||||
**6. LLMOps**:
|
||||
Monitorate e analizzate i log delle applicazioni e le prestazioni nel tempo. Potete migliorare continuamente prompt, dataset e modelli basandovi sui dati di produzione e sulle annotazioni.
|
||||
|
||||
**7. Backend-as-a-Service**:
|
||||
Tutte le offerte di Dify sono dotate di API corrispondenti, permettendovi di integrare facilmente Dify nella vostra logica di business.
|
||||
|
||||
## Utilizzo di Dify
|
||||
|
||||
- **Cloud <br/>**
|
||||
Ospitiamo un servizio [Dify Cloud](https://dify.ai) che chiunque può provare senza configurazione. Offre tutte le funzionalità della versione self-hosted e include 200 chiamate GPT-4 gratuite nel piano sandbox.
|
||||
|
||||
- **Dify Community Edition Self-Hosted<br/>**
|
||||
Avviate rapidamente Dify nel vostro ambiente con questa [guida di avvio rapido](#avvio-rapido). Utilizzate la nostra [documentazione](https://docs.dify.ai) per ulteriori informazioni e istruzioni dettagliate.
|
||||
|
||||
- **Dify per Aziende / Organizzazioni<br/>**
|
||||
Offriamo funzionalità aggiuntive specifiche per le aziende. [Potete comunicarci le vostre domande tramite questo chatbot](https://udify.app/chat/22L1zSxg6yW1cWQg) o [inviateci un'email](mailto:business@dify.ai?subject=%5BGitHub%5DBusiness%20License%20Inquiry) per discutere le vostre esigenze aziendali. <br/>
|
||||
|
||||
> Per startup e piccole imprese che utilizzano AWS, date un'occhiata a [Dify Premium su AWS Marketplace](https://aws.amazon.com/marketplace/pp/prodview-t22mebxzwjhu6) e distribuitelo con un solo clic nel vostro AWS VPC. Si tratta di un'offerta AMI conveniente con l'opzione di creare app con logo e branding personalizzati.
|
||||
|
||||
## Resta Sempre Aggiornato
|
||||
|
||||
Mettete una stella a Dify su GitHub e ricevete notifiche immediate sui nuovi rilasci.
|
||||
|
||||

|
||||
|
||||
## Configurazioni Avanzate
|
||||
|
||||
Se dovete personalizzare la configurazione, leggete i commenti nel nostro file [.env.example](../../docker/.env.example) e aggiornate i valori corrispondenti nel vostro file `.env`. Inoltre, potrebbe essere necessario apportare modifiche al file `docker-compose.yaml`, come cambiare le versioni delle immagini, le mappature delle porte o i mount dei volumi, a seconda del vostro ambiente di distribuzione specifico e dei vostri requisiti. Dopo aver apportato le modifiche, riavviate `docker-compose up -d`. L'elenco completo delle variabili d'ambiente disponibili è disponibile [qui](https://docs.dify.ai/getting-started/install-self-hosted/environments).
|
||||
|
||||
### Monitoraggio delle Metriche con Grafana
|
||||
|
||||
Importate la dashboard in Grafana, utilizzando il database PostgreSQL di Dify come origine dati, per monitorare le metriche a livello di app, tenant, messaggi e altro ancora.
|
||||
|
||||
- [Dashboard Grafana di @bowenliang123](https://github.com/bowenliang123/dify-grafana-dashboard)
|
||||
|
||||
### Distribuzione con Kubernetes
|
||||
|
||||
Se desiderate configurare un'installazione ad alta disponibilità, ci sono [Helm Charts](https://helm.sh/) e file YAML forniti dalla community che consentono di distribuire Dify su Kubernetes.
|
||||
|
||||
- [Helm Chart di @LeoQuote](https://github.com/douban/charts/tree/master/charts/dify)
|
||||
- [Helm Chart di @BorisPolonsky](https://github.com/BorisPolonsky/dify-helm)
|
||||
- [Helm Chart di @magicsong](https://github.com/magicsong/ai-charts)
|
||||
- [File YAML di @Winson-030](https://github.com/Winson-030/dify-kubernetes)
|
||||
- [File YAML di @wyy-holding](https://github.com/wyy-holding/dify-k8s)
|
||||
- [🚀 NUOVO! File YAML (Supporta Dify v1.6.0) di @Zhoneym](https://github.com/Zhoneym/DifyAI-Kubernetes)
|
||||
|
||||
#### Utilizzo di Terraform per la Distribuzione
|
||||
|
||||
Distribuite Dify con un solo clic su una piattaforma cloud utilizzando [terraform](https://www.terraform.io/).
|
||||
|
||||
##### Azure Global
|
||||
|
||||
- [Azure Terraform di @nikawang](https://github.com/nikawang/dify-azure-terraform)
|
||||
|
||||
##### Google Cloud
|
||||
|
||||
- [Google Cloud Terraform di @sotazum](https://github.com/DeNA/dify-google-cloud-terraform)
|
||||
|
||||
#### Utilizzo di AWS CDK per la Distribuzione
|
||||
|
||||
Distribuzione di Dify su AWS con [CDK](https://aws.amazon.com/cdk/)
|
||||
|
||||
##### AWS
|
||||
|
||||
- [AWS CDK di @KevinZhao (basato su EKS)](https://github.com/aws-samples/solution-for-deploying-dify-on-aws)
|
||||
- [AWS CDK di @tmokmss (basato su ECS)](https://github.com/aws-samples/dify-self-hosted-on-aws)
|
||||
|
||||
#### Alibaba Cloud
|
||||
|
||||
[Alibaba Cloud Computing Nest](https://computenest.console.aliyun.com/service/instance/create/default?type=user&ServiceName=Dify%E7%A4%BE%E5%8C%BA%E7%89%88)
|
||||
|
||||
#### Alibaba Cloud Data Management
|
||||
|
||||
Distribuzione con un clic di Dify su Alibaba Cloud con [Alibaba Cloud Data Management](https://www.alibabacloud.com/help/en/dms/dify-in-invitational-preview/)
|
||||
|
||||
#### Utilizzo di Azure DevOps Pipeline per la Distribuzione su AKS
|
||||
|
||||
Distribuite Dify con un clic in AKS utilizzando [Azure DevOps Pipeline Helm Chart di @LeoZhang](https://github.com/Ruiruiz30/Dify-helm-chart-AKS)
|
||||
|
||||
## Contribuire
|
||||
|
||||
Se desiderate contribuire con codice, leggete la nostra [Guida ai Contributi](../../CONTRIBUTING.md). Allo stesso tempo, vi chiediamo di supportare Dify condividendolo sui social media e presentandolo a eventi e conferenze.
|
||||
|
||||
> Cerchiamo collaboratori che aiutino a tradurre Dify in altre lingue oltre al mandarino o all'inglese. Se siete interessati a collaborare, leggete il [README i18n](https://github.com/langgenius/dify/blob/main/web/i18n-config/README.md) per ulteriori informazioni e lasciate un commento nel canale `global-users` del nostro [server della community Discord](https://discord.gg/8Tpq4AcN9c).
|
||||
|
||||
## Community & Contatti
|
||||
|
||||
- [GitHub Discussion](https://github.com/langgenius/dify/discussions). Ideale per: condividere feedback e porre domande.
|
||||
- [GitHub Issues](https://github.com/langgenius/dify/issues). Ideale per: bug che riscontrate durante l'utilizzo di Dify.AI e proposte di funzionalità. Consultate la nostra [Guida ai Contributi](../../CONTRIBUTING.md).
|
||||
- [Discord](https://discord.gg/FngNHpbcY7). Ideale per: condividere le vostre applicazioni e interagire con la community.
|
||||
- [X(Twitter)](https://twitter.com/dify_ai). Ideale per: condividere le vostre applicazioni e interagire con la community.
|
||||
|
||||
**Collaboratori**
|
||||
|
||||
<a href="https://github.com/langgenius/dify/graphs/contributors">
|
||||
<img src="https://contrib.rocks/image?repo=langgenius/dify" />
|
||||
</a>
|
||||
|
||||
## Storia delle Stelle
|
||||
|
||||
[](https://star-history.com/#langgenius/dify&Date)
|
||||
|
||||
## Divulgazione sulla Sicurezza
|
||||
|
||||
Per proteggere la vostra privacy, evitate di pubblicare problemi di sicurezza su GitHub. Inviate invece le vostre domande a security@dify.ai e vi forniremo una risposta più dettagliata.
|
||||
|
||||
## Licenza
|
||||
|
||||
Questo repository è disponibile sotto la [Dify Open Source License](../../LICENSE), che è essenzialmente Apache 2.0 con alcune restrizioni aggiuntive.
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
'use client'
|
||||
import type { FC, SVGProps } from 'react'
|
||||
import React from 'react'
|
||||
import Link from 'next/link'
|
||||
import { Trans, useTranslation } from 'react-i18next'
|
||||
import { basePath } from '@/utils/var'
|
||||
import { getRedirectionPath } from '@/utils/app-redirection'
|
||||
import type { App } from '@/types/app'
|
||||
import { AppModeEnum } from '@/types/app'
|
||||
|
||||
const ThreeDotsIcon = ({ className }: SVGProps<SVGElement>) => {
|
||||
return <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg" className={className ?? ''}>
|
||||
<path d="M5 6.5V5M8.93934 7.56066L10 6.5M10.0103 11.5H11.5103" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
|
||||
</svg>
|
||||
}
|
||||
|
||||
const EmptyElement: FC<{ appDetail: App }> = ({ appDetail }) => {
|
||||
const { t } = useTranslation()
|
||||
|
||||
const getWebAppType = (appType: AppModeEnum) => {
|
||||
if (appType !== AppModeEnum.COMPLETION && appType !== AppModeEnum.WORKFLOW)
|
||||
return AppModeEnum.CHAT
|
||||
return appType
|
||||
}
|
||||
|
||||
return <div className='flex h-full items-center justify-center'>
|
||||
<div className='box-border h-fit w-[560px] rounded-2xl bg-background-section-burn px-5 py-4'>
|
||||
<span className='system-md-semibold text-text-secondary'>{t('appLog.table.empty.element.title')}<ThreeDotsIcon className='relative -left-1.5 -top-3 inline text-text-secondary' /></span>
|
||||
<div className='system-sm-regular mt-2 text-text-tertiary'>
|
||||
<Trans
|
||||
i18nKey="appLog.table.empty.element.content"
|
||||
components={{
|
||||
shareLink: <Link href={`${appDetail.site.app_base_url}${basePath}/${getWebAppType(appDetail.mode)}/${appDetail.site.access_token}`} className='text-util-colors-blue-blue-600' target='_blank' rel='noopener noreferrer' />,
|
||||
testLink: <Link href={getRedirectionPath(true, appDetail)} className='text-util-colors-blue-blue-600' />,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
export default React.memo(EmptyElement)
|
||||
|
|
@ -1,16 +1,14 @@
|
|||
'use client'
|
||||
import type { FC, SVGProps } from 'react'
|
||||
import type { FC } from 'react'
|
||||
import React, { useState } from 'react'
|
||||
import useSWR from 'swr'
|
||||
import Link from 'next/link'
|
||||
import { usePathname } from 'next/navigation'
|
||||
import { useDebounce } from 'ahooks'
|
||||
import { omit } from 'lodash-es'
|
||||
import dayjs from 'dayjs'
|
||||
import { basePath } from '@/utils/var'
|
||||
import { Trans, useTranslation } from 'react-i18next'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import List from './list'
|
||||
import Filter, { TIME_PERIOD_MAPPING } from './filter'
|
||||
import EmptyElement from './empty-element'
|
||||
import Pagination from '@/app/components/base/pagination'
|
||||
import Loading from '@/app/components/base/loading'
|
||||
import { fetchChatConversations, fetchCompletionConversations } from '@/service/log'
|
||||
|
|
@ -28,30 +26,6 @@ export type QueryParam = {
|
|||
sort_by?: string
|
||||
}
|
||||
|
||||
const ThreeDotsIcon = ({ className }: SVGProps<SVGElement>) => {
|
||||
return <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg" className={className ?? ''}>
|
||||
<path d="M5 6.5V5M8.93934 7.56066L10 6.5M10.0103 11.5H11.5103" stroke="#374151" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
|
||||
</svg>
|
||||
}
|
||||
|
||||
const EmptyElement: FC<{ appUrl: string }> = ({ appUrl }) => {
|
||||
const { t } = useTranslation()
|
||||
const pathname = usePathname()
|
||||
const pathSegments = pathname.split('/')
|
||||
pathSegments.pop()
|
||||
return <div className='flex h-full items-center justify-center'>
|
||||
<div className='box-border h-fit w-[560px] rounded-2xl bg-background-section-burn px-5 py-4'>
|
||||
<span className='system-md-semibold text-text-secondary'>{t('appLog.table.empty.element.title')}<ThreeDotsIcon className='relative -left-1.5 -top-3 inline' /></span>
|
||||
<div className='system-sm-regular mt-2 text-text-tertiary'>
|
||||
<Trans
|
||||
i18nKey="appLog.table.empty.element.content"
|
||||
components={{ shareLink: <Link href={`${pathSegments.join('/')}/overview`} className='text-util-colors-blue-blue-600' />, testLink: <Link href={appUrl} className='text-util-colors-blue-blue-600' target='_blank' rel='noopener noreferrer' /> }}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
const Logs: FC<ILogsProps> = ({ appDetail }) => {
|
||||
const { t } = useTranslation()
|
||||
const [queryParams, setQueryParams] = useState<QueryParam>({
|
||||
|
|
@ -79,12 +53,6 @@ const Logs: FC<ILogsProps> = ({ appDetail }) => {
|
|||
...omit(debouncedQueryParams, ['period']),
|
||||
}
|
||||
|
||||
const getWebAppType = (appType: AppModeEnum) => {
|
||||
if (appType !== AppModeEnum.COMPLETION && appType !== AppModeEnum.WORKFLOW)
|
||||
return AppModeEnum.CHAT
|
||||
return appType
|
||||
}
|
||||
|
||||
// When the details are obtained, proceed to the next request
|
||||
const { data: chatConversations, mutate: mutateChatList } = useSWR(() => isChatMode
|
||||
? {
|
||||
|
|
@ -111,7 +79,7 @@ const Logs: FC<ILogsProps> = ({ appDetail }) => {
|
|||
? <Loading type='app' />
|
||||
: total > 0
|
||||
? <List logs={isChatMode ? chatConversations : completionConversations} appDetail={appDetail} onRefresh={isChatMode ? mutateChatList : mutateCompletionList} />
|
||||
: <EmptyElement appUrl={`${appDetail.site.app_base_url}${basePath}/${getWebAppType(appDetail.mode)}/${appDetail.site.access_token}`} />
|
||||
: <EmptyElement appDetail={appDetail} />
|
||||
}
|
||||
{/* Show Pagination only if the total is more than the limit */}
|
||||
{(total && total > APP_PAGE_LIMIT)
|
||||
|
|
|
|||
|
|
@ -1,23 +1,21 @@
|
|||
'use client'
|
||||
import type { FC, SVGProps } from 'react'
|
||||
import type { FC } from 'react'
|
||||
import React, { useState } from 'react'
|
||||
import useSWR from 'swr'
|
||||
import { usePathname } from 'next/navigation'
|
||||
import { useDebounce } from 'ahooks'
|
||||
import { omit } from 'lodash-es'
|
||||
import dayjs from 'dayjs'
|
||||
import utc from 'dayjs/plugin/utc'
|
||||
import timezone from 'dayjs/plugin/timezone'
|
||||
import { Trans, useTranslation } from 'react-i18next'
|
||||
import Link from 'next/link'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import List from './list'
|
||||
import { basePath } from '@/utils/var'
|
||||
import Filter, { TIME_PERIOD_MAPPING } from './filter'
|
||||
import EmptyElement from '@/app/components/app/log/empty-element'
|
||||
import Pagination from '@/app/components/base/pagination'
|
||||
import Loading from '@/app/components/base/loading'
|
||||
import { fetchWorkflowLogs } from '@/service/log'
|
||||
import { APP_PAGE_LIMIT } from '@/config'
|
||||
import { type App, AppModeEnum } from '@/types/app'
|
||||
import type { App } from '@/types/app'
|
||||
import { useAppContext } from '@/context/app-context'
|
||||
|
||||
dayjs.extend(utc)
|
||||
|
|
@ -33,29 +31,6 @@ export type QueryParam = {
|
|||
keyword?: string
|
||||
}
|
||||
|
||||
const ThreeDotsIcon = ({ className }: SVGProps<SVGElement>) => {
|
||||
return <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg" className={className ?? ''}>
|
||||
<path d="M5 6.5V5M8.93934 7.56066L10 6.5M10.0103 11.5H11.5103" stroke="#374151" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
|
||||
</svg>
|
||||
}
|
||||
const EmptyElement: FC<{ appUrl: string }> = ({ appUrl }) => {
|
||||
const { t } = useTranslation()
|
||||
const pathname = usePathname()
|
||||
const pathSegments = pathname.split('/')
|
||||
pathSegments.pop()
|
||||
return <div className='flex h-full items-center justify-center'>
|
||||
<div className='box-border h-fit w-[560px] rounded-2xl bg-background-section-burn px-5 py-4'>
|
||||
<span className='system-md-semibold text-text-secondary'>{t('appLog.table.empty.element.title')}<ThreeDotsIcon className='relative -left-1.5 -top-3 inline' /></span>
|
||||
<div className='system-sm-regular mt-2 text-text-tertiary'>
|
||||
<Trans
|
||||
i18nKey="appLog.table.empty.element.content"
|
||||
components={{ shareLink: <Link href={`${pathSegments.join('/')}/overview`} className='text-util-colors-blue-blue-600' />, testLink: <Link href={appUrl} className='text-util-colors-blue-blue-600' target='_blank' rel='noopener noreferrer' /> }}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
const Logs: FC<ILogsProps> = ({ appDetail }) => {
|
||||
const { t } = useTranslation()
|
||||
const { userProfile: { timezone } } = useAppContext()
|
||||
|
|
@ -78,12 +53,6 @@ const Logs: FC<ILogsProps> = ({ appDetail }) => {
|
|||
...omit(debouncedQueryParams, ['period', 'status']),
|
||||
}
|
||||
|
||||
const getWebAppType = (appType: AppModeEnum) => {
|
||||
if (appType !== AppModeEnum.COMPLETION && appType !== AppModeEnum.WORKFLOW)
|
||||
return AppModeEnum.CHAT
|
||||
return appType
|
||||
}
|
||||
|
||||
const { data: workflowLogs, mutate } = useSWR({
|
||||
url: `/apps/${appDetail.id}/workflow-app-logs`,
|
||||
params: query,
|
||||
|
|
@ -101,7 +70,7 @@ const Logs: FC<ILogsProps> = ({ appDetail }) => {
|
|||
? <Loading type='app' />
|
||||
: total > 0
|
||||
? <List logs={workflowLogs} appDetail={appDetail} onRefresh={mutate} />
|
||||
: <EmptyElement appUrl={`${appDetail.site.app_base_url}${basePath}/${getWebAppType(appDetail.mode)}/${appDetail.site.access_token}`} />
|
||||
: <EmptyElement appDetail={appDetail} />
|
||||
}
|
||||
{/* Show Pagination only if the total is more than the limit */}
|
||||
{(total && total > APP_PAGE_LIMIT)
|
||||
|
|
|
|||
|
|
@ -32,8 +32,8 @@ export const preprocessLaTeX = (content: string) => {
|
|||
}
|
||||
|
||||
export const preprocessThinkTag = (content: string) => {
|
||||
const thinkOpenTagRegex = /(<think>\n)+/g
|
||||
const thinkCloseTagRegex = /\n<\/think>/g
|
||||
const thinkOpenTagRegex = /(<think>\s*)+/g
|
||||
const thinkCloseTagRegex = /(\s*<\/think>)+/g
|
||||
return flow([
|
||||
(str: string) => str.replace(thinkOpenTagRegex, '<details data-think=true>\n'),
|
||||
(str: string) => str.replace(thinkCloseTagRegex, '\n[ENDTHINKFLAG]</details>'),
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ const PluginTasks = () => {
|
|||
|
||||
return (
|
||||
<div
|
||||
className='flex items-center'
|
||||
className={cn('flex items-center', opacity < 0 && 'hidden')}
|
||||
style={{ opacity }}
|
||||
>
|
||||
<PortalToFollowElem
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ const translation = {
|
|||
noOutput: '无输出',
|
||||
element: {
|
||||
title: '这里有人吗',
|
||||
content: '在这里观测和标注最终用户和 AI 应用程序之间的交互,以不断提高 AI 的准确性。您可以<testLink>试试</testLink> web app 或<shareLink>分享</shareLink>出去,然后返回此页面。',
|
||||
content: '在这里观测和标注最终用户和 AI 应用程序之间的交互,以不断提高 AI 的准确性。您可以尝试<shareLink>分享</shareLink>或<testLink>测试</testLink>此Web应用程序,然后返回此页面。',
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ const translation = {
|
|||
noOutput: '無輸出',
|
||||
element: {
|
||||
title: '這裡有人嗎',
|
||||
content: '在這裡觀測和標註終端使用者和 AI 應用程式之間的互動,以不斷提高 AI 的準確性。您可以<testLink>試試</testLink> web app 或<shareLink>分享</shareLink>出去,然後返回此頁面。',
|
||||
content: '在這裡觀測和標註終端使用者和 AI 應用程式之間的互動,以不斷提高 AI 的準確性。您可以嘗試<shareLink>分享</shareLink>或<testLink>測試</testLink>此Web應用程序,然後返回此頁面。',
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
|
|||
Loading…
Reference in New Issue