diff --git a/src/interfaze/_client.py b/src/interfaze/_client.py index 128ead9..e5e7768 100644 --- a/src/interfaze/_client.py +++ b/src/interfaze/_client.py @@ -1,7 +1,7 @@ from __future__ import annotations import os -from typing import Any, Dict, Optional +from typing import Any, Dict, Optional, Union from openai import AsyncOpenAI, OpenAI @@ -46,6 +46,14 @@ def _build_headers( return headers +# OpenAI() fills `organization` / `project` from OPENAI_ORG_ID / OPENAI_PROJECT_ID and sends them +# as OpenAI-Organization / OpenAI-Project headers. Those are OpenAI account ids, so keep them off +# Interfaze requests unless they were passed in explicitly. +def _drop_openai_env_ids(client: Union[OpenAI, AsyncOpenAI], kwargs: Dict[str, Any]) -> None: + client.organization = kwargs.get("organization") + client.project = kwargs.get("project") + + class Interfaze: def __init__( self, @@ -68,6 +76,7 @@ def __init__( ), **kwargs, ) + _drop_openai_env_ids(self.openai, kwargs) self.chat = Chat(self.openai) self.models = self.openai.models self.tasks = Tasks(self.chat.completions) @@ -95,6 +104,7 @@ def __init__( ), **kwargs, ) + _drop_openai_env_ids(self.openai, kwargs) self.chat = AsyncChat(self.openai) self.models = self.openai.models self.tasks = AsyncTasks(self.chat.completions) diff --git a/tests/test_chat.py b/tests/test_chat.py index c072e21..0e8b7ea 100644 --- a/tests/test_chat.py +++ b/tests/test_chat.py @@ -146,6 +146,33 @@ def test_default_headers_omit_control_flags_when_unset(): assert "x-admin-key" not in h +@respx.mock +def test_openai_org_and_project_env_not_sent(monkeypatch): + monkeypatch.setenv("OPENAI_ORG_ID", "org-from-env") + monkeypatch.setenv("OPENAI_PROJECT_ID", "proj_from_env") + route = mock_json(BASIC) + Interfaze(api_key="t").chat.completions.create(messages=[{"role": "user", "content": "x"}]) + h = last_headers(route) + assert "openai-organization" not in h and "openai-project" not in h + + asyncio.run( + AsyncInterfaze(api_key="t").chat.completions.create(messages=[{"role": "user", "content": "x"}]) + ) + h = last_headers(route) + assert "openai-organization" not in h and "openai-project" not in h + + +@respx.mock +def test_explicit_openai_org_and_project_still_sent(monkeypatch): + monkeypatch.setenv("OPENAI_ORG_ID", "org-from-env") + route = mock_json(BASIC) + Interfaze(api_key="t", organization="org-explicit", project="proj_explicit").chat.completions.create( + messages=[{"role": "user", "content": "x"}] + ) + h = last_headers(route) + assert h["openai-organization"] == "org-explicit" and h["openai-project"] == "proj_explicit" + + @respx.mock def test_per_request_extra_headers_override_client_default(): route = mock_json(BASIC)