yera 0.1.1__py3-none-any.whl → 0.2.0__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.
- infra_mvp/base_client.py +29 -0
- infra_mvp/base_server.py +68 -0
- infra_mvp/monitoring/__init__.py +15 -0
- infra_mvp/monitoring/metrics.py +185 -0
- infra_mvp/stream/README.md +56 -0
- infra_mvp/stream/__init__.py +14 -0
- infra_mvp/stream/__main__.py +101 -0
- infra_mvp/stream/agents/demos/financial/chart_additions_plan.md +170 -0
- infra_mvp/stream/agents/demos/financial/portfolio_assistant_stream.json +1571 -0
- infra_mvp/stream/agents/reference/blocks/action.json +170 -0
- infra_mvp/stream/agents/reference/blocks/button.json +66 -0
- infra_mvp/stream/agents/reference/blocks/date.json +65 -0
- infra_mvp/stream/agents/reference/blocks/input_prompt.json +94 -0
- infra_mvp/stream/agents/reference/blocks/layout.json +288 -0
- infra_mvp/stream/agents/reference/blocks/markdown.json +344 -0
- infra_mvp/stream/agents/reference/blocks/slider.json +67 -0
- infra_mvp/stream/agents/reference/blocks/spinner.json +110 -0
- infra_mvp/stream/agents/reference/blocks/table.json +56 -0
- infra_mvp/stream/agents/reference/chat_dynamics/branching_test_stream.json +145 -0
- infra_mvp/stream/app.py +49 -0
- infra_mvp/stream/container.py +112 -0
- infra_mvp/stream/schemas/__init__.py +16 -0
- infra_mvp/stream/schemas/agent.py +24 -0
- infra_mvp/stream/schemas/interaction.py +28 -0
- infra_mvp/stream/schemas/session.py +30 -0
- infra_mvp/stream/server.py +321 -0
- infra_mvp/stream/services/__init__.py +12 -0
- infra_mvp/stream/services/agent_service.py +40 -0
- infra_mvp/stream/services/event_converter.py +83 -0
- infra_mvp/stream/services/session_service.py +247 -0
- yera/__init__.py +50 -1
- yera/agents/__init__.py +2 -0
- yera/agents/context.py +41 -0
- yera/agents/dataclasses.py +69 -0
- yera/agents/decorator.py +207 -0
- yera/agents/discovery.py +124 -0
- yera/agents/typing/__init__.py +0 -0
- yera/agents/typing/coerce.py +408 -0
- yera/agents/typing/utils.py +19 -0
- yera/agents/typing/validate.py +206 -0
- yera/cli.py +377 -0
- yera/config/__init__.py +1 -0
- yera/config/config_utils.py +164 -0
- yera/config/function_config.py +55 -0
- yera/config/logging.py +18 -0
- yera/config/tool_config.py +8 -0
- yera/config2/__init__.py +8 -0
- yera/config2/dataclasses.py +534 -0
- yera/config2/keyring.py +270 -0
- yera/config2/paths.py +28 -0
- yera/config2/read.py +113 -0
- yera/config2/setup.py +109 -0
- yera/config2/setup_handlers/__init__.py +1 -0
- yera/config2/setup_handlers/anthropic.py +126 -0
- yera/config2/setup_handlers/azure.py +236 -0
- yera/config2/setup_handlers/base.py +125 -0
- yera/config2/setup_handlers/llama_cpp.py +205 -0
- yera/config2/setup_handlers/ollama.py +157 -0
- yera/config2/setup_handlers/openai.py +137 -0
- yera/config2/write.py +87 -0
- yera/dsl/__init__.py +0 -0
- yera/dsl/functions.py +94 -0
- yera/dsl/struct.py +20 -0
- yera/dsl/workspace.py +79 -0
- yera/events/__init__.py +57 -0
- yera/events/blocks/__init__.py +68 -0
- yera/events/blocks/action.py +57 -0
- yera/events/blocks/bar_chart.py +92 -0
- yera/events/blocks/base/__init__.py +20 -0
- yera/events/blocks/base/base.py +166 -0
- yera/events/blocks/base/chart.py +288 -0
- yera/events/blocks/base/layout.py +111 -0
- yera/events/blocks/buttons.py +37 -0
- yera/events/blocks/columns.py +26 -0
- yera/events/blocks/container.py +24 -0
- yera/events/blocks/date_picker.py +50 -0
- yera/events/blocks/exit.py +39 -0
- yera/events/blocks/form.py +24 -0
- yera/events/blocks/input_echo.py +22 -0
- yera/events/blocks/input_request.py +31 -0
- yera/events/blocks/line_chart.py +97 -0
- yera/events/blocks/markdown.py +67 -0
- yera/events/blocks/slider.py +54 -0
- yera/events/blocks/spinner.py +55 -0
- yera/events/blocks/system_prompt.py +22 -0
- yera/events/blocks/table.py +291 -0
- yera/events/models/__init__.py +39 -0
- yera/events/models/block_data.py +112 -0
- yera/events/models/in_event.py +7 -0
- yera/events/models/out_event.py +75 -0
- yera/events/runtime.py +187 -0
- yera/events/stream.py +91 -0
- yera/models/__init__.py +0 -0
- yera/models/data_classes.py +20 -0
- yera/models/llm_atlas_proxy.py +44 -0
- yera/models/llm_context.py +99 -0
- yera/models/llm_interfaces/__init__.py +0 -0
- yera/models/llm_interfaces/anthropic.py +153 -0
- yera/models/llm_interfaces/aws_bedrock.py +14 -0
- yera/models/llm_interfaces/azure_openai.py +143 -0
- yera/models/llm_interfaces/base.py +26 -0
- yera/models/llm_interfaces/interface_registry.py +74 -0
- yera/models/llm_interfaces/llama_cpp.py +136 -0
- yera/models/llm_interfaces/mock.py +29 -0
- yera/models/llm_interfaces/ollama_interface.py +118 -0
- yera/models/llm_interfaces/open_ai.py +150 -0
- yera/models/llm_workspace.py +19 -0
- yera/models/model_atlas.py +139 -0
- yera/models/model_definition.py +38 -0
- yera/models/model_factory.py +33 -0
- yera/opaque/__init__.py +9 -0
- yera/opaque/base.py +20 -0
- yera/opaque/decorator.py +8 -0
- yera/opaque/markdown.py +57 -0
- yera/opaque/opaque_function.py +25 -0
- yera/tools/__init__.py +29 -0
- yera/tools/atlas_tool.py +20 -0
- yera/tools/base.py +24 -0
- yera/tools/decorated_tool.py +18 -0
- yera/tools/decorator.py +35 -0
- yera/tools/tool_atlas.py +51 -0
- yera/tools/tool_utils.py +361 -0
- yera/ui/dist/404.html +1 -0
- yera/ui/dist/__next.__PAGE__.txt +10 -0
- yera/ui/dist/__next._full.txt +23 -0
- yera/ui/dist/__next._head.txt +6 -0
- yera/ui/dist/__next._index.txt +5 -0
- yera/ui/dist/__next._tree.txt +7 -0
- yera/ui/dist/_next/static/chunks/4c4688e1ff21ad98.js +1 -0
- yera/ui/dist/_next/static/chunks/652cd53c27924d50.js +4 -0
- yera/ui/dist/_next/static/chunks/786d2107b51e8499.css +1 -0
- yera/ui/dist/_next/static/chunks/7de9141b1af425c3.js +1 -0
- yera/ui/dist/_next/static/chunks/87ef65064d3524c1.js +2 -0
- yera/ui/dist/_next/static/chunks/a6dad97d9634a72d.js +1 -0
- yera/ui/dist/_next/static/chunks/a6dad97d9634a72d.js.map +1 -0
- yera/ui/dist/_next/static/chunks/c4c79d5d0b280aeb.js +1 -0
- yera/ui/dist/_next/static/chunks/dc2d2a247505d66f.css +5 -0
- yera/ui/dist/_next/static/chunks/f773f714b55ec620.js +37 -0
- yera/ui/dist/_next/static/chunks/turbopack-98b3031e1b1dbc33.js +4 -0
- yera/ui/dist/_next/static/lnhYLzJ1-a5EfNbW1uFF6/_buildManifest.js +11 -0
- yera/ui/dist/_next/static/lnhYLzJ1-a5EfNbW1uFF6/_clientMiddlewareManifest.json +1 -0
- yera/ui/dist/_next/static/lnhYLzJ1-a5EfNbW1uFF6/_ssgManifest.js +1 -0
- yera/ui/dist/_next/static/media/14e23f9b59180572-s.9c448f3c.woff2 +0 -0
- yera/ui/dist/_next/static/media/2a65768255d6b625-s.p.d19752fb.woff2 +0 -0
- yera/ui/dist/_next/static/media/2b2eb4836d2dad95-s.f36de3af.woff2 +0 -0
- yera/ui/dist/_next/static/media/31183d9fd602dc89-s.c4ff9b73.woff2 +0 -0
- yera/ui/dist/_next/static/media/3fcb63a1ac6a562e-s.2f77a576.woff2 +0 -0
- yera/ui/dist/_next/static/media/45ec8de98929b0f6-s.81056204.woff2 +0 -0
- yera/ui/dist/_next/static/media/4fa387ec64143e14-s.c1fdd6c2.woff2 +0 -0
- yera/ui/dist/_next/static/media/65c558afe41e89d6-s.e2c8389a.woff2 +0 -0
- yera/ui/dist/_next/static/media/67add6cc0f54b8cf-s.8ce53448.woff2 +0 -0
- yera/ui/dist/_next/static/media/7178b3e590c64307-s.b97b3418.woff2 +0 -0
- yera/ui/dist/_next/static/media/797e433ab948586e-s.p.dbea232f.woff2 +0 -0
- yera/ui/dist/_next/static/media/8a480f0b521d4e75-s.8e0177b5.woff2 +0 -0
- yera/ui/dist/_next/static/media/a8ff2d5d0ccb0d12-s.fc5b72a7.woff2 +0 -0
- yera/ui/dist/_next/static/media/aae5f0be330e13db-s.p.853e26d6.woff2 +0 -0
- yera/ui/dist/_next/static/media/b11a6ccf4a3edec7-s.2113d282.woff2 +0 -0
- yera/ui/dist/_next/static/media/b49b0d9b851e4899-s.4f3fa681.woff2 +0 -0
- yera/ui/dist/_next/static/media/bbc41e54d2fcbd21-s.799d8ef8.woff2 +0 -0
- yera/ui/dist/_next/static/media/caa3a2e1cccd8315-s.p.853070df.woff2 +0 -0
- yera/ui/dist/_next/static/media/favicon.0b3bf435.ico +0 -0
- yera/ui/dist/_not-found/__next._full.txt +14 -0
- yera/ui/dist/_not-found/__next._head.txt +6 -0
- yera/ui/dist/_not-found/__next._index.txt +5 -0
- yera/ui/dist/_not-found/__next._not-found.__PAGE__.txt +5 -0
- yera/ui/dist/_not-found/__next._not-found.txt +4 -0
- yera/ui/dist/_not-found/__next._tree.txt +2 -0
- yera/ui/dist/_not-found.html +1 -0
- yera/ui/dist/_not-found.txt +14 -0
- yera/ui/dist/agent-icon.svg +3 -0
- yera/ui/dist/favicon.ico +0 -0
- yera/ui/dist/file.svg +1 -0
- yera/ui/dist/globe.svg +1 -0
- yera/ui/dist/index.html +1 -0
- yera/ui/dist/index.txt +23 -0
- yera/ui/dist/logo/full_logo.png +0 -0
- yera/ui/dist/logo/rune_logo.png +0 -0
- yera/ui/dist/logo/rune_logo_borderless.png +0 -0
- yera/ui/dist/logo/text_logo.png +0 -0
- yera/ui/dist/next.svg +1 -0
- yera/ui/dist/send.png +0 -0
- yera/ui/dist/send_single.png +0 -0
- yera/ui/dist/vercel.svg +1 -0
- yera/ui/dist/window.svg +1 -0
- yera/utils/__init__.py +1 -0
- yera/utils/path_utils.py +38 -0
- yera-0.2.0.dist-info/METADATA +65 -0
- yera-0.2.0.dist-info/RECORD +190 -0
- {yera-0.1.1.dist-info → yera-0.2.0.dist-info}/WHEEL +1 -1
- yera-0.2.0.dist-info/entry_points.txt +2 -0
- yera-0.1.1.dist-info/METADATA +0 -11
- yera-0.1.1.dist-info/RECORD +0 -4
|
@@ -0,0 +1,534 @@
|
|
|
1
|
+
"""Data classes for Yera's config."""
|
|
2
|
+
|
|
3
|
+
from typing import Literal
|
|
4
|
+
|
|
5
|
+
from pydantic import BaseModel, ConfigDict, Field
|
|
6
|
+
|
|
7
|
+
MODEL_TYPES = ["llm", "embedding", "reranker", "image", "moderation", "tts", "stt"]
|
|
8
|
+
|
|
9
|
+
# ============================================================================
|
|
10
|
+
# Shared Components
|
|
11
|
+
# ============================================================================
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class ModelProperties(BaseModel):
|
|
15
|
+
"""Technical properties of a model."""
|
|
16
|
+
|
|
17
|
+
remote: bool = True
|
|
18
|
+
context_window: int | None = None # LLMs only
|
|
19
|
+
|
|
20
|
+
model_config = ConfigDict(extra="forbid")
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
# ============================================================================
|
|
24
|
+
# Global Defaults
|
|
25
|
+
# ============================================================================
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class GlobalDefaults(BaseModel):
|
|
29
|
+
"""Global default settings for Yera."""
|
|
30
|
+
|
|
31
|
+
max_retries: int = 3
|
|
32
|
+
timeout_seconds: int = 60
|
|
33
|
+
log_level: Literal["debug", "info", "warn", "error"] = "info"
|
|
34
|
+
enable_telemetry: bool = False
|
|
35
|
+
|
|
36
|
+
model_config = ConfigDict(extra="forbid")
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
# ============================================================================
|
|
40
|
+
# LLM Models
|
|
41
|
+
# ============================================================================
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class LLMCapabilities(BaseModel):
|
|
45
|
+
"""Capabilities specific to LLM models."""
|
|
46
|
+
|
|
47
|
+
function_calling: bool = False
|
|
48
|
+
structured_generation: bool = False
|
|
49
|
+
vision: bool = False
|
|
50
|
+
reasoning: bool = False
|
|
51
|
+
multilingual: bool = False
|
|
52
|
+
|
|
53
|
+
model_config = ConfigDict(extra="forbid")
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
class LLMCost(BaseModel):
|
|
57
|
+
"""Cost structure for LLM models."""
|
|
58
|
+
|
|
59
|
+
input_tokens_per_million: float
|
|
60
|
+
output_tokens_per_million: float
|
|
61
|
+
|
|
62
|
+
model_config = ConfigDict(extra="forbid")
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
class LLMInference(BaseModel):
|
|
66
|
+
"""Runtime inference parameters for LLM models."""
|
|
67
|
+
|
|
68
|
+
temperature: float | None = None
|
|
69
|
+
max_tokens: int | None = None
|
|
70
|
+
top_p: float | None = None
|
|
71
|
+
top_k: int | None = None
|
|
72
|
+
stop_sequences: list[str] = Field(default_factory=list)
|
|
73
|
+
|
|
74
|
+
model_config = ConfigDict(extra="allow")
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
class LLMConfig(BaseModel):
|
|
78
|
+
"""Configuration for a Language Model."""
|
|
79
|
+
|
|
80
|
+
id: str # Full identifier like "anthropic.claude-sonnet-4"
|
|
81
|
+
display_name: str
|
|
82
|
+
credentials: str
|
|
83
|
+
provider: str
|
|
84
|
+
interface: str
|
|
85
|
+
model_id: str
|
|
86
|
+
properties: ModelProperties = Field(default_factory=ModelProperties)
|
|
87
|
+
cost: LLMCost | None = None
|
|
88
|
+
capabilities: LLMCapabilities = Field(default_factory=LLMCapabilities)
|
|
89
|
+
inference: LLMInference = Field(default_factory=LLMInference)
|
|
90
|
+
|
|
91
|
+
model_config = ConfigDict(extra="forbid")
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
# ============================================================================
|
|
95
|
+
# Embedding Models
|
|
96
|
+
# ============================================================================
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
class EmbeddingCapabilities(BaseModel):
|
|
100
|
+
"""Capabilities specific to embedding models."""
|
|
101
|
+
|
|
102
|
+
cosine_similarity: bool = True
|
|
103
|
+
dot_product: bool = True
|
|
104
|
+
euclidean_distance: bool = False
|
|
105
|
+
|
|
106
|
+
model_config = ConfigDict(extra="forbid")
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
class EmbeddingCost(BaseModel):
|
|
110
|
+
"""Cost structure for embedding models."""
|
|
111
|
+
|
|
112
|
+
tokens_per_million: float
|
|
113
|
+
|
|
114
|
+
model_config = ConfigDict(extra="forbid")
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
class EmbeddingInference(BaseModel):
|
|
118
|
+
"""Runtime inference parameters for embedding models."""
|
|
119
|
+
|
|
120
|
+
batch_size: int | None = None
|
|
121
|
+
dimensions: int | None = None # For models that support configurable dimensions
|
|
122
|
+
|
|
123
|
+
model_config = ConfigDict(extra="forbid")
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
class EmbeddingModelConfig(BaseModel):
|
|
127
|
+
"""Configuration for an embedding model."""
|
|
128
|
+
|
|
129
|
+
id: str # Full identifier like "openai.text-embedding-3-small"
|
|
130
|
+
credentials: str
|
|
131
|
+
provider: str
|
|
132
|
+
interface: str
|
|
133
|
+
model_id: str
|
|
134
|
+
dimensions: int
|
|
135
|
+
max_input_tokens: int
|
|
136
|
+
status: Literal["stable", "beta", "deprecated"] = "stable"
|
|
137
|
+
properties: ModelProperties
|
|
138
|
+
cost: EmbeddingCost
|
|
139
|
+
capabilities: EmbeddingCapabilities = Field(default_factory=EmbeddingCapabilities)
|
|
140
|
+
inference: EmbeddingInference = Field(default_factory=EmbeddingInference)
|
|
141
|
+
|
|
142
|
+
model_config = ConfigDict(extra="forbid")
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
# ============================================================================
|
|
146
|
+
# Reranker Models
|
|
147
|
+
# ============================================================================
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
class RerankerCapabilities(BaseModel):
|
|
151
|
+
"""Capabilities specific to reranker models."""
|
|
152
|
+
|
|
153
|
+
multilingual: bool = False
|
|
154
|
+
context_aware: bool = True
|
|
155
|
+
|
|
156
|
+
model_config = ConfigDict(extra="forbid")
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
class RerankerCost(BaseModel):
|
|
160
|
+
"""Cost structure for reranker models."""
|
|
161
|
+
|
|
162
|
+
per_thousand_searches: float
|
|
163
|
+
|
|
164
|
+
model_config = ConfigDict(extra="forbid")
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
class RerankerInference(BaseModel):
|
|
168
|
+
"""Runtime inference parameters for reranker models."""
|
|
169
|
+
|
|
170
|
+
top_n: int | None = None
|
|
171
|
+
return_documents: bool = True
|
|
172
|
+
|
|
173
|
+
model_config = ConfigDict(extra="forbid")
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
class RerankerModelConfig(BaseModel):
|
|
177
|
+
"""Configuration for a reranker model."""
|
|
178
|
+
|
|
179
|
+
id: str # Full identifier like "cohere.rerank-english-v3"
|
|
180
|
+
credentials: str
|
|
181
|
+
provider: str
|
|
182
|
+
interface: str
|
|
183
|
+
model_id: str
|
|
184
|
+
max_documents: int
|
|
185
|
+
max_query_length: int
|
|
186
|
+
status: Literal["stable", "beta", "deprecated"] = "stable"
|
|
187
|
+
properties: ModelProperties
|
|
188
|
+
cost: RerankerCost
|
|
189
|
+
capabilities: RerankerCapabilities = Field(default_factory=RerankerCapabilities)
|
|
190
|
+
inference: RerankerInference = Field(default_factory=RerankerInference)
|
|
191
|
+
|
|
192
|
+
model_config = ConfigDict(extra="forbid")
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
# ============================================================================
|
|
196
|
+
# Image Generation Models
|
|
197
|
+
# ============================================================================
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
class ImageCapabilities(BaseModel):
|
|
201
|
+
"""Capabilities specific to image generation models."""
|
|
202
|
+
|
|
203
|
+
supports_variations: bool = False
|
|
204
|
+
supports_edits: bool = False
|
|
205
|
+
supports_transparent_background: bool = False
|
|
206
|
+
|
|
207
|
+
model_config = ConfigDict(extra="forbid")
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
class ImageCost(BaseModel):
|
|
211
|
+
"""Cost structure for image generation models."""
|
|
212
|
+
|
|
213
|
+
per_image_standard: float | None = None
|
|
214
|
+
per_image_hd: float | None = None
|
|
215
|
+
per_image_1024: float | None = None # DALL-E 2 pricing
|
|
216
|
+
per_image_512: float | None = None
|
|
217
|
+
per_image_256: float | None = None
|
|
218
|
+
|
|
219
|
+
model_config = ConfigDict(extra="forbid")
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
class ImageInference(BaseModel):
|
|
223
|
+
"""Runtime inference parameters for image generation models."""
|
|
224
|
+
|
|
225
|
+
size: str | None = None
|
|
226
|
+
quality: str | None = None
|
|
227
|
+
style: str | None = None
|
|
228
|
+
n: int = 1 # Number of images to generate
|
|
229
|
+
|
|
230
|
+
model_config = ConfigDict(extra="forbid")
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
class ImageModelConfig(BaseModel):
|
|
234
|
+
"""Configuration for an image generation model."""
|
|
235
|
+
|
|
236
|
+
id: str # Full identifier like "openai.dall-e-3"
|
|
237
|
+
credentials: str
|
|
238
|
+
provider: str
|
|
239
|
+
interface: str
|
|
240
|
+
model_id: str
|
|
241
|
+
supported_sizes: list[str]
|
|
242
|
+
supported_qualities: list[str]
|
|
243
|
+
supported_styles: list[str] = Field(default_factory=list)
|
|
244
|
+
status: Literal["stable", "beta", "deprecated"] = "stable"
|
|
245
|
+
properties: ModelProperties
|
|
246
|
+
cost: ImageCost
|
|
247
|
+
capabilities: ImageCapabilities = Field(default_factory=ImageCapabilities)
|
|
248
|
+
inference: ImageInference = Field(default_factory=ImageInference)
|
|
249
|
+
|
|
250
|
+
model_config = ConfigDict(extra="forbid")
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
# ============================================================================
|
|
254
|
+
# Moderation Models
|
|
255
|
+
# ============================================================================
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
class ModerationCapabilities(BaseModel):
|
|
259
|
+
"""Capabilities specific to moderation models."""
|
|
260
|
+
|
|
261
|
+
categories: list[str] = Field(default_factory=list)
|
|
262
|
+
|
|
263
|
+
model_config = ConfigDict(extra="forbid")
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
class ModerationCost(BaseModel):
|
|
267
|
+
"""Cost structure for moderation models."""
|
|
268
|
+
|
|
269
|
+
free: bool = True
|
|
270
|
+
|
|
271
|
+
model_config = ConfigDict(extra="forbid")
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
class ModerationInference(BaseModel):
|
|
275
|
+
"""Runtime inference parameters for moderation models."""
|
|
276
|
+
|
|
277
|
+
# Most moderation models have no configurable inference params
|
|
278
|
+
model_config = ConfigDict(extra="forbid")
|
|
279
|
+
|
|
280
|
+
|
|
281
|
+
class ModerationModelConfig(BaseModel):
|
|
282
|
+
"""Configuration for a moderation model."""
|
|
283
|
+
|
|
284
|
+
id: str # Full identifier like "openai.text-moderation-latest"
|
|
285
|
+
credentials: str
|
|
286
|
+
provider: str
|
|
287
|
+
interface: str
|
|
288
|
+
model_id: str
|
|
289
|
+
status: Literal["stable", "beta", "deprecated"] = "stable"
|
|
290
|
+
properties: ModelProperties
|
|
291
|
+
cost: ModerationCost
|
|
292
|
+
capabilities: ModerationCapabilities = Field(default_factory=ModerationCapabilities)
|
|
293
|
+
inference: ModerationInference = Field(default_factory=ModerationInference)
|
|
294
|
+
|
|
295
|
+
model_config = ConfigDict(extra="forbid")
|
|
296
|
+
|
|
297
|
+
|
|
298
|
+
# ============================================================================
|
|
299
|
+
# Text-to-Speech Models
|
|
300
|
+
# ============================================================================
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
class TTSCapabilities(BaseModel):
|
|
304
|
+
"""Capabilities specific to TTS models."""
|
|
305
|
+
|
|
306
|
+
streaming: bool = False
|
|
307
|
+
speed_control: bool = False
|
|
308
|
+
voice_cloning: bool = False
|
|
309
|
+
emotion_control: bool = False
|
|
310
|
+
|
|
311
|
+
model_config = ConfigDict(extra="forbid")
|
|
312
|
+
|
|
313
|
+
|
|
314
|
+
class TTSCost(BaseModel):
|
|
315
|
+
"""Cost structure for TTS models."""
|
|
316
|
+
|
|
317
|
+
chars_per_million: float
|
|
318
|
+
|
|
319
|
+
model_config = ConfigDict(extra="forbid")
|
|
320
|
+
|
|
321
|
+
|
|
322
|
+
class TTSInference(BaseModel):
|
|
323
|
+
"""Runtime inference parameters for TTS models."""
|
|
324
|
+
|
|
325
|
+
voice: str | None = None
|
|
326
|
+
speed: float | None = None
|
|
327
|
+
format: str | None = None # mp3, opus, etc.
|
|
328
|
+
sample_rate: int | None = None
|
|
329
|
+
|
|
330
|
+
model_config = ConfigDict(extra="forbid")
|
|
331
|
+
|
|
332
|
+
|
|
333
|
+
class TTSModelConfig(BaseModel):
|
|
334
|
+
"""Configuration for a text-to-speech model."""
|
|
335
|
+
|
|
336
|
+
id: str # Full identifier like "openai.tts-1"
|
|
337
|
+
credentials: str
|
|
338
|
+
provider: str
|
|
339
|
+
interface: str
|
|
340
|
+
model_id: str
|
|
341
|
+
voices: list[str] = Field(default_factory=list)
|
|
342
|
+
default_voice: str = ""
|
|
343
|
+
supported_formats: list[str] = Field(default_factory=list)
|
|
344
|
+
sample_rates: list[int] = Field(default_factory=list)
|
|
345
|
+
status: Literal["stable", "beta", "deprecated"] = "stable"
|
|
346
|
+
properties: ModelProperties
|
|
347
|
+
cost: TTSCost
|
|
348
|
+
capabilities: TTSCapabilities = Field(default_factory=TTSCapabilities)
|
|
349
|
+
inference: TTSInference = Field(default_factory=TTSInference)
|
|
350
|
+
|
|
351
|
+
model_config = ConfigDict(extra="forbid")
|
|
352
|
+
|
|
353
|
+
|
|
354
|
+
# ============================================================================
|
|
355
|
+
# Speech-to-Text Models
|
|
356
|
+
# ============================================================================
|
|
357
|
+
|
|
358
|
+
|
|
359
|
+
class STTCapabilities(BaseModel):
|
|
360
|
+
"""Capabilities specific to STT models."""
|
|
361
|
+
|
|
362
|
+
timestamps: bool = False
|
|
363
|
+
translation: bool = False
|
|
364
|
+
language_detection: bool = False
|
|
365
|
+
|
|
366
|
+
model_config = ConfigDict(extra="forbid")
|
|
367
|
+
|
|
368
|
+
|
|
369
|
+
class STTCost(BaseModel):
|
|
370
|
+
"""Cost structure for STT models."""
|
|
371
|
+
|
|
372
|
+
per_minute: float
|
|
373
|
+
|
|
374
|
+
model_config = ConfigDict(extra="forbid")
|
|
375
|
+
|
|
376
|
+
|
|
377
|
+
class STTInference(BaseModel):
|
|
378
|
+
"""Runtime inference parameters for STT models."""
|
|
379
|
+
|
|
380
|
+
language: str | None = None
|
|
381
|
+
enable_timestamps: bool = False
|
|
382
|
+
response_format: str | None = None # json, text, srt, vtt
|
|
383
|
+
|
|
384
|
+
model_config = ConfigDict(extra="forbid")
|
|
385
|
+
|
|
386
|
+
|
|
387
|
+
class STTModelConfig(BaseModel):
|
|
388
|
+
"""Configuration for a speech-to-text model."""
|
|
389
|
+
|
|
390
|
+
id: str # Full identifier like "openai.whisper-1"
|
|
391
|
+
credentials: str
|
|
392
|
+
provider: str
|
|
393
|
+
interface: str
|
|
394
|
+
model_id: str
|
|
395
|
+
supported_formats: list[str] = Field(default_factory=list)
|
|
396
|
+
max_file_size_mb: float = 25.0
|
|
397
|
+
languages: list[str] = Field(default_factory=list)
|
|
398
|
+
status: Literal["stable", "beta", "deprecated"] = "stable"
|
|
399
|
+
properties: ModelProperties
|
|
400
|
+
cost: STTCost
|
|
401
|
+
capabilities: STTCapabilities = Field(default_factory=STTCapabilities)
|
|
402
|
+
inference: STTInference = Field(default_factory=STTInference)
|
|
403
|
+
|
|
404
|
+
model_config = ConfigDict(extra="forbid")
|
|
405
|
+
|
|
406
|
+
|
|
407
|
+
# ============================================================================
|
|
408
|
+
# Model Registry
|
|
409
|
+
# ============================================================================
|
|
410
|
+
|
|
411
|
+
|
|
412
|
+
class ModelRegistry(BaseModel):
|
|
413
|
+
"""Registry of all configured models by type.
|
|
414
|
+
|
|
415
|
+
Models are keyed by their full dot-path identifier (e.g.,
|
|
416
|
+
"anthropic.claude-sonnet-4").
|
|
417
|
+
|
|
418
|
+
"""
|
|
419
|
+
|
|
420
|
+
llm: dict[str, LLMConfig] = Field(default_factory=dict)
|
|
421
|
+
embedding: dict[str, EmbeddingModelConfig] = Field(default_factory=dict)
|
|
422
|
+
reranker: dict[str, RerankerModelConfig] = Field(default_factory=dict)
|
|
423
|
+
image: dict[str, ImageModelConfig] = Field(default_factory=dict)
|
|
424
|
+
moderation: dict[str, ModerationModelConfig] = Field(default_factory=dict)
|
|
425
|
+
tts: dict[str, TTSModelConfig] = Field(default_factory=dict)
|
|
426
|
+
stt: dict[str, STTModelConfig] = Field(default_factory=dict)
|
|
427
|
+
|
|
428
|
+
model_config = ConfigDict(extra="forbid")
|
|
429
|
+
|
|
430
|
+
|
|
431
|
+
# ============================================================================
|
|
432
|
+
# Top-Level Configuration
|
|
433
|
+
# ============================================================================
|
|
434
|
+
|
|
435
|
+
|
|
436
|
+
class DefaultModels(BaseModel):
|
|
437
|
+
"""Default model selections by type."""
|
|
438
|
+
|
|
439
|
+
llm: str | None = None
|
|
440
|
+
embedding: str | None = None
|
|
441
|
+
reranker: str | None = None
|
|
442
|
+
image: str | None = None
|
|
443
|
+
tts: str | None = None
|
|
444
|
+
stt: str | None = None
|
|
445
|
+
moderation: str | None = None
|
|
446
|
+
|
|
447
|
+
model_config = ConfigDict(extra="forbid")
|
|
448
|
+
|
|
449
|
+
|
|
450
|
+
class Defaults(BaseModel):
|
|
451
|
+
"""Yera configuration defaults section."""
|
|
452
|
+
|
|
453
|
+
max_retries: int = 3
|
|
454
|
+
timeout_seconds: int = 60
|
|
455
|
+
log_level: Literal["debug", "info", "warn", "error"] = "info"
|
|
456
|
+
enable_telemetry: bool = False
|
|
457
|
+
|
|
458
|
+
models: DefaultModels = Field(default_factory=DefaultModels)
|
|
459
|
+
|
|
460
|
+
model_config = ConfigDict(extra="forbid")
|
|
461
|
+
|
|
462
|
+
|
|
463
|
+
class CredentialsMap(BaseModel):
|
|
464
|
+
"""Credentials for Yera configuration."""
|
|
465
|
+
|
|
466
|
+
providers: dict[str, dict[str, str]] = Field(default_factory=dict)
|
|
467
|
+
tools: dict[str, dict[str, str]] = Field(default_factory=dict)
|
|
468
|
+
|
|
469
|
+
|
|
470
|
+
class YeraConfig(BaseModel):
|
|
471
|
+
"""Complete Yera configuration.
|
|
472
|
+
|
|
473
|
+
This is the root configuration object that contains all provider credentials,
|
|
474
|
+
model definitions, and default selections.
|
|
475
|
+
"""
|
|
476
|
+
|
|
477
|
+
defaults: Defaults = Field(default_factory=Defaults)
|
|
478
|
+
credentials: CredentialsMap = Field(default_factory=CredentialsMap)
|
|
479
|
+
models: ModelRegistry = Field(default_factory=ModelRegistry)
|
|
480
|
+
|
|
481
|
+
model_config = ConfigDict(extra="forbid")
|
|
482
|
+
|
|
483
|
+
def merge(self, other: "YeraConfig") -> "YeraConfig":
|
|
484
|
+
"""Merge this configuration with another, creating a new config.
|
|
485
|
+
|
|
486
|
+
Creates a new YeraConfig by combining this configuration with another,
|
|
487
|
+
where values from `other` take precedence in case of conflicts. This is
|
|
488
|
+
for extending and updating yera config.
|
|
489
|
+
|
|
490
|
+
Args:
|
|
491
|
+
other: Another YeraConfig to merge with this one. Values from this
|
|
492
|
+
config will override values from self when keys conflict.
|
|
493
|
+
|
|
494
|
+
Returns:
|
|
495
|
+
A new YeraConfig instance containing the merged configuration. The
|
|
496
|
+
original configs (self and other) are not modified.
|
|
497
|
+
|
|
498
|
+
"""
|
|
499
|
+
merged_defaults = {
|
|
500
|
+
**self.defaults.model_dump(),
|
|
501
|
+
**other.defaults.model_dump(),
|
|
502
|
+
}
|
|
503
|
+
merged_default_models = {
|
|
504
|
+
**self.defaults.models.model_dump(),
|
|
505
|
+
**other.defaults.models.model_dump(),
|
|
506
|
+
}
|
|
507
|
+
defaults = self.defaults.model_validate(
|
|
508
|
+
{
|
|
509
|
+
**merged_defaults,
|
|
510
|
+
"models": merged_default_models,
|
|
511
|
+
}
|
|
512
|
+
)
|
|
513
|
+
|
|
514
|
+
providers_merge = {**self.credentials.providers, **other.credentials.providers}
|
|
515
|
+
tools_merge = {**self.credentials.tools, **other.credentials.tools}
|
|
516
|
+
credentials = self.credentials.model_copy(
|
|
517
|
+
update={
|
|
518
|
+
"providers": providers_merge,
|
|
519
|
+
"tools": tools_merge,
|
|
520
|
+
}
|
|
521
|
+
)
|
|
522
|
+
|
|
523
|
+
model_reg1 = self.models.model_dump()
|
|
524
|
+
model_reg2 = other.models.model_dump()
|
|
525
|
+
models_merge = {}
|
|
526
|
+
for k in model_reg1:
|
|
527
|
+
models_merge[k] = {**model_reg1[k], **model_reg2[k]}
|
|
528
|
+
models = ModelRegistry(**models_merge)
|
|
529
|
+
|
|
530
|
+
return YeraConfig(
|
|
531
|
+
defaults=defaults,
|
|
532
|
+
credentials=credentials,
|
|
533
|
+
models=models,
|
|
534
|
+
)
|