Skip to content
Merged
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
2 changes: 1 addition & 1 deletion aios/config/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ llms:
- name: "qwen3:1.7b"
backend: "ollama"
hostname: "http://localhost:11434" # Make sure to run ollama server

- name: "qwen3:4b"
backend: "ollama"
hostname: "http://localhost:11434" # Make sure to run ollama server
Expand Down
65 changes: 49 additions & 16 deletions aios/llm_core/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,13 @@
import re
import uuid
from copy import deepcopy

import logging
from typing import List, Dict, Any

# Configure logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)

def merge_messages_with_tools(messages: list, tools: list) -> list:
"""
Integrate tool information into the messages for open-sourced LLMs which don't support tool calling.
Expand Down Expand Up @@ -193,8 +197,8 @@ def decode_litellm_tool_calls(response):
```
"""
decoded_tool_calls = []
if response.choices[0].message.content is None:

if response.choices[0].message.content is None:
assert response.choices[0].message.tool_calls is not None
tool_calls = response.choices[0].message.tool_calls

Expand All @@ -211,24 +215,53 @@ def decode_litellm_tool_calls(response):
)
else:
assert response.choices[0].message.content is not None
# breakpoint()

# Some providers return a JSON string; attempt to parse. If parsing fails, treat as "no tools".
tool_calls = response.choices[0].message.content
if isinstance(tool_calls, str):
tool_calls = json.loads(tool_calls)

try:
parsed = json.loads(tool_calls)
if isinstance(parsed, (list, dict)):
tool_calls = parsed
# Unexpected JSON type → no-op; be forgiving.
else:
logger.info("decode_litellm_tool_calls: unexpected JSON type for tool_calls: %s", type(parsed))
tool_calls = []
except json.JSONDecodeError:
logger.info("decode_litellm_tool_calls: non-JSON tool_calls string, treating as no tools.")
tool_calls = []

if not isinstance(tool_calls, list):
tool_calls = [tool_calls]

for tool_call in tool_calls:
decoded_tool_calls.append(
{
"name": tool_call["name"],
"parameters": tool_call["arguments"],
"id": generator_tool_call_id()
}
)

try:
for tool_call in tool_calls:
name = None
if "name" in tool_call:
name = tool_call["name"]
elif "function_name" in tool_call:
name = tool_call["function_name"]
elif "tool_name" in tool_call:
name = tool_call["tool_name"]

if name is not None:
parameters = None
if "arguments" in tool_call:
parameters = tool_call["arguments"]
elif "parameters" in tool_call:
parameters = tool_call["parameters"]

if parameters is not None:
decoded_tool_calls.append(
{
"name": name,
"parameters": parameters,
"id": generator_tool_call_id()
}
)
except:
logger.info(f"decode_litellm_tool_calls: no valid attribute in tools, treating as no tools")

return decoded_tool_calls

def parse_tool_calls(message):
Expand Down
7 changes: 5 additions & 2 deletions aios/syscall/syscall.py
Original file line number Diff line number Diff line change
Expand Up @@ -654,13 +654,16 @@ def execute_request(self, agent_name: str, query: Any) -> Dict[str, Any]:

elif query.action_type == "call_tool":
llm_response = self.execute_llm_syscall(agent_name, query)["response"]
# breakpoint()
if llm_response.tool_calls == None or len(llm_response.tool_calls) == 0:
return ToolResponse(
response_message=f"No tool was called by LLM",
finished=False
)
tool_query = ToolQuery(
tool_calls=llm_response.tool_calls,
# action_type="tool_use"
)
tool_response = self.execute_tool_syscall(agent_name, tool_query)
# breakpoint()
return tool_response

elif query.action_type == "operate_file":
Expand Down
7 changes: 6 additions & 1 deletion aios/tool/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,11 @@ def cleanup(self):
def address_request(self, syscall) -> None:
tool_calls = syscall.query.tool_calls

if tool_calls == None or len(tool_calls) == 0:
return ToolResponse(
response_message=f"There is no tool to call",
finished=False
)
# breakpoint()
try:
for tool_call in tool_calls:
Expand All @@ -106,7 +111,7 @@ def address_request(self, syscall) -> None:
except Exception as e:
return ToolResponse(
response_message=f"Tool calling error: {e}",
finished=True
finished=False
)

def load_tool_instance(self, tool_org_and_name):
Expand Down
Loading