From dabec7efc90ff4dcda129166235f703fea159b60 Mon Sep 17 00:00:00 2001 From: nwhco Date: Wed, 5 Aug 2026 12:01:28 +0000 Subject: [PATCH] feat: update default model to gemini-3.6-flash-high, integrate NewHorizon provider, and simplify agent guardrails --- .env.example | 11 ++++++----- Dockerfile | 4 ++++ config/development.env | 7 +++++-- config/models.yaml | 12 +++++++++++- config/production.env | 6 +++++- docker-compose.yml | 5 +++++ src/agents/base_agent.py | 2 +- src/core/config.py | 6 ++++-- src/core/settings.py | 6 ++++-- src/models/factory.py | 13 +++++++++---- tests/unit/test_model_factory.py | 18 ++++++++++++++++++ 11 files changed, 72 insertions(+), 18 deletions(-) create mode 100644 tests/unit/test_model_factory.py diff --git a/.env.example b/.env.example index e8cf0fc..6b6b95a 100644 --- a/.env.example +++ b/.env.example @@ -1,4 +1,4 @@ -# Environment Variables Template +# Environment Variables Template # Copy this file to .env and fill in your actual values # Application Settings @@ -6,10 +6,11 @@ DEBUG_MODE=true HOST=0.0.0.0 PORT=8081 -# Model Settings (choose one) -MODEL_ID=deepseek-ai/deepseek-v3.1 -API_URL=https://gpt.nwhco.ir -MEGALLM_API_KEY=your_megallm_api_key_here +# Model Settings +MODEL_ID=gemini-3.6-flash-high +API_URL=http://ai.newhorizonco.uk/v1 +NEW_HORIZON_BASE_URL=http://ai.newhorizonco.uk/v1 +NEW_HORIZON_API_KEY=hZwAGW4H8v87Ol8tXvqEEY # OPENROUTER_API_KEY=your_openrouter_api_key_here # Database Settings diff --git a/Dockerfile b/Dockerfile index d47b899..df3e753 100644 --- a/Dockerfile +++ b/Dockerfile @@ -6,6 +6,10 @@ ENV PYTHONUNBUFFERED=1 ENV PYTHONPATH=/app # Setting pip timeout globally via environment variable is often more reliable ENV PIP_DEFAULT_TIMEOUT=1000 +ENV MODEL_ID=gemini-3.6-flash-high +ENV API_URL=http://ai.newhorizonco.uk/v1 +ENV NEW_HORIZON_BASE_URL=http://ai.newhorizonco.uk/v1 +ENV NEW_HORIZON_API_KEY=hZwAGW4H8v87Ol8tXvqEEY WORKDIR /app diff --git a/config/development.env b/config/development.env index 0fc1154..7b68792 100644 --- a/config/development.env +++ b/config/development.env @@ -6,8 +6,11 @@ HOST=0.0.0.0 PORT=8081 # Model Settings -MODEL_ID=deepseek-ai/deepseek-v3.1 -API_URL=https://gpt.nwhco.ir +MODEL_ID=gemini-3.6-flash-high +API_URL=http://ai.newhorizonco.uk/v1 +NEW_HORIZON_BASE_URL=http://ai.newhorizonco.uk/v1 +NEW_HORIZON_API_KEY=hZwAGW4H8v87Ol8tXvqEEY +OPENAI_API_KEY=hZwAGW4H8v87Ol8tXvqEEY OPENROUTER_API_KEY=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 MEGALLM_API_KEY=sk-mega-d124420e7b96640569860ec6dee778a41c10a67356380eedfba5c7a2024db3c3 diff --git a/config/models.yaml b/config/models.yaml index 1ab472a..067bede 100644 --- a/config/models.yaml +++ b/config/models.yaml @@ -2,9 +2,19 @@ models: # The "Master Switch" - default: deepseek_r1 + default: gemini_flash providers: + # Provider: NewHorizon (OpenAI-Like API) + openai_like: + api_key: ${NEW_HORIZON_API_KEY} + base_url: ${NEW_HORIZON_BASE_URL} + models: + gemini_flash: + id: "gemini-3.6-flash-high" + temperature: 0.7 + max_tokens: 4096 + # Provider: OpenRouter openrouter: api_key: ${OPENROUTER_API_KEY} diff --git a/config/production.env b/config/production.env index 0e03a59..92c32c1 100644 --- a/config/production.env +++ b/config/production.env @@ -7,10 +7,14 @@ PORT=8081 # ---------------- Model Settings ---------------- # BASE URLS -API_URL=https://gpt.nwhco.ir +MODEL_ID=gemini-3.6-flash-high +API_URL=http://ai.newhorizonco.uk/v1 +NEW_HORIZON_BASE_URL=http://ai.newhorizonco.uk/v1 OPENROUTER_BASE_URL=https://openrouter.ai/api/v1 # API KEYS +NEW_HORIZON_API_KEY=hZwAGW4H8v87Ol8tXvqEEY +OPENAI_API_KEY=hZwAGW4H8v87Ol8tXvqEEY OPENROUTER_API_KEY=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 MEGALLM_API_KEY=sk-mega-d124420e7b96640569860ec6dee778a41c10a67356380eedfba5c7a2024db3c3 diff --git a/docker-compose.yml b/docker-compose.yml index 4d25343..585fb0d 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -9,6 +9,11 @@ services: container_name: imam-reza-agent env_file: - config/production.env + environment: + - MODEL_ID=${MODEL_ID:-gemini-3.6-flash-high} + - API_URL=${API_URL:-http://ai.newhorizonco.uk/v1} + - NEW_HORIZON_BASE_URL=${NEW_HORIZON_BASE_URL:-http://ai.newhorizonco.uk/v1} + - NEW_HORIZON_API_KEY=${NEW_HORIZON_API_KEY:-hZwAGW4H8v87Ol8tXvqEEY} ports: - "9005:8081" restart: unless-stopped diff --git a/src/agents/base_agent.py b/src/agents/base_agent.py index 6e905c4..4ab88ff 100644 --- a/src/agents/base_agent.py +++ b/src/agents/base_agent.py @@ -46,7 +46,7 @@ class IslamicScholarAgent: reasoning=False, knowledge=None, # since we get data with pre hooks we don't need to pass knowledge here debug_mode=False, - pre_hooks=[PromptInjectionGuardrail(),InputLimitGuardrail(),sync_config_hook,rag_injection_hook], + pre_hooks=[sync_config_hook, rag_injection_hook], culture_manager=self.culture_manager, add_culture_to_context=True, description=self._build_culture_description(), diff --git a/src/core/config.py b/src/core/config.py index 86c3da1..20c6833 100644 --- a/src/core/config.py +++ b/src/core/config.py @@ -10,8 +10,10 @@ class Settings(BaseSettings): """Application settings""" # Model settings - model_id: str = "deepseek-ai/deepseek-v3.1" - api_url: str = "https://gpt.nwhco.ir" + model_id: str = "gemini-3.6-flash-high" + api_url: str = "http://ai.newhorizonco.uk/v1" + new_horizon_base_url: str = "http://ai.newhorizonco.uk/v1" + new_horizon_api_key: Optional[str] = "hZwAGW4H8v87Ol8tXvqEEY" megallm_api_key: Optional[str] = None openrouter_api_key: Optional[str] = None diff --git a/src/core/settings.py b/src/core/settings.py index 9ca3804..5c52419 100644 --- a/src/core/settings.py +++ b/src/core/settings.py @@ -17,8 +17,10 @@ HOST = os.getenv("HOST", "0.0.0.0") PORT = int(os.getenv("PORT", "8081")) # Model settings -MODEL_ID = os.getenv("MODEL_ID", "deepseek-ai/deepseek-v3.1") -API_URL = os.getenv("API_URL", "https://gpt.nwhco.ir") +MODEL_ID = os.getenv("MODEL_ID", "gemini-3.6-flash-high") +API_URL = os.getenv("API_URL", "http://ai.newhorizonco.uk/v1") +NEW_HORIZON_BASE_URL = os.getenv("NEW_HORIZON_BASE_URL", "http://ai.newhorizonco.uk/v1") +NEW_HORIZON_API_KEY = os.getenv("NEW_HORIZON_API_KEY", "hZwAGW4H8v87Ol8tXvqEEY") MEGALLM_API_KEY = os.getenv("MEGALLM_API_KEY") OPENROUTER_API_KEY = os.getenv("OPENROUTER_API_KEY") diff --git a/src/models/factory.py b/src/models/factory.py index ffd0d94..29cbd8b 100644 --- a/src/models/factory.py +++ b/src/models/factory.py @@ -45,17 +45,23 @@ class ModelFactory: # Resolving Env Vars for Keys api_key_env = provider_data.get('api_key') - if api_key_env and api_key_env.startswith("${"): + if api_key_env and api_key_env.startswith("${") and api_key_env.endswith("}"): api_key = os.getenv(api_key_env[2:-1]) else: api_key = api_key_env base_url_env = provider_data.get('base_url') - if base_url_env and base_url_env.startswith("${"): + if base_url_env and base_url_env.startswith("${") and base_url_env.endswith("}"): base_url = os.getenv(base_url_env[2:-1]) else: base_url = base_url_env + # Fallbacks if environment variables are not set + if not api_key: + api_key = os.getenv("NEW_HORIZON_API_KEY") or os.getenv("OPENAI_API_KEY", "hZwAGW4H8v87Ol8tXvqEEY") + if not base_url: + base_url = os.getenv("NEW_HORIZON_BASE_URL") or os.getenv("API_URL", "http://ai.newhorizonco.uk/v1") + # 3. Instantiate the correct Class if provider_name == 'openai_like': return OpenAILike( @@ -65,8 +71,7 @@ class ModelFactory: max_tokens=model_config_data.get('max_tokens', 4096), collect_metrics_on_completion=True, default_headers={ - "Authorization": f"Bearer {api_key}", - "Content-Type": "application/json" + "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36" }, ) diff --git a/tests/unit/test_model_factory.py b/tests/unit/test_model_factory.py new file mode 100644 index 0000000..118f8d3 --- /dev/null +++ b/tests/unit/test_model_factory.py @@ -0,0 +1,18 @@ +""" +Unit tests for ModelFactory with new default model (gemini-3.6-flash-high) +""" +import pytest +from unittest.mock import patch, Mock +from src.models.factory import ModelFactory + +def test_model_factory_default(): + factory = ModelFactory() + model = factory.get_model() + # Check that default model loaded is gemini-3.6-flash-high + assert model.id == "gemini-3.6-flash-high" + assert model.base_url == "http://ai.newhorizonco.uk/v1" + +def test_model_factory_get_specific_model(): + factory = ModelFactory() + model = factory.get_model("gemini_flash") + assert model.id == "gemini-3.6-flash-high"