feat: switch Query to langbot-plugin definition

This commit is contained in:
Junyan Qin
2025-06-15 22:04:31 +08:00
parent 0c2560cafb
commit 6b782f8761
88 changed files with 248 additions and 348 deletions
+1 -1
View File
@@ -1,7 +1,7 @@
from __future__ import annotations
import typing
import pydantic.v1 as pydantic
import pydantic
from pkg.provider import entities
+1 -1
View File
@@ -2,7 +2,7 @@ from __future__ import annotations
import typing
import pydantic.v1 as pydantic
import pydantic
from . import requester
from . import token
+2 -2
View File
@@ -4,11 +4,11 @@ import abc
import typing
from ...core import app
from ...core import entities as core_entities
from .. import entities as llm_entities
from ...entity.persistence import model as persistence_model
import langbot_plugin.api.entities.builtin.resource.tool as resource_tool
from . import token
import langbot_plugin.api.entities.builtin.pipeline.query as pipeline_query
class RuntimeLLMModel:
@@ -56,7 +56,7 @@ class LLMAPIRequester(metaclass=abc.ABCMeta):
@abc.abstractmethod
async def invoke_llm(
self,
query: core_entities.Query,
query: pipeline_query.Query,
model: RuntimeLLMModel,
messages: typing.List[llm_entities.Message],
funcs: typing.List[resource_tool.LLMTool] = None,
@@ -9,10 +9,10 @@ import httpx
from .. import errors, requester
from ....core import entities as core_entities
from ... import entities as llm_entities
from ....utils import image
import langbot_plugin.api.entities.builtin.resource.tool as resource_tool
import langbot_plugin.api.entities.builtin.pipeline.query as pipeline_query
class AnthropicMessages(requester.LLMAPIRequester):
@@ -48,7 +48,7 @@ class AnthropicMessages(requester.LLMAPIRequester):
async def invoke_llm(
self,
query: core_entities.Query,
query: pipeline_query.Query,
model: requester.RuntimeLLMModel,
messages: typing.List[llm_entities.Message],
funcs: typing.List[resource_tool.LLMTool] = None,
+3 -3
View File
@@ -8,9 +8,9 @@ import openai.types.chat.chat_completion as chat_completion
import httpx
from .. import errors, requester
from ....core import entities as core_entities
from ... import entities as llm_entities
import langbot_plugin.api.entities.builtin.resource.tool as resource_tool
import langbot_plugin.api.entities.builtin.pipeline.query as pipeline_query
class OpenAIChatCompletions(requester.LLMAPIRequester):
@@ -60,7 +60,7 @@ class OpenAIChatCompletions(requester.LLMAPIRequester):
async def _closure(
self,
query: core_entities.Query,
query: pipeline_query.Query,
req_messages: list[dict],
use_model: requester.RuntimeLLMModel,
use_funcs: list[resource_tool.LLMTool] = None,
@@ -101,7 +101,7 @@ class OpenAIChatCompletions(requester.LLMAPIRequester):
async def invoke_llm(
self,
query: core_entities.Query,
query: pipeline_query.Query,
model: requester.RuntimeLLMModel,
messages: typing.List[llm_entities.Message],
funcs: typing.List[resource_tool.LLMTool] = None,
@@ -4,9 +4,9 @@ import typing
from . import chatcmpl
from .. import errors, requester
from ....core import entities as core_entities
from ... import entities as llm_entities
import langbot_plugin.api.entities.builtin.resource.tool as resource_tool
import langbot_plugin.api.entities.builtin.pipeline.query as pipeline_query
class DeepseekChatCompletions(chatcmpl.OpenAIChatCompletions):
@@ -19,7 +19,7 @@ class DeepseekChatCompletions(chatcmpl.OpenAIChatCompletions):
async def _closure(
self,
query: core_entities.Query,
query: pipeline_query.Query,
req_messages: list[dict],
use_model: requester.RuntimeLLMModel,
use_funcs: list[resource_tool.LLMTool] = None,
@@ -5,9 +5,9 @@ import typing
from . import chatcmpl
from .. import requester
from ....core import entities as core_entities
from ... import entities as llm_entities
import langbot_plugin.api.entities.builtin.resource.tool as resource_tool
import langbot_plugin.api.entities.builtin.pipeline.query as pipeline_query
class GiteeAIChatCompletions(chatcmpl.OpenAIChatCompletions):
@@ -20,7 +20,7 @@ class GiteeAIChatCompletions(chatcmpl.OpenAIChatCompletions):
async def _closure(
self,
query: core_entities.Query,
query: pipeline_query.Query,
req_messages: list[dict],
use_model: requester.RuntimeLLMModel,
use_funcs: list[resource_tool.LLMTool] = None,
@@ -9,9 +9,9 @@ import openai.types.chat.chat_completion_message_tool_call as chat_completion_me
import httpx
from .. import entities, errors, requester
from ....core import entities as core_entities
from ... import entities as llm_entities
import langbot_plugin.api.entities.builtin.resource.tool as resource_tool
import langbot_plugin.api.entities.builtin.pipeline.query as pipeline_query
class ModelScopeChatCompletions(requester.LLMAPIRequester):
@@ -125,7 +125,7 @@ class ModelScopeChatCompletions(requester.LLMAPIRequester):
async def _closure(
self,
query: core_entities.Query,
query: pipeline_query.Query,
req_messages: list[dict],
use_model: requester.RuntimeLLMModel,
use_funcs: list[resource_tool.LLMTool] = None,
@@ -166,7 +166,7 @@ class ModelScopeChatCompletions(requester.LLMAPIRequester):
async def invoke_llm(
self,
query: core_entities.Query,
query: pipeline_query.Query,
model: entities.LLMModelInfo,
messages: typing.List[llm_entities.Message],
funcs: typing.List[resource_tool.LLMTool] = None,
@@ -5,9 +5,9 @@ import typing
from . import chatcmpl
from .. import requester
from ....core import entities as core_entities
from ... import entities as llm_entities
import langbot_plugin.api.entities.builtin.resource.tool as resource_tool
import langbot_plugin.api.entities.builtin.pipeline.query as pipeline_query
class MoonshotChatCompletions(chatcmpl.OpenAIChatCompletions):
@@ -20,7 +20,7 @@ class MoonshotChatCompletions(chatcmpl.OpenAIChatCompletions):
async def _closure(
self,
query: core_entities.Query,
query: pipeline_query.Query,
req_messages: list[dict],
use_model: requester.RuntimeLLMModel,
use_funcs: list[resource_tool.LLMTool] = None,
@@ -12,7 +12,7 @@ import ollama
from .. import errors, requester
from ... import entities as llm_entities
import langbot_plugin.api.entities.builtin.resource.tool as resource_tool
from ....core import entities as core_entities
import langbot_plugin.api.entities.builtin.pipeline.query as pipeline_query
REQUESTER_NAME: str = 'ollama-chat'
@@ -39,7 +39,7 @@ class OllamaChatCompletions(requester.LLMAPIRequester):
async def _closure(
self,
query: core_entities.Query,
query: pipeline_query.Query,
req_messages: list[dict],
use_model: requester.RuntimeLLMModel,
use_funcs: list[resource_tool.LLMTool] = None,
@@ -105,7 +105,7 @@ class OllamaChatCompletions(requester.LLMAPIRequester):
async def invoke_llm(
self,
query: core_entities.Query,
query: pipeline_query.Query,
model: requester.RuntimeLLMModel,
messages: typing.List[llm_entities.Message],
funcs: typing.List[resource_tool.LLMTool] = None,
+3 -2
View File
@@ -3,8 +3,9 @@ from __future__ import annotations
import abc
import typing
from ..core import app, entities as core_entities
from ..core import app
from . import entities as llm_entities
import langbot_plugin.api.entities.builtin.pipeline.query as pipeline_query
preregistered_runners: list[typing.Type[RequestRunner]] = []
@@ -35,6 +36,6 @@ class RequestRunner(abc.ABC):
self.pipeline_config = pipeline_config
@abc.abstractmethod
async def run(self, query: core_entities.Query) -> typing.AsyncGenerator[llm_entities.Message, None]:
async def run(self, query: pipeline_query.Query) -> typing.AsyncGenerator[llm_entities.Message, None]:
"""运行请求"""
pass
+8 -5
View File
@@ -6,8 +6,9 @@ import re
import dashscope
from .. import runner
from ...core import app, entities as core_entities
from ...core import app
from .. import entities as llm_entities
import langbot_plugin.api.entities.builtin.pipeline.query as pipeline_query
class DashscopeAPIError(Exception):
@@ -65,7 +66,7 @@ class DashScopeAPIRunner(runner.RequestRunner):
# 使用 re.sub() 进行替换
return pattern.sub(replacement, text)
async def _preprocess_user_message(self, query: core_entities.Query) -> tuple[str, list[str]]:
async def _preprocess_user_message(self, query: pipeline_query.Query) -> tuple[str, list[str]]:
"""预处理用户消息,提取纯文本,阿里云提供的上传文件方法过于复杂,暂不支持上传文件(包括图片)"""
plain_text = ''
image_ids = []
@@ -89,7 +90,7 @@ class DashScopeAPIRunner(runner.RequestRunner):
return plain_text, image_ids
async def _agent_messages(self, query: core_entities.Query) -> typing.AsyncGenerator[llm_entities.Message, None]:
async def _agent_messages(self, query: pipeline_query.Query) -> typing.AsyncGenerator[llm_entities.Message, None]:
"""Dashscope 智能体对话请求"""
# 局部变量
@@ -147,7 +148,9 @@ class DashScopeAPIRunner(runner.RequestRunner):
content=pending_content,
)
async def _workflow_messages(self, query: core_entities.Query) -> typing.AsyncGenerator[llm_entities.Message, None]:
async def _workflow_messages(
self, query: pipeline_query.Query
) -> typing.AsyncGenerator[llm_entities.Message, None]:
"""Dashscope 工作流对话请求"""
# 局部变量
@@ -210,7 +213,7 @@ class DashScopeAPIRunner(runner.RequestRunner):
content=pending_content,
)
async def run(self, query: core_entities.Query) -> typing.AsyncGenerator[llm_entities.Message, None]:
async def run(self, query: pipeline_query.Query) -> typing.AsyncGenerator[llm_entities.Message, None]:
"""运行"""
if self.app_type == 'agent':
async for msg in self._agent_messages(query):
+9 -7
View File
@@ -8,10 +8,10 @@ import base64
from .. import runner
from ...core import app, entities as core_entities
from ...core import app
from .. import entities as llm_entities
from ...utils import image
import langbot_plugin.api.entities.builtin.pipeline.query as pipeline_query
from libs.dify_service_api.v1 import client, errors
@@ -62,7 +62,7 @@ class DifyServiceAPIRunner(runner.RequestRunner):
content_text = re.sub(pattern, '', resp_text, flags=re.DOTALL)
return f'<think>{thinking_text.group(1)}</think>\n{content_text}'
async def _preprocess_user_message(self, query: core_entities.Query) -> tuple[str, list[str]]:
async def _preprocess_user_message(self, query: pipeline_query.Query) -> tuple[str, list[str]]:
"""预处理用户消息,提取纯文本,并将图片上传到 Dify 服务
Returns:
@@ -90,7 +90,7 @@ class DifyServiceAPIRunner(runner.RequestRunner):
return plain_text, image_ids
async def _chat_messages(self, query: core_entities.Query) -> typing.AsyncGenerator[llm_entities.Message, None]:
async def _chat_messages(self, query: pipeline_query.Query) -> typing.AsyncGenerator[llm_entities.Message, None]:
"""调用聊天助手"""
cov_id = query.session.using_conversation.uuid or ''
query.variables['conversation_id'] = cov_id
@@ -152,7 +152,7 @@ class DifyServiceAPIRunner(runner.RequestRunner):
query.session.using_conversation.uuid = chunk['conversation_id']
async def _agent_chat_messages(
self, query: core_entities.Query
self, query: pipeline_query.Query
) -> typing.AsyncGenerator[llm_entities.Message, None]:
"""调用聊天助手"""
cov_id = query.session.using_conversation.uuid or ''
@@ -244,7 +244,9 @@ class DifyServiceAPIRunner(runner.RequestRunner):
query.session.using_conversation.uuid = chunk['conversation_id']
async def _workflow_messages(self, query: core_entities.Query) -> typing.AsyncGenerator[llm_entities.Message, None]:
async def _workflow_messages(
self, query: pipeline_query.Query
) -> typing.AsyncGenerator[llm_entities.Message, None]:
"""调用工作流"""
if not query.session.using_conversation.uuid:
@@ -316,7 +318,7 @@ class DifyServiceAPIRunner(runner.RequestRunner):
yield msg
async def run(self, query: core_entities.Query) -> typing.AsyncGenerator[llm_entities.Message, None]:
async def run(self, query: pipeline_query.Query) -> typing.AsyncGenerator[llm_entities.Message, None]:
"""运行请求"""
if self.pipeline_config['ai']['dify-service-api']['app-type'] == 'chat':
async for msg in self._chat_messages(query):
+2 -2
View File
@@ -4,15 +4,15 @@ import json
import typing
from .. import runner
from ...core import entities as core_entities
from .. import entities as llm_entities
import langbot_plugin.api.entities.builtin.pipeline.query as pipeline_query
@runner.runner_class('local-agent')
class LocalAgentRunner(runner.RequestRunner):
"""本地Agent请求运行器"""
async def run(self, query: core_entities.Query) -> typing.AsyncGenerator[llm_entities.Message, None]:
async def run(self, query: pipeline_query.Query) -> typing.AsyncGenerator[llm_entities.Message, None]:
"""运行请求"""
pending_tool_calls = []
+5 -4
View File
@@ -6,8 +6,9 @@ import uuid
import aiohttp
from .. import runner
from ...core import app, entities as core_entities
from ...core import app
from .. import entities as llm_entities
import langbot_plugin.api.entities.builtin.pipeline.query as pipeline_query
class N8nAPIError(Exception):
@@ -49,7 +50,7 @@ class N8nServiceAPIRunner(runner.RequestRunner):
self.header_name = self.pipeline_config['ai']['n8n-service-api'].get('header-name', '')
self.header_value = self.pipeline_config['ai']['n8n-service-api'].get('header-value', '')
async def _preprocess_user_message(self, query: core_entities.Query) -> str:
async def _preprocess_user_message(self, query: pipeline_query.Query) -> str:
"""预处理用户消息,提取纯文本
Returns:
@@ -67,7 +68,7 @@ class N8nServiceAPIRunner(runner.RequestRunner):
return plain_text
async def _call_webhook(self, query: core_entities.Query) -> typing.AsyncGenerator[llm_entities.Message, None]:
async def _call_webhook(self, query: pipeline_query.Query) -> typing.AsyncGenerator[llm_entities.Message, None]:
"""调用n8n webhook"""
# 生成会话ID(如果不存在)
if not query.session.using_conversation.uuid:
@@ -153,7 +154,7 @@ class N8nServiceAPIRunner(runner.RequestRunner):
self.ap.logger.error(f'n8n webhook call exception: {str(e)}')
raise N8nAPIError(f'n8n webhook call exception: {str(e)}')
async def run(self, query: core_entities.Query) -> typing.AsyncGenerator[llm_entities.Message, None]:
async def run(self, query: pipeline_query.Query) -> typing.AsyncGenerator[llm_entities.Message, None]:
"""运行请求"""
async for msg in self._call_webhook(query):
yield msg
+4 -3
View File
@@ -2,9 +2,10 @@ from __future__ import annotations
import asyncio
from ...core import app, entities as core_entities
from ...core import app
from langbot_plugin.api.entities.builtin.provider import message as provider_message, prompt as provider_prompt
import langbot_plugin.api.entities.builtin.provider.session as provider_session
import langbot_plugin.api.entities.builtin.pipeline.query as pipeline_query
class SessionManager:
@@ -21,7 +22,7 @@ class SessionManager:
async def initialize(self):
pass
async def get_session(self, query: core_entities.Query) -> provider_session.Session:
async def get_session(self, query: pipeline_query.Query) -> provider_session.Session:
"""获取会话"""
for session in self.session_list:
if query.launcher_type == session.launcher_type and query.launcher_id == session.launcher_id:
@@ -39,7 +40,7 @@ class SessionManager:
async def get_conversation(
self,
query: core_entities.Query,
query: pipeline_query.Query,
session: provider_session.Session,
prompt_config: list[dict],
pipeline_uuid: str,
+3 -2
View File
@@ -3,8 +3,9 @@ from __future__ import annotations
import abc
import typing
from ...core import app, entities as core_entities
from ...core import app
import langbot_plugin.api.entities.builtin.resource.tool as resource_tool
import langbot_plugin.api.entities.builtin.pipeline.query as pipeline_query
preregistered_loaders: list[typing.Type[ToolLoader]] = []
@@ -45,7 +46,7 @@ class ToolLoader(abc.ABC):
pass
@abc.abstractmethod
async def invoke_tool(self, query: core_entities.Query, name: str, parameters: dict) -> typing.Any:
async def invoke_tool(self, query: pipeline_query.Query, name: str, parameters: dict) -> typing.Any:
"""执行工具调用"""
pass
+4 -3
View File
@@ -8,8 +8,9 @@ from mcp.client.stdio import stdio_client
from mcp.client.sse import sse_client
from .. import loader
from ....core import app, entities as core_entities
from ....core import app
import langbot_plugin.api.entities.builtin.resource.tool as resource_tool
import langbot_plugin.api.entities.builtin.pipeline.query as pipeline_query
class RuntimeMCPSession:
@@ -83,7 +84,7 @@ class RuntimeMCPSession:
for tool in tools.tools:
async def func(query: core_entities.Query, *, _tool=tool, **kwargs):
async def func(query: pipeline_query.Query, *, _tool=tool, **kwargs):
result = await self.session.call_tool(_tool.name, kwargs)
if result.isError:
raise Exception(result.content[0].text)
@@ -144,7 +145,7 @@ class MCPLoader(loader.ToolLoader):
async def has_tool(self, name: str) -> bool:
return name in [f.name for f in self._last_listed_functions]
async def invoke_tool(self, query: core_entities.Query, name: str, parameters: dict) -> typing.Any:
async def invoke_tool(self, query: pipeline_query.Query, name: str, parameters: dict) -> typing.Any:
for server_name, session in self.sessions.items():
for function in session.functions:
if function.name == name:
+2 -2
View File
@@ -4,9 +4,9 @@ import typing
import traceback
from .. import loader
from ....core import entities as core_entities
from ....plugin import context as plugin_context
import langbot_plugin.api.entities.builtin.resource.tool as resource_tool
import langbot_plugin.api.entities.builtin.pipeline.query as pipeline_query
@loader.loader_class('plugin-tool-loader')
@@ -49,7 +49,7 @@ class PluginToolLoader(loader.ToolLoader):
return function, plugin.plugin_inst
return None, None
async def invoke_tool(self, query: core_entities.Query, name: str, parameters: dict) -> typing.Any:
async def invoke_tool(self, query: pipeline_query.Query, name: str, parameters: dict) -> typing.Any:
try:
function, plugin = await self._get_function_and_plugin(name)
if function is None:
+3 -2
View File
@@ -2,11 +2,12 @@ from __future__ import annotations
import typing
from ...core import app, entities as core_entities
from ...core import app
from . import loader as tools_loader
from ...utils import importutil
from . import loaders
import langbot_plugin.api.entities.builtin.resource.tool as resource_tool
import langbot_plugin.api.entities.builtin.pipeline.query as pipeline_query
importutil.import_modules_in_pkg(loaders)
@@ -90,7 +91,7 @@ class ToolManager:
return tools
async def execute_func_call(self, query: core_entities.Query, name: str, parameters: dict) -> typing.Any:
async def execute_func_call(self, query: pipeline_query.Query, name: str, parameters: dict) -> typing.Any:
"""执行函数调用"""
for loader in self.loaders: