feat: backwards invoke app
parent
113ff27d07
commit
41ed2e0cc2
@ -0,0 +1,141 @@
|
||||
from collections.abc import Generator, Mapping
|
||||
from typing import Literal, Union
|
||||
|
||||
from core.app.apps.advanced_chat.app_generator import AdvancedChatAppGenerator
|
||||
from core.app.apps.workflow.app_generator import WorkflowAppGenerator
|
||||
from core.app.entities.app_invoke_entities import InvokeFrom
|
||||
from core.plugin.backwards_invocation.base import BaseBackwardsInvocation
|
||||
from extensions.ext_database import db
|
||||
from models.account import Account
|
||||
from models.model import App, AppMode, EndUser
|
||||
|
||||
|
||||
class PluginAppBackwardsInvocation(BaseBackwardsInvocation):
|
||||
@classmethod
|
||||
def invoke_app(
|
||||
cls, app_id: str,
|
||||
user_id: str,
|
||||
tenant_id: str,
|
||||
query: str,
|
||||
inputs: Mapping,
|
||||
files: list[dict],
|
||||
) -> Generator[dict, None, None] | dict:
|
||||
"""
|
||||
invoke app
|
||||
"""
|
||||
app = cls._get_app(app_id, tenant_id)
|
||||
if app.mode in [AppMode.ADVANCED_CHAT.value, AppMode.AGENT_CHAT.value, AppMode.CHAT.value]:
|
||||
return cls.invoke_chat_app(app, user_id, tenant_id, query, inputs, files)
|
||||
elif app.mode in [AppMode.WORKFLOW.value]:
|
||||
return cls.invoke_workflow_app(app, user_id, tenant_id, inputs, files)
|
||||
elif app.mode in [AppMode.COMPLETION]:
|
||||
return cls.invoke_completion_app(app, user_id, tenant_id, inputs, files)
|
||||
|
||||
raise ValueError("unexpected app type")
|
||||
|
||||
@classmethod
|
||||
def invoke_chat_app(
|
||||
cls,
|
||||
app: App,
|
||||
user: Account | EndUser,
|
||||
tenant_id: str,
|
||||
conversation_id: str,
|
||||
query: str,
|
||||
stream: bool,
|
||||
inputs: Mapping,
|
||||
files: list[dict],
|
||||
) -> Generator[dict, None, None] | dict:
|
||||
"""
|
||||
invoke chat app
|
||||
"""
|
||||
if app.mode == AppMode.ADVANCED_CHAT.value:
|
||||
workflow = app.workflow
|
||||
if not workflow:
|
||||
raise ValueError("unexpected app type")
|
||||
|
||||
generator = AdvancedChatAppGenerator()
|
||||
response = generator.generate(
|
||||
app_model=app,
|
||||
workflow=workflow,
|
||||
user=user,
|
||||
args={
|
||||
},
|
||||
invoke_from=InvokeFrom.SERVICE_API,
|
||||
stream=stream
|
||||
)
|
||||
|
||||
|
||||
|
||||
@classmethod
|
||||
def invoke_workflow_app(
|
||||
cls,
|
||||
app: App,
|
||||
user_id: str,
|
||||
tenant_id: str,
|
||||
inputs: Mapping,
|
||||
files: list[dict],
|
||||
):
|
||||
"""
|
||||
invoke workflow app
|
||||
"""
|
||||
workflow = app.workflow
|
||||
if not workflow:
|
||||
raise ValueError("")
|
||||
|
||||
generator = WorkflowAppGenerator()
|
||||
|
||||
result = generator.generate(
|
||||
app_model=app,
|
||||
workflow=workflow,
|
||||
user=cls._get_user(user_id),
|
||||
args={
|
||||
'inputs': tool_parameters,
|
||||
'files': files
|
||||
},
|
||||
invoke_from=self.runtime.invoke_from,
|
||||
stream=False,
|
||||
call_depth=self.workflow_call_depth + 1,
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def invoke_completion_app(
|
||||
cls,
|
||||
app: App,
|
||||
user_id: str,
|
||||
tenant_id: str,
|
||||
inputs: Mapping,
|
||||
files: list[dict],
|
||||
):
|
||||
"""
|
||||
invoke completion app
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def _get_user(cls, user_id: str) -> Union[EndUser, Account]:
|
||||
"""
|
||||
get the user by user id
|
||||
"""
|
||||
|
||||
user = db.session.query(EndUser).filter(EndUser.id == user_id).first()
|
||||
if not user:
|
||||
user = db.session.query(Account).filter(Account.id == user_id).first()
|
||||
|
||||
if not user:
|
||||
raise ValueError('user not found')
|
||||
|
||||
return user
|
||||
|
||||
@classmethod
|
||||
def _get_app(cls, app_id: str, tenant_id: str) -> App:
|
||||
"""
|
||||
get app
|
||||
"""
|
||||
app = db.session.query(App). \
|
||||
filter(App.id == app_id). \
|
||||
filter(App.tenant_id == tenant_id). \
|
||||
first()
|
||||
|
||||
if not app:
|
||||
raise ValueError("app not found")
|
||||
|
||||
return app
|
||||
@ -0,0 +1,20 @@
|
||||
import json
|
||||
from collections.abc import Generator
|
||||
|
||||
from pydantic import BaseModel
|
||||
|
||||
|
||||
class BaseBackwardsInvocation:
|
||||
@classmethod
|
||||
def convert_to_event_stream(cls, response: Generator[BaseModel | dict, None, None] | BaseModel | dict):
|
||||
if isinstance(response, Generator):
|
||||
for chunk in response:
|
||||
if isinstance(chunk, BaseModel):
|
||||
yield chunk.model_dump_json().encode() + b'\n\n'
|
||||
else:
|
||||
yield json.dumps(chunk).encode() + b'\n\n'
|
||||
else:
|
||||
if isinstance(response, BaseModel):
|
||||
yield response.model_dump_json().encode() + b'\n\n'
|
||||
else:
|
||||
yield json.dumps(response).encode() + b'\n\n'
|
||||
Loading…
Reference in New Issue