chore: remove duplicate class definitions (#1942)

This commit is contained in:
cthomas
2025-04-29 17:09:48 -07:00
committed by GitHub
parent 7fb6d68380
commit 903611940a

View File

@@ -486,199 +486,6 @@ class XAIProvider(OpenAIProvider):
return []
class DeepSeekProvider(OpenAIProvider):
"""
DeepSeek ChatCompletions API is similar to OpenAI's reasoning API,
but with slight differences:
* For example, DeepSeek's API requires perfect interleaving of user/assistant
* It also does not support native function calling
"""
name: str = "deepseek"
base_url: str = Field("https://api.deepseek.com/v1", description="Base URL for the DeepSeek API.")
api_key: str = Field(..., description="API key for the DeepSeek API.")
def get_model_context_window_size(self, model_name: str) -> Optional[int]:
# DeepSeek doesn't return context window in the model listing,
# so these are hardcoded from their website
if model_name == "deepseek-reasoner":
return 64000
elif model_name == "deepseek-chat":
return 64000
else:
return None
def list_llm_models(self) -> List[LLMConfig]:
from letta.llm_api.openai import openai_get_model_list
response = openai_get_model_list(self.base_url, api_key=self.api_key)
if "data" in response:
data = response["data"]
else:
data = response
configs = []
for model in data:
assert "id" in model, f"DeepSeek model missing 'id' field: {model}"
model_name = model["id"]
# In case DeepSeek starts supporting it in the future:
if "context_length" in model:
# Context length is returned in OpenRouter as "context_length"
context_window_size = model["context_length"]
else:
context_window_size = self.get_model_context_window_size(model_name)
if not context_window_size:
warnings.warn(f"Couldn't find context window size for model {model_name}")
continue
# Not used for deepseek-reasoner, but otherwise is true
put_inner_thoughts_in_kwargs = False if model_name == "deepseek-reasoner" else True
configs.append(
LLMConfig(
model=model_name,
model_endpoint_type="deepseek",
model_endpoint=self.base_url,
context_window=context_window_size,
handle=self.get_handle(model_name),
put_inner_thoughts_in_kwargs=put_inner_thoughts_in_kwargs,
)
)
return configs
def list_embedding_models(self) -> List[EmbeddingConfig]:
# No embeddings supported
return []
class LMStudioOpenAIProvider(OpenAIProvider):
name: str = "lmstudio-openai"
base_url: str = Field(..., description="Base URL for the LMStudio OpenAI API.")
api_key: Optional[str] = Field(None, description="API key for the LMStudio API.")
def list_llm_models(self) -> List[LLMConfig]:
from letta.llm_api.openai import openai_get_model_list
# For LMStudio, we want to hit 'GET /api/v0/models' instead of 'GET /v1/models'
MODEL_ENDPOINT_URL = f"{self.base_url.strip('/v1')}/api/v0"
response = openai_get_model_list(MODEL_ENDPOINT_URL)
"""
Example response:
{
"object": "list",
"data": [
{
"id": "qwen2-vl-7b-instruct",
"object": "model",
"type": "vlm",
"publisher": "mlx-community",
"arch": "qwen2_vl",
"compatibility_type": "mlx",
"quantization": "4bit",
"state": "not-loaded",
"max_context_length": 32768
},
...
"""
if "data" not in response:
warnings.warn(f"LMStudio OpenAI model query response missing 'data' field: {response}")
return []
configs = []
for model in response["data"]:
assert "id" in model, f"Model missing 'id' field: {model}"
model_name = model["id"]
if "type" not in model:
warnings.warn(f"LMStudio OpenAI model missing 'type' field: {model}")
continue
elif model["type"] not in ["vlm", "llm"]:
continue
if "max_context_length" in model:
context_window_size = model["max_context_length"]
else:
warnings.warn(f"LMStudio OpenAI model missing 'max_context_length' field: {model}")
continue
configs.append(
LLMConfig(
model=model_name,
model_endpoint_type="openai",
model_endpoint=self.base_url,
context_window=context_window_size,
handle=self.get_handle(model_name),
)
)
return configs
def list_embedding_models(self) -> List[EmbeddingConfig]:
from letta.llm_api.openai import openai_get_model_list
# For LMStudio, we want to hit 'GET /api/v0/models' instead of 'GET /v1/models'
MODEL_ENDPOINT_URL = f"{self.base_url.strip('/v1')}/api/v0"
response = openai_get_model_list(MODEL_ENDPOINT_URL)
"""
Example response:
{
"object": "list",
"data": [
{
"id": "text-embedding-nomic-embed-text-v1.5",
"object": "model",
"type": "embeddings",
"publisher": "nomic-ai",
"arch": "nomic-bert",
"compatibility_type": "gguf",
"quantization": "Q4_0",
"state": "not-loaded",
"max_context_length": 2048
}
...
"""
if "data" not in response:
warnings.warn(f"LMStudio OpenAI model query response missing 'data' field: {response}")
return []
configs = []
for model in response["data"]:
assert "id" in model, f"Model missing 'id' field: {model}"
model_name = model["id"]
if "type" not in model:
warnings.warn(f"LMStudio OpenAI model missing 'type' field: {model}")
continue
elif model["type"] not in ["embeddings"]:
continue
if "max_context_length" in model:
context_window_size = model["max_context_length"]
else:
warnings.warn(f"LMStudio OpenAI model missing 'max_context_length' field: {model}")
continue
configs.append(
EmbeddingConfig(
embedding_model=model_name,
embedding_endpoint_type="openai",
embedding_endpoint=self.base_url,
embedding_dim=context_window_size,
embedding_chunk_size=300, # NOTE: max is 2048
handle=self.get_handle(model_name),
),
)
return configs
class AnthropicProvider(Provider):
name: str = "anthropic"
api_key: str = Field(..., description="API key for the Anthropic API.")