Compare commits

...

4 Commits

Author SHA1 Message Date
Justin Tahara
7794a8977a fix(embedding): Fix Deletion of Same Name (#6149) 2025-11-11 11:19:24 -08:00
Justin Tahara
802420427d fix(gpt-5): Catch all (#6162) 2025-11-11 11:19:24 -08:00
Chris Weaver
e143c9558e fix: improve /llm/provider performance (#6158) 2025-11-11 11:19:24 -08:00
Chris Weaver
1f7b8446fc fix: infinite render on embedding model page (#6144) 2025-11-11 11:19:24 -08:00
5 changed files with 47 additions and 27 deletions

View File

@@ -422,9 +422,7 @@ class DefaultMultiLLM(LLM):
stream=stream,
# model params
temperature=(
1
if self.config.model_name in ["gpt-5", "gpt-5-mini", "gpt-5-nano"]
else self._temperature
1 if "gpt-5" in self.config.model_name else self._temperature
),
timeout=timeout_override or self._timeout,
# For now, we don't support parallel tool calls
@@ -447,12 +445,7 @@ class DefaultMultiLLM(LLM):
), # TODO: remove once LITELLM has patched
**(
{"reasoning_effort": "minimal"}
if self.config.model_name
in [
"gpt-5",
"gpt-5-mini",
"gpt-5-nano",
]
if "gpt-5" in self.config.model_name
else {}
), # TODO: remove once LITELLM has better support/we change API
**(

View File

@@ -777,7 +777,6 @@ def get_max_input_tokens_from_llm_provider(
def model_supports_image_input(model_name: str, model_provider: str) -> bool:
# First, try to read an explicit configuration from the model_configuration table
try:
with get_session_with_current_tenant() as db_session:
@@ -800,6 +799,15 @@ def model_supports_image_input(model_name: str, model_provider: str) -> bool:
)
# Fallback to looking up the model in the litellm model_cost dict
return litellm_thinks_model_supports_image_input(model_name, model_provider)
def litellm_thinks_model_supports_image_input(
model_name: str, model_provider: str
) -> bool:
"""Generally should call `model_supports_image_input` unless you already know that
`model_supports_image_input` from the DB is not set OR you need to avoid the performance
hit of querying the DB."""
try:
model_obj = find_model_obj(get_model_map(), model_provider, model_name)
if not model_obj:

View File

@@ -6,7 +6,7 @@ from pydantic import Field
from pydantic import field_validator
from onyx.llm.utils import get_max_input_tokens
from onyx.llm.utils import model_supports_image_input
from onyx.llm.utils import litellm_thinks_model_supports_image_input
if TYPE_CHECKING:
@@ -183,13 +183,18 @@ class ModelConfigurationView(BaseModel):
return cls(
name=model_configuration_model.name,
is_visible=model_configuration_model.is_visible,
max_input_tokens=model_configuration_model.max_input_tokens
or get_max_input_tokens(
model_name=model_configuration_model.name, model_provider=provider_name
max_input_tokens=(
model_configuration_model.max_input_tokens
or get_max_input_tokens(
model_name=model_configuration_model.name,
model_provider=provider_name,
)
),
supports_image_input=model_supports_image_input(
model_name=model_configuration_model.name,
model_provider=provider_name,
supports_image_input=(
model_configuration_model.supports_image_input
or litellm_thinks_model_supports_image_input(
model_configuration_model.name, provider_name
)
),
)

View File

@@ -142,7 +142,7 @@ export default function CloudEmbeddingPage({
<div className="flex flex-wrap gap-4">
{provider.embedding_models.map((model) => (
<CloudModelCard
key={model.model_name}
key={`${provider.provider_type}-${model.model_name}`}
model={model}
provider={provider}
currentModel={currentModel}
@@ -241,9 +241,12 @@ export default function CloudEmbeddingPage({
model.provider_type ===
EmbeddingProvider.LITELLM.toLowerCase()
)
.map((model) => (
.map((model, index) => (
<CloudModelCard
key={model.model_name}
key={
model.id ??
`${model.provider_type}-${model.model_name}-${index}`
}
model={model}
provider={LITELLM_CLOUD_PROVIDER}
currentModel={currentModel}
@@ -423,11 +426,23 @@ export function CloudModelCard({
}) {
const { popup, setPopup } = usePopup();
const [showDeleteModel, setShowDeleteModel] = useState(false);
const enabled =
const modelId = typeof model.id === "number" ? model.id : null;
const currentModelId =
typeof currentModel.id === "number" ? currentModel.id : null;
const idsMatch =
modelId !== null && currentModelId !== null && modelId === currentModelId;
const shouldCompareNames = modelId === null || currentModelId === null;
const namesMatch =
shouldCompareNames &&
model.model_name === currentModel.model_name &&
model.provider_type?.toLowerCase() ==
model.provider_type?.toLowerCase() ===
currentModel.provider_type?.toLowerCase();
const enabled = idsMatch || namesMatch;
const deleteModel = async () => {
if (!model.id) {
setPopup({ message: "Model cannot be deleted", type: "error" });

View File

@@ -33,8 +33,8 @@ export const EmbeddingFormProvider: React.FC<{
const pathname = usePathname();
// Initialize formStep based on the URL parameter
const initialStep = parseInt(searchParams?.get("step") || "0", 10);
const [formStep, setFormStep] = useState(initialStep);
const stepFromUrl = parseInt(searchParams?.get("step") || "0", 10);
const [formStep, setFormStep] = useState(stepFromUrl);
const [formValues, setFormValues] = useState<Record<string, any>>({});
const [allowAdvanced, setAllowAdvanced] = useState(false);
@@ -67,15 +67,14 @@ export const EmbeddingFormProvider: React.FC<{
} else if (newUrl !== pathname) {
router.push(newUrl);
}
}, [formStep, router, pathname, searchParams]);
}, [formStep, router, pathname]);
// Update formStep when URL changes
useEffect(() => {
const stepFromUrl = parseInt(searchParams?.get("step") || "0", 10);
if (stepFromUrl !== formStep) {
setFormStep(stepFromUrl);
}
}, [searchParams]);
}, [stepFromUrl]);
const contextValue: EmbeddingFormContextType = {
formStep,