feat: add new model provider Novita AI (#5380)
* feat: add new model provider Novita AI * [autofix.ci] apply automated fixes * fix: code format fix * fix: code format fix * fix: fix default Novita AI models * [autofix.ci] apply automated fixes * feat: Add real-time refresh for Novita API key and include it in VARIABLES_TO_GET_FROM_ENVIRONMENT --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: Gabriel Luiz Freitas Almeida <gabriel@langflow.org>
This commit is contained in:
parent
6b02ef0a70
commit
84c6ed2217
9 changed files with 245 additions and 0 deletions
35
src/backend/base/langflow/base/models/novita_constants.py
Normal file
35
src/backend/base/langflow/base/models/novita_constants.py
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
NOVITA_MODELS = [
|
||||
"meta-llama/llama-3.3-70b-instruct",
|
||||
"meta-llama/llama-3.1-8b-instruct",
|
||||
"meta-llama/llama-3.1-8b-instruct-max",
|
||||
"meta-llama/llama-3.1-70b-instruct",
|
||||
"meta-llama/llama-3.1-405b-instruct",
|
||||
"meta-llama/llama-3-8b-instruct",
|
||||
"meta-llama/llama-3-70b-instruct",
|
||||
"gryphe/mythomax-l2-13b",
|
||||
"google/gemma-2-9b-it",
|
||||
"mistralai/mistral-nemo",
|
||||
"microsoft/wizardlm-2-8x22b",
|
||||
"mistralai/mistral-7b-instruct",
|
||||
"openchat/openchat-7b",
|
||||
"nousresearch/hermes-2-pro-llama-3-8b",
|
||||
"sao10k/l3-70b-euryale-v2.1",
|
||||
"cognitivecomputations/dolphin-mixtral-8x22b",
|
||||
"jondurbin/airoboros-l2-70b",
|
||||
"lzlv_70b",
|
||||
"nousresearch/nous-hermes-llama2-13b",
|
||||
"teknium/openhermes-2.5-mistral-7b",
|
||||
"sophosympatheia/midnight-rose-70b",
|
||||
"Sao10K/L3-8B-Stheno-v3.2",
|
||||
"sao10k/l3-8b-lunaris",
|
||||
"qwen/qwen-2-vl-72b-instruct",
|
||||
"meta-llama/llama-3.2-1b-instruct",
|
||||
"meta-llama/llama-3.2-11b-vision-instruct",
|
||||
"meta-llama/llama-3.2-3b-instruct",
|
||||
"meta-llama/llama-3.1-8b-instruct-bf16",
|
||||
"qwen/qwen-2.5-72b-instruct",
|
||||
"sao10k/l31-70b-euryale-v2.2",
|
||||
"qwen/qwen-2-7b-instruct",
|
||||
"qwen/qwen-2-72b-instruct",
|
||||
]
|
||||
MODEL_NAMES = NOVITA_MODELS # reverse compatibility
|
||||
|
|
@ -11,6 +11,7 @@ from .huggingface import HuggingFaceEndpointsComponent
|
|||
from .lmstudiomodel import LMStudioModelComponent
|
||||
from .maritalk import MaritalkModelComponent
|
||||
from .mistral import MistralAIModelComponent
|
||||
from .novita import NovitaModelComponent
|
||||
from .nvidia import NVIDIAModelComponent
|
||||
from .ollama import ChatOllamaComponent
|
||||
from .openai import OpenAIModelComponent
|
||||
|
|
@ -35,6 +36,7 @@ __all__ = [
|
|||
"MaritalkModelComponent",
|
||||
"MistralAIModelComponent",
|
||||
"NVIDIAModelComponent",
|
||||
"NovitaModelComponent",
|
||||
"OpenAIModelComponent",
|
||||
"OpenRouterComponent",
|
||||
"PerplexityComponent",
|
||||
|
|
|
|||
130
src/backend/base/langflow/components/models/novita.py
Normal file
130
src/backend/base/langflow/components/models/novita.py
Normal file
|
|
@ -0,0 +1,130 @@
|
|||
import requests
|
||||
from langchain_openai import ChatOpenAI
|
||||
from pydantic.v1 import SecretStr
|
||||
from typing_extensions import override
|
||||
|
||||
from langflow.base.models.model import LCModelComponent
|
||||
from langflow.base.models.novita_constants import MODEL_NAMES
|
||||
from langflow.field_typing import LanguageModel
|
||||
from langflow.field_typing.range_spec import RangeSpec
|
||||
from langflow.inputs import (
|
||||
BoolInput,
|
||||
DictInput,
|
||||
DropdownInput,
|
||||
IntInput,
|
||||
SecretStrInput,
|
||||
SliderInput,
|
||||
)
|
||||
from langflow.inputs.inputs import HandleInput
|
||||
|
||||
|
||||
class NovitaModelComponent(LCModelComponent):
|
||||
display_name = "Novita AI"
|
||||
description = "Generates text using Novita AI LLMs (OpenAI compatible)."
|
||||
icon = "Novita"
|
||||
name = "NovitaModel"
|
||||
|
||||
inputs = [
|
||||
*LCModelComponent._base_inputs,
|
||||
IntInput(
|
||||
name="max_tokens",
|
||||
display_name="Max Tokens",
|
||||
advanced=True,
|
||||
info="The maximum number of tokens to generate. Set to 0 for unlimited tokens.",
|
||||
range_spec=RangeSpec(min=0, max=128000),
|
||||
),
|
||||
DictInput(
|
||||
name="model_kwargs",
|
||||
display_name="Model Kwargs",
|
||||
advanced=True,
|
||||
info="Additional keyword arguments to pass to the model.",
|
||||
),
|
||||
BoolInput(
|
||||
name="json_mode",
|
||||
display_name="JSON Mode",
|
||||
advanced=True,
|
||||
info="If True, it will output JSON regardless of passing a schema.",
|
||||
),
|
||||
DropdownInput(
|
||||
name="model_name",
|
||||
display_name="Model Name",
|
||||
advanced=False,
|
||||
options=MODEL_NAMES,
|
||||
value=MODEL_NAMES[0],
|
||||
refresh_button=True,
|
||||
),
|
||||
SecretStrInput(
|
||||
name="api_key",
|
||||
display_name="Novita API Key",
|
||||
info="The Novita API Key to use for Novita AI models.",
|
||||
advanced=False,
|
||||
value="NOVITA_API_KEY",
|
||||
real_time_refresh=True,
|
||||
),
|
||||
SliderInput(name="temperature", display_name="Temperature", value=0.1, range_spec=RangeSpec(min=0, max=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",
|
||||
info="The parser to use to parse the output of the model",
|
||||
advanced=True,
|
||||
input_types=["OutputParser"],
|
||||
),
|
||||
]
|
||||
|
||||
def get_models(self) -> list[str]:
|
||||
base_url = "https://api.novita.ai/v3/openai"
|
||||
url = f"{base_url}/models"
|
||||
|
||||
headers = {"Content-Type": "application/json"}
|
||||
|
||||
try:
|
||||
response = requests.get(url, headers=headers, timeout=10)
|
||||
response.raise_for_status()
|
||||
model_list = response.json()
|
||||
return [model["id"] for model in model_list.get("data", [])]
|
||||
except requests.RequestException as e:
|
||||
self.status = f"Error fetching models: {e}"
|
||||
return MODEL_NAMES
|
||||
|
||||
@override
|
||||
def update_build_config(self, build_config: dict, field_value: str, field_name: str | None = None):
|
||||
if field_name in {"api_key", "model_name"}:
|
||||
models = self.get_models()
|
||||
build_config["model_name"]["options"] = models
|
||||
return build_config
|
||||
|
||||
def build_model(self) -> LanguageModel: # type: ignore[type-var]
|
||||
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 {}
|
||||
json_mode = self.json_mode
|
||||
seed = self.seed
|
||||
|
||||
try:
|
||||
output = ChatOpenAI(
|
||||
model=model_name,
|
||||
api_key=(SecretStr(api_key).get_secret_value() if api_key else None),
|
||||
max_tokens=max_tokens or None,
|
||||
temperature=temperature,
|
||||
model_kwargs=model_kwargs,
|
||||
streaming=self.stream,
|
||||
seed=seed,
|
||||
base_url="https://api.novita.ai/v3/openai",
|
||||
)
|
||||
except Exception as e:
|
||||
msg = "Could not connect to Novita API."
|
||||
raise ValueError(msg) from e
|
||||
|
||||
if json_mode:
|
||||
output = output.bind(response_format={"type": "json_object"})
|
||||
|
||||
return output
|
||||
|
|
@ -25,4 +25,5 @@ VARIABLES_TO_GET_FROM_ENVIRONMENT = [
|
|||
"VECTARA_API_KEY",
|
||||
"AWS_ACCESS_KEY_ID",
|
||||
"AWS_SECRET_ACCESS_KEY",
|
||||
"NOVITA_API_KEY",
|
||||
]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue