From 7844f26d599b6366a7a06aa5341fa1142859d997 Mon Sep 17 00:00:00 2001 From: Jonathan Lucas Date: Sun, 1 Jun 2025 11:50:12 -0500 Subject: [PATCH] Testing with qwen and updating tools --- base_telegram_inference_bot.py | 9 +- chatgpt_telegram_inference_bot.py | 32 +- telegram_helper.py | 4 +- tools/github_tool.py | 623 +++++++++++++++++------------- tools/log_tool.py | 26 +- tools/metrics_tool.py | 35 +- 6 files changed, 418 insertions(+), 311 deletions(-) diff --git a/base_telegram_inference_bot.py b/base_telegram_inference_bot.py index 599fd2b..3e4709d 100644 --- a/base_telegram_inference_bot.py +++ b/base_telegram_inference_bot.py @@ -11,7 +11,8 @@ class BaseTelegramInferenceBot(ABC): self.processing_status = {} self.system_prompt = self.load_system_prompt() self.tools, self.functions = self.load_functions() - print(f'Github Token: {os.environ.get("GITHUB_TOKEN")}') + print(f'System Prompt: {os.environ.get("SYSTEM_PROMPT_PATH")}') + print(f'Github Repository: {os.environ.get("GITHUB_REPOSITORY")}') @staticmethod def load_system_prompt(): @@ -59,8 +60,10 @@ class BaseTelegramInferenceBot(ABC): function_name = function_call_name function_args = json.loads(function_call_arguments if function_call_arguments is not None else "{}") for tool in self.tools: - if function_name in [f["name"] for f in tool.get_functions()]: - return tool.execute(function_name, **function_args) + for function in tool.get_functions(): + if function["function"]["name"] == function_name: + return tool.execute(function_name, **function_args) + @abstractmethod async def start(self): diff --git a/chatgpt_telegram_inference_bot.py b/chatgpt_telegram_inference_bot.py index 0a6ef43..5d030c0 100644 --- a/chatgpt_telegram_inference_bot.py +++ b/chatgpt_telegram_inference_bot.py @@ -8,16 +8,16 @@ from openai import OpenAI class ChatGPTTelegramInferenceBot(BaseTelegramInferenceBot): def __init__(self): super().__init__() - self.client = OpenAI(api_key=os.environ.get("OPENAI_API_KEY")) - self.model = "gpt-4o-mini" - self.max_tokens = 16384 + self.client = OpenAI(api_key=os.environ.get("OPENAI_API_KEY"), base_url="http://localhost:1234/v1") + self.model = "qwen3-1.7b" + self.max_tokens = 32768 def get_chat_response(self, messages): response = self.client.chat.completions.create( model=self.model, messages=[{"role": "system", "content": self.system_prompt}] + messages, - functions=self.functions, - function_call="auto", + tools=self.functions, + tool_choice = "auto", max_tokens=self.max_tokens ) return response @@ -34,8 +34,8 @@ class ChatGPTTelegramInferenceBot(BaseTelegramInferenceBot): tool_calls = [] for message_part in response.choices: - if message_part.finish_reason == "function_call": - tool_calls.append(message_part.message.function_call) + if message_part.finish_reason == "tool_calls": + tool_calls.extend(message_part.message.tool_calls) messages.append(response.choices[0].message) @@ -44,9 +44,13 @@ class ChatGPTTelegramInferenceBot(BaseTelegramInferenceBot): tool_use_results = [] while len(tool_calls) > 0: - tool_call = tool_calls.pop(0) + tool_call = tool_calls.pop(0).function tool_response = self.call_tool(tool_call.name, tool_call.arguments) - tool_use_results.append({"role": "function", "name": tool_call.name, "content": json.dumps(tool_response)}) + try: + tool_use_results.append({"role": "tool", "name": tool_call.name, "content": tool_response}) + except (TypeError, ValueError) as e: + logging.error(f"Failed to serialize tool response: {e}") + tool_use_results.append({"role": "function", "name": tool_call.name, "content": "Serialization error"}) messages.extend(tool_use_results) @@ -84,12 +88,12 @@ class ChatGPTTelegramInferenceBot(BaseTelegramInferenceBot): return "No active processing to abort." async def switch_model(self): - if self.model == "gpt-4o-mini": - self.model = "gpt-4o" - self.max_tokens = 4096 + if self.model == "qwen3-4b": + self.model = "qwen3-30b-a3b" + # self.max_tokens = 4096 else: - self.model = "gpt-4o-mini" - self.max_tokens = 16384 + self.model = "qwen3-4b" + # self.max_tokens = 16384 logging.info(f"Switched to model: {self.model}") return f"Switched to model: {self.model}" diff --git a/telegram_helper.py b/telegram_helper.py index 5cc9e92..e2fdaff 100644 --- a/telegram_helper.py +++ b/telegram_helper.py @@ -63,7 +63,9 @@ class TelegramHelper: await context.bot.delete_message(chat_id=update.effective_chat.id, message_id=status_message.message_id) del self.bot.processing_status[user_id] - await update.message.reply_text(response) + response = response.replace("", "
Thinking...").replace("", "
") + # Return response as html message + await update.message.reply_html(response) except Exception as e: logging.error(f"An error occurred: {str(e)}") diff --git a/tools/github_tool.py b/tools/github_tool.py index cd1b814..67d89c6 100644 --- a/tools/github_tool.py +++ b/tools/github_tool.py @@ -46,54 +46,65 @@ class GitHubTool(BaseTool): def get_functions(self): return [ - { - "name": "read_file", - "description": "Read a file from the repository", - "parameters": { - "type": "object", - "properties": { + { + "type": "function", + "function": { + "name": "read_file", + "description": "Read a file from the repository", + "parameters": { + "type": "object", + "properties": { "path": { "type": "string", "description": "Path to the file in the repository" } - }, - "required": ["path"] - } - }, - { - "name": "list_files", - "description": "List files in a directory of the repository", - "parameters": { - "type": "object", - "properties": { + }, + "required": ["path"] + } + } + }, + { + "type": "function", + "function": { + "name": "list_files", + "description": "List files in a directory of the repository", + "parameters": { + "type": "object", + "properties": { "path": { "type": "string", "description": "Path to the directory in the repository" } - }, - "required": ["path"] - } - }, - { - "name": "search_code", - "description": "Search for code in the repository", - "parameters": { - "type": "object", - "properties": { + }, + "required": ["path"] + } + } + }, + { + "type": "function", + "function": { + "name": "search_code", + "description": "Search for code in the repository", + "parameters": { + "type": "object", + "properties": { "query": { "type": "string", "description": "Search query" } - }, - "required": ["query"] - } - }, - { - "name": "create_branch", - "description": "Create a new branch in the repository", - "parameters": { - "type": "object", - "properties": { + }, + "required": ["query"] + } + } + }, + { + "type": "function", + "function": { + "name": "create_branch", + "description": "Create a new branch in the repository", + "parameters": { + "type": "object", + "properties": { "branch_name": { "type": "string", "description": "Name of the new branch" @@ -103,16 +114,19 @@ class GitHubTool(BaseTool): "description": "Name of the base branch", "default": "main" } - }, - "required": ["branch_name"] - } - }, - { - "name": "commit_file", - "description": "Commit a file to a branch (not main)", - "parameters": { - "type": "object", - "properties": { + }, + "required": ["branch_name"] + } + } + }, + { + "type": "function", + "function": { + "name": "commit_file", + "description": "Commit a file to a branch (not main)", + "parameters": { + "type": "object", + "properties": { "file_path": { "type": "string", "description": "Path to the file in the repository" @@ -125,16 +139,19 @@ class GitHubTool(BaseTool): "type": "string", "description": "Content of the file" } - }, - "required": ["file_path", "commit_message", "content"] - } - }, - { - "name": "create_pull_request", - "description": "Create a pull request", - "parameters": { - "type": "object", - "properties": { + }, + "required": ["file_path", "commit_message", "content"] + } + } + }, + { + "type": "function", + "function": { + "name": "create_pull_request", + "description": "Create a pull request", + "parameters": { + "type": "object", + "properties": { "title": { "type": "string", "description": "Title of the pull request" @@ -148,16 +165,19 @@ class GitHubTool(BaseTool): "description": "The name of the branch you want the changes pulled into", "default": "main" } - }, - "required": ["title", "body"] - } - }, - { - "name": "get_commit_history", - "description": "Get commit history for a file", - "parameters": { - "type": "object", - "properties": { + }, + "required": ["title", "body"] + } + } + }, + { + "type": "function", + "function": { + "name": "get_commit_history", + "description": "Get commit history for a file", + "parameters": { + "type": "object", + "properties": { "file_path": { "type": "string", "description": "Path to the file in the repository" @@ -167,49 +187,61 @@ class GitHubTool(BaseTool): "description": "Number of commits to retrieve", "default": 10 } - }, - "required": ["file_path"] - } - }, - { - "name": "get_branch_sha", - "description": "Get the SHA of the latest commit on a branch", - "parameters": { - "type": "object", - "properties": { + }, + "required": ["file_path"] + } + } + }, + { + "type": "function", + "function": { + "name": "get_branch_sha", + "description": "Get the SHA of the latest commit on a branch", + "parameters": { + "type": "object", + "properties": { "branch": { "type": "string", "description": "Name of the branch" } - }, - "required": ["branch"] - } - }, - { - "name": "get_current_branch", - "description": "Get the name of the current branch", - "parameters": {} - }, - { - "name": "set_current_branch", - "description": "Set the current branch", - "parameters": { - "type": "object", - "properties": { + }, + "required": ["branch"] + } + } + }, + { + "type": "function", + "function": { + "name": "get_current_branch", + "description": "Get the name of the current branch", + "parameters": { "type": "object", "properties": {} } + } + }, + { + "type": "function", + "function": { + "name": "set_current_branch", + "description": "Set the current branch", + "parameters": { + "type": "object", + "properties": { "branch_name": { "type": "string", "description": "Name of the branch to set as current" } - }, - "required": ["branch_name"] - } - }, - { - "name": "get_file_at_commit", - "description": "Get the contents of a file at a specific commit", - "parameters": { - "type": "object", - "properties": { + }, + "required": ["branch_name"] + } + } + }, + { + "type": "function", + "function": { + "name": "get_file_at_commit", + "description": "Get the contents of a file at a specific commit", + "parameters": { + "type": "object", + "properties": { "file_path": { "type": "string", "description": "Path to the file in the repository" @@ -218,16 +250,19 @@ class GitHubTool(BaseTool): "type": "string", "description": "SHA of the commit to retrieve the file from" } - }, - "required": ["file_path", "commit_sha"] - } - }, - { - "name": "list_branches", - "description": "List all branches in the repository", - "parameters": { - "type": "object", - "properties": { + }, + "required": ["file_path", "commit_sha"] + } + } + }, + { + "type": "function", + "function": { + "name": "list_branches", + "description": "List all branches in the repository", + "parameters": { + "type": "object", + "properties": { "per_page": { "type": "integer", "description": "Number of branches to return per page (max 100)", @@ -238,43 +273,52 @@ class GitHubTool(BaseTool): "description": "Whether to fetch all pages of results", "default": True } + } } - } - }, - { - "name": "approve_pull_request", - "description": "Approve a pull request", - "parameters": { - "type": "object", - "properties": { + } + }, + { + "type": "function", + "function": { + "name": "approve_pull_request", + "description": "Approve a pull request", + "parameters": { + "type": "object", + "properties": { "pull_number": { "type": "integer", "description": "The number of the pull request" } - }, - "required": ["pull_number"] - } - }, - { - "name": "close_pull_request", - "description": "Close a pull request", - "parameters": { - "type": "object", - "properties": { + }, + "required": ["pull_number"] + } + } + }, + { + "type": "function", + "function": { + "name": "close_pull_request", + "description": "Close a pull request", + "parameters": { + "type": "object", + "properties": { "pull_number": { "type": "integer", "description": "The number of the pull request" } - }, - "required": ["pull_number"] - } - }, - { - "name": "merge_pull_request", - "description": "Merge a pull request", - "parameters": { - "type": "object", - "properties": { + }, + "required": ["pull_number"] + } + } + }, + { + "type": "function", + "function": { + "name": "merge_pull_request", + "description": "Merge a pull request", + "parameters": { + "type": "object", + "properties": { "pull_number": { "type": "integer", "description": "The number of the pull request" @@ -295,44 +339,53 @@ class GitHubTool(BaseTool): "enum": ["merge", "squash", "rebase"], "default": "merge" } - }, - "required": ["pull_number"] - } - }, - { - "name": "delete_branch", - "description": "Delete a branch", - "parameters": { - "type": "object", - "properties": { + }, + "required": ["pull_number"] + } + } + }, + { + "type": "function", + "function": { + "name": "delete_branch", + "description": "Delete a branch", + "parameters": { + "type": "object", + "properties": { "branch_name": { "type": "string", "description": "Name of the branch to delete" } - }, - "required": ["branch_name"] - } - }, - { - "name": "get_issue_details", - "description": "Get details of a specific issue", - "parameters": { - "type": "object", - "properties": { + }, + "required": ["branch_name"] + } + } + }, + { + "type": "function", + "function": { + "name": "get_issue_details", + "description": "Get details of a specific issue", + "parameters": { + "type": "object", + "properties": { "issue_number": { "type": "integer", "description": "The number of the issue" } - }, - "required": ["issue_number"] - } - }, - { - "name": "create_issue", - "description": "Create a new issue in the repository", - "parameters": { - "type": "object", - "properties": { + }, + "required": ["issue_number"] + } + } + }, + { + "type": "function", + "function": { + "name": "create_issue", + "description": "Create a new issue in the repository", + "parameters": { + "type": "object", + "properties": { "title": { "type": "string", "description": "Title of the issue" @@ -344,20 +397,23 @@ class GitHubTool(BaseTool): "labels": { "type": "array", "items": { - "type": "string" + "type": "string" }, "description": "Labels to apply to the issue" } - }, - "required": ["title", "body"] - } - }, - { - "name": "list_issues", - "description": "List issues in the repository", - "parameters": { - "type": "object", - "properties": { + }, + "required": ["title", "body"] + } + } + }, + { + "type": "function", + "function": { + "name": "list_issues", + "description": "List issues in the repository", + "parameters": { + "type": "object", + "properties": { "state": { "type": "string", "enum": ["open", "closed", "all"], @@ -374,15 +430,18 @@ class GitHubTool(BaseTool): "default": 1, "description": "Page number of the results to fetch" } + } } - } - }, - { - "name": "add_issue_comment", - "description": "Add a comment to an issue", - "parameters": { - "type": "object", - "properties": { + } + }, + { + "type": "function", + "function": { + "name": "add_issue_comment", + "description": "Add a comment to an issue", + "parameters": { + "type": "object", + "properties": { "issue_number": { "type": "integer", "description": "The number of the issue" @@ -391,30 +450,36 @@ class GitHubTool(BaseTool): "type": "string", "description": "The comment to add to the issue" } - }, - "required": ["issue_number", "comment"] - } - }, - { - "name": "get_issue_comments", - "description": "Get comments for an issue", - "parameters": { - "type": "object", - "properties": { + }, + "required": ["issue_number", "comment"] + } + } + }, + { + "type": "function", + "function": { + "name": "get_issue_comments", + "description": "Get comments for an issue", + "parameters": { + "type": "object", + "properties": { "issue_number": { "type": "integer", "description": "The number of the issue" } - }, - "required": ["issue_number"] - } - }, - { - "name": "create_project_board", - "description": "Create a new project board", - "parameters": { - "type": "object", - "properties": { + }, + "required": ["issue_number"] + } + } + }, + { + "type": "function", + "function": { + "name": "create_project_board", + "description": "Create a new project board", + "parameters": { + "type": "object", + "properties": { "name": { "type": "string", "description": "Name of the project board" @@ -423,16 +488,19 @@ class GitHubTool(BaseTool): "type": "string", "description": "Body of the project board" } - }, - "required": ["name"] - } - }, - { - "name": "create_project_column", - "description": "Create a new column in a project board", - "parameters": { - "type": "object", - "properties": { + }, + "required": ["name"] + } + } + }, + { + "type": "function", + "function": { + "name": "create_project_column", + "description": "Create a new column in a project board", + "parameters": { + "type": "object", + "properties": { "project_id": { "type": "integer", "description": "ID of the project board" @@ -441,16 +509,19 @@ class GitHubTool(BaseTool): "type": "string", "description": "Name of the column" } - }, - "required": ["project_id", "column_name"] - } - }, - { - "name": "create_project_card", - "description": "Create a new card in a project column", - "parameters": { - "type": "object", - "properties": { + }, + "required": ["project_id", "column_name"] + } + } + }, + { + "type": "function", + "function": { + "name": "create_project_card", + "description": "Create a new card in a project column", + "parameters": { + "type": "object", + "properties": { "column_id": { "type": "integer", "description": "ID of the project column" @@ -459,16 +530,19 @@ class GitHubTool(BaseTool): "type": "string", "description": "Note for the project card" } - }, - "required": ["column_id", "note"] - } - }, - { - "name": "move_project_card", - "description": "Move a card to a new position", - "parameters": { - "type": "object", - "properties": { + }, + "required": ["column_id", "note"] + } + } + }, + { + "type": "function", + "function": { + "name": "move_project_card", + "description": "Move a card to a new position", + "parameters": { + "type": "object", + "properties": { "card_id": { "type": "integer", "description": "ID of the project card" @@ -481,16 +555,19 @@ class GitHubTool(BaseTool): "type": "integer", "description": "ID of the target column" } - }, - "required": ["card_id", "position", "column_id"] - } - }, - { - "name": "link_issue_to_project_card", - "description": "Link an issue or pull request to a project card", - "parameters": { - "type": "object", - "properties": { + }, + "required": ["card_id", "position", "column_id"] + } + } + }, + { + "type": "function", + "function": { + "name": "link_issue_to_project_card", + "description": "Link an issue or pull request to a project card", + "parameters": { + "type": "object", + "properties": { "card_id": { "type": "integer", "description": "ID of the project card" @@ -503,29 +580,36 @@ class GitHubTool(BaseTool): "type": "string", "description": "Type of the content (Issue or PullRequest)" } - }, - "required": ["card_id", "content_id", "content_type"] - } - }, - { - "name": "list_project_boards", - "description": "List project boards associated with the repository", - "parameters": {} - }, - { - "name": "view_project_board_items", - "description": "View items (columns and cards) in a specific project board", - "parameters": { - "type": "object", - "properties" : { + }, + "required": ["card_id", "content_id", "content_type"] + } + } + }, + { + "type": "function", + "function": { + "name": "list_project_boards", + "description": "List project boards associated with the repository", + "parameters": { "type": "object", "properties": {} } + } + }, + { + "type": "function", + "function": { + "name": "view_project_board_items", + "description": "View items (columns and cards) in a specific project board", + "parameters": { + "type": "object", + "properties": { "project_id": { "type": "integer", "description": "ID of the project board" } - }, - "required": ["project_id"] + }, + "required": ["project_id"] + } + } } - } ] @@ -712,10 +796,11 @@ class GitHubTool(BaseTool): url = f"{self.base_url}/repos/{self.repo}/contents/{path}" response = requests.get(url, headers=self.headers, params={"ref": self.current_branch}) if response.status_code == 200: - files = [item["name"] for item in response.json() if item["type"] == "file"] - directories = [item["name"] for item in response.json() if item["type"] == "dir"] + files = [{"type": "file", "name": item["name"]} for item in response.json() if item["type"] == "file"] + directories = [{"type": "directory", "name": item["name"]} for item in response.json() if item["type"] == "dir"] self.logger.info(f"Successfully listed files and directories in {path}") - return {"files": files, "directories": directories} + files.extend(directories) + return files else: error_message = f"Error listing files: {response.status_code}" self.logger.error(error_message) diff --git a/tools/log_tool.py b/tools/log_tool.py index e051f25..4a34557 100644 --- a/tools/log_tool.py +++ b/tools/log_tool.py @@ -33,19 +33,23 @@ class LogTool(BaseTool): pass def get_functions(self): + return [ { - "name": "get_log_contents", - "description": "Get the contents of the log file.", - "parameters": { - "type": "object", - "properties": { - "line_count": { - "type": "integer", - "description": "Number of lines from the end of the log file to retrieve" - } - }, - "required": [] + "type": "function", + "function": { + "name": "get_log_contents", + "description": "Get the contents of the log file.", + "parameters": { + "type": "object", + "properties": { + "line_count": { + "type": "integer", + "description": "Number of lines from the end of the log file to retrieve" + } + }, + "required": [] + } } } ] diff --git a/tools/metrics_tool.py b/tools/metrics_tool.py index 4db57be..8ba6116 100644 --- a/tools/metrics_tool.py +++ b/tools/metrics_tool.py @@ -13,40 +13,49 @@ class MetricsTool(BaseTool): def get_functions(self): return [ { - "name": "get_function_metrics", - "description": "Get metrics for all measured functions.", - "parameters": { + "type": "function", + "function": { + "name": "get_function_metrics", + "description": "Get metrics for all measured functions.", + "parameters": { "type": "object", "properties": {}, "required": [] + } } }, { - "name": "get_specific_function_metrics", - "description": "Get metrics for a specific function.", - "parameters": { + "type": "function", + "function": { + "name": "get_specific_function_metrics", + "description": "Get metrics for a specific function.", + "parameters": { "type": "object", "properties": { "function_name": { - "type": "string", - "description": "Name of the function to get metrics for" + "type": "string", + "description": "Name of the function to get metrics for" } }, "required": ["function_name"] + } } }, { - "name": "get_top_n_functions", - "description": "Get the top N functions by total execution time.", - "parameters": { + "type": "function", + "function": { + "name": "get_top_n_functions", + "description": "Get the top N functions by total execution time.", + "parameters": { "type": "object", "properties": { "n": { - "type": "integer", - "description": "Number of top functions to retrieve" + "type": "integer", + "description": "Number of top functions to retrieve" } }, "required": ["n"] + } } } ]