fix(nextjs): changes ollama and custom llm endpoints, fix(fastapi): fixes broken image search due to ImageAsset
This commit is contained in:
parent
41a17da47d
commit
6ae502fc9e
8 changed files with 210 additions and 208 deletions
|
|
@ -1,6 +1,8 @@
|
|||
from fastapi import APIRouter
|
||||
|
||||
from models.image_prompt import ImagePrompt
|
||||
from models.sql.image_asset import ImageAsset
|
||||
from services.database import get_sql_session
|
||||
from services.image_generation_service import ImageGenerationService
|
||||
from utils.asset_directory_utils import get_images_directory
|
||||
|
||||
|
|
@ -13,4 +15,12 @@ async def generate_image(prompt: str):
|
|||
image_prompt = ImagePrompt(prompt=prompt)
|
||||
image_generation_service = ImageGenerationService(images_directory)
|
||||
|
||||
return await image_generation_service.generate_image(image_prompt)
|
||||
image = await image_generation_service.generate_image(image_prompt)
|
||||
if not isinstance(image, ImageAsset):
|
||||
return image
|
||||
|
||||
with get_sql_session() as sql_session:
|
||||
sql_session.add(image)
|
||||
sql_session.commit()
|
||||
|
||||
return image.path
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ async def get_available_models():
|
|||
return await list_pulled_ollama_models()
|
||||
|
||||
|
||||
@OLLAMA_ROUTER.get("/models/pull", response_model=OllamaModelStatus)
|
||||
@OLLAMA_ROUTER.get("/model/pull", response_model=OllamaModelStatus)
|
||||
async def pull_model(model: str, background_tasks: BackgroundTasks):
|
||||
|
||||
if model not in SUPPORTED_OLLAMA_MODELS:
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ SUPPORTED_OLLAMA_MODELS = {
|
|||
description="❌ Graphs not supported.",
|
||||
size="4.7GB",
|
||||
supports_graph=False,
|
||||
icon="/static/servers/fastapi/assets/icons/meta.png",
|
||||
icon="/static/icons/meta.png",
|
||||
),
|
||||
"llama3:70b": OllamaModelMetadata(
|
||||
label="Llama 3:70b",
|
||||
|
|
@ -16,7 +16,7 @@ SUPPORTED_OLLAMA_MODELS = {
|
|||
description="✅ Graphs supported.",
|
||||
size="40GB",
|
||||
supports_graph=True,
|
||||
icon="/static/servers/fastapi/assets/icons/meta.png",
|
||||
icon="/static/icons/meta.png",
|
||||
),
|
||||
"llama3.1:8b": OllamaModelMetadata(
|
||||
label="Llama 3.1:8b",
|
||||
|
|
@ -24,7 +24,7 @@ SUPPORTED_OLLAMA_MODELS = {
|
|||
description="❌ Graphs not supported.",
|
||||
size="4.9GB",
|
||||
supports_graph=False,
|
||||
icon="/static/servers/fastapi/assets/icons/meta.png",
|
||||
icon="/static/icons/meta.png",
|
||||
),
|
||||
"llama3.1:70b": OllamaModelMetadata(
|
||||
label="Llama 3.1:70b",
|
||||
|
|
@ -32,7 +32,7 @@ SUPPORTED_OLLAMA_MODELS = {
|
|||
description="✅ Graphs supported.",
|
||||
size="43GB",
|
||||
supports_graph=True,
|
||||
icon="/static/servers/fastapi/assets/icons/meta.png",
|
||||
icon="/static/icons/meta.png",
|
||||
),
|
||||
"llama3.1:405b": OllamaModelMetadata(
|
||||
label="Llama 3.1:405b",
|
||||
|
|
@ -40,7 +40,7 @@ SUPPORTED_OLLAMA_MODELS = {
|
|||
description="✅ Graphs supported.",
|
||||
size="243GB",
|
||||
supports_graph=True,
|
||||
icon="/static/servers/fastapi/assets/icons/meta.png",
|
||||
icon="/static/icons/meta.png",
|
||||
),
|
||||
"llama3.2:1b": OllamaModelMetadata(
|
||||
label="Llama 3.2:1b",
|
||||
|
|
@ -48,7 +48,7 @@ SUPPORTED_OLLAMA_MODELS = {
|
|||
description="❌ Graphs not supported.",
|
||||
size="1.3GB",
|
||||
supports_graph=False,
|
||||
icon="/static/servers/fastapi/assets/icons/meta.png",
|
||||
icon="/static/icons/meta.png",
|
||||
),
|
||||
"llama3.2:3b": OllamaModelMetadata(
|
||||
label="Llama 3.2:3b",
|
||||
|
|
@ -56,7 +56,7 @@ SUPPORTED_OLLAMA_MODELS = {
|
|||
description="❌ Graphs not supported.",
|
||||
size="2GB",
|
||||
supports_graph=False,
|
||||
icon="/static/servers/fastapi/assets/icons/meta.png",
|
||||
icon="/static/icons/meta.png",
|
||||
),
|
||||
"llama3.3:70b": OllamaModelMetadata(
|
||||
label="Llama 3.3:70b",
|
||||
|
|
@ -64,7 +64,7 @@ SUPPORTED_OLLAMA_MODELS = {
|
|||
description="✅ Graphs supported.",
|
||||
size="43GB",
|
||||
supports_graph=True,
|
||||
icon="/static/servers/fastapi/assets/icons/meta.png",
|
||||
icon="/static/icons/meta.png",
|
||||
),
|
||||
"llama4:16x17b": OllamaModelMetadata(
|
||||
label="Llama 4:16x17b",
|
||||
|
|
@ -72,7 +72,7 @@ SUPPORTED_OLLAMA_MODELS = {
|
|||
description="✅ Graphs supported.",
|
||||
size="67GB",
|
||||
supports_graph=True,
|
||||
icon="/static/servers/fastapi/assets/icons/meta.png",
|
||||
icon="/static/icons/meta.png",
|
||||
),
|
||||
"llama4:128x17b": OllamaModelMetadata(
|
||||
label="Llama 4:128x17b",
|
||||
|
|
@ -80,7 +80,7 @@ SUPPORTED_OLLAMA_MODELS = {
|
|||
description="✅ Graphs supported.",
|
||||
size="245GB",
|
||||
supports_graph=True,
|
||||
icon="/static/servers/fastapi/assets/icons/meta.png",
|
||||
icon="/static/icons/meta.png",
|
||||
),
|
||||
}
|
||||
|
||||
|
|
@ -91,7 +91,7 @@ SUPPORTED_GEMMA_MODELS = {
|
|||
description="❌ Graphs not supported.",
|
||||
size="815MB",
|
||||
supports_graph=False,
|
||||
icon="/static/servers/fastapi/assets/icons/gemma.png",
|
||||
icon="/static/icons/gemma.png",
|
||||
),
|
||||
"gemma3:4b": OllamaModelMetadata(
|
||||
label="Gemma 3:4b",
|
||||
|
|
@ -99,7 +99,7 @@ SUPPORTED_GEMMA_MODELS = {
|
|||
description="❌ Graphs not supported.",
|
||||
size="3.3GB",
|
||||
supports_graph=False,
|
||||
icon="/static/servers/fastapi/assets/icons/gemma.png",
|
||||
icon="/static/icons/gemma.png",
|
||||
),
|
||||
"gemma3:12b": OllamaModelMetadata(
|
||||
label="Gemma 3:12b",
|
||||
|
|
@ -107,7 +107,7 @@ SUPPORTED_GEMMA_MODELS = {
|
|||
description="❌ Graphs not supported.",
|
||||
size="8.1GB",
|
||||
supports_graph=False,
|
||||
icon="/static/servers/fastapi/assets/icons/gemma.png",
|
||||
icon="/static/icons/gemma.png",
|
||||
),
|
||||
"gemma3:27b": OllamaModelMetadata(
|
||||
label="Gemma 3:27b",
|
||||
|
|
@ -115,7 +115,7 @@ SUPPORTED_GEMMA_MODELS = {
|
|||
description="✅ Graphs supported.",
|
||||
size="17GB",
|
||||
supports_graph=True,
|
||||
icon="/static/servers/fastapi/assets/icons/gemma.png",
|
||||
icon="/static/icons/gemma.png",
|
||||
),
|
||||
}
|
||||
|
||||
|
|
@ -126,7 +126,7 @@ SUPPORTED_DEEPSEEK_MODELS = {
|
|||
description="❌ Graphs not supported.",
|
||||
size="1.1GB",
|
||||
supports_graph=False,
|
||||
icon="/static/servers/fastapi/assets/icons/deepseek.png",
|
||||
icon="/static/icons/deepseek.png",
|
||||
),
|
||||
"deepseek-r1:7b": OllamaModelMetadata(
|
||||
label="DeepSeek R1:7b",
|
||||
|
|
@ -134,7 +134,7 @@ SUPPORTED_DEEPSEEK_MODELS = {
|
|||
description="❌ Graphs not supported.",
|
||||
size="4.7GB",
|
||||
supports_graph=False,
|
||||
icon="/static/servers/fastapi/assets/icons/deepseek.png",
|
||||
icon="/static/icons/deepseek.png",
|
||||
),
|
||||
"deepseek-r1:8b": OllamaModelMetadata(
|
||||
label="DeepSeek R1:8b",
|
||||
|
|
@ -142,7 +142,7 @@ SUPPORTED_DEEPSEEK_MODELS = {
|
|||
description="❌ Graphs not supported.",
|
||||
size="5.2GB",
|
||||
supports_graph=False,
|
||||
icon="/static/servers/fastapi/assets/icons/deepseek.png",
|
||||
icon="/static/icons/deepseek.png",
|
||||
),
|
||||
"deepseek-r1:14b": OllamaModelMetadata(
|
||||
label="DeepSeek R1:14b",
|
||||
|
|
@ -150,7 +150,7 @@ SUPPORTED_DEEPSEEK_MODELS = {
|
|||
description="❌ Graphs not supported.",
|
||||
size="9GB",
|
||||
supports_graph=False,
|
||||
icon="/static/servers/fastapi/assets/icons/deepseek.png",
|
||||
icon="/static/icons/deepseek.png",
|
||||
),
|
||||
"deepseek-r1:32b": OllamaModelMetadata(
|
||||
label="DeepSeek R1:32b",
|
||||
|
|
@ -158,7 +158,7 @@ SUPPORTED_DEEPSEEK_MODELS = {
|
|||
description="✅ Graphs supported.",
|
||||
size="20GB",
|
||||
supports_graph=True,
|
||||
icon="/static/servers/fastapi/assets/icons/deepseek.png",
|
||||
icon="/static/icons/deepseek.png",
|
||||
),
|
||||
"deepseek-r1:70b": OllamaModelMetadata(
|
||||
label="DeepSeek R1:70b",
|
||||
|
|
@ -166,7 +166,7 @@ SUPPORTED_DEEPSEEK_MODELS = {
|
|||
description="✅ Graphs supported.",
|
||||
size="43GB",
|
||||
supports_graph=True,
|
||||
icon="/static/servers/fastapi/assets/icons/deepseek.png",
|
||||
icon="/static/icons/deepseek.png",
|
||||
),
|
||||
"deepseek-r1:671b": OllamaModelMetadata(
|
||||
label="DeepSeek R1:671b",
|
||||
|
|
@ -174,7 +174,7 @@ SUPPORTED_DEEPSEEK_MODELS = {
|
|||
description="✅ Graphs supported.",
|
||||
size="404GB",
|
||||
supports_graph=True,
|
||||
icon="/static/servers/fastapi/assets/icons/deepseek.png",
|
||||
icon="/static/icons/deepseek.png",
|
||||
),
|
||||
}
|
||||
|
||||
|
|
@ -185,7 +185,7 @@ SUPPORTED_QWEN_MODELS = {
|
|||
description="❌ Graphs not supported.",
|
||||
size="523MB",
|
||||
supports_graph=False,
|
||||
icon="/static/servers/fastapi/assets/icons/qwen.png",
|
||||
icon="/static/icons/qwen.png",
|
||||
),
|
||||
"qwen3:1.7b": OllamaModelMetadata(
|
||||
label="Qwen 3:1.7b",
|
||||
|
|
@ -193,7 +193,7 @@ SUPPORTED_QWEN_MODELS = {
|
|||
description="❌ Graphs not supported.",
|
||||
size="1.4GB",
|
||||
supports_graph=False,
|
||||
icon="/static/servers/fastapi/assets/icons/qwen.png",
|
||||
icon="/static/icons/qwen.png",
|
||||
),
|
||||
"qwen3:4b": OllamaModelMetadata(
|
||||
label="Qwen 3:4b",
|
||||
|
|
@ -201,7 +201,7 @@ SUPPORTED_QWEN_MODELS = {
|
|||
description="❌ Graphs not supported.",
|
||||
size="2.6GB",
|
||||
supports_graph=False,
|
||||
icon="/static/servers/fastapi/assets/icons/qwen.png",
|
||||
icon="/static/icons/qwen.png",
|
||||
),
|
||||
"qwen3:8b": OllamaModelMetadata(
|
||||
label="Qwen 3:8b",
|
||||
|
|
@ -209,7 +209,7 @@ SUPPORTED_QWEN_MODELS = {
|
|||
description="❌ Graphs not supported.",
|
||||
size="5.2GB",
|
||||
supports_graph=False,
|
||||
icon="/static/servers/fastapi/assets/icons/qwen.png",
|
||||
icon="/static/icons/qwen.png",
|
||||
),
|
||||
"qwen3:14b": OllamaModelMetadata(
|
||||
label="Qwen 3:14b",
|
||||
|
|
@ -217,7 +217,7 @@ SUPPORTED_QWEN_MODELS = {
|
|||
description="❌ Graphs not supported.",
|
||||
size="9.3GB",
|
||||
supports_graph=False,
|
||||
icon="/static/servers/fastapi/assets/icons/qwen.png",
|
||||
icon="/static/icons/qwen.png",
|
||||
),
|
||||
"qwen3:30b": OllamaModelMetadata(
|
||||
label="Qwen 3:30b",
|
||||
|
|
@ -225,7 +225,7 @@ SUPPORTED_QWEN_MODELS = {
|
|||
description="✅ Graphs supported.",
|
||||
size="19GB",
|
||||
supports_graph=True,
|
||||
icon="/static/servers/fastapi/assets/icons/qwen.png",
|
||||
icon="/static/icons/qwen.png",
|
||||
),
|
||||
"qwen3:32b": OllamaModelMetadata(
|
||||
label="Qwen 3:32b",
|
||||
|
|
@ -233,7 +233,7 @@ SUPPORTED_QWEN_MODELS = {
|
|||
description="✅ Graphs supported.",
|
||||
size="20GB",
|
||||
supports_graph=True,
|
||||
icon="/static/servers/fastapi/assets/icons/qwen.png",
|
||||
icon="/static/icons/qwen.png",
|
||||
),
|
||||
"qwen3:235b": OllamaModelMetadata(
|
||||
label="Qwen 3:235b",
|
||||
|
|
@ -241,7 +241,7 @@ SUPPORTED_QWEN_MODELS = {
|
|||
description="✅ Graphs supported.",
|
||||
size="142GB",
|
||||
supports_graph=True,
|
||||
icon="/static/servers/fastapi/assets/icons/qwen.png",
|
||||
icon="/static/icons/qwen.png",
|
||||
),
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,18 +9,15 @@ from models.sql.image_asset import ImageAsset
|
|||
from utils.download_helpers import download_file
|
||||
from utils.get_env import get_pexels_api_key_env
|
||||
from utils.get_env import get_pixabay_api_key_env
|
||||
from utils.llm_provider import (
|
||||
get_llm_client,
|
||||
is_google_selected,
|
||||
is_openai_selected,
|
||||
)
|
||||
from utils.llm_provider import get_llm_client
|
||||
from utils.image_provider import (
|
||||
is_pixels_selected,
|
||||
is_pixabay_selected,
|
||||
is_gemini_flash_selected,
|
||||
is_dalle3_selected
|
||||
is_dalle3_selected,
|
||||
)
|
||||
|
||||
|
||||
class ImageGenerationService:
|
||||
|
||||
def __init__(self, output_directory: str):
|
||||
|
|
@ -53,14 +50,18 @@ class ImageGenerationService:
|
|||
print("No image generation function found. Using placeholder image.")
|
||||
return "/static/images/placeholder.jpg"
|
||||
|
||||
image_prompt = prompt.get_image_prompt(with_theme=not self.is_stock_provider_selected())
|
||||
image_prompt = prompt.get_image_prompt(
|
||||
with_theme=not self.is_stock_provider_selected()
|
||||
)
|
||||
print(f"Request - Generating Image for {image_prompt}")
|
||||
|
||||
try:
|
||||
if self.is_stock_provider_selected():
|
||||
image_path = await self.image_gen_func(image_prompt)
|
||||
else:
|
||||
image_path = await self.image_gen_func(image_prompt, self.output_directory)
|
||||
image_path = await self.image_gen_func(
|
||||
image_prompt, self.output_directory
|
||||
)
|
||||
if image_path:
|
||||
if image_path.startswith("http"):
|
||||
return image_path
|
||||
|
|
@ -118,11 +119,11 @@ class ImageGenerationService:
|
|||
data = await response.json()
|
||||
image_url = data["photos"][0]["src"]["large"]
|
||||
return image_url
|
||||
|
||||
|
||||
async def get_image_from_pixabay(self, prompt: str) -> str:
|
||||
async with aiohttp.ClientSession() as session:
|
||||
response = await session.get(
|
||||
f"https://pixabay.com/api/?key={get_pixabay_api_key_env()}&q={prompt}&image_type=photo&per_page=3"
|
||||
f"https://pixabay.com/api/?key={get_pixabay_api_key_env()}&q={prompt}&image_type=photo&per_page=1"
|
||||
)
|
||||
data = await response.json()
|
||||
image_url = data["hits"][0]["largeImageURL"]
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
import os
|
||||
from enums.image_provider import ImageProvider
|
||||
from utils.get_env import (
|
||||
get_google_api_key_env,
|
||||
|
|
|
|||
|
|
@ -178,13 +178,13 @@ const SettingsPage = () => {
|
|||
|
||||
const fetchOllamaModelsWithConfig = async (config: any) => {
|
||||
try {
|
||||
const response = await fetch("/api/v1/ppt/ollama/list-supported-models");
|
||||
const data = await response.json();
|
||||
setOllamaModels(data.models);
|
||||
const response = await fetch("/api/v1/ppt/ollama/models/supported");
|
||||
const models = await response.json();
|
||||
setOllamaModels(models);
|
||||
|
||||
// Check if currently selected model is still available
|
||||
if (config.OLLAMA_MODEL && data.models.length > 0) {
|
||||
const isModelAvailable = data.models.some(
|
||||
if (config.OLLAMA_MODEL && models.length > 0) {
|
||||
const isModelAvailable = models.some(
|
||||
(model: any) => model.value === config.OLLAMA_MODEL
|
||||
);
|
||||
if (!isModelAvailable) {
|
||||
|
|
@ -220,7 +220,7 @@ const SettingsPage = () => {
|
|||
const interval = setInterval(async () => {
|
||||
try {
|
||||
const response = await fetch(
|
||||
`/api/v1/ppt/ollama/pull-model?name=${llmConfig.OLLAMA_MODEL}`
|
||||
`/api/v1/ppt/ollama/model/pull?model=${llmConfig.OLLAMA_MODEL}`
|
||||
);
|
||||
if (response.status === 200) {
|
||||
const data = await response.json();
|
||||
|
|
@ -259,7 +259,7 @@ const SettingsPage = () => {
|
|||
const fetchCustomModels = async () => {
|
||||
try {
|
||||
setCustomModelsLoading(true);
|
||||
const response = await fetch("/api/v1/ppt/models/list/custom", {
|
||||
const response = await fetch("/api/v1/ppt/custom_llm/models/available", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
|
|
@ -384,24 +384,22 @@ const SettingsPage = () => {
|
|||
<button
|
||||
key={provider}
|
||||
onClick={() => changeProvider(provider)}
|
||||
className={`relative p-4 rounded-lg border-2 transition-all duration-200 ${
|
||||
llmConfig.LLM === provider
|
||||
className={`relative p-4 rounded-lg border-2 transition-all duration-200 ${llmConfig.LLM === provider
|
||||
? "border-blue-500 bg-blue-50"
|
||||
: "border-gray-200 hover:border-blue-200 hover:bg-gray-50"
|
||||
}`}
|
||||
}`}
|
||||
>
|
||||
<div className="flex items-center justify-center gap-3">
|
||||
<span
|
||||
className={`font-medium text-center ${
|
||||
llmConfig.LLM === provider
|
||||
className={`font-medium text-center ${llmConfig.LLM === provider
|
||||
? "text-blue-700"
|
||||
: "text-gray-700"
|
||||
}`}
|
||||
}`}
|
||||
>
|
||||
{provider === "openai"
|
||||
? "OpenAI"
|
||||
: provider.charAt(0).toUpperCase() +
|
||||
provider.slice(1)}
|
||||
provider.slice(1)}
|
||||
</span>
|
||||
</div>
|
||||
</button>
|
||||
|
|
@ -481,8 +479,8 @@ const SettingsPage = () => {
|
|||
<span className="text-sm font-medium text-gray-900">
|
||||
{llmConfig.OLLAMA_MODEL
|
||||
? ollamaModels.find(
|
||||
(m) => m.value === llmConfig.OLLAMA_MODEL
|
||||
)?.label || llmConfig.OLLAMA_MODEL
|
||||
(m) => m.value === llmConfig.OLLAMA_MODEL
|
||||
)?.label || llmConfig.OLLAMA_MODEL
|
||||
: "Select a model"}
|
||||
</span>
|
||||
{llmConfig.OLLAMA_MODEL && (
|
||||
|
|
@ -686,80 +684,80 @@ const SettingsPage = () => {
|
|||
{/* Model selection dropdown - show if models are available or if there's a selected model */}
|
||||
{((customModelsChecked && customModels.length > 0) ||
|
||||
llmConfig.CUSTOM_MODEL) && (
|
||||
<div>
|
||||
<div className="mb-3 p-3 bg-amber-50 border border-amber-200 rounded-lg">
|
||||
<p className="text-sm text-amber-800">
|
||||
<strong>Important:</strong> Only models with function
|
||||
calling capabilities (tool calls) or JSON schema support
|
||||
will work.
|
||||
</p>
|
||||
</div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">
|
||||
Select Model
|
||||
</label>
|
||||
<div className="w-full">
|
||||
<Popover
|
||||
open={openModelSelect}
|
||||
onOpenChange={setOpenModelSelect}
|
||||
>
|
||||
<PopoverTrigger asChild>
|
||||
<Button
|
||||
variant="outline"
|
||||
role="combobox"
|
||||
aria-expanded={openModelSelect}
|
||||
className="w-full h-12 px-4 py-4 outline-none border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500/20 focus:border-blue-500 transition-colors hover:border-gray-400 justify-between"
|
||||
>
|
||||
<span className="text-sm font-medium text-gray-900">
|
||||
{llmConfig.CUSTOM_MODEL || "Select a model"}
|
||||
</span>
|
||||
<ChevronsUpDown className="w-4 h-4 text-gray-500" />
|
||||
</Button>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent
|
||||
className="p-0"
|
||||
align="start"
|
||||
style={{
|
||||
width: "var(--radix-popover-trigger-width)",
|
||||
}}
|
||||
<div>
|
||||
<div className="mb-3 p-3 bg-amber-50 border border-amber-200 rounded-lg">
|
||||
<p className="text-sm text-amber-800">
|
||||
<strong>Important:</strong> Only models with function
|
||||
calling capabilities (tool calls) or JSON schema support
|
||||
will work.
|
||||
</p>
|
||||
</div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">
|
||||
Select Model
|
||||
</label>
|
||||
<div className="w-full">
|
||||
<Popover
|
||||
open={openModelSelect}
|
||||
onOpenChange={setOpenModelSelect}
|
||||
>
|
||||
<Command>
|
||||
<CommandInput placeholder="Search model..." />
|
||||
<CommandList>
|
||||
<CommandEmpty>No model found.</CommandEmpty>
|
||||
<CommandGroup>
|
||||
{customModels.map((model, index) => (
|
||||
<CommandItem
|
||||
key={index}
|
||||
value={model}
|
||||
onSelect={(value) => {
|
||||
setLlmConfig({
|
||||
...llmConfig,
|
||||
CUSTOM_MODEL: value,
|
||||
});
|
||||
setOpenModelSelect(false);
|
||||
}}
|
||||
>
|
||||
<Check
|
||||
className={cn(
|
||||
"mr-2 h-4 w-4",
|
||||
llmConfig.CUSTOM_MODEL === model
|
||||
? "opacity-100"
|
||||
: "opacity-0"
|
||||
)}
|
||||
/>
|
||||
<span className="text-sm font-medium text-gray-900">
|
||||
{model}
|
||||
</span>
|
||||
</CommandItem>
|
||||
))}
|
||||
</CommandGroup>
|
||||
</CommandList>
|
||||
</Command>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
<PopoverTrigger asChild>
|
||||
<Button
|
||||
variant="outline"
|
||||
role="combobox"
|
||||
aria-expanded={openModelSelect}
|
||||
className="w-full h-12 px-4 py-4 outline-none border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500/20 focus:border-blue-500 transition-colors hover:border-gray-400 justify-between"
|
||||
>
|
||||
<span className="text-sm font-medium text-gray-900">
|
||||
{llmConfig.CUSTOM_MODEL || "Select a model"}
|
||||
</span>
|
||||
<ChevronsUpDown className="w-4 h-4 text-gray-500" />
|
||||
</Button>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent
|
||||
className="p-0"
|
||||
align="start"
|
||||
style={{
|
||||
width: "var(--radix-popover-trigger-width)",
|
||||
}}
|
||||
>
|
||||
<Command>
|
||||
<CommandInput placeholder="Search model..." />
|
||||
<CommandList>
|
||||
<CommandEmpty>No model found.</CommandEmpty>
|
||||
<CommandGroup>
|
||||
{customModels.map((model, index) => (
|
||||
<CommandItem
|
||||
key={index}
|
||||
value={model}
|
||||
onSelect={(value) => {
|
||||
setLlmConfig({
|
||||
...llmConfig,
|
||||
CUSTOM_MODEL: value,
|
||||
});
|
||||
setOpenModelSelect(false);
|
||||
}}
|
||||
>
|
||||
<Check
|
||||
className={cn(
|
||||
"mr-2 h-4 w-4",
|
||||
llmConfig.CUSTOM_MODEL === model
|
||||
? "opacity-100"
|
||||
: "opacity-0"
|
||||
)}
|
||||
/>
|
||||
<span className="text-sm font-medium text-gray-900">
|
||||
{model}
|
||||
</span>
|
||||
</CommandItem>
|
||||
))}
|
||||
</CommandGroup>
|
||||
</CommandList>
|
||||
</Command>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
)}
|
||||
|
||||
{/* Check for available models button - show when no models checked or no models found, and no model is selected */}
|
||||
{(!customModelsChecked ||
|
||||
|
|
@ -771,11 +769,10 @@ const SettingsPage = () => {
|
|||
disabled={
|
||||
customModelsLoading || !llmConfig.CUSTOM_LLM_URL
|
||||
}
|
||||
className={`w-full py-2.5 px-4 rounded-lg transition-all duration-200 border-2 font-semibold ${
|
||||
customModelsLoading || !llmConfig.CUSTOM_LLM_URL
|
||||
className={`w-full py-2.5 px-4 rounded-lg transition-all duration-200 border-2 font-semibold ${customModelsLoading || !llmConfig.CUSTOM_LLM_URL
|
||||
? "bg-gray-100 border-gray-300 cursor-not-allowed text-gray-500"
|
||||
: "bg-white border-blue-600 text-blue-600 hover:bg-blue-50 focus:ring-2 focus:ring-blue-500/20"
|
||||
}`}
|
||||
}`}
|
||||
>
|
||||
{customModelsLoading ? (
|
||||
<div className="flex items-center justify-center gap-2">
|
||||
|
|
@ -806,11 +803,10 @@ const SettingsPage = () => {
|
|||
disabled={
|
||||
customModelsLoading || !llmConfig.CUSTOM_LLM_URL
|
||||
}
|
||||
className={`w-full py-2.5 px-4 rounded-lg transition-all duration-200 border-2 font-semibold ${
|
||||
customModelsLoading || !llmConfig.CUSTOM_LLM_URL
|
||||
className={`w-full py-2.5 px-4 rounded-lg transition-all duration-200 border-2 font-semibold ${customModelsLoading || !llmConfig.CUSTOM_LLM_URL
|
||||
? "bg-gray-100 border-gray-300 cursor-not-allowed text-gray-500"
|
||||
: "bg-white border-gray-600 text-gray-600 hover:bg-gray-50 focus:ring-2 focus:ring-gray-500/20"
|
||||
}`}
|
||||
}`}
|
||||
>
|
||||
{customModelsLoading ? (
|
||||
<div className="flex items-center justify-center gap-2">
|
||||
|
|
@ -868,7 +864,7 @@ const SettingsPage = () => {
|
|||
<span className="text-sm font-medium text-gray-900">
|
||||
{llmConfig.IMAGE_PROVIDER
|
||||
? IMAGE_PROVIDERS[llmConfig.IMAGE_PROVIDER]
|
||||
?.title || llmConfig.IMAGE_PROVIDER
|
||||
?.title || llmConfig.IMAGE_PROVIDER
|
||||
: "Select image provider"}
|
||||
</span>
|
||||
</div>
|
||||
|
|
@ -962,8 +958,8 @@ const SettingsPage = () => {
|
|||
provider.apiKeyField === "PEXELS_API_KEY"
|
||||
? llmConfig.PEXELS_API_KEY || ""
|
||||
: provider.apiKeyField === "PIXABAY_API_KEY"
|
||||
? llmConfig.PIXABAY_API_KEY || ""
|
||||
: ""
|
||||
? llmConfig.PIXABAY_API_KEY || ""
|
||||
: ""
|
||||
}
|
||||
onChange={(e) => {
|
||||
if (provider.apiKeyField === "PEXELS_API_KEY") {
|
||||
|
|
@ -998,25 +994,24 @@ const SettingsPage = () => {
|
|||
(llmConfig.LLM === "ollama" && !llmConfig.OLLAMA_MODEL) ||
|
||||
(llmConfig.LLM === "custom" && !llmConfig.CUSTOM_MODEL)
|
||||
}
|
||||
className={`mt-8 w-full font-semibold py-3 px-4 rounded-lg transition-all duration-500 ${
|
||||
isLoading ||
|
||||
(llmConfig.LLM === "ollama" && !llmConfig.OLLAMA_MODEL) ||
|
||||
(llmConfig.LLM === "custom" && !llmConfig.CUSTOM_MODEL)
|
||||
className={`mt-8 w-full font-semibold py-3 px-4 rounded-lg transition-all duration-500 ${isLoading ||
|
||||
(llmConfig.LLM === "ollama" && !llmConfig.OLLAMA_MODEL) ||
|
||||
(llmConfig.LLM === "custom" && !llmConfig.CUSTOM_MODEL)
|
||||
? "bg-gray-400 cursor-not-allowed"
|
||||
: "bg-gradient-to-r from-blue-600 to-indigo-600 hover:from-blue-700 hover:to-indigo-700 focus:ring-4 focus:ring-blue-200"
|
||||
} text-white`}
|
||||
} text-white`}
|
||||
>
|
||||
{isLoading ? (
|
||||
<div className="flex items-center justify-center gap-2">
|
||||
<Loader2 className="w-4 h-4 animate-spin" />
|
||||
{(llmConfig.LLM === "ollama" &&
|
||||
downloadingModel.downloaded) ||
|
||||
0 > 0
|
||||
0 > 0
|
||||
? `Downloading Model (${(
|
||||
((downloadingModel.downloaded || 0) /
|
||||
(downloadingModel.size || 1)) *
|
||||
100
|
||||
).toFixed(0)}%)`
|
||||
((downloadingModel.downloaded || 0) /
|
||||
(downloadingModel.size || 1)) *
|
||||
100
|
||||
).toFixed(0)}%)`
|
||||
: "Saving Configuration..."}
|
||||
</div>
|
||||
) : (llmConfig.LLM === "ollama" && !llmConfig.OLLAMA_MODEL) ||
|
||||
|
|
|
|||
|
|
@ -84,9 +84,9 @@ export function StoreInitializer({ children }: { children: React.ReactNode }) {
|
|||
|
||||
const checkIfSelectedOllamaModelIsPulled = async (ollamaModel: string) => {
|
||||
try {
|
||||
const response = await fetch('/api/v1/ppt/ollama/list-pulled-models');
|
||||
const data = await response.json();
|
||||
const pulledModels = data.map((model: any) => model.name);
|
||||
const response = await fetch('/api/v1/ppt/ollama/models/available');
|
||||
const models = await response.json();
|
||||
const pulledModels = models.map((model: any) => model.name);
|
||||
return pulledModels.includes(ollamaModel);
|
||||
} catch (error) {
|
||||
console.error('Error checking if selected Ollama model is pulled:', error);
|
||||
|
|
@ -96,7 +96,7 @@ export function StoreInitializer({ children }: { children: React.ReactNode }) {
|
|||
|
||||
const checkIfSelectedCustomModelIsAvailable = async (customModel: string) => {
|
||||
try {
|
||||
const response = await fetch('/api/v1/ppt/models/list/custom', {
|
||||
const response = await fetch('/api/v1/ppt/custom_llm/models/available', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
|
|
|
|||
|
|
@ -214,7 +214,8 @@ export default function Home() {
|
|||
const router = useRouter();
|
||||
const [openImageProviderSelect, setOpenImageProviderSelect] = useState(false);
|
||||
const config = useSelector((state: RootState) => state.userConfig);
|
||||
const [llmConfig, setLlmConfig] = useState({...config.llm_config,
|
||||
const [llmConfig, setLlmConfig] = useState({
|
||||
...config.llm_config,
|
||||
IMAGE_PROVIDER: "dall-e-3",
|
||||
});
|
||||
const [ollamaModels, setOllamaModels] = useState<
|
||||
|
|
@ -297,13 +298,13 @@ export default function Home() {
|
|||
|
||||
const fetchOllamaModelsWithConfig = async (config: any) => {
|
||||
try {
|
||||
const response = await fetch("/api/v1/ppt/ollama/list-supported-models");
|
||||
const data = await response.json();
|
||||
setOllamaModels(data.models || []);
|
||||
const response = await fetch("/api/v1/ppt/ollama/models/supported");
|
||||
const models = await response.json();
|
||||
setOllamaModels(models || []);
|
||||
|
||||
// Check if currently selected model is still available
|
||||
if (config.OLLAMA_MODEL && data.models && data.models.length > 0) {
|
||||
const isModelAvailable = data.models.some(
|
||||
if (config.OLLAMA_MODEL && models && models.length > 0) {
|
||||
const isModelAvailable = models.some(
|
||||
(model: any) => model.value === config.OLLAMA_MODEL
|
||||
);
|
||||
if (!isModelAvailable) {
|
||||
|
|
@ -350,7 +351,7 @@ export default function Home() {
|
|||
const interval = setInterval(async () => {
|
||||
try {
|
||||
const response = await fetch(
|
||||
`/api/v1/ppt/ollama/pull-model?name=${llmConfig.OLLAMA_MODEL}`
|
||||
`/api/v1/ppt/ollama/model/pull?model=${llmConfig.OLLAMA_MODEL}`
|
||||
);
|
||||
if (response.status === 200) {
|
||||
const data = await response.json();
|
||||
|
|
@ -389,7 +390,7 @@ export default function Home() {
|
|||
const fetchCustomModels = async () => {
|
||||
try {
|
||||
setCustomModelsLoading(true);
|
||||
const response = await fetch("/api/v1/ppt/models/list/custom", {
|
||||
const response = await fetch("/api/v1/ppt/custom_llm/models/available", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
|
|
@ -505,19 +506,17 @@ export default function Home() {
|
|||
<button
|
||||
key={provider}
|
||||
onClick={() => changeProvider(provider)}
|
||||
className={`relative p-4 rounded-lg border-2 transition-all duration-200 ${
|
||||
llmConfig.LLM === provider
|
||||
? "border-blue-500 bg-blue-50"
|
||||
: "border-gray-200 hover:border-blue-200 hover:bg-gray-50"
|
||||
}`}
|
||||
className={`relative p-4 rounded-lg border-2 transition-all duration-200 ${llmConfig.LLM === provider
|
||||
? "border-blue-500 bg-blue-50"
|
||||
: "border-gray-200 hover:border-blue-200 hover:bg-gray-50"
|
||||
}`}
|
||||
>
|
||||
<div className="flex items-center justify-center gap-3">
|
||||
<span
|
||||
className={`font-medium text-center ${
|
||||
llmConfig.LLM === provider
|
||||
? "text-blue-700"
|
||||
: "text-gray-700"
|
||||
}`}
|
||||
className={`font-medium text-center ${llmConfig.LLM === provider
|
||||
? "text-blue-700"
|
||||
: "text-gray-700"
|
||||
}`}
|
||||
>
|
||||
{provider === "openai"
|
||||
? "OpenAI"
|
||||
|
|
@ -599,8 +598,8 @@ export default function Home() {
|
|||
<span className="text-sm font-medium text-gray-900">
|
||||
{llmConfig.OLLAMA_MODEL
|
||||
? ollamaModels?.find(
|
||||
(m) => m.value === llmConfig.OLLAMA_MODEL
|
||||
)?.label || llmConfig.OLLAMA_MODEL
|
||||
(m) => m.value === llmConfig.OLLAMA_MODEL
|
||||
)?.label || llmConfig.OLLAMA_MODEL
|
||||
: "Select a model"}
|
||||
</span>
|
||||
{llmConfig.OLLAMA_MODEL && (
|
||||
|
|
@ -840,27 +839,26 @@ export default function Home() {
|
|||
{/* Check for available models button - show when no models checked or no models found */}
|
||||
{(!customModelsChecked ||
|
||||
(customModelsChecked && customModels.length === 0)) && (
|
||||
<div className="mb-4">
|
||||
<button
|
||||
onClick={fetchCustomModels}
|
||||
disabled={customModelsLoading || !llmConfig.CUSTOM_LLM_URL}
|
||||
className={`w-full py-2.5 px-4 rounded-lg transition-all duration-200 border-2 ${
|
||||
customModelsLoading || !llmConfig.CUSTOM_LLM_URL
|
||||
<div className="mb-4">
|
||||
<button
|
||||
onClick={fetchCustomModels}
|
||||
disabled={customModelsLoading || !llmConfig.CUSTOM_LLM_URL}
|
||||
className={`w-full py-2.5 px-4 rounded-lg transition-all duration-200 border-2 ${customModelsLoading || !llmConfig.CUSTOM_LLM_URL
|
||||
? "bg-gray-100 border-gray-300 cursor-not-allowed text-gray-500"
|
||||
: "bg-white border-blue-600 text-blue-600 hover:bg-blue-50 focus:ring-2 focus:ring-blue-500/20"
|
||||
}`}
|
||||
>
|
||||
{customModelsLoading ? (
|
||||
<div className="flex items-center justify-center gap-2">
|
||||
<Loader2 className="w-4 h-4 animate-spin" />
|
||||
Checking for models...
|
||||
</div>
|
||||
) : (
|
||||
"Check for available models"
|
||||
)}
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
}`}
|
||||
>
|
||||
{customModelsLoading ? (
|
||||
<div className="flex items-center justify-center gap-2">
|
||||
<Loader2 className="w-4 h-4 animate-spin" />
|
||||
Checking for models...
|
||||
</div>
|
||||
) : (
|
||||
"Check for available models"
|
||||
)}
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Show message if no models found */}
|
||||
{customModelsChecked && customModels.length === 0 && (
|
||||
|
|
@ -893,7 +891,7 @@ export default function Home() {
|
|||
<span className="text-sm font-medium text-gray-900">
|
||||
{llmConfig.IMAGE_PROVIDER
|
||||
? IMAGE_PROVIDERS[llmConfig.IMAGE_PROVIDER]?.label ||
|
||||
llmConfig.IMAGE_PROVIDER
|
||||
llmConfig.IMAGE_PROVIDER
|
||||
: "Select image provider"}
|
||||
</span>
|
||||
</div>
|
||||
|
|
@ -986,8 +984,8 @@ export default function Home() {
|
|||
provider.apiKeyField === "PEXELS_API_KEY"
|
||||
? llmConfig.PEXELS_API_KEY || ""
|
||||
: provider.apiKeyField === "PIXABAY_API_KEY"
|
||||
? llmConfig.PIXABAY_API_KEY || ""
|
||||
: ""
|
||||
? llmConfig.PIXABAY_API_KEY || ""
|
||||
: ""
|
||||
}
|
||||
onChange={(e) => {
|
||||
if (provider.apiKeyField === "PEXELS_API_KEY") {
|
||||
|
|
@ -1022,11 +1020,11 @@ export default function Home() {
|
|||
{llmConfig.LLM === "ollama"
|
||||
? llmConfig.OLLAMA_MODEL ?? "_____"
|
||||
: llmConfig.LLM === "custom"
|
||||
? llmConfig.CUSTOM_MODEL ?? "_____"
|
||||
: PROVIDER_CONFIGS[llmConfig.LLM!].textModels[0].label}{" "}
|
||||
? llmConfig.CUSTOM_MODEL ?? "_____"
|
||||
: PROVIDER_CONFIGS[llmConfig.LLM!].textModels[0].label}{" "}
|
||||
for text generation and{" "}
|
||||
{llmConfig.IMAGE_PROVIDER &&
|
||||
IMAGE_PROVIDERS[llmConfig.IMAGE_PROVIDER]
|
||||
IMAGE_PROVIDERS[llmConfig.IMAGE_PROVIDER]
|
||||
? IMAGE_PROVIDERS[llmConfig.IMAGE_PROVIDER].label
|
||||
: "_____"}{" "}
|
||||
for images
|
||||
|
|
@ -1101,24 +1099,23 @@ export default function Home() {
|
|||
(llmConfig.LLM === "ollama" && !llmConfig.OLLAMA_MODEL) ||
|
||||
(llmConfig.LLM === "custom" && !llmConfig.CUSTOM_MODEL)
|
||||
}
|
||||
className={`mt-8 w-full font-semibold py-3 px-4 rounded-lg transition-all duration-500 ${
|
||||
isLoading ||
|
||||
className={`mt-8 w-full font-semibold py-3 px-4 rounded-lg transition-all duration-500 ${isLoading ||
|
||||
(llmConfig.LLM === "ollama" && !llmConfig.OLLAMA_MODEL) ||
|
||||
(llmConfig.LLM === "custom" && !llmConfig.CUSTOM_MODEL)
|
||||
? "bg-gray-400 cursor-not-allowed"
|
||||
: "bg-gradient-to-r from-blue-600 to-indigo-600 hover:from-blue-700 hover:to-indigo-700 focus:ring-4 focus:ring-blue-200"
|
||||
} text-white`}
|
||||
? "bg-gray-400 cursor-not-allowed"
|
||||
: "bg-gradient-to-r from-blue-600 to-indigo-600 hover:from-blue-700 hover:to-indigo-700 focus:ring-4 focus:ring-blue-200"
|
||||
} text-white`}
|
||||
>
|
||||
{isLoading ? (
|
||||
<div className="flex items-center justify-center gap-2">
|
||||
<Loader2 className="w-4 h-4 animate-spin" />
|
||||
{(llmConfig.LLM === "ollama" && downloadingModel.downloaded) ||
|
||||
0 > 0
|
||||
0 > 0
|
||||
? `Downloading Model (${(
|
||||
((downloadingModel.downloaded || 0) /
|
||||
(downloadingModel.size || 1)) *
|
||||
100
|
||||
).toFixed(0)}%)`
|
||||
((downloadingModel.downloaded || 0) /
|
||||
(downloadingModel.size || 1)) *
|
||||
100
|
||||
).toFixed(0)}%)`
|
||||
: "Saving Configuration..."}
|
||||
</div>
|
||||
) : (llmConfig.LLM === "ollama" && !llmConfig.OLLAMA_MODEL) ||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue