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:
Jason 2025-01-20 20:53:28 +08:00 • committed by GitHub
commit 84c6ed2217
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 245 additions and 0 deletions

View 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

View file

@ -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",

View 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

View file

@ -25,4 +25,5 @@ VARIABLES_TO_GET_FROM_ENVIRONMENT = [
"VECTARA_API_KEY",
"AWS_ACCESS_KEY_ID",
"AWS_SECRET_ACCESS_KEY",
"NOVITA_API_KEY",
]