Accept GOOGLE_API_KEY for local Gemini eval
This workspace uses GOOGLE_API_KEY as the canonical Google credential. Accept it ahead of the Gemini-specific aliases so the local evaluation harness can run without a separate GEMINI_API_KEY export. Validation: uv run python -m unittest tests.test_env_project tests.test_evaluate_search_quality and a one-shot keychain-backed resolution check.
This commit is contained in:
@@ -34,7 +34,8 @@ uv run python scripts/evaluate_search_quality.py \
|
|||||||
|
|
||||||
Gemini configuration:
|
Gemini configuration:
|
||||||
|
|
||||||
- set `GEMINI_API_KEY` to enable LLM judging
|
- preferred on this workspace: set `GOOGLE_API_KEY`
|
||||||
|
- also accepted: `GEMINI_API_KEY` or `GOOGLE_GENAI_API_KEY`
|
||||||
- optional: set `GEMINI_MODEL`
|
- optional: set `GEMINI_MODEL`
|
||||||
- default model is `gemini-3-pro-preview` for the direct Gemini API
|
- default model is `gemini-3-pro-preview` for the direct Gemini API
|
||||||
|
|
||||||
|
|||||||
@@ -276,6 +276,22 @@ def extract_gemini_text(payload: Dict[str, Any]) -> str:
|
|||||||
raise ValueError("Gemini response did not contain text")
|
raise ValueError("Gemini response did not contain text")
|
||||||
|
|
||||||
|
|
||||||
|
def resolve_google_judge_api_key(config: Dict[str, Any]) -> Optional[str]:
|
||||||
|
"""Resolve the local canonical Google API key name.
|
||||||
|
|
||||||
|
This workspace conventionally uses GOOGLE_API_KEY. We also accept the
|
||||||
|
more Gemini-specific aliases for portability.
|
||||||
|
"""
|
||||||
|
return (
|
||||||
|
os.environ.get("GOOGLE_API_KEY")
|
||||||
|
or config.get("GOOGLE_API_KEY")
|
||||||
|
or os.environ.get("GEMINI_API_KEY")
|
||||||
|
or config.get("GEMINI_API_KEY")
|
||||||
|
or os.environ.get("GOOGLE_GENAI_API_KEY")
|
||||||
|
or config.get("GOOGLE_GENAI_API_KEY")
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def call_gemini_judge(api_key: str, model: str, prompt: str) -> Dict[str, Any]:
|
def call_gemini_judge(api_key: str, model: str, prompt: str) -> Dict[str, Any]:
|
||||||
body = {
|
body = {
|
||||||
"contents": [{"parts": [{"text": prompt}]}],
|
"contents": [{"parts": [{"text": prompt}]}],
|
||||||
@@ -497,7 +513,7 @@ def main() -> int:
|
|||||||
|
|
||||||
judge_config = envlib.get_config()
|
judge_config = envlib.get_config()
|
||||||
judge_provider = args.judge_provider
|
judge_provider = args.judge_provider
|
||||||
gemini_api_key = judge_config.get("GEMINI_API_KEY")
|
gemini_api_key = resolve_google_judge_api_key(judge_config)
|
||||||
judge_model = args.judge_model or judge_config.get("GEMINI_MODEL") or DEFAULT_JUDGE_MODEL
|
judge_model = args.judge_model or judge_config.get("GEMINI_MODEL") or DEFAULT_JUDGE_MODEL
|
||||||
if judge_provider == "auto":
|
if judge_provider == "auto":
|
||||||
judge_provider = "gemini" if gemini_api_key else "none"
|
judge_provider = "gemini" if gemini_api_key else "none"
|
||||||
|
|||||||
@@ -243,7 +243,9 @@ def get_config() -> Dict[str, Any]:
|
|||||||
|
|
||||||
keys = [
|
keys = [
|
||||||
('XAI_API_KEY', None),
|
('XAI_API_KEY', None),
|
||||||
|
('GOOGLE_API_KEY', None),
|
||||||
('GEMINI_API_KEY', None),
|
('GEMINI_API_KEY', None),
|
||||||
|
('GOOGLE_GENAI_API_KEY', None),
|
||||||
('OPENROUTER_API_KEY', None),
|
('OPENROUTER_API_KEY', None),
|
||||||
('PARALLEL_API_KEY', None),
|
('PARALLEL_API_KEY', None),
|
||||||
('BRAVE_API_KEY', None),
|
('BRAVE_API_KEY', None),
|
||||||
|
|||||||
@@ -96,6 +96,21 @@ class TestConfigPrecedence(unittest.TestCase):
|
|||||||
self.assertEqual(config['GEMINI_API_KEY'], 'gem-key')
|
self.assertEqual(config['GEMINI_API_KEY'], 'gem-key')
|
||||||
self.assertEqual(config['GEMINI_MODEL'], 'gemini-3-pro-preview')
|
self.assertEqual(config['GEMINI_MODEL'], 'gemini-3-pro-preview')
|
||||||
|
|
||||||
|
def test_google_api_key_loads_from_project_env(self):
|
||||||
|
import tempfile
|
||||||
|
with tempfile.TemporaryDirectory() as tmpdir:
|
||||||
|
project_dir = Path(tmpdir) / ".claude"
|
||||||
|
project_dir.mkdir()
|
||||||
|
project_env = project_dir / "last30days.env"
|
||||||
|
project_env.write_text("GOOGLE_API_KEY=google-key\n")
|
||||||
|
|
||||||
|
with patch.object(Path, 'cwd', return_value=Path(tmpdir)), \
|
||||||
|
patch.object(env, 'CONFIG_FILE', None), \
|
||||||
|
patch.dict(os.environ, {}, clear=False):
|
||||||
|
os.environ.pop('GOOGLE_API_KEY', None)
|
||||||
|
config = env.get_config()
|
||||||
|
self.assertEqual(config['GOOGLE_API_KEY'], 'google-key')
|
||||||
|
|
||||||
|
|
||||||
class TestConfigSource(unittest.TestCase):
|
class TestConfigSource(unittest.TestCase):
|
||||||
"""Tests for _CONFIG_SOURCE tracking."""
|
"""Tests for _CONFIG_SOURCE tracking."""
|
||||||
|
|||||||
@@ -77,5 +77,25 @@ class TestPathWithoutNode(unittest.TestCase):
|
|||||||
self.assertEqual(filtered, "/usr/bin:/opt/homebrew/bin")
|
self.assertEqual(filtered, "/usr/bin:/opt/homebrew/bin")
|
||||||
|
|
||||||
|
|
||||||
|
class TestJudgeKeyResolution(unittest.TestCase):
|
||||||
|
def test_prefers_google_api_key(self):
|
||||||
|
config = {
|
||||||
|
"GOOGLE_API_KEY": "google-key",
|
||||||
|
"GEMINI_API_KEY": "gem-key",
|
||||||
|
"GOOGLE_GENAI_API_KEY": "genai-key",
|
||||||
|
}
|
||||||
|
self.assertEqual(evalsq.resolve_google_judge_api_key(config), "google-key")
|
||||||
|
|
||||||
|
def test_falls_back_to_gemini_aliases(self):
|
||||||
|
self.assertEqual(
|
||||||
|
evalsq.resolve_google_judge_api_key({"GEMINI_API_KEY": "gem-key"}),
|
||||||
|
"gem-key",
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
evalsq.resolve_google_judge_api_key({"GOOGLE_GENAI_API_KEY": "genai-key"}),
|
||||||
|
"genai-key",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|||||||
Reference in New Issue
Block a user