diff --git a/assistant/commands/admin.py b/assistant/commands/admin.py index 2351f26a..b09c0657 100644 --- a/assistant/commands/admin.py +++ b/assistant/commands/admin.py @@ -169,6 +169,7 @@ async def view_settings(self, ctx: commands.Context, private: bool = False): custom_func_field = ( _("`Function Calling: `{}\n").format(conf.use_function_calls) + + _("`Tool Output Format: `{}\n").format(self.db.tool_format) + _("`Maximum Recursion: `{}\n").format(conf.max_function_calls) + _("`Function Tokens: `{}\n").format(humanize_number(func_tokens)) ) @@ -2131,3 +2132,20 @@ async def toggle_bot_listen(self, ctx: commands.Context): self.db.listen_to_bots = True await ctx.send(_("Assistant will listen to other bot messages")) await self.save_conf() + + @assistant.command(name="toolformat") + @commands.is_owner() + async def toggle_tool_formatting(self, ctx: commands.Context, true_or_false: bool): + """ + Assistant will submit enabled functions to your endpoint as tools instead of functions. + + Useful for troubleshooting function calling with a custom endpoint. + """ + match true_or_false: + case True: + self.db.tool_format = True + await ctx.send("Assistant will now send functions via tools.") + case False: + self.db.tool_format = False + await ctx.send("Assistant will now send functions via functions.") + await self.save_conf() \ No newline at end of file diff --git a/assistant/common/api.py b/assistant/common/api.py index 898ce51a..f4cb5a17 100644 --- a/assistant/common/api.py +++ b/assistant/common/api.py @@ -96,6 +96,7 @@ async def request_response( presence_penalty=conf.presence_penalty, seed=conf.seed, base_url=self.db.endpoint_override, + db=self.db, ) message: ChatCompletionMessage = response.choices[0].message diff --git a/assistant/common/calls.py b/assistant/common/calls.py index 05fb3f9f..8a2436b8 100644 --- a/assistant/common/calls.py +++ b/assistant/common/calls.py @@ -9,6 +9,8 @@ from openai.types.chat import ChatCompletion from pydantic import BaseModel from sentry_sdk import add_breadcrumb +from ..common.models import DB + from tenacity import ( retry, retry_if_exception_type, @@ -45,6 +47,7 @@ async def request_chat_completion_raw( seed: int = None, base_url: Optional[str] = None, reasoning_effort: Optional[str] = None, + db: Optional[any] = None, ) -> ChatCompletion: client = openai.AsyncOpenAI(api_key=api_key, base_url=base_url) @@ -66,8 +69,10 @@ async def request_chat_completion_raw( if seed and model in SUPPORTS_SEED: kwargs["seed"] = seed - if functions and model not in NO_DEVELOPER_ROLE: - if model in SUPPORTS_TOOLS: + if functions: + if model not in NO_DEVELOPER_ROLE or db.endpoint_override: + + if model in SUPPORTS_TOOLS or db.tool_format: tools = [] for func in functions: function = {"type": "function", "function": func, "name": func["name"]} @@ -88,6 +93,7 @@ async def request_chat_completion_raw( # Remove the message from the payload del kwargs["messages"][idx] + add_breadcrumb( category="api", message=f"Calling request_chat_completion_raw: {model}", diff --git a/assistant/common/models.py b/assistant/common/models.py index cba20619..90308739 100644 --- a/assistant/common/models.py +++ b/assistant/common/models.py @@ -345,6 +345,7 @@ class DB(AssistantBaseModel): listen_to_bots: bool = False brave_api_key: t.Optional[str] = None endpoint_override: t.Optional[str] = None + tool_format: t.Optional[bool] = False def get_conf(self, guild: t.Union[discord.Guild, int]) -> GuildSettings: gid = guild if isinstance(guild, int) else guild.id