mirror of
https://github.com/langgenius/dify.git
synced 2026-08-30 04:23:20 +08:00
508 lines
14 KiB
Python
508 lines
14 KiB
Python
from __future__ import annotations
|
|
|
|
from typing import Annotated, Any, Literal
|
|
|
|
from pydantic import BaseModel, ConfigDict, Field, RootModel, WithJsonSchema, computed_field
|
|
|
|
from fields.base import ResponseModel
|
|
from graphon.file import helpers as file_helpers
|
|
from models.model import IconType
|
|
|
|
type JSONValue = str | int | float | bool | None | dict[str, Any] | list[Any]
|
|
type JSONObject = dict[str, Any]
|
|
URLString = Annotated[str, WithJsonSchema({"format": "url", "type": "string"})]
|
|
UUIDString = Annotated[str, WithJsonSchema({"format": "uuid", "type": "string"})]
|
|
Int64 = Annotated[int, WithJsonSchema({"format": "int64", "type": "integer"})]
|
|
FloatNumber = Annotated[float, WithJsonSchema({"format": "float", "type": "number"})]
|
|
DoubleNumber = Annotated[float, WithJsonSchema({"format": "double", "type": "number"})]
|
|
DecimalString = Annotated[str, WithJsonSchema({"format": "decimal", "type": "string"})]
|
|
|
|
FeatureToggleObject = Annotated[
|
|
JSONObject,
|
|
WithJsonSchema({"type": "object", "properties": {"enabled": {"type": "boolean"}}}),
|
|
]
|
|
TextToSpeechObject = Annotated[
|
|
JSONObject,
|
|
WithJsonSchema(
|
|
{
|
|
"type": "object",
|
|
"properties": {
|
|
"enabled": {"type": "boolean"},
|
|
"voice": {"type": "string"},
|
|
"language": {"type": "string"},
|
|
"autoPlay": {"type": "string"},
|
|
},
|
|
}
|
|
),
|
|
]
|
|
FileUploadObject = Annotated[
|
|
JSONObject,
|
|
WithJsonSchema(
|
|
{
|
|
"type": "object",
|
|
"properties": {
|
|
"enabled": {"type": "boolean"},
|
|
"number_limits": {"type": "integer"},
|
|
"allowed_file_types": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "string",
|
|
"enum": ["document", "image", "audio", "video", "custom"],
|
|
},
|
|
},
|
|
"allowed_file_extensions": {"type": "array", "items": {"type": "string"}},
|
|
"allowed_file_upload_methods": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "string",
|
|
"enum": ["remote_url", "local_file"],
|
|
},
|
|
},
|
|
"image": {
|
|
"type": "object",
|
|
"properties": {
|
|
"enabled": {"type": "boolean"},
|
|
"number_limits": {"type": "integer"},
|
|
"detail": {"type": "string"},
|
|
"transfer_methods": {"type": "array", "items": {"type": "string"}},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
),
|
|
]
|
|
USER_INPUT_FORM_TYPES = (
|
|
"text-input",
|
|
"select",
|
|
"paragraph",
|
|
"number",
|
|
"external_data_tool",
|
|
"file",
|
|
"file-list",
|
|
"checkbox",
|
|
"json_object",
|
|
)
|
|
USER_INPUT_FORM_ITEM_CONFIG_SCHEMA: dict[str, object] = {
|
|
"type": "object",
|
|
"required": ["label", "variable"],
|
|
"properties": {
|
|
"variable": {"type": "string"},
|
|
"label": {"type": "string"},
|
|
"description": {"type": "string"},
|
|
"required": {"type": "boolean"},
|
|
"hide": {"type": "boolean"},
|
|
# Defaults are typed by the form kind: strings, numbers, booleans,
|
|
# JSON objects, and file references are all valid public values.
|
|
"default": {},
|
|
"type": {"enum": list(USER_INPUT_FORM_TYPES), "type": "string"},
|
|
"max_length": {"anyOf": [{"type": "integer"}, {"type": "null"}]},
|
|
"options": {"type": "array", "items": {"type": "string"}},
|
|
"allowed_file_types": {"anyOf": [{"type": "array", "items": {"type": "string"}}, {"type": "null"}]},
|
|
"allowed_file_extensions": {"anyOf": [{"type": "array", "items": {"type": "string"}}, {"type": "null"}]},
|
|
"allowed_file_upload_methods": {"anyOf": [{"type": "array", "items": {"type": "string"}}, {"type": "null"}]},
|
|
"json_schema": {
|
|
"anyOf": [
|
|
{"type": "object", "additionalProperties": True},
|
|
{"type": "null"},
|
|
]
|
|
},
|
|
"config": {"type": "object", "additionalProperties": True},
|
|
},
|
|
}
|
|
UserInputFormList = Annotated[
|
|
list[JSONObject],
|
|
WithJsonSchema(
|
|
{
|
|
"type": "array",
|
|
"items": {
|
|
"type": "object",
|
|
"oneOf": [
|
|
{
|
|
"type": "object",
|
|
"additionalProperties": False,
|
|
"properties": {form_type: USER_INPUT_FORM_ITEM_CONFIG_SCHEMA},
|
|
"required": [form_type],
|
|
}
|
|
for form_type in USER_INPUT_FORM_TYPES
|
|
],
|
|
},
|
|
}
|
|
),
|
|
]
|
|
|
|
|
|
class SystemParameters(BaseModel):
|
|
image_file_size_limit: int
|
|
video_file_size_limit: int
|
|
audio_file_size_limit: int
|
|
file_size_limit: int
|
|
workflow_file_upload_limit: int
|
|
|
|
|
|
class BlockingUsageResponse(ResponseModel):
|
|
model_config = ConfigDict(extra="allow")
|
|
|
|
prompt_tokens: int | None = None
|
|
prompt_unit_price: DecimalString | None = None
|
|
prompt_price_unit: DecimalString | None = None
|
|
prompt_price: DecimalString | None = None
|
|
completion_tokens: int | None = None
|
|
completion_unit_price: DecimalString | None = None
|
|
completion_price_unit: DecimalString | None = None
|
|
completion_price: DecimalString | None = None
|
|
total_tokens: int | None = None
|
|
total_price: DecimalString | None = None
|
|
currency: str | None = None
|
|
latency: DoubleNumber | None = None
|
|
|
|
|
|
class BlockingRetrieverResourceResponse(ResponseModel):
|
|
model_config = ConfigDict(extra="allow")
|
|
|
|
id: UUIDString | None = None
|
|
message_id: UUIDString | None = None
|
|
position: int
|
|
dataset_id: UUIDString | None = None
|
|
dataset_name: str | None = None
|
|
document_id: UUIDString | None = None
|
|
document_name: str | None = None
|
|
data_source_type: str | None = None
|
|
segment_id: UUIDString | None = None
|
|
score: FloatNumber | None = None
|
|
hit_count: int | None = None
|
|
word_count: int | None = None
|
|
segment_position: int | None = None
|
|
index_node_hash: str | None = None
|
|
content: str | None = None
|
|
summary: str | None = None
|
|
created_at: Int64 | None = None
|
|
|
|
|
|
class BlockingMetadataResponse(ResponseModel):
|
|
model_config = ConfigDict(extra="allow")
|
|
|
|
usage: BlockingUsageResponse | None = None
|
|
retriever_resources: list[BlockingRetrieverResourceResponse] | None = None
|
|
|
|
|
|
class ChatMessageBlockingResponse(ResponseModel):
|
|
model_config = ConfigDict(extra="allow")
|
|
|
|
event: Literal["message"]
|
|
task_id: UUIDString
|
|
id: UUIDString
|
|
message_id: UUIDString
|
|
conversation_id: UUIDString
|
|
mode: str
|
|
answer: str
|
|
metadata: BlockingMetadataResponse = Field(description="Metadata including usage and retriever resources.")
|
|
created_at: Int64
|
|
|
|
|
|
class PauseReasonResponseBase(ResponseModel):
|
|
model_config = ConfigDict(extra="allow")
|
|
|
|
form_id: UUIDString | None = None
|
|
node_id: str | None = None
|
|
node_title: str | None = None
|
|
form_content: str | None = None
|
|
inputs: list[JSONObject] = Field(default_factory=list)
|
|
actions: list[JSONObject] = Field(default_factory=list)
|
|
display_in_ui: bool | None = None
|
|
resolved_default_values: dict[str, Any] = Field(default_factory=dict)
|
|
form_token: str | None = None
|
|
approval_channels: list[str] = Field(default_factory=list)
|
|
expiration_time: Int64 | None = None
|
|
message: str | None = None
|
|
|
|
|
|
class ChatPauseReasonResponse(PauseReasonResponseBase):
|
|
"""Public pause reason emitted by a blocking Chatflow execution."""
|
|
|
|
TYPE: str
|
|
|
|
|
|
class WorkflowPauseReasonResponse(PauseReasonResponseBase):
|
|
"""Public pause reason emitted by a blocking Workflow execution."""
|
|
|
|
TYPE: str
|
|
|
|
|
|
class ChatPausedBlockingDataResponse(ResponseModel):
|
|
model_config = ConfigDict(extra="allow")
|
|
|
|
id: UUIDString
|
|
mode: str
|
|
conversation_id: UUIDString
|
|
message_id: UUIDString
|
|
workflow_run_id: UUIDString
|
|
answer: str
|
|
metadata: BlockingMetadataResponse = Field(description="Metadata including usage and retriever resources.")
|
|
created_at: Int64
|
|
paused_nodes: list[str]
|
|
reasons: list[ChatPauseReasonResponse]
|
|
status: Literal["paused"]
|
|
elapsed_time: FloatNumber
|
|
total_tokens: int
|
|
total_steps: int
|
|
|
|
|
|
class ChatPausedBlockingResponse(ResponseModel):
|
|
model_config = ConfigDict(extra="allow")
|
|
|
|
event: Literal["workflow_paused"]
|
|
task_id: UUIDString
|
|
id: UUIDString
|
|
message_id: UUIDString
|
|
conversation_id: UUIDString
|
|
mode: str
|
|
answer: str
|
|
metadata: BlockingMetadataResponse = Field(description="Metadata including usage and retriever resources.")
|
|
created_at: Int64
|
|
workflow_run_id: UUIDString
|
|
data: ChatPausedBlockingDataResponse
|
|
|
|
|
|
class ChatBlockingResponse(
|
|
RootModel[
|
|
Annotated[
|
|
ChatMessageBlockingResponse | ChatPausedBlockingResponse,
|
|
Field(discriminator="event"),
|
|
]
|
|
]
|
|
):
|
|
"""Blocking chat response for a completed message or paused Chatflow."""
|
|
|
|
|
|
class CompletionBlockingResponse(ResponseModel):
|
|
model_config = ConfigDict(extra="allow")
|
|
|
|
event: str
|
|
task_id: UUIDString
|
|
id: UUIDString
|
|
message_id: UUIDString
|
|
mode: str
|
|
answer: str
|
|
metadata: BlockingMetadataResponse = Field(description="Metadata including usage and retriever resources.")
|
|
created_at: Int64
|
|
|
|
|
|
class WorkflowBlockingDataBase(ResponseModel):
|
|
model_config = ConfigDict(extra="allow")
|
|
|
|
id: UUIDString
|
|
workflow_id: UUIDString
|
|
outputs: dict[str, Any] | None
|
|
error: str | None
|
|
elapsed_time: FloatNumber
|
|
total_tokens: int
|
|
total_steps: int
|
|
created_at: Int64
|
|
finished_at: Int64 | None
|
|
|
|
|
|
class WorkflowFinishedBlockingDataResponse(WorkflowBlockingDataBase):
|
|
status: Literal["succeeded", "failed", "stopped", "partial-succeeded"]
|
|
|
|
|
|
class WorkflowPausedBlockingDataResponse(WorkflowBlockingDataBase):
|
|
status: Literal["paused"]
|
|
paused_nodes: list[str]
|
|
reasons: list[WorkflowPauseReasonResponse]
|
|
|
|
|
|
class WorkflowFinishedBlockingResponse(ResponseModel):
|
|
model_config = ConfigDict(extra="allow")
|
|
|
|
task_id: UUIDString
|
|
workflow_run_id: UUIDString
|
|
data: WorkflowFinishedBlockingDataResponse
|
|
|
|
|
|
class WorkflowPausedBlockingResponse(ResponseModel):
|
|
model_config = ConfigDict(extra="allow")
|
|
|
|
task_id: UUIDString
|
|
workflow_run_id: UUIDString
|
|
data: WorkflowPausedBlockingDataResponse
|
|
|
|
|
|
class WorkflowBlockingResponse(RootModel[WorkflowFinishedBlockingResponse | WorkflowPausedBlockingResponse]):
|
|
"""Blocking workflow response for a finished or paused execution."""
|
|
|
|
|
|
class SimpleResultResponse(ResponseModel):
|
|
result: str = Field(description="Operation result.")
|
|
|
|
|
|
class GeneratedAppResponse(RootModel[JSONValue]):
|
|
root: JSONValue
|
|
|
|
|
|
class EventStreamResponse(RootModel[str]):
|
|
root: str
|
|
|
|
|
|
class TextFileResponse(RootModel[str]):
|
|
root: str
|
|
|
|
|
|
class RedirectResponse(RootModel[str]):
|
|
root: str
|
|
|
|
|
|
class BinaryFileResponse(RootModel[bytes]):
|
|
root: bytes
|
|
|
|
|
|
class AudioBinaryResponse(RootModel[bytes]):
|
|
root: bytes
|
|
|
|
|
|
class AudioTranscriptResponse(ResponseModel):
|
|
text: str
|
|
|
|
|
|
class ValidationResultResponse(ResponseModel):
|
|
result: Literal["success", "error"]
|
|
error: str | None = None
|
|
|
|
|
|
class SimpleResultMessageResponse(ResponseModel):
|
|
result: str
|
|
message: str
|
|
|
|
|
|
class SimpleMessageResponse(ResponseModel):
|
|
message: str
|
|
|
|
|
|
class SimpleDataResponse(ResponseModel):
|
|
data: str
|
|
|
|
|
|
class SimpleResultDataResponse(ResponseModel):
|
|
result: str
|
|
data: str
|
|
|
|
|
|
class SimpleResultStringListResponse(ResponseModel):
|
|
result: str
|
|
data: list[str]
|
|
|
|
|
|
class SimpleResultOptionalDataResponse(ResponseModel):
|
|
result: str
|
|
data: str | None = None
|
|
|
|
|
|
class AccessTokenData(ResponseModel):
|
|
access_token: str
|
|
|
|
|
|
class AccessTokenResultResponse(ResponseModel):
|
|
result: str
|
|
data: AccessTokenData
|
|
|
|
|
|
class VerificationTokenResponse(ResponseModel):
|
|
is_valid: bool
|
|
email: str
|
|
token: str
|
|
|
|
|
|
class LoginStatusResponse(ResponseModel):
|
|
logged_in: bool
|
|
app_logged_in: bool
|
|
|
|
|
|
class AccessModeResponse(ResponseModel):
|
|
access_mode: str = Field(serialization_alias="accessMode", validation_alias="accessMode")
|
|
|
|
|
|
class BooleanResultResponse(ResponseModel):
|
|
result: bool
|
|
|
|
|
|
class SuccessResponse(ResponseModel):
|
|
success: bool
|
|
|
|
|
|
class UsageCheckResponse(ResponseModel):
|
|
is_using: bool
|
|
|
|
|
|
class UsageCountResponse(ResponseModel):
|
|
is_using: bool
|
|
count: int
|
|
|
|
|
|
class AvatarUrlResponse(ResponseModel):
|
|
avatar_url: str
|
|
|
|
|
|
class TextContentResponse(ResponseModel):
|
|
content: str
|
|
|
|
|
|
class AllowedExtensionsResponse(ResponseModel):
|
|
allowed_extensions: list[str]
|
|
|
|
|
|
class UrlResponse(ResponseModel):
|
|
url: str
|
|
|
|
|
|
class RedirectUrlResponse(ResponseModel):
|
|
redirect_url: str
|
|
|
|
|
|
class ApiBaseUrlResponse(ResponseModel):
|
|
api_base_url: str
|
|
|
|
|
|
class NewAppResponse(ResponseModel):
|
|
new_app_id: str
|
|
permission_keys: list[str] = Field(default_factory=list)
|
|
|
|
|
|
class Parameters(BaseModel):
|
|
opening_statement: str | None = None
|
|
suggested_questions: list[str]
|
|
suggested_questions_after_answer: FeatureToggleObject
|
|
speech_to_text: FeatureToggleObject
|
|
text_to_speech: TextToSpeechObject
|
|
retriever_resource: FeatureToggleObject
|
|
annotation_reply: FeatureToggleObject
|
|
more_like_this: FeatureToggleObject
|
|
user_input_form: UserInputFormList
|
|
sensitive_word_avoidance: FeatureToggleObject
|
|
file_upload: FileUploadObject
|
|
system_parameters: SystemParameters = Field(description="System-level parameter limits.")
|
|
|
|
|
|
class Site(BaseModel):
|
|
model_config = ConfigDict(from_attributes=True)
|
|
|
|
title: str
|
|
chat_color_theme: str | None = None
|
|
chat_color_theme_inverted: bool
|
|
icon_type: str | None = None
|
|
icon: str | None = None
|
|
icon_background: str | None = None
|
|
description: str | None = None
|
|
copyright: str | None = None
|
|
privacy_policy: str | None = None
|
|
input_placeholder: str | None = None
|
|
custom_disclaimer: str | None = None
|
|
default_language: str
|
|
show_workflow_steps: bool
|
|
use_icon_as_answer_icon: bool
|
|
|
|
@computed_field(return_type=URLString | None) # type: ignore
|
|
@property
|
|
def icon_url(self) -> str | None:
|
|
if self.icon and self.icon_type == IconType.IMAGE:
|
|
return file_helpers.get_signed_file_url(self.icon)
|
|
return None
|