reactifact 0.6.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.
- reactifact/__init__.py +96 -0
- reactifact/__main__.py +10 -0
- reactifact/_extras.py +36 -0
- reactifact/agents.py +173 -0
- reactifact/artifacts.py +130 -0
- reactifact/branching.py +255 -0
- reactifact/budget.py +41 -0
- reactifact/chat.py +373 -0
- reactifact/checkpoints.py +329 -0
- reactifact/cli/__init__.py +73 -0
- reactifact/cli/branch.py +77 -0
- reactifact/cli/common.py +67 -0
- reactifact/cli/context.py +53 -0
- reactifact/cli/graph.py +21 -0
- reactifact/cli/replay.py +69 -0
- reactifact/cli/scenario.py +94 -0
- reactifact/cli/trace.py +45 -0
- reactifact/commit.py +97 -0
- reactifact/commit_log.py +235 -0
- reactifact/consume.py +96 -0
- reactifact/context.py +599 -0
- reactifact/effects.py +232 -0
- reactifact/eval.py +319 -0
- reactifact/events.py +34 -0
- reactifact/interrupt.py +22 -0
- reactifact/llm_agent.py +172 -0
- reactifact/operations.py +192 -0
- reactifact/patches.py +112 -0
- reactifact/produce.py +226 -0
- reactifact/prompts.py +111 -0
- reactifact/providers/__init__.py +153 -0
- reactifact/providers/_retry.py +61 -0
- reactifact/providers/anthropic.py +182 -0
- reactifact/providers/azure.py +31 -0
- reactifact/providers/cerebras.py +11 -0
- reactifact/providers/chat.py +417 -0
- reactifact/providers/contracts.py +105 -0
- reactifact/providers/deepseek.py +11 -0
- reactifact/providers/fake.py +40 -0
- reactifact/providers/fireworks.py +17 -0
- reactifact/providers/gemini.py +284 -0
- reactifact/providers/github_models.py +13 -0
- reactifact/providers/groq.py +18 -0
- reactifact/providers/image.py +157 -0
- reactifact/providers/mistral.py +17 -0
- reactifact/providers/nvidia.py +18 -0
- reactifact/providers/ollama.py +18 -0
- reactifact/providers/openai.py +44 -0
- reactifact/providers/openrouter.py +70 -0
- reactifact/providers/perplexity.py +11 -0
- reactifact/providers/qwen.py +17 -0
- reactifact/providers/speech.py +347 -0
- reactifact/providers/together.py +17 -0
- reactifact/providers/video.py +407 -0
- reactifact/providers/xai.py +11 -0
- reactifact/providers/zai.py +11 -0
- reactifact/py.typed +0 -0
- reactifact/recipes/__init__.py +63 -0
- reactifact/recipes/inputs.py +34 -0
- reactifact/recipes/memory.py +166 -0
- reactifact/recipes/resolve.py +51 -0
- reactifact/recipes/rollback.py +87 -0
- reactifact/recipes/search.py +81 -0
- reactifact/recipes/skills.py +108 -0
- reactifact/recipes/status.py +79 -0
- reactifact/recipes/text.py +202 -0
- reactifact/relations.py +104 -0
- reactifact/replay.py +187 -0
- reactifact/resources.py +45 -0
- reactifact/runtime.py +498 -0
- reactifact/scheduler.py +188 -0
- reactifact/session.py +75 -0
- reactifact/sources.py +498 -0
- reactifact/streaming.py +58 -0
- reactifact/structured.py +245 -0
- reactifact/testing/__init__.py +48 -0
- reactifact/testing/assertions.py +326 -0
- reactifact/testing/exceptions.py +27 -0
- reactifact/testing/fault.py +164 -0
- reactifact/testing/lab.py +350 -0
- reactifact/testing/mock.py +166 -0
- reactifact/testing/record.py +50 -0
- reactifact/testing/registry.py +87 -0
- reactifact/tool_use.py +528 -0
- reactifact/tools.py +111 -0
- reactifact/tracing/__init__.py +29 -0
- reactifact/tracing/langfuse.py +125 -0
- reactifact/tracing/models.py +93 -0
- reactifact/tracing/postgres.py +220 -0
- reactifact/tracing/store.py +254 -0
- reactifact/tracing/templates/ui.html +196 -0
- reactifact/tracing/templates/ui_run.html +264 -0
- reactifact/tracing/tracer.py +370 -0
- reactifact/tracing/web.py +117 -0
- reactifact/triggers.py +41 -0
- reactifact/viz.py +248 -0
- reactifact/web.py +117 -0
- reactifact-0.6.0.dist-info/METADATA +226 -0
- reactifact-0.6.0.dist-info/RECORD +103 -0
- reactifact-0.6.0.dist-info/WHEEL +5 -0
- reactifact-0.6.0.dist-info/entry_points.txt +2 -0
- reactifact-0.6.0.dist-info/licenses/LICENSE +21 -0
- reactifact-0.6.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,347 @@
|
|
|
1
|
+
"""Speech: text-to-speech (synthesis) and speech-to-text (transcription).
|
|
2
|
+
|
|
3
|
+
Both are OpenAI-compatible (`/audio/speech` and `/audio/transcriptions`), so
|
|
4
|
+
they also cover vendors that mirror OpenAI (Groq Whisper, Azure Speech, ...)
|
|
5
|
+
by pointing `base_url` at their OpenAI-compatible endpoint. Auth header/scheme
|
|
6
|
+
and proxy are configurable like every other provider.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
from abc import ABC, abstractmethod
|
|
12
|
+
from collections.abc import Callable
|
|
13
|
+
from typing import Any
|
|
14
|
+
|
|
15
|
+
import httpx
|
|
16
|
+
|
|
17
|
+
from ._retry import with_retry
|
|
18
|
+
from .chat import _network_knobs, _resolve_env_api_key
|
|
19
|
+
from .contracts import auth_value
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class SpeechProvider(ABC):
|
|
23
|
+
"""Text-to-speech: returns audio bytes from text."""
|
|
24
|
+
|
|
25
|
+
@abstractmethod
|
|
26
|
+
async def synthesize(self, text: str, **params: Any) -> bytes:
|
|
27
|
+
"""Synthesizes speech; returns audio bytes (mp3/opus/wav/aac...)."""
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class TranscriberProvider(ABC):
|
|
31
|
+
"""Speech-to-text: returns a transcript from audio bytes."""
|
|
32
|
+
|
|
33
|
+
@abstractmethod
|
|
34
|
+
async def transcribe(self, audio: bytes, **params: Any) -> str:
|
|
35
|
+
"""Transcribes audio; returns the text."""
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class Connectable:
|
|
39
|
+
"""Shared HTTP client builder for the OpenAI-compatible speech endpoints.
|
|
40
|
+
|
|
41
|
+
No global Content-Type: httpx sets it per request (JSON for `json=`,
|
|
42
|
+
multipart boundary for `files=`) — forcing it here would break the
|
|
43
|
+
multipart transcription upload.
|
|
44
|
+
"""
|
|
45
|
+
|
|
46
|
+
def build_client(
|
|
47
|
+
self,
|
|
48
|
+
timeout: float,
|
|
49
|
+
transport: Any,
|
|
50
|
+
proxy: str | None,
|
|
51
|
+
api_key: str | None,
|
|
52
|
+
auth_header: str,
|
|
53
|
+
auth_scheme: str | None,
|
|
54
|
+
) -> httpx.AsyncClient:
|
|
55
|
+
headers: dict[str, str] = {}
|
|
56
|
+
if api_key:
|
|
57
|
+
headers[auth_header] = auth_value(api_key, auth_scheme)
|
|
58
|
+
return httpx.AsyncClient(
|
|
59
|
+
timeout=timeout, transport=transport, headers=headers, proxy=proxy
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
class OpenAICompatSpeech(SpeechProvider):
|
|
64
|
+
"""TTS via `{base}/audio/speech` (OpenAI tts-1/gpt-4o-mini-tts, Azure...)."""
|
|
65
|
+
|
|
66
|
+
def __init__(
|
|
67
|
+
self,
|
|
68
|
+
base_url: str = "https://api.openai.com/v1",
|
|
69
|
+
api_key: str | None = None,
|
|
70
|
+
model: str = "tts-1",
|
|
71
|
+
voice: str = "alloy",
|
|
72
|
+
timeout: float = 60.0,
|
|
73
|
+
transport: Any | None = None,
|
|
74
|
+
proxy: str | None = None,
|
|
75
|
+
auth_header: str = "Authorization",
|
|
76
|
+
auth_scheme: str | None = "Bearer",
|
|
77
|
+
extra_params: dict[str, Any] | None = None,
|
|
78
|
+
retry_attempts: int = 3,
|
|
79
|
+
):
|
|
80
|
+
self.base_url = base_url.rstrip("/")
|
|
81
|
+
self.api_key = api_key
|
|
82
|
+
self.model = model
|
|
83
|
+
self.voice = voice
|
|
84
|
+
self._timeout = timeout
|
|
85
|
+
self._extra = dict(extra_params or {})
|
|
86
|
+
self._transport = transport
|
|
87
|
+
self._proxy = proxy
|
|
88
|
+
self._auth_header = auth_header
|
|
89
|
+
self._auth_scheme = auth_scheme
|
|
90
|
+
self.retry_attempts = retry_attempts
|
|
91
|
+
self._client: httpx.AsyncClient | None = None
|
|
92
|
+
|
|
93
|
+
def _get_client(self) -> httpx.AsyncClient:
|
|
94
|
+
if self._client is None:
|
|
95
|
+
self._client = Connectable().build_client(
|
|
96
|
+
self._timeout,
|
|
97
|
+
self._transport,
|
|
98
|
+
self._proxy,
|
|
99
|
+
self.api_key,
|
|
100
|
+
self._auth_header,
|
|
101
|
+
self._auth_scheme,
|
|
102
|
+
)
|
|
103
|
+
return self._client
|
|
104
|
+
|
|
105
|
+
async def synthesize(self, text: str, **params: Any) -> bytes:
|
|
106
|
+
payload: dict[str, Any] = {
|
|
107
|
+
"model": params.get("model") or self.model,
|
|
108
|
+
"input": text,
|
|
109
|
+
"voice": params.get("voice") or self.voice,
|
|
110
|
+
}
|
|
111
|
+
for key in ("response_format", "speed", "instructions"):
|
|
112
|
+
if params.get(key):
|
|
113
|
+
payload[key] = params[key]
|
|
114
|
+
payload.update(self._extra)
|
|
115
|
+
|
|
116
|
+
async def _call() -> bytes:
|
|
117
|
+
response = await self._get_client().post(
|
|
118
|
+
f"{self.base_url}/audio/speech", json=payload
|
|
119
|
+
)
|
|
120
|
+
response.raise_for_status()
|
|
121
|
+
return response.content
|
|
122
|
+
|
|
123
|
+
return await with_retry(_call, attempts=self.retry_attempts)
|
|
124
|
+
|
|
125
|
+
async def aclose(self) -> None:
|
|
126
|
+
if self._client is not None:
|
|
127
|
+
await self._client.aclose()
|
|
128
|
+
self._client = None
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
class OpenAICompatTranscriber(TranscriberProvider):
|
|
132
|
+
"""STT via `{base}/audio/transcriptions` (OpenAI Whisper, Groq Whisper...)."""
|
|
133
|
+
|
|
134
|
+
def __init__(
|
|
135
|
+
self,
|
|
136
|
+
base_url: str = "https://api.openai.com/v1",
|
|
137
|
+
api_key: str | None = None,
|
|
138
|
+
model: str = "whisper-1",
|
|
139
|
+
timeout: float = 120.0,
|
|
140
|
+
transport: Any | None = None,
|
|
141
|
+
proxy: str | None = None,
|
|
142
|
+
auth_header: str = "Authorization",
|
|
143
|
+
auth_scheme: str | None = "Bearer",
|
|
144
|
+
mime_type: str = "audio/webm",
|
|
145
|
+
filename: str = "audio.webm",
|
|
146
|
+
retry_attempts: int = 3,
|
|
147
|
+
):
|
|
148
|
+
self.base_url = base_url.rstrip("/")
|
|
149
|
+
self.api_key = api_key
|
|
150
|
+
self.model = model
|
|
151
|
+
self._timeout = timeout
|
|
152
|
+
self._transport = transport
|
|
153
|
+
self._proxy = proxy
|
|
154
|
+
self._auth_header = auth_header
|
|
155
|
+
self._auth_scheme = auth_scheme
|
|
156
|
+
self._mime_type = mime_type
|
|
157
|
+
self._filename = filename
|
|
158
|
+
self.retry_attempts = retry_attempts
|
|
159
|
+
self._client: httpx.AsyncClient | None = None
|
|
160
|
+
|
|
161
|
+
def _get_client(self) -> httpx.AsyncClient:
|
|
162
|
+
if self._client is None:
|
|
163
|
+
self._client = Connectable().build_client(
|
|
164
|
+
self._timeout,
|
|
165
|
+
self._transport,
|
|
166
|
+
self._proxy,
|
|
167
|
+
self.api_key,
|
|
168
|
+
self._auth_header,
|
|
169
|
+
self._auth_scheme,
|
|
170
|
+
)
|
|
171
|
+
return self._client
|
|
172
|
+
|
|
173
|
+
async def transcribe(self, audio: bytes, **params: Any) -> str:
|
|
174
|
+
model = params.get("model") or self.model
|
|
175
|
+
files = {
|
|
176
|
+
"file": (params.get("filename") or self._filename, audio, self._mime_type)
|
|
177
|
+
}
|
|
178
|
+
data: dict[str, str] = {"model": model}
|
|
179
|
+
for key in ("language", "prompt", "response_format"):
|
|
180
|
+
if params.get(key):
|
|
181
|
+
data[key] = str(params[key])
|
|
182
|
+
|
|
183
|
+
async def _call() -> str:
|
|
184
|
+
response = await self._get_client().post(
|
|
185
|
+
f"{self.base_url}/audio/transcriptions",
|
|
186
|
+
files=files,
|
|
187
|
+
data=data,
|
|
188
|
+
)
|
|
189
|
+
response.raise_for_status()
|
|
190
|
+
body = response.json()
|
|
191
|
+
if isinstance(body, dict):
|
|
192
|
+
return str(body.get("text", ""))
|
|
193
|
+
return str(body)
|
|
194
|
+
|
|
195
|
+
return await with_retry(_call, attempts=self.retry_attempts)
|
|
196
|
+
|
|
197
|
+
async def aclose(self) -> None:
|
|
198
|
+
if self._client is not None:
|
|
199
|
+
await self._client.aclose()
|
|
200
|
+
self._client = None
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
def _factory_extra(overrides: dict[str, Any], skip: tuple[str, ...]) -> dict[str, Any]:
|
|
204
|
+
return {k: v for k, v in overrides.items() if k not in skip}
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
def _openai_compat_speech(
|
|
208
|
+
*,
|
|
209
|
+
env_prefix: str,
|
|
210
|
+
default_model: str,
|
|
211
|
+
default_voice: str,
|
|
212
|
+
default_base_url: str,
|
|
213
|
+
env_api_key_vars: tuple[str, ...] | None = None,
|
|
214
|
+
name: str | None = None,
|
|
215
|
+
doc: str = "",
|
|
216
|
+
) -> Callable[..., OpenAICompatSpeech]:
|
|
217
|
+
"""Builds a `<vendor>_speech(model=..., voice=..., base_url=...,
|
|
218
|
+
api_key=None, **kwargs)` TTS factory for a vendor whose `/audio/speech`
|
|
219
|
+
endpoint is OpenAI-compatible — the speech counterpart of
|
|
220
|
+
`_openai_compat_llm` (`reactifact.providers.chat`).
|
|
221
|
+
"""
|
|
222
|
+
key_vars = env_api_key_vars or (f"{env_prefix}_API_KEY",)
|
|
223
|
+
|
|
224
|
+
def factory(
|
|
225
|
+
model: str = default_model,
|
|
226
|
+
voice: str = default_voice,
|
|
227
|
+
base_url: str = default_base_url,
|
|
228
|
+
api_key: str | None = None,
|
|
229
|
+
**kwargs: Any,
|
|
230
|
+
) -> OpenAICompatSpeech:
|
|
231
|
+
merged = {**_network_knobs(env_prefix, kwargs), **kwargs}
|
|
232
|
+
return OpenAICompatSpeech(
|
|
233
|
+
base_url=base_url,
|
|
234
|
+
api_key=_resolve_env_api_key(api_key, key_vars),
|
|
235
|
+
model=model,
|
|
236
|
+
voice=voice,
|
|
237
|
+
**merged,
|
|
238
|
+
)
|
|
239
|
+
|
|
240
|
+
factory.__name__ = name or f"{env_prefix.lower()}_speech"
|
|
241
|
+
factory.__qualname__ = factory.__name__
|
|
242
|
+
factory.__doc__ = doc or (
|
|
243
|
+
f"{env_prefix.title()} — OpenAI-compatible text-to-speech "
|
|
244
|
+
f"(key from {' or '.join(key_vars)})."
|
|
245
|
+
)
|
|
246
|
+
return factory
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
def _openai_compat_transcriber(
|
|
250
|
+
*,
|
|
251
|
+
env_prefix: str,
|
|
252
|
+
default_model: str,
|
|
253
|
+
default_base_url: str,
|
|
254
|
+
env_api_key_vars: tuple[str, ...] | None = None,
|
|
255
|
+
name: str | None = None,
|
|
256
|
+
doc: str = "",
|
|
257
|
+
) -> Callable[..., OpenAICompatTranscriber]:
|
|
258
|
+
"""Builds a `<vendor>_transcriber(model=..., base_url=..., api_key=None,
|
|
259
|
+
**kwargs)` STT factory for a vendor whose `/audio/transcriptions`
|
|
260
|
+
endpoint takes the same multipart-file request OpenAI's Whisper API
|
|
261
|
+
does (not every "OpenAI-compatible" STT endpoint does — OpenRouter's,
|
|
262
|
+
for one, takes base64 JSON instead, so it does *not* use this factory).
|
|
263
|
+
"""
|
|
264
|
+
key_vars = env_api_key_vars or (f"{env_prefix}_API_KEY",)
|
|
265
|
+
|
|
266
|
+
def factory(
|
|
267
|
+
model: str = default_model,
|
|
268
|
+
base_url: str = default_base_url,
|
|
269
|
+
api_key: str | None = None,
|
|
270
|
+
**kwargs: Any,
|
|
271
|
+
) -> OpenAICompatTranscriber:
|
|
272
|
+
merged = {**_network_knobs(env_prefix, kwargs), **kwargs}
|
|
273
|
+
return OpenAICompatTranscriber(
|
|
274
|
+
base_url=base_url,
|
|
275
|
+
api_key=_resolve_env_api_key(api_key, key_vars),
|
|
276
|
+
model=model,
|
|
277
|
+
**merged,
|
|
278
|
+
)
|
|
279
|
+
|
|
280
|
+
factory.__name__ = name or f"{env_prefix.lower()}_transcriber"
|
|
281
|
+
factory.__qualname__ = factory.__name__
|
|
282
|
+
factory.__doc__ = doc or (
|
|
283
|
+
f"{env_prefix.title()} — OpenAI-compatible transcription "
|
|
284
|
+
f"(key from {' or '.join(key_vars)})."
|
|
285
|
+
)
|
|
286
|
+
return factory
|
|
287
|
+
|
|
288
|
+
|
|
289
|
+
def speech_from_env(**overrides: Any) -> OpenAICompatSpeech | None:
|
|
290
|
+
"""Builds a TTS provider from env (SPEECH_* or OPENAI_*).
|
|
291
|
+
|
|
292
|
+
Keys: SPEECH_BASE_URL / SPEECH_API_KEY / SPEECH_MODEL / SPEECH_VOICE plus
|
|
293
|
+
the usual SPEECH_PROXY / SPEECH_AUTH_HEADER / SPEECH_AUTH_SCHEME.
|
|
294
|
+
"""
|
|
295
|
+
import os
|
|
296
|
+
|
|
297
|
+
api_key = (
|
|
298
|
+
overrides.get("api_key")
|
|
299
|
+
or os.getenv("SPEECH_API_KEY")
|
|
300
|
+
or os.getenv("OPENAI_API_KEY")
|
|
301
|
+
)
|
|
302
|
+
if not api_key:
|
|
303
|
+
return None
|
|
304
|
+
merged = {
|
|
305
|
+
**_network_knobs("SPEECH", overrides),
|
|
306
|
+
**_factory_extra(overrides, ("api_key", "base_url", "model", "voice")),
|
|
307
|
+
}
|
|
308
|
+
return OpenAICompatSpeech(
|
|
309
|
+
base_url=overrides.get("base_url")
|
|
310
|
+
or os.getenv("SPEECH_BASE_URL")
|
|
311
|
+
or "https://api.openai.com/v1",
|
|
312
|
+
api_key=api_key,
|
|
313
|
+
model=overrides.get("model") or os.getenv("SPEECH_MODEL") or "tts-1",
|
|
314
|
+
voice=overrides.get("voice") or os.getenv("SPEECH_VOICE") or "alloy",
|
|
315
|
+
**merged,
|
|
316
|
+
)
|
|
317
|
+
|
|
318
|
+
|
|
319
|
+
def transcriber_from_env(**overrides: Any) -> OpenAICompatTranscriber | None:
|
|
320
|
+
"""Builds an STT provider from env (TRANSCRIBER_* or OPENAI_*).
|
|
321
|
+
|
|
322
|
+
Keys: TRANSCRIBER_BASE_URL / TRANSCRIBER_API_KEY / TRANSCRIBER_MODEL plus
|
|
323
|
+
the usual TRANSCRIBER_PROXY / TRANSCRIBER_AUTH_HEADER / AUTH_SCHEME.
|
|
324
|
+
Point TRANSCRIBER_BASE_URL at api.groq.com/openai/v1 and set
|
|
325
|
+
TRANSCRIBER_MODEL=whisper-large-v3-turbo for Groq Whisper.
|
|
326
|
+
"""
|
|
327
|
+
import os
|
|
328
|
+
|
|
329
|
+
api_key = (
|
|
330
|
+
overrides.get("api_key")
|
|
331
|
+
or os.getenv("TRANSCRIBER_API_KEY")
|
|
332
|
+
or os.getenv("OPENAI_API_KEY")
|
|
333
|
+
)
|
|
334
|
+
if not api_key:
|
|
335
|
+
return None
|
|
336
|
+
merged = {
|
|
337
|
+
**_network_knobs("TRANSCRIBER", overrides),
|
|
338
|
+
**_factory_extra(overrides, ("api_key", "base_url", "model")),
|
|
339
|
+
}
|
|
340
|
+
return OpenAICompatTranscriber(
|
|
341
|
+
base_url=overrides.get("base_url")
|
|
342
|
+
or os.getenv("TRANSCRIBER_BASE_URL")
|
|
343
|
+
or "https://api.openai.com/v1",
|
|
344
|
+
api_key=api_key,
|
|
345
|
+
model=overrides.get("model") or os.getenv("TRANSCRIBER_MODEL") or "whisper-1",
|
|
346
|
+
**merged,
|
|
347
|
+
)
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"""Together AI — hosted open models (OpenAI-compatible), plus embeddings."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from .chat import _openai_compat_embedder, _openai_compat_llm
|
|
6
|
+
|
|
7
|
+
together_llm = _openai_compat_llm(
|
|
8
|
+
env_prefix="TOGETHER",
|
|
9
|
+
default_model="meta-llama/Llama-3.3-70B-Instruct-Turbo",
|
|
10
|
+
default_base_url="https://api.together.xyz/v1",
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
together_embedder = _openai_compat_embedder(
|
|
14
|
+
env_prefix="TOGETHER",
|
|
15
|
+
default_model="BAAI/bge-large-en-v1.5",
|
|
16
|
+
default_base_url="https://api.together.xyz/v1",
|
|
17
|
+
)
|