Skip to content

Conversation

@februarysea
Copy link

Hi, When I was trying to write a beginner-friendly tutorial, I wanted users to be able to experiment with ModuleLLM freely. However, the default Gemini free-tier rate limit (RPD = 20) is often not sufficient for experimentation. So I decided to switch to a local Ollama setup with a lightweight model (qwen3:8b). During this process, I encountered the issue described
below.

Summary

Fixes a crash / infinite retry issue when using ModuleLLM with Ollama models(e.g. ollama/qwen3:8b) and tool calling enabled.

Bug / Issue

When using ModuleLLM with an Ollama model and enabling tool calling, the application may enter an infinite retry loop or fail with a validation error.

The root cause is that when no system_prompt is provided, ModuleLLM initializes the system message with content=None. Ollama (via litellm) strictly requires content to be a string. This becomes problematic during tool calling, where the system prompt is dynamically modified to inject tool schemas, causing validation failures or retries.

Expected Behavior

ModuleLLM should handle tool calling with Ollama models correctly without crashing. The system message content should default to an empty string ("") instead of None to ensure compatibility with stricter API contracts such as Ollama's.

Implementation

The system message initialization logic was updated to default the content field to an empty string ("") when no system prompt is provided. This ensures safe concatenation and modification of the system prompt during tool calling and maintains compatibility across providers.

Testing

  • Tested locally on macOS (Apple Silicon)
  • Ollama running locally with model qwen3:8b
  • Tool calling enabled with a simple function schema
  • Verified that tool invocation succeeds without validation errors or infinite retry loops

⚠️ Prerequisite:
This issue requires Ollama to be installed and running locally, with the qwen3:8b model pulled.

import asyncio
import os
import sys

# Add the current directory to sys.path to ensure we can import the module
sys.path.append(os.getcwd())

from mesa_llm.module_llm import ModuleLLM

# Define a simple tool schema
tool_schema = [
    {
        "type": "function",
        "function": {
            "name": "get_current_weather",
            "description": "Get the current weather in a given location",
            "parameters": {
                "type": "object",
                "properties": {
                    "location": {
                        "type": "string",
                        "description": "The city and state, e.g. San Francisco, CA",
                    },
                    "unit": {
                        "type": "string",
                        "enum": ["celsius", "fahrenheit"],
                    },
                },
                "required": ["location"],
            },
        },
    }
]

async def reproduce():
    print("Initializing ModuleLLM with ollama/qwen3:8b...")
    # Initialize ModuleLLM with an Ollama model
    llm = ModuleLLM(llm_model="ollama/qwen3:8b")

    print("Attempting to generate response with tool calling...")
    try:
        # This call is expected to fail or hang due to invalid system message content
        response = await llm.agenerate(
            prompt="What's the weather in San Francisco?",
            tool_schema=tool_schema
        )
        print("Response received:", response)
    except Exception as e:
        print(f"Caught exception: {type(e).__name__}: {e}")

if __name__ == "__main__":
    try:
        asyncio.run(reproduce())
    except KeyboardInterrupt:
        print("\nInterrupted by user (infinite retry loop detected?)")

Additional Notes

N/A

@coderabbitai
Copy link

coderabbitai bot commented Dec 16, 2025

Important

Review skipped

Auto reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Collaborator

@colinfrisch colinfrisch left a comment

Choose a reason for hiding this comment

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

Thanks for spotting this ! I'll give a bit of time for the other maintainers to review and merge in a few days.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants