Sync fork with upstream TauricResearch/TradingAgents (v0.2.1) (#12)
* chore: remove unused chainlit dependency (CVE-2026-22218) * fix: pass debate round config to ConditionalLogic (#361) * fix: pass max_debate_rounds and max_risk_discuss_rounds config to ConditionalLogic * use config values * fix: add explicit UTF-8 encoding to all file open() calls Prevents UnicodeEncodeError on Windows where the default encoding (cp1252/gbk) cannot handle Unicode characters in LLM output. Closes #77, closes #114, closes #126, closes #215, closes #332 * fix: initialize all debate state fields in propagation.py InvestDebateState was missing bull_history, bear_history, judge_decision. RiskDebateState was missing aggressive_history, conservative_history, neutral_history, latest_speaker, judge_decision. This caused KeyError in _log_state() and reflection, especially with edge-case config values. * fix: handle comma-separated indicators in get_indicators tool LLMs (especially smaller models) sometimes pass multiple indicator names as a single comma-separated string instead of making separate tool calls. Split and process each individually at the tool boundary. * fix: add missing console import to cli/utils.py Seven error-handling paths used console.print() but console was never imported, causing NameError on invalid user input. * fix: harden stock data parsing against malformed CSV and NaN values Add _clean_dataframe() to normalize stock DataFrames before stockstats: coerce invalid dates/prices, drop rows missing Close, fill price gaps. Also add on_bad_lines="skip" to all cached CSV reads. * chore: update model lists, bump to v0.2.1, fix package build - OpenAI: add GPT-5.4, GPT-5.4 Pro; remove o-series and legacy GPT-4o - Anthropic: add Claude Opus 4.6, Sonnet 4.6; remove legacy 4.1/4.0/3.x - Google: add Gemini 3.1 Pro, 3.1 Flash Lite; remove deprecated gemini-3-pro-preview and Gemini 2.0 series - xAI: clean up model list to match current API - Simplify UnifiedChatOpenAI GPT-5 temperature handling - Add missing tradingagents/__init__.py (fixes pip install building) * docs: add v0.2.1 release note to README * fix: add http_client support for SSL certificate customization - Add http_client and http_async_client parameters to all LLM clients - OpenAIClient, GoogleClient, AnthropicClient now support custom httpx clients - Fixes SSL certificate verification errors on Windows Conda environments - Users can now pass custom httpx.Client with verify=False or custom certs Fixes #369 * Initial plan --------- Co-authored-by: Yijia-Xiao <yijia-xiao@outlook.com> Co-authored-by: makk9 <117951691+makk9@users.noreply.github.com> Co-authored-by: 阳虎 <yanghu@yanghudeMacBook-Pro.local> Co-authored-by: Yijia Xiao <48253104+Yijia-Xiao@users.noreply.github.com> Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: ahmet guzererler <guzererler@gmail.com>
This commit is contained in:
parent
ff81333f5b
commit
9f397fee75
|
|
@ -28,6 +28,7 @@
|
|||
# TradingAgents: Multi-Agents LLM Financial Trading Framework
|
||||
|
||||
## News
|
||||
- [2026-03] **TradingAgents v0.2.1** released with GPT-5.4, Gemini 3.1, Claude 4.6 model coverage and improved system stability.
|
||||
- [2026-02] **TradingAgents v0.2.0** released with multi-provider LLM support (GPT-5.x, Gemini 3.x, Claude 4.x, Grok 4.x) and improved system architecture.
|
||||
- [2026-01] **Trading-R1** [Technical Report](https://arxiv.org/abs/2509.11420) released, with [Terminal](https://github.com/TauricResearch/Trading-R1) expected to land soon.
|
||||
|
||||
|
|
|
|||
72
cli/utils.py
72
cli/utils.py
|
|
@ -1,6 +1,7 @@
|
|||
import questionary
|
||||
import requests
|
||||
from typing import List, Optional, Tuple, Dict
|
||||
|
||||
from rich.console import Console
|
||||
|
||||
from cli.models import AnalystType
|
||||
|
|
@ -154,30 +155,30 @@ def select_shallow_thinking_agent(provider) -> str:
|
|||
return model.strip()
|
||||
options = ollama_models
|
||||
else:
|
||||
# Ordering: medium → light → heavy (balanced first for quick tasks)
|
||||
# Within same tier, newer models first
|
||||
SHALLOW_AGENT_OPTIONS = {
|
||||
"openai": [
|
||||
("GPT-5 Mini - Cost-optimized reasoning", "gpt-5-mini"),
|
||||
("GPT-5 Nano - Ultra-fast, high-throughput", "gpt-5-nano"),
|
||||
("GPT-5.2 - Latest flagship", "gpt-5.2"),
|
||||
("GPT-5.1 - Flexible reasoning", "gpt-5.1"),
|
||||
("GPT-4.1 - Smartest non-reasoning, 1M context", "gpt-4.1"),
|
||||
("GPT-5 Mini - Balanced speed, cost, and capability", "gpt-5-mini"),
|
||||
("GPT-5 Nano - High-throughput, simple tasks", "gpt-5-nano"),
|
||||
("GPT-5.4 - Latest frontier, 1M context", "gpt-5.4"),
|
||||
("GPT-4.1 - Smartest non-reasoning model", "gpt-4.1"),
|
||||
],
|
||||
"anthropic": [
|
||||
("Claude Haiku 4.5 - Fast + extended thinking", "claude-haiku-4-5"),
|
||||
("Claude Sonnet 4.5 - Best for agents/coding", "claude-sonnet-4-5"),
|
||||
("Claude Sonnet 4 - High-performance", "claude-sonnet-4-20250514"),
|
||||
("Claude Sonnet 4.6 - Best speed and intelligence balance", "claude-sonnet-4-6"),
|
||||
("Claude Haiku 4.5 - Fast, near-instant responses", "claude-haiku-4-5"),
|
||||
("Claude Sonnet 4.5 - Agents and coding", "claude-sonnet-4-5"),
|
||||
],
|
||||
"google": [
|
||||
("Gemini 3 Flash - Next-gen fast", "gemini-3-flash-preview"),
|
||||
("Gemini 2.5 Flash - Balanced, recommended", "gemini-2.5-flash"),
|
||||
("Gemini 3 Pro - Reasoning-first", "gemini-3-pro-preview"),
|
||||
("Gemini 2.5 Flash - Balanced, stable", "gemini-2.5-flash"),
|
||||
("Gemini 3.1 Flash Lite - Most cost-efficient", "gemini-3.1-flash-lite-preview"),
|
||||
("Gemini 2.5 Flash Lite - Fast, low-cost", "gemini-2.5-flash-lite"),
|
||||
],
|
||||
"xai": [
|
||||
("Grok 4.1 Fast (Non-Reasoning) - Speed optimized, 2M ctx", "grok-4-1-fast-non-reasoning"),
|
||||
("Grok 4 Fast (Non-Reasoning) - Speed optimized", "grok-4-fast-non-reasoning"),
|
||||
("Grok 4.1 Fast (Reasoning) - High-performance, 2M ctx", "grok-4-1-fast-reasoning"),
|
||||
("Grok 4 Fast (Reasoning) - High-performance", "grok-4-fast-reasoning"),
|
||||
],
|
||||
"openrouter": [
|
||||
("NVIDIA Nemotron 3 Nano 30B (free)", "nvidia/nemotron-3-nano-30b-a3b:free"),
|
||||
|
|
@ -227,22 +228,24 @@ def select_mid_thinking_agent(provider) -> str:
|
|||
return model.strip()
|
||||
options = ollama_models
|
||||
else:
|
||||
# Ordering: medium → light → heavy (balanced for mid-tier tasks)
|
||||
# Within same tier, newer models first
|
||||
MID_AGENT_OPTIONS = {
|
||||
"openai": [
|
||||
("GPT-5.1 - Flexible reasoning", "gpt-5.1"),
|
||||
("GPT-5 - Advanced reasoning", "gpt-5"),
|
||||
("GPT-4.1 - Smartest non-reasoning, 1M context", "gpt-4.1"),
|
||||
("GPT-5 Mini - Cost-optimized reasoning", "gpt-5-mini"),
|
||||
("GPT-5.2 - Strong reasoning, cost-effective", "gpt-5.2"),
|
||||
("GPT-5 Mini - Balanced speed, cost, and capability", "gpt-5-mini"),
|
||||
("GPT-5.4 - Latest frontier, 1M context", "gpt-5.4"),
|
||||
("GPT-4.1 - Smartest non-reasoning model", "gpt-4.1"),
|
||||
],
|
||||
"anthropic": [
|
||||
("Claude Sonnet 4.5 - Best for agents/coding", "claude-sonnet-4-5"),
|
||||
("Claude Sonnet 4 - High-performance", "claude-sonnet-4-20250514"),
|
||||
("Claude Haiku 4.5 - Fast + extended thinking", "claude-haiku-4-5"),
|
||||
("Claude Sonnet 4.6 - Best speed and intelligence balance", "claude-sonnet-4-6"),
|
||||
("Claude Sonnet 4.5 - Agents and coding", "claude-sonnet-4-5"),
|
||||
("Claude Haiku 4.5 - Fast, near-instant responses", "claude-haiku-4-5"),
|
||||
],
|
||||
"google": [
|
||||
("Gemini 2.5 Flash - Balanced, recommended", "gemini-2.5-flash"),
|
||||
("Gemini 2.5 Flash - Balanced, stable", "gemini-2.5-flash"),
|
||||
("Gemini 3 Flash - Next-gen fast", "gemini-3-flash-preview"),
|
||||
("Gemini 3 Pro - Reasoning-first", "gemini-3-pro-preview"),
|
||||
("Gemini 2.5 Pro - Stable pro model", "gemini-2.5-pro"),
|
||||
],
|
||||
"xai": [
|
||||
("Grok 4.1 Fast (Reasoning) - High-performance, 2M ctx", "grok-4-1-fast-reasoning"),
|
||||
|
|
@ -250,7 +253,6 @@ def select_mid_thinking_agent(provider) -> str:
|
|||
("Grok 4.1 Fast (Non-Reasoning) - Speed optimized, 2M ctx", "grok-4-1-fast-non-reasoning"),
|
||||
],
|
||||
"openrouter": [
|
||||
("DeepSeek R1 - Strong open-source reasoning", "deepseek/deepseek-r1"),
|
||||
("Z.AI GLM 4.5 Air (free)", "z-ai/glm-4.5-air:free"),
|
||||
("NVIDIA Nemotron 3 Nano 30B (free)", "nvidia/nemotron-3-nano-30b-a3b:free"),
|
||||
],
|
||||
|
|
@ -296,36 +298,34 @@ def select_deep_thinking_agent(provider) -> str:
|
|||
return model.strip()
|
||||
options = ollama_models
|
||||
else:
|
||||
# Ordering: heavy → medium → light (most capable first for deep tasks)
|
||||
# Within same tier, newer models first
|
||||
DEEP_AGENT_OPTIONS = {
|
||||
"openai": [
|
||||
("GPT-5.2 - Latest flagship", "gpt-5.2"),
|
||||
("GPT-5.1 - Flexible reasoning", "gpt-5.1"),
|
||||
("GPT-5 - Advanced reasoning", "gpt-5"),
|
||||
("GPT-4.1 - Smartest non-reasoning, 1M context", "gpt-4.1"),
|
||||
("GPT-5 Mini - Cost-optimized reasoning", "gpt-5-mini"),
|
||||
("GPT-5 Nano - Ultra-fast, high-throughput", "gpt-5-nano"),
|
||||
("GPT-5.4 - Latest frontier, 1M context", "gpt-5.4"),
|
||||
("GPT-5.2 - Strong reasoning, cost-effective", "gpt-5.2"),
|
||||
("GPT-5 Mini - Balanced speed, cost, and capability", "gpt-5-mini"),
|
||||
("GPT-5.4 Pro - Most capable, expensive ($30/$180 per 1M tokens)", "gpt-5.4-pro"),
|
||||
],
|
||||
"anthropic": [
|
||||
("Claude Sonnet 4.5 - Best for agents/coding", "claude-sonnet-4-5"),
|
||||
("Claude Opus 4.6 - Most intelligent, agents and coding", "claude-opus-4-6"),
|
||||
("Claude Opus 4.5 - Premium, max intelligence", "claude-opus-4-5"),
|
||||
("Claude Opus 4.1 - Most capable model", "claude-opus-4-1-20250805"),
|
||||
("Claude Haiku 4.5 - Fast + extended thinking", "claude-haiku-4-5"),
|
||||
("Claude Sonnet 4 - High-performance", "claude-sonnet-4-20250514"),
|
||||
("Claude Sonnet 4.6 - Best speed and intelligence balance", "claude-sonnet-4-6"),
|
||||
("Claude Sonnet 4.5 - Agents and coding", "claude-sonnet-4-5"),
|
||||
],
|
||||
"google": [
|
||||
("Gemini 3 Pro - Reasoning-first", "gemini-3-pro-preview"),
|
||||
("Gemini 3.1 Pro - Reasoning-first, complex workflows", "gemini-3.1-pro-preview"),
|
||||
("Gemini 3 Flash - Next-gen fast", "gemini-3-flash-preview"),
|
||||
("Gemini 2.5 Flash - Balanced, recommended", "gemini-2.5-flash"),
|
||||
("Gemini 2.5 Pro - Stable pro model", "gemini-2.5-pro"),
|
||||
("Gemini 2.5 Flash - Balanced, stable", "gemini-2.5-flash"),
|
||||
],
|
||||
"xai": [
|
||||
("Grok 4 - Flagship model", "grok-4-0709"),
|
||||
("Grok 4.1 Fast (Reasoning) - High-performance, 2M ctx", "grok-4-1-fast-reasoning"),
|
||||
("Grok 4 Fast (Reasoning) - High-performance", "grok-4-fast-reasoning"),
|
||||
("Grok 4 - Flagship model", "grok-4-0709"),
|
||||
("Grok 4.1 Fast (Non-Reasoning) - Speed optimized, 2M ctx", "grok-4-1-fast-non-reasoning"),
|
||||
("Grok 4 Fast (Non-Reasoning) - Speed optimized", "grok-4-fast-non-reasoning"),
|
||||
],
|
||||
"openrouter": [
|
||||
("DeepSeek R1 - Strong open-source reasoning", "deepseek/deepseek-r1"),
|
||||
("Z.AI GLM 4.5 Air (free)", "z-ai/glm-4.5-air:free"),
|
||||
("NVIDIA Nemotron 3 Nano 30B (free)", "nvidia/nemotron-3-nano-30b-a3b:free"),
|
||||
],
|
||||
|
|
|
|||
|
|
@ -4,14 +4,13 @@ build-backend = "setuptools.build_meta"
|
|||
|
||||
[project]
|
||||
name = "tradingagents"
|
||||
version = "0.2.0"
|
||||
version = "0.2.1"
|
||||
description = "TradingAgents: Multi-Agents LLM Financial Trading Framework"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.10"
|
||||
dependencies = [
|
||||
"langchain-core>=0.3.81",
|
||||
"backtrader>=1.9.78.123",
|
||||
"chainlit>=2.5.5",
|
||||
"langchain-anthropic>=0.3.15",
|
||||
"langchain-experimental>=0.3.4",
|
||||
"langchain-google-genai>=2.1.5",
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@ requests
|
|||
tqdm
|
||||
pytz
|
||||
redis
|
||||
chainlit
|
||||
rich
|
||||
typer
|
||||
questionary
|
||||
|
|
|
|||
|
|
@ -10,14 +10,22 @@ def get_indicators(
|
|||
look_back_days: Annotated[int, "how many days to look back"] = 30,
|
||||
) -> str:
|
||||
"""
|
||||
Retrieve technical indicators for a given ticker symbol.
|
||||
Retrieve a single technical indicator for a given ticker symbol.
|
||||
Uses the configured technical_indicators vendor.
|
||||
Args:
|
||||
symbol (str): Ticker symbol of the company, e.g. AAPL, TSM
|
||||
indicator (str): Technical indicator to get the analysis and report of
|
||||
indicator (str): A single technical indicator name, e.g. 'rsi', 'macd'. Call this tool once per indicator.
|
||||
curr_date (str): The current trading date you are trading on, YYYY-mm-dd
|
||||
look_back_days (int): How many days to look back, default is 30
|
||||
Returns:
|
||||
str: A formatted dataframe containing the technical indicators for the specified ticker symbol and indicator.
|
||||
"""
|
||||
return route_to_vendor("get_indicators", symbol, indicator, curr_date, look_back_days)
|
||||
# LLMs sometimes pass multiple indicators as a comma-separated string;
|
||||
# split and process each individually.
|
||||
indicators = [i.strip() for i in indicator.split(",") if i.strip()]
|
||||
if len(indicators) > 1:
|
||||
results = []
|
||||
for ind in indicators:
|
||||
results.append(route_to_vendor("get_indicators", symbol, ind, curr_date, look_back_days))
|
||||
return "\n\n".join(results)
|
||||
return route_to_vendor("get_indicators", symbol, indicator.strip(), curr_date, look_back_days)
|
||||
|
|
@ -6,6 +6,19 @@ import os
|
|||
from .config import get_config
|
||||
|
||||
|
||||
def _clean_dataframe(data: pd.DataFrame) -> pd.DataFrame:
|
||||
"""Normalize a stock DataFrame for stockstats: parse dates, drop invalid rows, fill price gaps."""
|
||||
data["Date"] = pd.to_datetime(data["Date"], errors="coerce")
|
||||
data = data.dropna(subset=["Date"])
|
||||
|
||||
price_cols = [c for c in ["Open", "High", "Low", "Close", "Volume"] if c in data.columns]
|
||||
data[price_cols] = data[price_cols].apply(pd.to_numeric, errors="coerce")
|
||||
data = data.dropna(subset=["Close"])
|
||||
data[price_cols] = data[price_cols].ffill().bfill()
|
||||
|
||||
return data
|
||||
|
||||
|
||||
class StockstatsUtils:
|
||||
@staticmethod
|
||||
def get_stock_stats(
|
||||
|
|
@ -36,8 +49,7 @@ class StockstatsUtils:
|
|||
)
|
||||
|
||||
if os.path.exists(data_file):
|
||||
data = pd.read_csv(data_file)
|
||||
data["Date"] = pd.to_datetime(data["Date"])
|
||||
data = pd.read_csv(data_file, on_bad_lines="skip")
|
||||
else:
|
||||
data = yf.download(
|
||||
symbol,
|
||||
|
|
@ -50,6 +62,7 @@ class StockstatsUtils:
|
|||
data = data.reset_index()
|
||||
data.to_csv(data_file, index=False)
|
||||
|
||||
data = _clean_dataframe(data)
|
||||
df = wrap(data)
|
||||
df["Date"] = df["Date"].dt.strftime("%Y-%m-%d")
|
||||
curr_date_str = curr_date_dt.strftime("%Y-%m-%d")
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ from datetime import datetime
|
|||
from dateutil.relativedelta import relativedelta
|
||||
import yfinance as yf
|
||||
import os
|
||||
from .stockstats_utils import StockstatsUtils
|
||||
from .stockstats_utils import StockstatsUtils, _clean_dataframe
|
||||
|
||||
def get_YFin_data_online(
|
||||
symbol: Annotated[str, "ticker symbol of the company"],
|
||||
|
|
@ -209,9 +209,9 @@ def _get_stock_stats_bulk(
|
|||
os.path.join(
|
||||
config.get("data_cache_dir", "data"),
|
||||
f"{symbol}-YFin-data-2015-01-01-2025-03-25.csv",
|
||||
),
|
||||
on_bad_lines="skip",
|
||||
)
|
||||
)
|
||||
df = wrap(data)
|
||||
except FileNotFoundError:
|
||||
raise Exception("Stockstats fail: Yahoo Finance data not fetched yet!")
|
||||
else:
|
||||
|
|
@ -232,8 +232,7 @@ def _get_stock_stats_bulk(
|
|||
)
|
||||
|
||||
if os.path.exists(data_file):
|
||||
data = pd.read_csv(data_file)
|
||||
data["Date"] = pd.to_datetime(data["Date"])
|
||||
data = pd.read_csv(data_file, on_bad_lines="skip")
|
||||
else:
|
||||
data = yf.download(
|
||||
symbol,
|
||||
|
|
@ -246,6 +245,7 @@ def _get_stock_stats_bulk(
|
|||
data = data.reset_index()
|
||||
data.to_csv(data_file, index=False)
|
||||
|
||||
data = _clean_dataframe(data)
|
||||
df = wrap(data)
|
||||
df["Date"] = df["Date"].dt.strftime("%Y-%m-%d")
|
||||
|
||||
|
|
|
|||
|
|
@ -24,14 +24,26 @@ class Propagator:
|
|||
"company_of_interest": company_name,
|
||||
"trade_date": str(trade_date),
|
||||
"investment_debate_state": InvestDebateState(
|
||||
{"history": "", "current_response": "", "count": 0}
|
||||
{
|
||||
"bull_history": "",
|
||||
"bear_history": "",
|
||||
"history": "",
|
||||
"current_response": "",
|
||||
"judge_decision": "",
|
||||
"count": 0,
|
||||
}
|
||||
),
|
||||
"risk_debate_state": RiskDebateState(
|
||||
{
|
||||
"aggressive_history": "",
|
||||
"conservative_history": "",
|
||||
"neutral_history": "",
|
||||
"history": "",
|
||||
"latest_speaker": "",
|
||||
"current_aggressive_response": "",
|
||||
"current_conservative_response": "",
|
||||
"current_neutral_response": "",
|
||||
"judge_decision": "",
|
||||
"count": 0,
|
||||
}
|
||||
),
|
||||
|
|
|
|||
|
|
@ -326,6 +326,7 @@ class TradingAgentsGraph:
|
|||
with open(
|
||||
f"eval_results/{self.ticker}/TradingAgentsStrategy_logs/full_states_log_{trade_date}.json",
|
||||
"w",
|
||||
encoding="utf-8",
|
||||
) as f:
|
||||
json.dump(self.log_states_dict, f, indent=4)
|
||||
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ class AnthropicClient(BaseLLMClient):
|
|||
"""Return configured ChatAnthropic instance."""
|
||||
llm_kwargs = {"model": self.model}
|
||||
|
||||
for key in ("timeout", "max_retries", "api_key", "max_tokens", "callbacks"):
|
||||
for key in ("timeout", "max_retries", "api_key", "max_tokens", "callbacks", "http_client", "http_async_client"):
|
||||
if key in self.kwargs:
|
||||
llm_kwargs[key] = self.kwargs[key]
|
||||
|
||||
|
|
|
|||
|
|
@ -19,6 +19,12 @@ def create_llm_client(
|
|||
model: Model name/identifier
|
||||
base_url: Optional base URL for API endpoint
|
||||
**kwargs: Additional provider-specific arguments
|
||||
- http_client: Custom httpx.Client for SSL proxy or certificate customization
|
||||
- http_async_client: Custom httpx.AsyncClient for async operations
|
||||
- timeout: Request timeout in seconds
|
||||
- max_retries: Maximum retry attempts
|
||||
- api_key: API key for the provider
|
||||
- callbacks: LangChain callbacks
|
||||
|
||||
Returns:
|
||||
Configured BaseLLMClient instance
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ class GoogleClient(BaseLLMClient):
|
|||
"""Return configured ChatGoogleGenerativeAI instance."""
|
||||
llm_kwargs = {"model": self.model}
|
||||
|
||||
for key in ("timeout", "max_retries", "google_api_key", "callbacks"):
|
||||
for key in ("timeout", "max_retries", "google_api_key", "callbacks", "http_client", "http_async_client"):
|
||||
if key in self.kwargs:
|
||||
llm_kwargs[key] = self.kwargs[key]
|
||||
|
||||
|
|
|
|||
|
|
@ -8,25 +8,23 @@ from .validators import validate_model
|
|||
|
||||
|
||||
class UnifiedChatOpenAI(ChatOpenAI):
|
||||
"""ChatOpenAI subclass that strips incompatible params for certain models."""
|
||||
"""ChatOpenAI subclass that strips temperature/top_p for GPT-5 family models.
|
||||
|
||||
GPT-5 family models use reasoning natively. temperature/top_p are only
|
||||
accepted when reasoning.effort is 'none'; with any other effort level
|
||||
(or for older GPT-5/GPT-5-mini/GPT-5-nano which always reason) the API
|
||||
rejects these params. Langchain defaults temperature=0.7, so we must
|
||||
strip it to avoid errors.
|
||||
|
||||
Non-GPT-5 models (GPT-4.1, xAI, Ollama, etc.) are unaffected.
|
||||
"""
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
model = kwargs.get("model", "")
|
||||
if self._is_reasoning_model(model):
|
||||
if "gpt-5" in kwargs.get("model", "").lower():
|
||||
kwargs.pop("temperature", None)
|
||||
kwargs.pop("top_p", None)
|
||||
super().__init__(**kwargs)
|
||||
|
||||
@staticmethod
|
||||
def _is_reasoning_model(model: str) -> bool:
|
||||
"""Check if model is a reasoning model that doesn't support temperature."""
|
||||
model_lower = model.lower()
|
||||
return (
|
||||
model_lower.startswith("o1")
|
||||
or model_lower.startswith("o3")
|
||||
or "gpt-5" in model_lower
|
||||
)
|
||||
|
||||
|
||||
class OpenAIClient(BaseLLMClient):
|
||||
"""Client for OpenAI, Ollama, OpenRouter, and xAI providers."""
|
||||
|
|
@ -65,7 +63,7 @@ class OpenAIClient(BaseLLMClient):
|
|||
elif self.base_url:
|
||||
llm_kwargs["base_url"] = self.base_url
|
||||
|
||||
for key in ("timeout", "max_retries", "reasoning_effort", "api_key", "callbacks"):
|
||||
for key in ("timeout", "max_retries", "reasoning_effort", "api_key", "callbacks", "http_client", "http_async_client"):
|
||||
if key in self.kwargs:
|
||||
llm_kwargs[key] = self.kwargs[key]
|
||||
|
||||
|
|
|
|||
|
|
@ -6,59 +6,44 @@ Let LLM providers use their own defaults for unspecified params.
|
|||
|
||||
VALID_MODELS = {
|
||||
"openai": [
|
||||
# GPT-5 series (2025)
|
||||
# GPT-5 series
|
||||
"gpt-5.4-pro",
|
||||
"gpt-5.4",
|
||||
"gpt-5.2",
|
||||
"gpt-5.1",
|
||||
"gpt-5",
|
||||
"gpt-5-mini",
|
||||
"gpt-5-nano",
|
||||
# GPT-4.1 series (2025)
|
||||
# GPT-4.1 series
|
||||
"gpt-4.1",
|
||||
"gpt-4.1-mini",
|
||||
"gpt-4.1-nano",
|
||||
# o-series reasoning models
|
||||
"o4-mini",
|
||||
"o3",
|
||||
"o3-mini",
|
||||
"o1",
|
||||
"o1-preview",
|
||||
# GPT-4o series (legacy but still supported)
|
||||
"gpt-4o",
|
||||
"gpt-4o-mini",
|
||||
],
|
||||
"anthropic": [
|
||||
# Claude 4.5 series (2025)
|
||||
# Claude 4.6 series (latest)
|
||||
"claude-opus-4-6",
|
||||
"claude-sonnet-4-6",
|
||||
# Claude 4.5 series
|
||||
"claude-opus-4-5",
|
||||
"claude-sonnet-4-5",
|
||||
"claude-haiku-4-5",
|
||||
# Claude 4.x series
|
||||
"claude-opus-4-1-20250805",
|
||||
"claude-sonnet-4-20250514",
|
||||
# Claude 3.7 series
|
||||
"claude-3-7-sonnet-20250219",
|
||||
# Claude 3.5 series (legacy)
|
||||
"claude-3-5-haiku-20241022",
|
||||
"claude-3-5-sonnet-20241022",
|
||||
],
|
||||
"google": [
|
||||
# Gemini 3.1 series (preview)
|
||||
"gemini-3.1-pro-preview",
|
||||
"gemini-3.1-flash-lite-preview",
|
||||
# Gemini 3 series (preview)
|
||||
"gemini-3-pro-preview",
|
||||
"gemini-3-flash-preview",
|
||||
# Gemini 2.5 series
|
||||
"gemini-2.5-pro",
|
||||
"gemini-2.5-flash",
|
||||
"gemini-2.5-flash-lite",
|
||||
# Gemini 2.0 series
|
||||
"gemini-2.0-flash",
|
||||
"gemini-2.0-flash-lite",
|
||||
],
|
||||
"xai": [
|
||||
# Grok 4.1 series
|
||||
"grok-4-1-fast",
|
||||
"grok-4-1-fast-reasoning",
|
||||
"grok-4-1-fast-non-reasoning",
|
||||
# Grok 4 series
|
||||
"grok-4",
|
||||
"grok-4-0709",
|
||||
"grok-4-fast-reasoning",
|
||||
"grok-4-fast-non-reasoning",
|
||||
|
|
|
|||
Loading…
Reference in New Issue