revised models page
This commit is contained in:
parent
6532411d33
commit
e4e2384587
1 changed files with 211 additions and 200 deletions
|
|
@ -1,10 +1,10 @@
|
||||||
import os
|
import os
|
||||||
|
|
||||||
import streamlit as st
|
import streamlit as st
|
||||||
|
from esperanto import AIFactory
|
||||||
|
|
||||||
from open_notebook.config import CONFIG
|
from open_notebook.config import CONFIG
|
||||||
from open_notebook.domain.models import DefaultModels, Model, model_manager
|
from open_notebook.domain.models import DefaultModels, Model, model_manager
|
||||||
from open_notebook.models import MODEL_CLASS_MAP
|
|
||||||
from pages.components.model_selector import model_selector
|
from pages.components.model_selector import model_selector
|
||||||
from pages.stream_app.utils import setup_page
|
from pages.stream_app.utils import setup_page
|
||||||
|
|
||||||
|
|
@ -13,8 +13,6 @@ setup_page("🤖 Models", only_check_mandatory_models=False, stop_on_model_error
|
||||||
|
|
||||||
st.title("🤖 Models")
|
st.title("🤖 Models")
|
||||||
|
|
||||||
model_tab, model_defaults_tab = st.tabs(["Models", "Model Defaults"])
|
|
||||||
|
|
||||||
provider_status = {}
|
provider_status = {}
|
||||||
|
|
||||||
model_types = [
|
model_types = [
|
||||||
|
|
@ -25,39 +23,44 @@ model_types = [
|
||||||
"speech_to_text",
|
"speech_to_text",
|
||||||
]
|
]
|
||||||
|
|
||||||
provider_status["ollama"] = os.environ.get("OLLAMA_API_BASE") is not None
|
|
||||||
provider_status["openai"] = os.environ.get("OPENAI_API_KEY") is not None
|
|
||||||
provider_status["groq"] = os.environ.get("GROQ_API_KEY") is not None
|
|
||||||
provider_status["xai"] = os.environ.get("XAI_API_KEY") is not None
|
|
||||||
provider_status["vertexai"] = (
|
|
||||||
os.environ.get("VERTEX_PROJECT") is not None
|
|
||||||
and os.environ.get("VERTEX_LOCATION") is not None
|
|
||||||
and os.environ.get("GOOGLE_APPLICATION_CREDENTIALS") is not None
|
|
||||||
)
|
|
||||||
provider_status["vertexai-anthropic"] = (
|
|
||||||
os.environ.get("VERTEX_PROJECT") is not None
|
|
||||||
and os.environ.get("VERTEX_LOCATION") is not None
|
|
||||||
and os.environ.get("GOOGLE_APPLICATION_CREDENTIALS") is not None
|
|
||||||
)
|
|
||||||
provider_status["gemini"] = os.environ.get("GOOGLE_API_KEY") is not None
|
|
||||||
provider_status["openrouter"] = (
|
|
||||||
os.environ.get("OPENROUTER_API_KEY") is not None
|
|
||||||
and os.environ.get("OPENAI_API_KEY") is not None
|
|
||||||
and os.environ.get("OPENROUTER_BASE_URL") is not None
|
|
||||||
)
|
|
||||||
provider_status["anthropic"] = os.environ.get("ANTHROPIC_API_KEY") is not None
|
|
||||||
provider_status["elevenlabs"] = os.environ.get("ELEVENLABS_API_KEY") is not None
|
|
||||||
provider_status["litellm"] = (
|
|
||||||
provider_status["ollama"]
|
|
||||||
or provider_status["vertexai"]
|
|
||||||
or provider_status["vertexai-anthropic"]
|
|
||||||
or provider_status["anthropic"]
|
|
||||||
or provider_status["openai"]
|
|
||||||
or provider_status["gemini"]
|
|
||||||
)
|
|
||||||
|
|
||||||
available_providers = [k for k, v in provider_status.items() if v]
|
def check_available_providers():
|
||||||
unavailable_providers = [k for k, v in provider_status.items() if not v]
|
provider_status["ollama"] = os.environ.get("OLLAMA_API_BASE") is not None
|
||||||
|
provider_status["openai"] = os.environ.get("OPENAI_API_KEY") is not None
|
||||||
|
provider_status["groq"] = os.environ.get("GROQ_API_KEY") is not None
|
||||||
|
provider_status["xai"] = os.environ.get("XAI_API_KEY") is not None
|
||||||
|
provider_status["vertexai"] = (
|
||||||
|
os.environ.get("VERTEX_PROJECT") is not None
|
||||||
|
and os.environ.get("VERTEX_LOCATION") is not None
|
||||||
|
and os.environ.get("GOOGLE_APPLICATION_CREDENTIALS") is not None
|
||||||
|
)
|
||||||
|
# provider_status["vertexai-anthropic"] = (
|
||||||
|
# os.environ.get("VERTEX_PROJECT") is not None
|
||||||
|
# and os.environ.get("VERTEX_LOCATION") is not None
|
||||||
|
# and os.environ.get("GOOGLE_APPLICATION_CREDENTIALS") is not None
|
||||||
|
# )
|
||||||
|
provider_status["gemini"] = os.environ.get("GOOGLE_API_KEY") is not None
|
||||||
|
provider_status["openrouter"] = (
|
||||||
|
os.environ.get("OPENROUTER_API_KEY") is not None
|
||||||
|
and os.environ.get("OPENAI_API_KEY") is not None
|
||||||
|
and os.environ.get("OPENROUTER_BASE_URL") is not None
|
||||||
|
)
|
||||||
|
provider_status["anthropic"] = os.environ.get("ANTHROPIC_API_KEY") is not None
|
||||||
|
provider_status["elevenlabs"] = os.environ.get("ELEVENLABS_API_KEY") is not None
|
||||||
|
provider_status["voyage"] = os.environ.get("VORAGE_API_KEY") is not None
|
||||||
|
provider_status["azure"] = (
|
||||||
|
os.environ.get("AZURE_OPENAI_API_KEY") is not None
|
||||||
|
and os.environ.get("AZURE_OPENAI_ENDPOINT") is not None
|
||||||
|
and os.environ.get("AZURE_OPENAI_DEPLOYMENT_NAME") is not None
|
||||||
|
and os.environ.get("AZURE_OPENAI_API_VERSION") is not None
|
||||||
|
)
|
||||||
|
provider_status["mistral"] = os.environ.get("MISTRAL_API_KEY") is not None
|
||||||
|
provider_status["deepseek"] = os.environ.get("DEEPSEEK_API_KEY") is not None
|
||||||
|
|
||||||
|
available_providers = [k for k, v in provider_status.items() if v]
|
||||||
|
unavailable_providers = [k for k, v in provider_status.items() if not v]
|
||||||
|
|
||||||
|
return available_providers, unavailable_providers
|
||||||
|
|
||||||
|
|
||||||
def generate_new_models(models, suggested_models):
|
def generate_new_models(models, suggested_models):
|
||||||
|
|
@ -91,186 +94,194 @@ def generate_new_models(models, suggested_models):
|
||||||
|
|
||||||
default_models = DefaultModels()
|
default_models = DefaultModels()
|
||||||
all_models = Model.get_all()
|
all_models = Model.get_all()
|
||||||
|
esperanto_available_providers = AIFactory.get_available_providers()
|
||||||
|
|
||||||
with model_tab:
|
|
||||||
st.subheader("Add Model")
|
|
||||||
|
|
||||||
provider = st.selectbox("Provider", available_providers)
|
st.subheader("Provider Availability")
|
||||||
if len(unavailable_providers) > 0:
|
st.markdown(
|
||||||
st.caption(
|
"Below, you'll find all AI providers supported and their current availability status. To enable more providers, you need to setup some of their ENV Variables. Please check [the documentation](https://github.com/lfnovo/open-notebook) for instructions on how to do so."
|
||||||
f"Unavailable Providers: {', '.join(unavailable_providers)}. Please check docs page if you wish to enable them."
|
)
|
||||||
)
|
available_providers, unavailable_providers = check_available_providers()
|
||||||
|
with st.expander("Available Providers"):
|
||||||
|
st.write(available_providers)
|
||||||
|
with st.expander("Unavailable Providers"):
|
||||||
|
st.write(unavailable_providers)
|
||||||
|
|
||||||
# Filter model types based on provider availability in MODEL_CLASS_MAP
|
st.divider()
|
||||||
available_model_types = []
|
st.subheader("Add Model")
|
||||||
for model_type in model_types:
|
st.markdown(
|
||||||
if model_type in MODEL_CLASS_MAP and provider in MODEL_CLASS_MAP[model_type]:
|
"Even though a lot of models can be supported, not all will perform optimally. Some are more fit for use in this tool than others. To help you decide which models to use, please refer to [Which model to choose?](https://github.com/lfnovo/open-notebook/blob/main/docs/SETUP.md#which-model-to-choose) for more information. You can also play with some models in the [Transformations](https://try-it-out.open-notebook.com) page to see if they match your needs."
|
||||||
available_model_types.append(model_type)
|
)
|
||||||
|
|
||||||
if not available_model_types:
|
available_model_types = esperanto_available_providers.keys()
|
||||||
st.error(f"No compatible model types available for provider: {provider}")
|
model_type = st.selectbox(
|
||||||
else:
|
"Model Type",
|
||||||
model_type = st.selectbox(
|
available_model_types,
|
||||||
"Model Type",
|
help="Use language for text generation models, text_to_speech for TTS models for generating podcasts, etc.",
|
||||||
available_model_types,
|
)
|
||||||
help="Use language for text generation models, text_to_speech for TTS models for generating podcasts, etc.",
|
provider = st.selectbox("Provider", esperanto_available_providers[model_type])
|
||||||
)
|
|
||||||
if model_type == "text_to_speech" and provider == "gemini":
|
if model_type == "text_to_speech" and provider == "gemini":
|
||||||
model_name = "gemini-default"
|
model_name = "gemini-default"
|
||||||
st.markdown("Gemini models are pre-configured. Using the default model.")
|
st.markdown("Gemini models are pre-configured. Using the default model.")
|
||||||
else:
|
else:
|
||||||
model_name = st.text_input(
|
model_name = st.text_input(
|
||||||
"Model Name", "", help="gpt-4o-mini, claude, gemini, llama3, etc"
|
"Model Name", "", help="gpt-4o-mini, claude, gemini, llama3, etc"
|
||||||
|
)
|
||||||
|
if st.button("Save"):
|
||||||
|
model = Model(name=model_name, provider=provider, type=model_type)
|
||||||
|
model.save()
|
||||||
|
st.success("Saved")
|
||||||
|
|
||||||
|
st.divider()
|
||||||
|
suggested_models = CONFIG.get("suggested_models", [])
|
||||||
|
recommendations = generate_new_models(all_models, suggested_models)
|
||||||
|
if len(recommendations) > 0:
|
||||||
|
with st.expander("💁♂️ Recommended models to get you started.."):
|
||||||
|
for recommendation in recommendations:
|
||||||
|
st.markdown(
|
||||||
|
f"**{recommendation['name']}** ({recommendation['provider']}, {recommendation['type']})"
|
||||||
)
|
)
|
||||||
if st.button("Save"):
|
if st.button("Add", key=f"add_{recommendation['name']}"):
|
||||||
model = Model(name=model_name, provider=provider, type=model_type)
|
new_model = Model(**recommendation)
|
||||||
model.save()
|
new_model.save()
|
||||||
st.success("Saved")
|
|
||||||
|
|
||||||
st.divider()
|
|
||||||
suggested_models = CONFIG.get("suggested_models", [])
|
|
||||||
recommendations = generate_new_models(all_models, suggested_models)
|
|
||||||
if len(recommendations) > 0:
|
|
||||||
with st.expander("💁♂️ Recommended models to get you started.."):
|
|
||||||
for recommendation in recommendations:
|
|
||||||
st.markdown(
|
|
||||||
f"**{recommendation['name']}** ({recommendation['provider']}, {recommendation['type']})"
|
|
||||||
)
|
|
||||||
if st.button("Add", key=f"add_{recommendation['name']}"):
|
|
||||||
new_model = Model(**recommendation)
|
|
||||||
new_model.save()
|
|
||||||
st.rerun()
|
|
||||||
st.subheader("Configured Models")
|
|
||||||
model_types_available = {
|
|
||||||
# "vision": False,
|
|
||||||
"language": False,
|
|
||||||
"embedding": False,
|
|
||||||
"text_to_speech": False,
|
|
||||||
"speech_to_text": False,
|
|
||||||
}
|
|
||||||
for model in all_models:
|
|
||||||
model_types_available[model.type] = True
|
|
||||||
with st.container(border=True):
|
|
||||||
st.markdown(f"{model.name} ({model.provider}, {model.type})")
|
|
||||||
if st.button("Delete", key=f"delete_{model.id}"):
|
|
||||||
model.delete()
|
|
||||||
st.rerun()
|
st.rerun()
|
||||||
|
st.divider()
|
||||||
|
|
||||||
for model_type, available in model_types_available.items():
|
st.subheader("Configured Models")
|
||||||
if not available:
|
model_types_available = {
|
||||||
st.warning(f"No models available for {model_type}")
|
# "vision": False,
|
||||||
|
"language": False,
|
||||||
|
"embedding": False,
|
||||||
|
"text_to_speech": False,
|
||||||
|
"speech_to_text": False,
|
||||||
|
}
|
||||||
|
for model in all_models:
|
||||||
|
model_types_available[model.type] = True
|
||||||
|
with st.container(border=True):
|
||||||
|
st.markdown(f"{model.name} ({model.provider}, {model.type})")
|
||||||
|
if st.button("Delete", key=f"delete_{model.id}"):
|
||||||
|
model.delete()
|
||||||
|
st.rerun()
|
||||||
|
|
||||||
with model_defaults_tab:
|
for model_type, available in model_types_available.items():
|
||||||
text_generation_models = [model for model in all_models if model.type == "language"]
|
if not available:
|
||||||
|
st.warning(f"No models available for {model_type}")
|
||||||
|
|
||||||
text_to_speech_models = [
|
|
||||||
model for model in all_models if model.type == "text_to_speech"
|
|
||||||
]
|
|
||||||
|
|
||||||
speech_to_text_models = [
|
st.divider()
|
||||||
model for model in all_models if model.type == "speech_to_text"
|
|
||||||
]
|
|
||||||
vision_models = [model for model in all_models if model.type == "vision"]
|
|
||||||
embedding_models = [model for model in all_models if model.type == "embedding"]
|
|
||||||
st.write(
|
|
||||||
"In this section, you can select the default models to be used on the various content operations done by Open Notebook. Some of these can be overriden in the different modules."
|
|
||||||
)
|
|
||||||
defs = {}
|
|
||||||
# Handle chat model selection
|
|
||||||
selected_model = model_selector(
|
|
||||||
"Default Chat Model",
|
|
||||||
"default_chat_model",
|
|
||||||
selected_id=default_models.default_chat_model,
|
|
||||||
help="This model will be used for chat.",
|
|
||||||
model_type="language",
|
|
||||||
)
|
|
||||||
if selected_model:
|
|
||||||
default_models.default_chat_model = selected_model.id
|
|
||||||
st.divider()
|
|
||||||
# Handle transformation model selection
|
|
||||||
selected_model = model_selector(
|
|
||||||
"Default Transformation Model",
|
|
||||||
"default_transformation_model",
|
|
||||||
selected_id=default_models.default_transformation_model,
|
|
||||||
help="This model will be used for text transformations such as summaries, insights, etc.",
|
|
||||||
model_type="language",
|
|
||||||
)
|
|
||||||
if selected_model:
|
|
||||||
default_models.default_transformation_model = selected_model.id
|
|
||||||
st.caption("You can use a cheap model here like gpt-4o-mini, llama3, etc.")
|
|
||||||
st.divider()
|
|
||||||
|
|
||||||
# Handle tools model selection
|
st.subheader("Select Default Models")
|
||||||
selected_model = model_selector(
|
text_generation_models = [model for model in all_models if model.type == "language"]
|
||||||
"Default Tools Model",
|
|
||||||
"default_tools_model",
|
|
||||||
selected_id=default_models.default_tools_model,
|
|
||||||
help="This model will be used for calling tools. Currently, it's best to use Open AI and Anthropic for this.",
|
|
||||||
model_type="language",
|
|
||||||
)
|
|
||||||
if selected_model:
|
|
||||||
default_models.default_tools_model = selected_model.id
|
|
||||||
st.caption("Recommended to use a capable model here, like gpt-4o, claude, etc.")
|
|
||||||
st.divider()
|
|
||||||
|
|
||||||
# Handle large context model selection
|
text_to_speech_models = [
|
||||||
selected_model = model_selector(
|
model for model in all_models if model.type == "text_to_speech"
|
||||||
"Large Context Model",
|
]
|
||||||
"large_context_model",
|
|
||||||
selected_id=default_models.large_context_model,
|
|
||||||
help="This model will be used for larger context generation -- recommended: Gemini",
|
|
||||||
model_type="language",
|
|
||||||
)
|
|
||||||
if selected_model:
|
|
||||||
default_models.large_context_model = selected_model.id
|
|
||||||
st.caption("Recommended to use Gemini models for larger context processing")
|
|
||||||
st.divider()
|
|
||||||
|
|
||||||
# Handle text-to-speech model selection
|
speech_to_text_models = [
|
||||||
selected_model = model_selector(
|
model for model in all_models if model.type == "speech_to_text"
|
||||||
"Default Text to Speech Model",
|
]
|
||||||
"default_text_to_speech_model",
|
vision_models = [model for model in all_models if model.type == "vision"]
|
||||||
selected_id=default_models.default_text_to_speech_model,
|
embedding_models = [model for model in all_models if model.type == "embedding"]
|
||||||
help="This is the default model for converting text to speech (podcasts, etc)",
|
st.write(
|
||||||
model_type="text_to_speech",
|
"In this section, you can select the default models to be used on the various content operations done by Open Notebook. Some of these can be overriden in the different modules."
|
||||||
)
|
)
|
||||||
st.caption("You can override this model on different podcasts")
|
defs = {}
|
||||||
if selected_model:
|
# Handle chat model selection
|
||||||
default_models.default_text_to_speech_model = selected_model.id
|
selected_model = model_selector(
|
||||||
st.divider()
|
"Default Chat Model",
|
||||||
|
"default_chat_model",
|
||||||
|
selected_id=default_models.default_chat_model,
|
||||||
|
help="This model will be used for chat.",
|
||||||
|
model_type="language",
|
||||||
|
)
|
||||||
|
if selected_model:
|
||||||
|
default_models.default_chat_model = selected_model.id
|
||||||
|
st.divider()
|
||||||
|
# Handle transformation model selection
|
||||||
|
selected_model = model_selector(
|
||||||
|
"Default Transformation Model",
|
||||||
|
"default_transformation_model",
|
||||||
|
selected_id=default_models.default_transformation_model,
|
||||||
|
help="This model will be used for text transformations such as summaries, insights, etc.",
|
||||||
|
model_type="language",
|
||||||
|
)
|
||||||
|
if selected_model:
|
||||||
|
default_models.default_transformation_model = selected_model.id
|
||||||
|
st.caption("You can use a cheap model here like gpt-4o-mini, llama3, etc.")
|
||||||
|
st.divider()
|
||||||
|
|
||||||
# Handle speech-to-text model selection
|
# Handle tools model selection
|
||||||
selected_model = model_selector(
|
selected_model = model_selector(
|
||||||
"Default Speech to Text Model",
|
"Default Tools Model",
|
||||||
selected_id=default_models.default_speech_to_text_model,
|
"default_tools_model",
|
||||||
help="This is the default model for converting speech to text (audio transcriptions, etc)",
|
selected_id=default_models.default_tools_model,
|
||||||
model_type="speech_to_text",
|
help="This model will be used for calling tools. Currently, it's best to use Open AI and Anthropic for this.",
|
||||||
key="default_speech_to_text_model",
|
model_type="language",
|
||||||
)
|
)
|
||||||
|
if selected_model:
|
||||||
|
default_models.default_tools_model = selected_model.id
|
||||||
|
st.caption("Recommended to use a capable model here, like gpt-4o, claude, etc.")
|
||||||
|
st.divider()
|
||||||
|
|
||||||
if selected_model:
|
# Handle large context model selection
|
||||||
default_models.default_speech_to_text_model = selected_model.id
|
selected_model = model_selector(
|
||||||
|
"Large Context Model",
|
||||||
|
"large_context_model",
|
||||||
|
selected_id=default_models.large_context_model,
|
||||||
|
help="This model will be used for larger context generation -- recommended: Gemini",
|
||||||
|
model_type="language",
|
||||||
|
)
|
||||||
|
if selected_model:
|
||||||
|
default_models.large_context_model = selected_model.id
|
||||||
|
st.caption("Recommended to use Gemini models for larger context processing")
|
||||||
|
st.divider()
|
||||||
|
|
||||||
st.divider()
|
# Handle text-to-speech model selection
|
||||||
# Handle embedding model selection
|
selected_model = model_selector(
|
||||||
selected_model = model_selector(
|
"Default Text to Speech Model",
|
||||||
"Default Speech to Text Model",
|
"default_text_to_speech_model",
|
||||||
"default_embedding_model",
|
selected_id=default_models.default_text_to_speech_model,
|
||||||
selected_id=default_models.default_embedding_model,
|
help="This is the default model for converting text to speech (podcasts, etc)",
|
||||||
help="This is the default model for embeddings (semantic search, etc)",
|
model_type="text_to_speech",
|
||||||
model_type="embedding",
|
)
|
||||||
)
|
st.caption("You can override this model on different podcasts")
|
||||||
if selected_model:
|
if selected_model:
|
||||||
default_models.default_embedding_model = selected_model.id
|
default_models.default_text_to_speech_model = selected_model.id
|
||||||
st.warning(
|
st.divider()
|
||||||
"Caution: you cannot change the embedding model once there is embeddings or they will need to be regenerated"
|
|
||||||
)
|
|
||||||
|
|
||||||
for k, v in defs.items():
|
# Handle speech-to-text model selection
|
||||||
if v:
|
selected_model = model_selector(
|
||||||
defs[k] = v.id
|
"Default Speech to Text Model",
|
||||||
|
selected_id=default_models.default_speech_to_text_model,
|
||||||
|
help="This is the default model for converting speech to text (audio transcriptions, etc)",
|
||||||
|
model_type="speech_to_text",
|
||||||
|
key="default_speech_to_text_model",
|
||||||
|
)
|
||||||
|
|
||||||
if st.button("Save Defaults"):
|
if selected_model:
|
||||||
default_models.patch(defs)
|
default_models.default_speech_to_text_model = selected_model.id
|
||||||
model_manager.refresh_defaults()
|
|
||||||
st.success("Saved")
|
st.divider()
|
||||||
|
# Handle embedding model selection
|
||||||
|
selected_model = model_selector(
|
||||||
|
"Default Embedding Model",
|
||||||
|
"default_embedding_model",
|
||||||
|
selected_id=default_models.default_embedding_model,
|
||||||
|
help="This is the default model for embeddings (semantic search, etc)",
|
||||||
|
model_type="embedding",
|
||||||
|
)
|
||||||
|
if selected_model:
|
||||||
|
default_models.default_embedding_model = selected_model.id
|
||||||
|
st.warning(
|
||||||
|
"Caution: you cannot change the embedding model once there is embeddings or they will need to be regenerated"
|
||||||
|
)
|
||||||
|
|
||||||
|
for k, v in defs.items():
|
||||||
|
if v:
|
||||||
|
defs[k] = v.id
|
||||||
|
|
||||||
|
if st.button("Save Defaults"):
|
||||||
|
default_models.patch(defs)
|
||||||
|
model_manager.refresh_defaults()
|
||||||
|
st.success("Saved")
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue