From faee93e562c0f870f8484568f14ea9bc5c179d2c Mon Sep 17 00:00:00 2001 From: waterstark <84220220+waterstark@users.noreply.github.com> Date: Tue, 19 Nov 2024 17:27:03 +0400 Subject: [PATCH] feat: make AIML load dynamically and fix minor issues (#4374) * Added auto upgrade for list of AIML models, minor fixes for AIML component * fix minor issues * Fix minor issues * Fix embeddings * Resolve conflicts * refactor: clean up imports and improve type hints in AIML components * Fix import path for AIMLEmbeddingsImpl in aiml.py * Fix update_build_config --------- Co-authored-by: Gabriel Luiz Freitas Almeida --- .../langflow/base/models/aiml_constants.py | 301 +++--------------- .../langflow/components/embeddings/aiml.py | 7 +- .../base/langflow/components/models/aiml.py | 41 ++- 3 files changed, 75 insertions(+), 274 deletions(-) diff --git a/src/backend/base/langflow/base/models/aiml_constants.py b/src/backend/base/langflow/base/models/aiml_constants.py index 48fa89ce4..1d4591746 100644 --- a/src/backend/base/langflow/base/models/aiml_constants.py +++ b/src/backend/base/langflow/base/models/aiml_constants.py @@ -1,252 +1,51 @@ -AIML_CHAT_MODELS = [ - "#g1_aura-angus-en", - "#g1_aura-arcas-en", - "#g1_aura-asteria-en", - "#g1_aura-athena-en", - "#g1_aura-helios-en", - "#g1_aura-hera-en", - "#g1_aura-luna-en", - "#g1_aura-orion-en", - "#g1_aura-orpheus-en", - "#g1_aura-perseus-en", - "#g1_aura-stella-en", - "#g1_aura-zeus-en", - "#g1_nova-2-automotive", - "#g1_nova-2-conversationalai", - "#g1_nova-2-drivethru", - "#g1_nova-2-finance", - "#g1_nova-2-general", - "#g1_nova-2-medical", - "#g1_nova-2-meeting", - "#g1_nova-2-phonecall", - "#g1_nova-2-video", - "#g1_nova-2-voicemail", - "#g1_redaction", - "#g1_whisper-base", - "#g1_whisper-large", - "#g1_whisper-medium", - "#g1_whisper-small", - "#g1_whisper-tiny", - "Austism/chronos-hermes-13b", - "BAAI/bge-base-en-v1.5", - "BAAI/bge-large-en-v1.5", - "EleutherAI/llemma_7b", - "Gryphe/MythoMax-L2-13b", - "HuggingFaceH4/zephyr-7b-beta", - "Meta-Llama/Llama-Guard-7b", - "Nexusflow/NexusRaven-V2-13B", - "NousResearch/Hermes-2-Theta-Llama-3-70B", - "NousResearch/Nous-Capybara-7B-V1p9", - "NousResearch/Nous-Hermes-13b", - "NousResearch/Nous-Hermes-2-Mistral-7B-DPO", - "NousResearch/Nous-Hermes-2-Mixtral-8x7B-DPO", - "NousResearch/Nous-Hermes-2-Mixtral-8x7B-SFT", - "NousResearch/Nous-Hermes-2-Yi-34B", - "NousResearch/Nous-Hermes-Llama2-13b", - "NousResearch/Nous-Hermes-Llama2-70b", - "NousResearch/Nous-Hermes-llama-2-7b", - "NumbersStation/nsql-llama-2-7B", - "Open-Orca/Mistral-7B-OpenOrca", - "Phind/Phind-CodeLlama-34B-Python-v1", - "Phind/Phind-CodeLlama-34B-v2", - "Qwen/Qwen1.5-0.5B", - "Qwen/Qwen1.5-0.5B-Chat", - "Qwen/Qwen1.5-1.8B", - "Qwen/Qwen1.5-1.8B-Chat", - "Qwen/Qwen1.5-110B-Chat", - "Qwen/Qwen1.5-14B", - "Qwen/Qwen1.5-14B-Chat", - "Qwen/Qwen1.5-32B", - "Qwen/Qwen1.5-32B-Chat", - "Qwen/Qwen1.5-4B", - "Qwen/Qwen1.5-4B-Chat", - "Qwen/Qwen1.5-72B", - "Qwen/Qwen1.5-72B-Chat", - "Qwen/Qwen1.5-7B", - "Qwen/Qwen1.5-7B-Chat", - "Qwen/Qwen2-1.5B", - "Qwen/Qwen2-1.5B-Instruct", - "Qwen/Qwen2-72B", - "Qwen/Qwen2-72B-Instruct", - "Qwen/Qwen2-7B", - "Qwen/Qwen2-7B-Instruct", - "SG161222/Realistic_Vision_V3.0_VAE", - "Snowflake/snowflake-arctic-instruct", - "Undi95/ReMM-SLERP-L2-13B", - "Undi95/Toppy-M-7B", - "WhereIsAI/UAE-Large-V1", - "WizardLM/WizardCoder-Python-34B-V1.0", - "WizardLM/WizardLM-13B-V1.2", - "WizardLM/WizardLM-70B-V1.0", - "allenai/OLMo-7B", - "allenai/OLMo-7B-Instruct", - "allenai/OLMo-7B-Twin-2T", - "bert-base-uncased", - "carson/ml318br", - "chatgpt-4o-latest", - "claude-3-5-sonnet-20240620", - "claude-3-haiku-20240307", - "claude-3-opus-20240229", - "claude-3-sonnet-20240229", - "codellama/CodeLlama-13b-Instruct-hf", - "codellama/CodeLlama-13b-Python-hf", - "codellama/CodeLlama-13b-hf", - "codellama/CodeLlama-34b-Instruct-hf", - "codellama/CodeLlama-34b-Python-hf", - "codellama/CodeLlama-34b-hf", - "codellama/CodeLlama-70b-Instruct-hf", - "codellama/CodeLlama-70b-Python-hf", - "codellama/CodeLlama-70b-hf", - "codellama/CodeLlama-7b-Instruct-hf", - "codellama/CodeLlama-7b-Python-hf", - "codellama/CodeLlama-7b-hf", - "cognitivecomputations/dolphin-2.5-mixtral-8x7b", - "dall-e-2", - "dall-e-3", - "databricks/dbrx-instruct", - "deepseek-ai/deepseek-coder-33b-instruct", - "deepseek-ai/deepseek-llm-67b-chat", - "flux-pro", - "flux-realism", - "flux/dev", - "flux/dev/image-to-image", - "flux/schnell", - "garage-bAInd/Platypus2-70B-instruct", - "gemini-1.5-flash", - "gemini-1.5-pro", - "gemini-pro", - "google/gemma-2-27b-it", - "google/gemma-2-9b-it", - "google/gemma-2b", - "google/gemma-2b-it", - "google/gemma-7b", - "google/gemma-7b-it", - "gpt-3.5-turbo-0125", - "gpt-3.5-turbo-0301", - "gpt-3.5-turbo-0613", - "gpt-3.5-turbo-1106", - "gpt-3.5-turbo-16k-0613", - "gpt-3.5-turbo-instruct", - "gpt-4", - "gpt-4-0125-preview", - "gpt-4-1106-preview", - "gpt-4-32k", - "gpt-4-turbo", - "gpt-4-turbo-2024-04-09", - "gpt-4-vision-preview", - "gpt-4o", - "gpt-4o-2024-05-13", - "gpt-4o-2024-08-06", - "gpt-4o-mini", - "gpt-4o-mini-2024-07-18", - "gradientai/Llama-3-70B-Instruct-Gradient-1048k", - "huggyllama/llama-13b", - "huggyllama/llama-30b", - "huggyllama/llama-65b", - "huggyllama/llama-7b", - "lmsys/vicuna-13b-v1.3", - "lmsys/vicuna-13b-v1.5", - "lmsys/vicuna-13b-v1.5-16k", - "lmsys/vicuna-7b-v1.3", - "lmsys/vicuna-7b-v1.5", - "meta-llama/Llama-2-13b-chat-hf", - "meta-llama/Llama-2-13b-hf", - "meta-llama/Llama-2-70b-chat-hf", - "meta-llama/Llama-2-70b-hf", - "meta-llama/Llama-2-7b-chat-hf", - "meta-llama/Llama-2-7b-hf", - "meta-llama/Llama-3-70b-chat-hf", - "meta-llama/Llama-3-70b-hf", - "meta-llama/Llama-3-8b-chat-hf", - "meta-llama/Llama-3-8b-hf", - "meta-llama/LlamaGuard-2-8b", - "meta-llama/Meta-Llama-3-70B", - "meta-llama/Meta-Llama-3-70B-Instruct", - "meta-llama/Meta-Llama-3-70B-Instruct-Lite", - "meta-llama/Meta-Llama-3-70B-Instruct-Turbo", - "meta-llama/Meta-Llama-3-8B", - "meta-llama/Meta-Llama-3-8B-Instruct", - "meta-llama/Meta-Llama-3-8B-Instruct-Lite", - "meta-llama/Meta-Llama-3-8B-Instruct-Turbo", - "meta-llama/Meta-Llama-3.1-405B-Instruct-Turbo", - "meta-llama/Meta-Llama-3.1-70B-Instruct-Reference", - "meta-llama/Meta-Llama-3.1-70B-Instruct-Turbo", - "meta-llama/Meta-Llama-3.1-70B-Reference", - "meta-llama/Meta-Llama-3.1-8B-Instruct-Turbo", - "meta-llama/Meta-Llama-3.1-8B-Reference", - "meta-llama/Meta-Llama-Guard-3-8B", - "microsoft/WizardLM-2-8x22B", - "microsoft/phi-2", - "mistralai/Mistral-7B-Instruct-v0.1", - "mistralai/Mistral-7B-Instruct-v0.2", - "mistralai/Mistral-7B-Instruct-v0.3", - "mistralai/Mistral-7B-v0.1", - "mistralai/Mixtral-8x22B", - "mistralai/Mixtral-8x22B-Instruct-v0.1", - "mistralai/Mixtral-8x7B-Instruct-v0.1", - "mistralai/Mixtral-8x7B-v0.1", - "openchat/openchat-3.5-1210", - "prompthero/openjourney", - "runwayml/stable-diffusion-v1-5", - "sentence-transformers/msmarco-bert-base-dot-v5", - "snorkelai/Snorkel-Mistral-PairRM-DPO", - "stabilityai/stable-diffusion-2-1", - "stabilityai/stable-diffusion-xl-base-1.0", - "stable-diffusion-v3-medium", - "teknium/OpenHermes-2-Mistral-7B", - "teknium/OpenHermes-2p5-Mistral-7B", - "togethercomputer/CodeLlama-13b-Instruct", - "togethercomputer/CodeLlama-13b-Python", - "togethercomputer/CodeLlama-34b", - "togethercomputer/CodeLlama-34b-Instruct", - "togethercomputer/CodeLlama-34b-Python", - "togethercomputer/CodeLlama-7b-Instruct", - "togethercomputer/CodeLlama-7b-Python", - "togethercomputer/Koala-13B", - "togethercomputer/Koala-7B", - "togethercomputer/LLaMA-2-7B-32K", - "togethercomputer/Llama-2-7B-32K-Instruct", - "togethercomputer/Llama-3-8b-chat-hf-int4", - "togethercomputer/Llama-3-8b-chat-hf-int8", - "togethercomputer/SOLAR-10.7B-Instruct-v1.0-int4", - "togethercomputer/StripedHyena-Hessian-7B", - "togethercomputer/StripedHyena-Nous-7B", - "togethercomputer/alpaca-7b", - "togethercomputer/evo-1-131k-base", - "togethercomputer/evo-1-8k-base", - "togethercomputer/guanaco-13b", - "togethercomputer/guanaco-33b", - "togethercomputer/guanaco-65b", - "togethercomputer/guanaco-7b", - "togethercomputer/llama-2-13b", - "togethercomputer/llama-2-13b-chat", - "togethercomputer/llama-2-70b", - "togethercomputer/llama-2-70b-chat", - "togethercomputer/llama-2-7b", - "togethercomputer/llama-2-7b-chat", - "togethercomputer/m2-bert-80M-2k-retrieval", - "togethercomputer/m2-bert-80M-32k-retrieval", - "togethercomputer/m2-bert-80M-8k-retrieval", - "upstage/SOLAR-10.7B-Instruct-v1.0", - "voyage-2", - "voyage-code-2", - "voyage-finance-2", - "voyage-large-2", - "voyage-large-2-instruct", - "voyage-law-2", - "voyage-multilingual-2", - "wavymulder/Analog-Diffusion", - "zero-one-ai/Yi-34B", - "zero-one-ai/Yi-34B-Chat", - "zero-one-ai/Yi-6B", -] +import httpx +from openai import APIConnectionError, APIError -AIML_EMBEDDING_MODELS = [ - "text-embedding-3-large", - "text-embedding-3-small", - "text-embedding-ada-002", - "text-multilingual-embedding-002", - "textembedding-gecko-multilingual@001", - "textembedding-gecko@001", - "textembedding-gecko@003", -] + +class AimlModels: + def __init__(self): + self.chat_models = [] + self.image_models = [] + self.embedding_models = [] + self.stt_models = [] + self.tts_models = [] + self.language_models = [] + + def get_aiml_models(self): + try: + with httpx.Client() as client: + response = client.get("https://api.aimlapi.com/models") + response.raise_for_status() + except httpx.RequestError as e: + msg = "Failed to connect to the AIML API." + raise APIConnectionError(msg) from e + except httpx.HTTPStatusError as e: + msg = f"AIML API responded with status code: {e.response.status_code}" + raise APIError( + message=msg, + body=None, + request=e.request, + ) from e + + try: + models = response.json().get("data", []) + self.separate_models_by_type(models) + except (ValueError, KeyError, TypeError) as e: + msg = "Failed to parse response data from AIML API. The format may be incorrect." + raise ValueError(msg) from e + + def separate_models_by_type(self, models): + model_type_mapping = { + "chat-completion": self.chat_models, + "image": self.image_models, + "embedding": self.embedding_models, + "stt": self.stt_models, + "tts": self.tts_models, + "language-completion": self.language_models, + } + + for model in models: + model_type = model.get("type") + model_id = model.get("id") + if model_type in model_type_mapping: + model_type_mapping[model_type].append(model_id) diff --git a/src/backend/base/langflow/components/embeddings/aiml.py b/src/backend/base/langflow/components/embeddings/aiml.py index fcdab9aae..e9ed2bdfd 100644 --- a/src/backend/base/langflow/components/embeddings/aiml.py +++ b/src/backend/base/langflow/components/embeddings/aiml.py @@ -1,6 +1,5 @@ from langflow.base.embeddings.aiml_embeddings import AIMLEmbeddingsImpl from langflow.base.embeddings.model import LCEmbeddingsModel -from langflow.base.models.aiml_constants import AIML_EMBEDDING_MODELS from langflow.field_typing import Embeddings from langflow.inputs.inputs import DropdownInput from langflow.io import SecretStrInput @@ -16,7 +15,11 @@ class AIMLEmbeddingsComponent(LCEmbeddingsModel): DropdownInput( name="model_name", display_name="Model Name", - options=AIML_EMBEDDING_MODELS, + options=[ + "text-embedding-3-small", + "text-embedding-3-large", + "text-embedding-ada-002", + ], required=True, ), SecretStrInput( diff --git a/src/backend/base/langflow/components/models/aiml.py b/src/backend/base/langflow/components/models/aiml.py index 7bf3500a2..bce906a12 100644 --- a/src/backend/base/langflow/components/models/aiml.py +++ b/src/backend/base/langflow/components/models/aiml.py @@ -1,18 +1,13 @@ +from typing import override + from langchain_openai import ChatOpenAI from pydantic.v1 import SecretStr -from langflow.base.models.aiml_constants import AIML_CHAT_MODELS +from langflow.base.models.aiml_constants import AimlModels from langflow.base.models.model import LCModelComponent from langflow.field_typing import LanguageModel from langflow.field_typing.range_spec import RangeSpec -from langflow.inputs import ( - DictInput, - DropdownInput, - FloatInput, - IntInput, - SecretStrInput, - StrInput, -) +from langflow.inputs import DictInput, DropdownInput, FloatInput, IntInput, SecretStrInput, StrInput from langflow.inputs.inputs import HandleInput @@ -37,8 +32,8 @@ class AIMLModelComponent(LCModelComponent): name="model_name", display_name="Model Name", advanced=False, - options=AIML_CHAT_MODELS, - value=AIML_CHAT_MODELS[0], + options=[], + refresh_button=True, ), StrInput( name="aiml_api_base", @@ -55,13 +50,6 @@ class AIMLModelComponent(LCModelComponent): value="AIML_API_KEY", ), FloatInput(name="temperature", display_name="Temperature", value=0.1), - IntInput( - name="seed", - display_name="Seed", - info="The seed controls the reproducibility of the job.", - advanced=True, - value=1, - ), HandleInput( name="output_parser", display_name="Output Parser", @@ -71,24 +59,35 @@ class AIMLModelComponent(LCModelComponent): ), ] + @override + def update_build_config(self, build_config: dict, field_value: str, field_name: str | None = None): + if field_name in ("api_key", "aiml_api_base", "model_name"): + aiml = AimlModels() + aiml.get_aiml_models() + build_config["model_name"]["options"] = aiml.chat_models + return build_config + def build_model(self) -> LanguageModel: # type: ignore[type-var] aiml_api_key = self.api_key temperature = self.temperature model_name: str = self.model_name max_tokens = self.max_tokens model_kwargs = self.model_kwargs or {} - aiml_api_base = self.aiml_api_base or "https://api.aimlapi.com" - seed = self.seed + aiml_api_base = self.aiml_api_base or "https://api.aimlapi.com/v2" openai_api_key = aiml_api_key.get_secret_value() if isinstance(aiml_api_key, SecretStr) else aiml_api_key + # TODO: Once OpenAI fixes their o1 models, this part will need to be removed + # to work correctly with o1 temperature settings. + if "o1" in model_name: + temperature = 1 + return ChatOpenAI( model=model_name, temperature=temperature, api_key=openai_api_key, base_url=aiml_api_base, max_tokens=max_tokens or None, - seed=seed, **model_kwargs, )