Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions assistant/commands/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -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))
)
Expand Down Expand Up @@ -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()
1 change: 1 addition & 0 deletions assistant/common/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
10 changes: 8 additions & 2 deletions assistant/common/calls.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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)

Expand All @@ -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:
Comment on lines +73 to +75
Copy link

Copilot AI Jun 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Before accessing properties on 'db', such as 'db.endpoint_override' and 'db.tool_format', consider adding a guard to ensure 'db' is not None to prevent potential attribute errors.

Suggested change
if model not in NO_DEVELOPER_ROLE or db.endpoint_override:
if model in SUPPORTS_TOOLS or db.tool_format:
if model not in NO_DEVELOPER_ROLE or (db is not None and db.endpoint_override):
if model in SUPPORTS_TOOLS or (db is not None and db.tool_format):

Copilot uses AI. Check for mistakes.
tools = []
for func in functions:
function = {"type": "function", "function": func, "name": func["name"]}
Expand All @@ -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}",
Expand Down
1 change: 1 addition & 0 deletions assistant/common/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down