-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch '1Panel-dev:main' into main
- Loading branch information
Showing
167 changed files
with
6,232 additions
and
2,241 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
# coding=utf-8 | ||
from .impl import * |
40 changes: 40 additions & 0 deletions
40
apps/application/flow/step_node/application_node/i_application_node.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
# coding=utf-8 | ||
from typing import Type | ||
|
||
from rest_framework import serializers | ||
|
||
from application.flow.i_step_node import INode, NodeResult | ||
from common.util.field_message import ErrMessage | ||
|
||
|
||
class ApplicationNodeSerializer(serializers.Serializer): | ||
application_id = serializers.CharField(required=True, error_messages=ErrMessage.char("应用id")) | ||
question_reference_address = serializers.ListField(required=True, error_messages=ErrMessage.list("用户问题")) | ||
api_input_field_list = serializers.ListField(required=False, error_messages=ErrMessage.list("api输入字段")) | ||
user_input_field_list = serializers.ListField(required=False, error_messages=ErrMessage.uuid("用户输入字段")) | ||
|
||
|
||
class IApplicationNode(INode): | ||
type = 'application-node' | ||
|
||
def get_node_params_serializer_class(self) -> Type[serializers.Serializer]: | ||
return ApplicationNodeSerializer | ||
|
||
def _run(self): | ||
question = self.workflow_manage.get_reference_field( | ||
self.node_params_serializer.data.get('question_reference_address')[0], | ||
self.node_params_serializer.data.get('question_reference_address')[1:]) | ||
kwargs = {} | ||
for api_input_field in self.node_params_serializer.data.get('api_input_field_list', []): | ||
kwargs[api_input_field['variable']] = self.workflow_manage.get_reference_field(api_input_field['value'][0], | ||
api_input_field['value'][1:]) | ||
for user_input_field in self.node_params_serializer.data.get('user_input_field_list', []): | ||
kwargs[user_input_field['field']] = self.workflow_manage.get_reference_field(user_input_field['value'][0], | ||
user_input_field['value'][1:]) | ||
|
||
return self.execute(**self.node_params_serializer.data, **self.flow_params_serializer.data, | ||
message=str(question), **kwargs) | ||
|
||
def execute(self, application_id, message, chat_id, chat_record_id, stream, re_chat, client_id, client_type, | ||
**kwargs) -> NodeResult: | ||
pass |
2 changes: 2 additions & 0 deletions
2
apps/application/flow/step_node/application_node/impl/__init__.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
# coding=utf-8 | ||
from .base_application_node import BaseApplicationNode |
130 changes: 130 additions & 0 deletions
130
apps/application/flow/step_node/application_node/impl/base_application_node.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
# coding=utf-8 | ||
import json | ||
import time | ||
import uuid | ||
from typing import List, Dict | ||
from application.flow.i_step_node import NodeResult, INode | ||
from application.flow.step_node.application_node.i_application_node import IApplicationNode | ||
from application.models import Chat | ||
from common.handle.impl.response.openai_to_response import OpenaiToResponse | ||
|
||
|
||
def string_to_uuid(input_str): | ||
return str(uuid.uuid5(uuid.NAMESPACE_DNS, input_str)) | ||
|
||
|
||
def _write_context(node_variable: Dict, workflow_variable: Dict, node: INode, workflow, answer: str): | ||
result = node_variable.get('result') | ||
node.context['message_tokens'] = result.get('usage', {}).get('prompt_tokens', 0) | ||
node.context['answer_tokens'] = result.get('usage', {}).get('completion_tokens', 0) | ||
node.context['answer'] = answer | ||
node.context['question'] = node_variable['question'] | ||
node.context['run_time'] = time.time() - node.context['start_time'] | ||
if workflow.is_result(node, NodeResult(node_variable, workflow_variable)): | ||
node.answer_text = answer | ||
|
||
|
||
def write_context_stream(node_variable: Dict, workflow_variable: Dict, node: INode, workflow): | ||
""" | ||
写入上下文数据 (流式) | ||
@param node_variable: 节点数据 | ||
@param workflow_variable: 全局数据 | ||
@param node: 节点 | ||
@param workflow: 工作流管理器 | ||
""" | ||
response = node_variable.get('result') | ||
answer = '' | ||
usage = {} | ||
for chunk in response: | ||
# 先把流转成字符串 | ||
response_content = chunk.decode('utf-8')[6:] | ||
response_content = json.loads(response_content) | ||
choices = response_content.get('choices') | ||
if choices and isinstance(choices, list) and len(choices) > 0: | ||
content = choices[0].get('delta', {}).get('content', '') | ||
answer += content | ||
yield content | ||
usage = response_content.get('usage', {}) | ||
node_variable['result'] = {'usage': usage} | ||
_write_context(node_variable, workflow_variable, node, workflow, answer) | ||
|
||
|
||
def write_context(node_variable: Dict, workflow_variable: Dict, node: INode, workflow): | ||
""" | ||
写入上下文数据 | ||
@param node_variable: 节点数据 | ||
@param workflow_variable: 全局数据 | ||
@param node: 节点实例对象 | ||
@param workflow: 工作流管理器 | ||
""" | ||
response = node_variable.get('result')['choices'][0]['message'] | ||
answer = response.get('content', '') or "抱歉,没有查找到相关内容,请重新描述您的问题或提供更多信息。" | ||
_write_context(node_variable, workflow_variable, node, workflow, answer) | ||
|
||
|
||
class BaseApplicationNode(IApplicationNode): | ||
|
||
def save_context(self, details, workflow_manage): | ||
self.context['answer'] = details.get('answer') | ||
self.context['question'] = details.get('question') | ||
self.context['type'] = details.get('type') | ||
self.answer_text = details.get('answer') | ||
|
||
def execute(self, application_id, message, chat_id, chat_record_id, stream, re_chat, client_id, client_type, | ||
**kwargs) -> NodeResult: | ||
from application.serializers.chat_message_serializers import ChatMessageSerializer | ||
# 生成嵌入应用的chat_id | ||
current_chat_id = string_to_uuid(chat_id + application_id) | ||
Chat.objects.get_or_create(id=current_chat_id, defaults={ | ||
'application_id': application_id, | ||
'abstract': message | ||
}) | ||
response = ChatMessageSerializer( | ||
data={'chat_id': current_chat_id, 'message': message, | ||
're_chat': re_chat, | ||
'stream': stream, | ||
'application_id': application_id, | ||
'client_id': client_id, | ||
'client_type': client_type, 'form_data': kwargs}).chat(base_to_response=OpenaiToResponse()) | ||
if response.status_code == 200: | ||
if stream: | ||
content_generator = response.streaming_content | ||
return NodeResult({'result': content_generator, 'question': message}, {}, | ||
_write_context=write_context_stream) | ||
else: | ||
data = json.loads(response.content) | ||
return NodeResult({'result': data, 'question': message}, {}, | ||
_write_context=write_context) | ||
|
||
def get_details(self, index: int, **kwargs): | ||
global_fields = [] | ||
for api_input_field in self.node_params_serializer.data.get('api_input_field_list', []): | ||
global_fields.append({ | ||
'label': api_input_field['variable'], | ||
'key': api_input_field['variable'], | ||
'value': self.workflow_manage.get_reference_field( | ||
api_input_field['value'][0], | ||
api_input_field['value'][1:]) | ||
}) | ||
for user_input_field in self.node_params_serializer.data.get('user_input_field_list', []): | ||
global_fields.append({ | ||
'label': user_input_field['label'], | ||
'key': user_input_field['field'], | ||
'value': self.workflow_manage.get_reference_field( | ||
user_input_field['value'][0], | ||
user_input_field['value'][1:]) | ||
}) | ||
return { | ||
'name': self.node.properties.get('stepName'), | ||
"index": index, | ||
"info": self.node.properties.get('node_data'), | ||
'run_time': self.context.get('run_time'), | ||
'question': self.context.get('question'), | ||
'answer': self.context.get('answer'), | ||
'type': self.node.type, | ||
'message_tokens': self.context.get('message_tokens'), | ||
'answer_tokens': self.context.get('answer_tokens'), | ||
'status': self.status, | ||
'err_message': self.err_message, | ||
'global_fields': global_fields | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
1 change: 1 addition & 0 deletions
1
apps/application/flow/step_node/document_extract_node/__init__.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
from .impl import * |
27 changes: 27 additions & 0 deletions
27
apps/application/flow/step_node/document_extract_node/i_document_extract_node.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
# coding=utf-8 | ||
|
||
from typing import Type | ||
|
||
from rest_framework import serializers | ||
|
||
from application.flow.i_step_node import INode, NodeResult | ||
from common.util.field_message import ErrMessage | ||
|
||
|
||
class DocumentExtractNodeSerializer(serializers.Serializer): | ||
document_list = serializers.ListField(required=False, error_messages=ErrMessage.list("文档")) | ||
|
||
|
||
class IDocumentExtractNode(INode): | ||
type = 'document-extract-node' | ||
|
||
def get_node_params_serializer_class(self) -> Type[serializers.Serializer]: | ||
return DocumentExtractNodeSerializer | ||
|
||
def _run(self): | ||
res = self.workflow_manage.get_reference_field(self.node_params_serializer.data.get('document_list')[0], | ||
self.node_params_serializer.data.get('document_list')[1:]) | ||
return self.execute(document=res, **self.flow_params_serializer.data) | ||
|
||
def execute(self, document, **kwargs) -> NodeResult: | ||
pass |
1 change: 1 addition & 0 deletions
1
apps/application/flow/step_node/document_extract_node/impl/__init__.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
from .base_document_extract_node import BaseDocumentExtractNode |
Oops, something went wrong.