amd-gaia 0.14.3__py3-none-any.whl → 0.15.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {amd_gaia-0.14.3.dist-info → amd_gaia-0.15.1.dist-info}/METADATA +223 -223
- amd_gaia-0.15.1.dist-info/RECORD +178 -0
- {amd_gaia-0.14.3.dist-info → amd_gaia-0.15.1.dist-info}/entry_points.txt +1 -0
- {amd_gaia-0.14.3.dist-info → amd_gaia-0.15.1.dist-info}/licenses/LICENSE.md +20 -20
- gaia/__init__.py +29 -29
- gaia/agents/__init__.py +19 -19
- gaia/agents/base/__init__.py +9 -9
- gaia/agents/base/agent.py +2177 -2177
- gaia/agents/base/api_agent.py +120 -120
- gaia/agents/base/console.py +1841 -1841
- gaia/agents/base/errors.py +237 -237
- gaia/agents/base/mcp_agent.py +86 -86
- gaia/agents/base/tools.py +83 -83
- gaia/agents/blender/agent.py +556 -556
- gaia/agents/blender/agent_simple.py +133 -135
- gaia/agents/blender/app.py +211 -211
- gaia/agents/blender/app_simple.py +41 -41
- gaia/agents/blender/core/__init__.py +16 -16
- gaia/agents/blender/core/materials.py +506 -506
- gaia/agents/blender/core/objects.py +316 -316
- gaia/agents/blender/core/rendering.py +225 -225
- gaia/agents/blender/core/scene.py +220 -220
- gaia/agents/blender/core/view.py +146 -146
- gaia/agents/chat/__init__.py +9 -9
- gaia/agents/chat/agent.py +835 -835
- gaia/agents/chat/app.py +1058 -1058
- gaia/agents/chat/session.py +508 -508
- gaia/agents/chat/tools/__init__.py +15 -15
- gaia/agents/chat/tools/file_tools.py +96 -96
- gaia/agents/chat/tools/rag_tools.py +1729 -1729
- gaia/agents/chat/tools/shell_tools.py +436 -436
- gaia/agents/code/__init__.py +7 -7
- gaia/agents/code/agent.py +549 -549
- gaia/agents/code/cli.py +377 -0
- gaia/agents/code/models.py +135 -135
- gaia/agents/code/orchestration/__init__.py +24 -24
- gaia/agents/code/orchestration/checklist_executor.py +1763 -1763
- gaia/agents/code/orchestration/checklist_generator.py +713 -713
- gaia/agents/code/orchestration/factories/__init__.py +9 -9
- gaia/agents/code/orchestration/factories/base.py +63 -63
- gaia/agents/code/orchestration/factories/nextjs_factory.py +118 -118
- gaia/agents/code/orchestration/factories/python_factory.py +106 -106
- gaia/agents/code/orchestration/orchestrator.py +841 -841
- gaia/agents/code/orchestration/project_analyzer.py +391 -391
- gaia/agents/code/orchestration/steps/__init__.py +67 -67
- gaia/agents/code/orchestration/steps/base.py +188 -188
- gaia/agents/code/orchestration/steps/error_handler.py +314 -314
- gaia/agents/code/orchestration/steps/nextjs.py +828 -828
- gaia/agents/code/orchestration/steps/python.py +307 -307
- gaia/agents/code/orchestration/template_catalog.py +469 -469
- gaia/agents/code/orchestration/workflows/__init__.py +14 -14
- gaia/agents/code/orchestration/workflows/base.py +80 -80
- gaia/agents/code/orchestration/workflows/nextjs.py +186 -186
- gaia/agents/code/orchestration/workflows/python.py +94 -94
- gaia/agents/code/prompts/__init__.py +11 -11
- gaia/agents/code/prompts/base_prompt.py +77 -77
- gaia/agents/code/prompts/code_patterns.py +2036 -2036
- gaia/agents/code/prompts/nextjs_prompt.py +40 -40
- gaia/agents/code/prompts/python_prompt.py +109 -109
- gaia/agents/code/schema_inference.py +365 -365
- gaia/agents/code/system_prompt.py +41 -41
- gaia/agents/code/tools/__init__.py +42 -42
- gaia/agents/code/tools/cli_tools.py +1138 -1138
- gaia/agents/code/tools/code_formatting.py +319 -319
- gaia/agents/code/tools/code_tools.py +769 -769
- gaia/agents/code/tools/error_fixing.py +1347 -1347
- gaia/agents/code/tools/external_tools.py +180 -180
- gaia/agents/code/tools/file_io.py +845 -845
- gaia/agents/code/tools/prisma_tools.py +190 -190
- gaia/agents/code/tools/project_management.py +1016 -1016
- gaia/agents/code/tools/testing.py +321 -321
- gaia/agents/code/tools/typescript_tools.py +122 -122
- gaia/agents/code/tools/validation_parsing.py +461 -461
- gaia/agents/code/tools/validation_tools.py +806 -806
- gaia/agents/code/tools/web_dev_tools.py +1758 -1758
- gaia/agents/code/validators/__init__.py +16 -16
- gaia/agents/code/validators/antipattern_checker.py +241 -241
- gaia/agents/code/validators/ast_analyzer.py +197 -197
- gaia/agents/code/validators/requirements_validator.py +145 -145
- gaia/agents/code/validators/syntax_validator.py +171 -171
- gaia/agents/docker/__init__.py +7 -7
- gaia/agents/docker/agent.py +642 -642
- gaia/agents/emr/__init__.py +8 -8
- gaia/agents/emr/agent.py +1506 -1506
- gaia/agents/emr/cli.py +1322 -1322
- gaia/agents/emr/constants.py +475 -475
- gaia/agents/emr/dashboard/__init__.py +4 -4
- gaia/agents/emr/dashboard/server.py +1974 -1974
- gaia/agents/jira/__init__.py +11 -11
- gaia/agents/jira/agent.py +894 -894
- gaia/agents/jira/jql_templates.py +299 -299
- gaia/agents/routing/__init__.py +7 -7
- gaia/agents/routing/agent.py +567 -570
- gaia/agents/routing/system_prompt.py +75 -75
- gaia/agents/summarize/__init__.py +11 -0
- gaia/agents/summarize/agent.py +885 -0
- gaia/agents/summarize/prompts.py +129 -0
- gaia/api/__init__.py +23 -23
- gaia/api/agent_registry.py +238 -238
- gaia/api/app.py +305 -305
- gaia/api/openai_server.py +575 -575
- gaia/api/schemas.py +186 -186
- gaia/api/sse_handler.py +373 -373
- gaia/apps/__init__.py +4 -4
- gaia/apps/llm/__init__.py +6 -6
- gaia/apps/llm/app.py +173 -169
- gaia/apps/summarize/app.py +116 -633
- gaia/apps/summarize/html_viewer.py +133 -133
- gaia/apps/summarize/pdf_formatter.py +284 -284
- gaia/audio/__init__.py +2 -2
- gaia/audio/audio_client.py +439 -439
- gaia/audio/audio_recorder.py +269 -269
- gaia/audio/kokoro_tts.py +599 -599
- gaia/audio/whisper_asr.py +432 -432
- gaia/chat/__init__.py +16 -16
- gaia/chat/app.py +430 -430
- gaia/chat/prompts.py +522 -522
- gaia/chat/sdk.py +1228 -1225
- gaia/cli.py +5481 -5621
- gaia/database/__init__.py +10 -10
- gaia/database/agent.py +176 -176
- gaia/database/mixin.py +290 -290
- gaia/database/testing.py +64 -64
- gaia/eval/batch_experiment.py +2332 -2332
- gaia/eval/claude.py +542 -542
- gaia/eval/config.py +37 -37
- gaia/eval/email_generator.py +512 -512
- gaia/eval/eval.py +3179 -3179
- gaia/eval/groundtruth.py +1130 -1130
- gaia/eval/transcript_generator.py +582 -582
- gaia/eval/webapp/README.md +167 -167
- gaia/eval/webapp/package-lock.json +875 -875
- gaia/eval/webapp/package.json +20 -20
- gaia/eval/webapp/public/app.js +3402 -3402
- gaia/eval/webapp/public/index.html +87 -87
- gaia/eval/webapp/public/styles.css +3661 -3661
- gaia/eval/webapp/server.js +415 -415
- gaia/eval/webapp/test-setup.js +72 -72
- gaia/llm/__init__.py +9 -2
- gaia/llm/base_client.py +60 -0
- gaia/llm/exceptions.py +12 -0
- gaia/llm/factory.py +70 -0
- gaia/llm/lemonade_client.py +3236 -3221
- gaia/llm/lemonade_manager.py +294 -294
- gaia/llm/providers/__init__.py +9 -0
- gaia/llm/providers/claude.py +108 -0
- gaia/llm/providers/lemonade.py +120 -0
- gaia/llm/providers/openai_provider.py +79 -0
- gaia/llm/vlm_client.py +382 -382
- gaia/logger.py +189 -189
- gaia/mcp/agent_mcp_server.py +245 -245
- gaia/mcp/blender_mcp_client.py +138 -138
- gaia/mcp/blender_mcp_server.py +648 -648
- gaia/mcp/context7_cache.py +332 -332
- gaia/mcp/external_services.py +518 -518
- gaia/mcp/mcp_bridge.py +811 -550
- gaia/mcp/servers/__init__.py +6 -6
- gaia/mcp/servers/docker_mcp.py +83 -83
- gaia/perf_analysis.py +361 -0
- gaia/rag/__init__.py +10 -10
- gaia/rag/app.py +293 -293
- gaia/rag/demo.py +304 -304
- gaia/rag/pdf_utils.py +235 -235
- gaia/rag/sdk.py +2194 -2194
- gaia/security.py +163 -163
- gaia/talk/app.py +289 -289
- gaia/talk/sdk.py +538 -538
- gaia/testing/__init__.py +87 -87
- gaia/testing/assertions.py +330 -330
- gaia/testing/fixtures.py +333 -333
- gaia/testing/mocks.py +493 -493
- gaia/util.py +46 -46
- gaia/utils/__init__.py +33 -33
- gaia/utils/file_watcher.py +675 -675
- gaia/utils/parsing.py +223 -223
- gaia/version.py +100 -100
- amd_gaia-0.14.3.dist-info/RECORD +0 -168
- gaia/agents/code/app.py +0 -266
- gaia/llm/llm_client.py +0 -729
- {amd_gaia-0.14.3.dist-info → amd_gaia-0.15.1.dist-info}/WHEEL +0 -0
- {amd_gaia-0.14.3.dist-info → amd_gaia-0.15.1.dist-info}/top_level.txt +0 -0
gaia/eval/webapp/test-setup.js
CHANGED
|
@@ -1,73 +1,73 @@
|
|
|
1
|
-
// Copyright(C) 2025-2026 Advanced Micro Devices, Inc. All rights reserved.
|
|
2
|
-
// SPDX-License-Identifier: MIT
|
|
3
|
-
|
|
4
|
-
const fs = require('fs');
|
|
5
|
-
const path = require('path');
|
|
6
|
-
|
|
7
|
-
console.log('🧪 Testing Gaia Evaluation Visualizer Setup...\n');
|
|
8
|
-
|
|
9
|
-
// Test 1: Check required files exist
|
|
10
|
-
const requiredFiles = [
|
|
11
|
-
'package.json',
|
|
12
|
-
'server.js',
|
|
13
|
-
'public/index.html',
|
|
14
|
-
'public/styles.css',
|
|
15
|
-
'public/app.js',
|
|
16
|
-
'README.md'
|
|
17
|
-
];
|
|
18
|
-
|
|
19
|
-
let allFilesExist = true;
|
|
20
|
-
requiredFiles.forEach(file => {
|
|
21
|
-
const filePath = path.join(__dirname, file);
|
|
22
|
-
if (fs.existsSync(filePath)) {
|
|
23
|
-
console.log(`✅ ${file} exists`);
|
|
24
|
-
} else {
|
|
25
|
-
console.log(`❌ ${file} missing`);
|
|
26
|
-
allFilesExist = false;
|
|
27
|
-
}
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
// Test 2: Check data directories
|
|
31
|
-
const experimentsPath = path.join(__dirname, '../../../..', 'experiments');
|
|
32
|
-
const evaluationsPath = path.join(__dirname, '../../../..', 'evaluation');
|
|
33
|
-
|
|
34
|
-
console.log('\n📁 Checking data directories:');
|
|
35
|
-
if (fs.existsSync(experimentsPath)) {
|
|
36
|
-
const experimentFiles = fs.readdirSync(experimentsPath).filter(f => f.endsWith('.experiment.json'));
|
|
37
|
-
console.log(`✅ Experiments directory: ${experimentFiles.length} files found`);
|
|
38
|
-
experimentFiles.forEach(file => console.log(` - ${file}`));
|
|
39
|
-
} else {
|
|
40
|
-
console.log(`❌ Experiments directory not found: ${experimentsPath}`);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
if (fs.existsSync(evaluationsPath)) {
|
|
44
|
-
const evaluationFiles = fs.readdirSync(evaluationsPath).filter(f => f.endsWith('.experiment.eval.json'));
|
|
45
|
-
console.log(`✅ Evaluations directory: ${evaluationFiles.length} files found`);
|
|
46
|
-
evaluationFiles.forEach(file => console.log(` - ${file}`));
|
|
47
|
-
} else {
|
|
48
|
-
console.log(`❌ Evaluations directory not found: ${evaluationsPath}`);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
// Test 3: Check package.json
|
|
52
|
-
console.log('\n📦 Checking package.json:');
|
|
53
|
-
try {
|
|
54
|
-
const packageJson = JSON.parse(fs.readFileSync(path.join(__dirname, 'package.json'), 'utf8'));
|
|
55
|
-
console.log(`✅ Package name: ${packageJson.name}`);
|
|
56
|
-
console.log(`✅ Version: ${packageJson.version}`);
|
|
57
|
-
console.log(`✅ Dependencies: ${Object.keys(packageJson.dependencies || {}).join(', ')}`);
|
|
58
|
-
} catch (error) {
|
|
59
|
-
console.log(`❌ Error reading package.json: ${error.message}`);
|
|
60
|
-
allFilesExist = false;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
console.log('\n🚀 Next Steps:');
|
|
64
|
-
if (allFilesExist) {
|
|
65
|
-
console.log('1. Run: npm install');
|
|
66
|
-
console.log('2. Run: npm start');
|
|
67
|
-
console.log('3. Open: http://localhost:3000');
|
|
68
|
-
console.log('\n✨ Setup looks good! Ready to visualize evaluation results.');
|
|
69
|
-
} else {
|
|
70
|
-
console.log('❌ Some files are missing. Please check the setup.');
|
|
71
|
-
}
|
|
72
|
-
|
|
1
|
+
// Copyright(C) 2025-2026 Advanced Micro Devices, Inc. All rights reserved.
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
|
|
4
|
+
const fs = require('fs');
|
|
5
|
+
const path = require('path');
|
|
6
|
+
|
|
7
|
+
console.log('🧪 Testing Gaia Evaluation Visualizer Setup...\n');
|
|
8
|
+
|
|
9
|
+
// Test 1: Check required files exist
|
|
10
|
+
const requiredFiles = [
|
|
11
|
+
'package.json',
|
|
12
|
+
'server.js',
|
|
13
|
+
'public/index.html',
|
|
14
|
+
'public/styles.css',
|
|
15
|
+
'public/app.js',
|
|
16
|
+
'README.md'
|
|
17
|
+
];
|
|
18
|
+
|
|
19
|
+
let allFilesExist = true;
|
|
20
|
+
requiredFiles.forEach(file => {
|
|
21
|
+
const filePath = path.join(__dirname, file);
|
|
22
|
+
if (fs.existsSync(filePath)) {
|
|
23
|
+
console.log(`✅ ${file} exists`);
|
|
24
|
+
} else {
|
|
25
|
+
console.log(`❌ ${file} missing`);
|
|
26
|
+
allFilesExist = false;
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
// Test 2: Check data directories
|
|
31
|
+
const experimentsPath = path.join(__dirname, '../../../..', 'experiments');
|
|
32
|
+
const evaluationsPath = path.join(__dirname, '../../../..', 'evaluation');
|
|
33
|
+
|
|
34
|
+
console.log('\n📁 Checking data directories:');
|
|
35
|
+
if (fs.existsSync(experimentsPath)) {
|
|
36
|
+
const experimentFiles = fs.readdirSync(experimentsPath).filter(f => f.endsWith('.experiment.json'));
|
|
37
|
+
console.log(`✅ Experiments directory: ${experimentFiles.length} files found`);
|
|
38
|
+
experimentFiles.forEach(file => console.log(` - ${file}`));
|
|
39
|
+
} else {
|
|
40
|
+
console.log(`❌ Experiments directory not found: ${experimentsPath}`);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (fs.existsSync(evaluationsPath)) {
|
|
44
|
+
const evaluationFiles = fs.readdirSync(evaluationsPath).filter(f => f.endsWith('.experiment.eval.json'));
|
|
45
|
+
console.log(`✅ Evaluations directory: ${evaluationFiles.length} files found`);
|
|
46
|
+
evaluationFiles.forEach(file => console.log(` - ${file}`));
|
|
47
|
+
} else {
|
|
48
|
+
console.log(`❌ Evaluations directory not found: ${evaluationsPath}`);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Test 3: Check package.json
|
|
52
|
+
console.log('\n📦 Checking package.json:');
|
|
53
|
+
try {
|
|
54
|
+
const packageJson = JSON.parse(fs.readFileSync(path.join(__dirname, 'package.json'), 'utf8'));
|
|
55
|
+
console.log(`✅ Package name: ${packageJson.name}`);
|
|
56
|
+
console.log(`✅ Version: ${packageJson.version}`);
|
|
57
|
+
console.log(`✅ Dependencies: ${Object.keys(packageJson.dependencies || {}).join(', ')}`);
|
|
58
|
+
} catch (error) {
|
|
59
|
+
console.log(`❌ Error reading package.json: ${error.message}`);
|
|
60
|
+
allFilesExist = false;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
console.log('\n🚀 Next Steps:');
|
|
64
|
+
if (allFilesExist) {
|
|
65
|
+
console.log('1. Run: npm install');
|
|
66
|
+
console.log('2. Run: npm start');
|
|
67
|
+
console.log('3. Open: http://localhost:3000');
|
|
68
|
+
console.log('\n✨ Setup looks good! Ready to visualize evaluation results.');
|
|
69
|
+
} else {
|
|
70
|
+
console.log('❌ Some files are missing. Please check the setup.');
|
|
71
|
+
}
|
|
72
|
+
|
|
73
73
|
console.log('\n📖 For detailed instructions, see README.md');
|
gaia/llm/__init__.py
CHANGED
|
@@ -1,2 +1,9 @@
|
|
|
1
|
-
# Copyright(C) 2025-2026 Advanced Micro Devices, Inc. All rights reserved.
|
|
2
|
-
# SPDX-License-Identifier: MIT
|
|
1
|
+
# Copyright(C) 2025-2026 Advanced Micro Devices, Inc. All rights reserved.
|
|
2
|
+
# SPDX-License-Identifier: MIT
|
|
3
|
+
"""LLM client package."""
|
|
4
|
+
|
|
5
|
+
from .base_client import LLMClient
|
|
6
|
+
from .exceptions import NotSupportedError
|
|
7
|
+
from .factory import create_client
|
|
8
|
+
|
|
9
|
+
__all__ = ["create_client", "LLMClient", "NotSupportedError"]
|
gaia/llm/base_client.py
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# Copyright(C) 2025-2026 Advanced Micro Devices, Inc. All rights reserved.
|
|
2
|
+
# SPDX-License-Identifier: MIT
|
|
3
|
+
"""Base LLM client interface."""
|
|
4
|
+
|
|
5
|
+
from abc import ABC, abstractmethod
|
|
6
|
+
from typing import Iterator, Union
|
|
7
|
+
|
|
8
|
+
from .exceptions import NotSupportedError
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class LLMClient(ABC):
|
|
12
|
+
"""
|
|
13
|
+
Unified LLM client interface.
|
|
14
|
+
|
|
15
|
+
Methods raise NotSupportedError if not available for this provider.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
@property
|
|
19
|
+
@abstractmethod
|
|
20
|
+
def provider_name(self) -> str:
|
|
21
|
+
"""Return the provider name for error messages."""
|
|
22
|
+
...
|
|
23
|
+
|
|
24
|
+
@abstractmethod
|
|
25
|
+
def generate(
|
|
26
|
+
self,
|
|
27
|
+
prompt: str,
|
|
28
|
+
model: str | None = None,
|
|
29
|
+
stream: bool = False,
|
|
30
|
+
**kwargs,
|
|
31
|
+
) -> Union[str, Iterator[str]]:
|
|
32
|
+
"""Generate text completion."""
|
|
33
|
+
...
|
|
34
|
+
|
|
35
|
+
@abstractmethod
|
|
36
|
+
def chat(
|
|
37
|
+
self,
|
|
38
|
+
messages: list[dict],
|
|
39
|
+
model: str | None = None,
|
|
40
|
+
stream: bool = False,
|
|
41
|
+
**kwargs,
|
|
42
|
+
) -> Union[str, Iterator[str]]:
|
|
43
|
+
"""Chat completion."""
|
|
44
|
+
...
|
|
45
|
+
|
|
46
|
+
# Optional - default raises NotSupportedError
|
|
47
|
+
def embed(self, texts: list[str], **kwargs) -> list[list[float]]:
|
|
48
|
+
raise NotSupportedError(self.provider_name, "embed")
|
|
49
|
+
|
|
50
|
+
def vision(self, images: list[bytes], prompt: str, **kwargs) -> str:
|
|
51
|
+
raise NotSupportedError(self.provider_name, "vision")
|
|
52
|
+
|
|
53
|
+
def get_performance_stats(self) -> dict:
|
|
54
|
+
raise NotSupportedError(self.provider_name, "get_performance_stats")
|
|
55
|
+
|
|
56
|
+
def load_model(self, model_name: str, **kwargs) -> None:
|
|
57
|
+
raise NotSupportedError(self.provider_name, "load_model")
|
|
58
|
+
|
|
59
|
+
def unload_model(self) -> None:
|
|
60
|
+
raise NotSupportedError(self.provider_name, "unload_model")
|
gaia/llm/exceptions.py
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# Copyright(C) 2025-2026 Advanced Micro Devices, Inc. All rights reserved.
|
|
2
|
+
# SPDX-License-Identifier: MIT
|
|
3
|
+
"""LLM client exceptions."""
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class NotSupportedError(Exception):
|
|
7
|
+
"""Raised when a provider doesn't support a method."""
|
|
8
|
+
|
|
9
|
+
def __init__(self, provider: str, method: str):
|
|
10
|
+
self.provider = provider
|
|
11
|
+
self.method = method
|
|
12
|
+
super().__init__(f"{provider} does not support {method}")
|
gaia/llm/factory.py
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# Copyright(C) 2025-2026 Advanced Micro Devices, Inc. All rights reserved.
|
|
2
|
+
# SPDX-License-Identifier: MIT
|
|
3
|
+
"""LLM client factory."""
|
|
4
|
+
|
|
5
|
+
from typing import Optional
|
|
6
|
+
|
|
7
|
+
from .base_client import LLMClient
|
|
8
|
+
|
|
9
|
+
_PROVIDERS: dict[str, str] = {
|
|
10
|
+
"lemonade": "gaia.llm.providers.lemonade.LemonadeProvider",
|
|
11
|
+
"openai": "gaia.llm.providers.openai_provider.OpenAIProvider",
|
|
12
|
+
"claude": "gaia.llm.providers.claude.ClaudeProvider",
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def create_client(
|
|
17
|
+
provider: Optional[str] = None,
|
|
18
|
+
use_claude: bool = False,
|
|
19
|
+
use_openai: bool = False,
|
|
20
|
+
**kwargs,
|
|
21
|
+
) -> LLMClient:
|
|
22
|
+
"""
|
|
23
|
+
Create an LLM client, auto-detecting provider from parameters.
|
|
24
|
+
|
|
25
|
+
Args:
|
|
26
|
+
provider: Explicit provider name ("lemonade", "openai", or "claude").
|
|
27
|
+
If not specified, auto-detected from use_claude/use_openai flags.
|
|
28
|
+
use_claude: If True, use Claude provider (ignored if provider is specified)
|
|
29
|
+
use_openai: If True, use OpenAI provider (ignored if provider is specified)
|
|
30
|
+
**kwargs: Provider-specific arguments (base_url, model, api_key, etc.)
|
|
31
|
+
|
|
32
|
+
Note:
|
|
33
|
+
The design using these flags maintains backward compatibility
|
|
34
|
+
while allowing explicit provider selection. If both use_claude and
|
|
35
|
+
use_openai are False and provider is not specified, the default
|
|
36
|
+
provider "lemonade" is used. This was deemed better than updating all
|
|
37
|
+
existing callers with conditional logic and multiple `create_client` calls.
|
|
38
|
+
|
|
39
|
+
Returns:
|
|
40
|
+
LLMClient instance for the specified or detected provider
|
|
41
|
+
|
|
42
|
+
Raises:
|
|
43
|
+
ValueError: If provider is not recognized or both use_claude and use_openai are True
|
|
44
|
+
"""
|
|
45
|
+
# Auto-detect provider from flags if not explicitly specified
|
|
46
|
+
if provider is None:
|
|
47
|
+
if use_claude and use_openai:
|
|
48
|
+
raise ValueError(
|
|
49
|
+
"Cannot specify both use_claude and use_openai. Please choose one."
|
|
50
|
+
)
|
|
51
|
+
elif use_claude:
|
|
52
|
+
provider = "claude"
|
|
53
|
+
elif use_openai:
|
|
54
|
+
provider = "openai"
|
|
55
|
+
else:
|
|
56
|
+
provider = "lemonade"
|
|
57
|
+
|
|
58
|
+
provider_lower = provider.lower()
|
|
59
|
+
|
|
60
|
+
if provider_lower not in _PROVIDERS:
|
|
61
|
+
available = ", ".join(_PROVIDERS.keys())
|
|
62
|
+
raise ValueError(f"Unknown provider: {provider}. Available: {available}")
|
|
63
|
+
|
|
64
|
+
import importlib
|
|
65
|
+
|
|
66
|
+
module_path, class_name = _PROVIDERS[provider_lower].rsplit(".", 1)
|
|
67
|
+
module = importlib.import_module(module_path)
|
|
68
|
+
provider_class = getattr(module, class_name)
|
|
69
|
+
|
|
70
|
+
return provider_class(**kwargs)
|