From 0bd9420f7ba73926d09f8384054333cf629beebe Mon Sep 17 00:00:00 2001 From: voodoohop Date: Wed, 30 Apr 2025 11:30:30 +0200 Subject: [PATCH 1/2] Fix OpenAI client to properly stringify function arguments --- utils/llm_client.py | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/utils/llm_client.py b/utils/llm_client.py index 8ba5c81..ce8ca05 100644 --- a/utils/llm_client.py +++ b/utils/llm_client.py @@ -400,10 +400,14 @@ class OpenAIDirectClient(LLMClient): def __init__(self, model_name: str, max_retries=2, cot_model: bool = True): """Initialize the OpenAI first party client.""" api_key = os.getenv("OPENAI_API_KEY") - self.client = openai.OpenAI( - api_key=api_key, - max_retries=1, - ) + base_url = os.getenv("OPENAI_BASE_URL") + + # Initialize the client with optional base_url if provided + client_kwargs = {"api_key": api_key, "max_retries": 1} + if base_url: + client_kwargs["base_url"] = base_url + + self.client = openai.OpenAI(**client_kwargs) self.model_name = model_name self.max_retries = max_retries self.cot_model = cot_model @@ -454,12 +458,18 @@ def generate( openai_message = {"role": "assistant", "content": [message_content]} elif str(type(augment_message)) == str(ToolCall): augment_message = cast(ToolCall, augment_message) + # Ensure arguments are always a JSON string, not an object + if isinstance(augment_message.tool_input, (dict, list)): + tool_input_str = json.dumps(augment_message.tool_input) + else: + tool_input_str = str(augment_message.tool_input) + tool_call = { "type": "function", "id": augment_message.tool_call_id, "function": { "name": augment_message.tool_name, - "arguments": augment_message.tool_input, + "arguments": tool_input_str, }, } openai_message = { @@ -601,4 +611,4 @@ def get_client(client_name: str, **kwargs) -> LLMClient: elif client_name == "openai-direct": return OpenAIDirectClient(**kwargs) else: - raise ValueError(f"Unknown client name: {client_name}") + raise ValueError(f"Unknown client name: {client_name}") \ No newline at end of file From df3381096ff2a16efb1baf8a4349107353bc37f8 Mon Sep 17 00:00:00 2001 From: voodoohop Date: Wed, 30 Apr 2025 11:31:14 +0200 Subject: [PATCH 2/2] Update CLI to support custom OpenAI endpoint when Anthropic API key is not available --- cli.py | 58 +++++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 49 insertions(+), 9 deletions(-) diff --git a/cli.py b/cli.py index 36872bf..deba3cd 100644 --- a/cli.py +++ b/cli.py @@ -73,6 +73,18 @@ def main(): action="store_true", default=False, ) + parser.add_argument( + "--openai-base-url", + type=str, + default=None, + help="(Optional) Base URL for OpenAI API. Used when ANTHROPIC_API_KEY is not set.", + ) + parser.add_argument( + "--openai-model", + type=str, + default="gpt-4-turbo", + help="(Optional) OpenAI model to use when ANTHROPIC_API_KEY is not set.", + ) args = parser.parse_args() @@ -86,11 +98,31 @@ def main(): else: logger_for_agent_logs.propagate = False + # Set OpenAI base URL if provided via command line + if args.openai_base_url: + os.environ["OPENAI_BASE_URL"] = args.openai_base_url + # Check if ANTHROPIC_API_KEY is set if "ANTHROPIC_API_KEY" not in os.environ: - print("Error: ANTHROPIC_API_KEY environment variable is not set.") - print("Please set it to your Anthropic API key.") - sys.exit(1) + openai_base_url = os.getenv("OPENAI_BASE_URL", "") + base_url_info = f" with base URL {openai_base_url}" if openai_base_url else "" + + if not args.minimize_stdout_logs: + console = Console() + console.print( + Panel( + f"[bold yellow]Warning: ANTHROPIC_API_KEY environment variable is not set.[/bold yellow]\n" + + f"Using OpenAI{base_url_info} with model {args.openai_model} instead.", + title="[bold yellow]API Key Warning[/bold yellow]", + border_style="yellow", + padding=(1, 2), + ) + ) + else: + logger_for_agent_logs.info( + f"Warning: ANTHROPIC_API_KEY environment variable is not set. " + f"Using OpenAI{base_url_info} with model {args.openai_model} instead." + ) # Initialize console console = Console() @@ -113,11 +145,19 @@ def main(): ) # Initialize LLM client - client = get_client( - "anthropic-direct", - model_name="claude-3-7-sonnet-20250219", - use_caching=True, - ) + if "ANTHROPIC_API_KEY" in os.environ: + client = get_client( + "anthropic-direct", + model_name="claude-3-7-sonnet-20250219", + use_caching=True, + ) + else: + # Use OpenAI client when Anthropic API key is not available + client = get_client( + "openai-direct", + model_name=args.openai_model, + cot_model=False, + ) # Initialize workspace manager workspace_path = Path(args.workspace).resolve() @@ -189,4 +229,4 @@ def main(): if __name__ == "__main__": - main() + main() \ No newline at end of file