Skip to content

Commit

Permalink
Merge branch 'langgenius:main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
ybalbert001 authored Jul 29, 2024
2 parents 50b7e4d + 2026870 commit c6c9b44
Show file tree
Hide file tree
Showing 57 changed files with 1,494 additions and 323 deletions.
4 changes: 2 additions & 2 deletions .devcontainer/post_create_command.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
cd web && npm install
pipx install poetry

echo 'alias start-api="cd /workspaces/dify/api && flask run --host 0.0.0.0 --port=5001 --debug"' >> ~/.bashrc
echo 'alias start-worker="cd /workspaces/dify/api && celery -A app.celery worker -P gevent -c 1 --loglevel INFO -Q dataset,generation,mail,ops_trace,app_deletion"' >> ~/.bashrc
echo 'alias start-api="cd /workspaces/dify/api && poetry run python -m flask run --host 0.0.0.0 --port=5001 --debug"' >> ~/.bashrc
echo 'alias start-worker="cd /workspaces/dify/api && poetry run python -m celery -A app.celery worker -P gevent -c 1 --loglevel INFO -Q dataset,generation,mail,ops_trace,app_deletion"' >> ~/.bashrc
echo 'alias start-web="cd /workspaces/dify/web && npm run dev"' >> ~/.bashrc
echo 'alias start-containers="cd /workspaces/dify/docker && docker-compose -f docker-compose.middleware.yaml -p dify up -d"' >> ~/.bashrc

Expand Down
10 changes: 5 additions & 5 deletions CONTRIBUTING_JA.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Dify にコントリビュートしたいとお考えなのですね。それは素晴らしいことです。
私たちは、LLM アプリケーションの構築と管理のための最も直感的なワークフローを設計するという壮大な野望を持っています。人数も資金も限られている新興企業として、コミュニティからの支援は本当に重要です。

私たちは現状を鑑み、機敏かつ迅速に開発をする必要がありますが、同時にあなたのようなコントリビューターの方々に、可能な限りスムーズな貢献体験をしていただきたいと思っています。そのためにこのコントリビュートガイドを作成しました。
私たちは現状を鑑み、機敏かつ迅速に開発をする必要がありますが、同時にあなた様のようなコントリビューターの方々に、可能な限りスムーズな貢献体験をしていただきたいと思っています。そのためにこのコントリビュートガイドを作成しました。
コードベースやコントリビュータの方々と私たちがどのように仕事をしているのかに慣れていただき、楽しいパートにすぐに飛び込めるようにすることが目的です。

このガイドは Dify そのものと同様に、継続的に改善されています。実際のプロジェクトに遅れをとることがあるかもしれませんが、ご理解のほどよろしくお願いいたします。
Expand All @@ -14,13 +14,13 @@ Dify にコントリビュートしたいとお考えなのですね。それは

### 機能リクエスト

* 新しい機能要望を出す場合は、提案する機能が何を実現するものなのかを説明し、可能な限り多くのコンテキストを含めてください。[@perzeusss](https://github.com/perzeuss)は、あなたの要望を書き出すのに役立つ [Feature Request Copilot](https://udify.app/chat/MK2kVSnw1gakVwMX) を作ってくれました。気軽に試してみてください。
* 新しい機能要望を出す場合は、提案する機能が何を実現するものなのかを説明し、可能な限り多くのコンテキストを含めてください。[@perzeusss](https://github.com/perzeuss)は、あなた様の要望を書き出すのに役立つ [Feature Request Copilot](https://udify.app/chat/MK2kVSnw1gakVwMX) を作ってくれました。気軽に試してみてください。

* 既存の課題から 1 つ選びたい場合は、その下にコメントを書いてください。

関連する方向で作業しているチームメンバーが参加します。すべてが良好であれば、コーディングを開始する許可が与えられます。私たちが変更を提案した場合にあなたの作業が無駄になることがないよう、それまでこの機能の作業を控えていただくようお願いいたします。
関連する方向で作業しているチームメンバーが参加します。すべてが良好であれば、コーディングを開始する許可が与えられます。私たちが変更を提案した場合にあなた様の作業が無駄になることがないよう、それまでこの機能の作業を控えていただくようお願いいたします。

提案された機能がどの分野に属するかによって、あなたは異なるチーム・メンバーと話をするかもしれません。以下は、各チームメンバーが現在取り組んでいる分野の概要です。
提案された機能がどの分野に属するかによって、あなた様は異なるチーム・メンバーと話をするかもしれません。以下は、各チームメンバーが現在取り組んでいる分野の概要です。

| Member | Scope |
| --------------------------------------------------------------------------------------- | ------------------------------------ |
Expand Down Expand Up @@ -153,7 +153,7 @@ Dify のバックエンドは[Flask](https://flask.palletsprojects.com/en/3.0.x/
いよいよ、私たちのリポジトリにプルリクエスト (PR) を提出する時が来ました。主要な機能については、まず `deploy/dev` ブランチにマージしてテストしてから `main` ブランチにマージします。
マージ競合などの問題が発生した場合、またはプル リクエストを開く方法がわからない場合は、[GitHub's pull request tutorial](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests) をチェックしてみてください。

これで完了です!あなたの PR がマージされると、[README](https://github.com/langgenius/dify/blob/main/README.md) にコントリビューターとして紹介されます。
これで完了です!あなた様の PR がマージされると、[README](https://github.com/langgenius/dify/blob/main/README.md) にコントリビューターとして紹介されます。

## ヘルプを得る

Expand Down
4 changes: 2 additions & 2 deletions api/core/app/apps/base_app_queue_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
from enum import Enum
from typing import Any

from flask import current_app
from sqlalchemy.orm import DeclarativeMeta

from configs import dify_config
from core.app.entities.app_invoke_entities import InvokeFrom
from core.app.entities.queue_entities import (
AppQueueEvent,
Expand Down Expand Up @@ -48,7 +48,7 @@ def listen(self) -> Generator:
:return:
"""
# wait for APP_MAX_EXECUTION_TIME seconds to stop listen
listen_timeout = current_app.config.get("APP_MAX_EXECUTION_TIME")
listen_timeout = dify_config.APP_MAX_EXECUTION_TIME
start_time = time.time()
last_ping_time = 0
while True:
Expand Down
16 changes: 12 additions & 4 deletions api/core/app/segments/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from .segment_group import SegmentGroup
from .segments import (
ArraySegment,
ArrayAnySegment,
FileSegment,
FloatSegment,
IntegerSegment,
Expand All @@ -11,7 +11,11 @@
)
from .types import SegmentType
from .variables import (
ArrayVariable,
ArrayAnyVariable,
ArrayFileVariable,
ArrayNumberVariable,
ArrayObjectVariable,
ArrayStringVariable,
FileVariable,
FloatVariable,
IntegerVariable,
Expand All @@ -29,7 +33,7 @@
'SecretVariable',
'FileVariable',
'StringVariable',
'ArrayVariable',
'ArrayAnyVariable',
'Variable',
'SegmentType',
'SegmentGroup',
Expand All @@ -39,7 +43,11 @@
'IntegerSegment',
'FloatSegment',
'ObjectSegment',
'ArraySegment',
'ArrayAnySegment',
'FileSegment',
'StringSegment',
'ArrayStringVariable',
'ArrayNumberVariable',
'ArrayObjectVariable',
'ArrayFileVariable',
]
28 changes: 24 additions & 4 deletions api/core/app/segments/factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from core.file.file_obj import FileVar

from .segments import (
ArraySegment,
ArrayAnySegment,
FileSegment,
FloatSegment,
IntegerSegment,
Expand All @@ -15,8 +15,14 @@
)
from .types import SegmentType
from .variables import (
ArrayFileVariable,
ArrayNumberVariable,
ArrayObjectVariable,
ArrayStringVariable,
FileVariable,
FloatVariable,
IntegerVariable,
ObjectVariable,
SecretVariable,
StringVariable,
Variable,
Expand All @@ -33,14 +39,28 @@ def build_variable_from_mapping(m: Mapping[str, Any], /) -> Variable:
match value_type:
case SegmentType.STRING:
return StringVariable.model_validate(m)
case SegmentType.SECRET:
return SecretVariable.model_validate(m)
case SegmentType.NUMBER if isinstance(value, int):
return IntegerVariable.model_validate(m)
case SegmentType.NUMBER if isinstance(value, float):
return FloatVariable.model_validate(m)
case SegmentType.SECRET:
return SecretVariable.model_validate(m)
case SegmentType.NUMBER if not isinstance(value, float | int):
raise ValueError(f'invalid number value {value}')
case SegmentType.FILE:
return FileVariable.model_validate(m)
case SegmentType.OBJECT if isinstance(value, dict):
return ObjectVariable.model_validate(
{**m, 'value': {k: build_variable_from_mapping(v) for k, v in value.items()}}
)
case SegmentType.ARRAY_STRING if isinstance(value, list):
return ArrayStringVariable.model_validate({**m, 'value': [build_variable_from_mapping(v) for v in value]})
case SegmentType.ARRAY_NUMBER if isinstance(value, list):
return ArrayNumberVariable.model_validate({**m, 'value': [build_variable_from_mapping(v) for v in value]})
case SegmentType.ARRAY_OBJECT if isinstance(value, list):
return ArrayObjectVariable.model_validate({**m, 'value': [build_variable_from_mapping(v) for v in value]})
case SegmentType.ARRAY_FILE if isinstance(value, list):
return ArrayFileVariable.model_validate({**m, 'value': [build_variable_from_mapping(v) for v in value]})
raise ValueError(f'not supported value type {value_type}')


Expand All @@ -60,7 +80,7 @@ def build_segment(value: Any, /) -> Segment:
if isinstance(value, list):
# TODO: Limit the depth of the array
elements = [build_segment(v) for v in value]
return ArraySegment(value=elements)
return ArrayAnySegment(value=elements)
if isinstance(value, FileVar):
return FileSegment(value=value)
raise ValueError(f'not supported value {value}')
43 changes: 33 additions & 10 deletions api/core/app/segments/segments.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ class StringSegment(Segment):
value_type: SegmentType = SegmentType.STRING
value: str


class FloatSegment(Segment):
value_type: SegmentType = SegmentType.NUMBER
value: float
Expand All @@ -72,6 +73,16 @@ class IntegerSegment(Segment):
value: int


class FileSegment(Segment):
value_type: SegmentType = SegmentType.FILE
# TODO: embed FileVar in this model.
value: FileVar

@property
def markdown(self) -> str:
return self.value.to_markdown()


class ObjectSegment(Segment):
value_type: SegmentType = SegmentType.OBJECT
value: Mapping[str, Segment]
Expand All @@ -96,9 +107,6 @@ def to_object(self):


class ArraySegment(Segment):
value_type: SegmentType = SegmentType.ARRAY
value: Sequence[Segment]

@property
def markdown(self) -> str:
return '\n'.join(['- ' + item.markdown for item in self.value])
Expand All @@ -107,11 +115,26 @@ def to_object(self):
return [v.to_object() for v in self.value]


class FileSegment(Segment):
value_type: SegmentType = SegmentType.FILE
# TODO: embed FileVar in this model.
value: FileVar
class ArrayAnySegment(ArraySegment):
value_type: SegmentType = SegmentType.ARRAY_ANY
value: Sequence[Segment]

@property
def markdown(self) -> str:
return self.value.to_markdown()

class ArrayStringSegment(ArraySegment):
value_type: SegmentType = SegmentType.ARRAY_STRING
value: Sequence[StringSegment]


class ArrayNumberSegment(ArraySegment):
value_type: SegmentType = SegmentType.ARRAY_NUMBER
value: Sequence[FloatSegment | IntegerSegment]


class ArrayObjectSegment(ArraySegment):
value_type: SegmentType = SegmentType.ARRAY_OBJECT
value: Sequence[ObjectSegment]


class ArrayFileSegment(ArraySegment):
value_type: SegmentType = SegmentType.ARRAY_FILE
value: Sequence[FileSegment]
6 changes: 5 additions & 1 deletion api/core/app/segments/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@ class SegmentType(str, Enum):
NUMBER = 'number'
STRING = 'string'
SECRET = 'secret'
ARRAY = 'array'
ARRAY_ANY = 'array[any]'
ARRAY_STRING = 'array[string]'
ARRAY_NUMBER = 'array[number]'
ARRAY_OBJECT = 'array[object]'
ARRAY_FILE = 'array[file]'
OBJECT = 'object'
FILE = 'file'

Expand Down
27 changes: 23 additions & 4 deletions api/core/app/segments/variables.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@

from pydantic import Field

from core.helper import encrypter

from .segments import (
ArraySegment,
ArrayAnySegment,
ArrayFileSegment,
ArrayNumberSegment,
ArrayObjectSegment,
ArrayStringSegment,
FileSegment,
FloatSegment,
IntegerSegment,
Expand Down Expand Up @@ -41,15 +44,31 @@ class IntegerVariable(IntegerSegment, Variable):
pass


class FileVariable(FileSegment, Variable):
pass


class ObjectVariable(ObjectSegment, Variable):
pass


class ArrayVariable(ArraySegment, Variable):
class ArrayAnyVariable(ArrayAnySegment, Variable):
pass


class FileVariable(FileSegment, Variable):
class ArrayStringVariable(ArrayStringSegment, Variable):
pass


class ArrayNumberVariable(ArrayNumberSegment, Variable):
pass


class ArrayObjectVariable(ArrayObjectSegment, Variable):
pass


class ArrayFileVariable(ArrayFileSegment, Variable):
pass


Expand Down
13 changes: 6 additions & 7 deletions api/core/file/upload_file_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@
import time
from typing import Optional

from flask import current_app

from configs import dify_config
from extensions.ext_storage import storage

IMAGE_EXTENSIONS = ['jpg', 'jpeg', 'png', 'webp', 'gif', 'svg']
Expand All @@ -23,7 +22,7 @@ def get_image_data(cls, upload_file, force_url: bool = False) -> Optional[str]:
if upload_file.extension not in IMAGE_EXTENSIONS:
return None

if current_app.config['MULTIMODAL_SEND_IMAGE_FORMAT'] == 'url' or force_url:
if dify_config.MULTIMODAL_SEND_IMAGE_FORMAT == 'url' or force_url:
return cls.get_signed_temp_image_url(upload_file.id)
else:
# get image file base64
Expand All @@ -44,13 +43,13 @@ def get_signed_temp_image_url(cls, upload_file_id) -> str:
:param upload_file: UploadFile object
:return:
"""
base_url = current_app.config.get('FILES_URL')
base_url = dify_config.FILES_URL
image_preview_url = f'{base_url}/files/{upload_file_id}/image-preview'

timestamp = str(int(time.time()))
nonce = os.urandom(16).hex()
data_to_sign = f"image-preview|{upload_file_id}|{timestamp}|{nonce}"
secret_key = current_app.config['SECRET_KEY'].encode()
secret_key = dify_config.SECRET_KEY.encode()
sign = hmac.new(secret_key, data_to_sign.encode(), hashlib.sha256).digest()
encoded_sign = base64.urlsafe_b64encode(sign).decode()

Expand All @@ -68,7 +67,7 @@ def verify_image_file_signature(cls, upload_file_id: str, timestamp: str, nonce:
:return:
"""
data_to_sign = f"image-preview|{upload_file_id}|{timestamp}|{nonce}"
secret_key = current_app.config['SECRET_KEY'].encode()
secret_key = dify_config.SECRET_KEY.encode()
recalculated_sign = hmac.new(secret_key, data_to_sign.encode(), hashlib.sha256).digest()
recalculated_encoded_sign = base64.urlsafe_b64encode(recalculated_sign).decode()

Expand All @@ -77,4 +76,4 @@ def verify_image_file_signature(cls, upload_file_id: str, timestamp: str, nonce:
return False

current_time = int(time.time())
return current_time - int(timestamp) <= current_app.config.get('FILES_ACCESS_TIMEOUT')
return current_time - int(timestamp) <= dify_config.FILES_ACCESS_TIMEOUT
16 changes: 4 additions & 12 deletions api/core/helper/position_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,10 @@ def get_position_map(folder_path: str, *, file_name: str = "_position.yaml") ->
:param file_name: the YAML file name, default to '_position.yaml'
:return: a dict with name as key and index as value
"""
position_file_name = os.path.join(folder_path, file_name)
if not position_file_name or not os.path.exists(position_file_name):
return {}

positions = load_yaml_file(position_file_name, ignore_error=True)
position_map = {}
index = 0
for _, name in enumerate(positions):
if name and isinstance(name, str):
position_map[name.strip()] = index
index += 1
return position_map
position_file_path = os.path.join(folder_path, file_name)
yaml_content = load_yaml_file(file_path=position_file_path, default_value=[])
positions = [item.strip() for item in yaml_content if item and isinstance(item, str) and item.strip()]
return {name: index for index, name in enumerate(positions)}


def sort_by_position_map(
Expand Down
2 changes: 1 addition & 1 deletion api/core/model_runtime/model_providers/__base/ai_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ def predefined_models(self) -> list[AIModelEntity]:
# traverse all model_schema_yaml_paths
for model_schema_yaml_path in model_schema_yaml_paths:
# read yaml data from yaml file
yaml_data = load_yaml_file(model_schema_yaml_path, ignore_error=True)
yaml_data = load_yaml_file(model_schema_yaml_path)

new_parameter_rules = []
for parameter_rule in yaml_data.get('parameter_rules', []):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ def get_provider_schema(self) -> ProviderEntity:

# read provider schema from yaml file
yaml_path = os.path.join(current_path, f'{provider_name}.yaml')
yaml_data = load_yaml_file(yaml_path, ignore_error=True)
yaml_data = load_yaml_file(yaml_path)

try:
# yaml_data to entity
Expand Down
Loading

0 comments on commit c6c9b44

Please sign in to comment.