mirror of
https://github.com/Part-DB/Part-DB-server.git
synced 2026-07-31 21:51:38 +00:00
Compare commits
2 commits
b60887c71d
...
3e725dd2ec
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3e725dd2ec | ||
|
|
ec80115d0a |
11 changed files with 74 additions and 2 deletions
|
|
@ -2,3 +2,4 @@ ai:
|
||||||
platform:
|
platform:
|
||||||
lmstudio:
|
lmstudio:
|
||||||
host_url: '%env(string:settings:ai_lmstudio:hostURL)%'
|
host_url: '%env(string:settings:ai_lmstudio:hostURL)%'
|
||||||
|
http_client: 'app.http_client.ai_lmstudio'
|
||||||
|
|
|
||||||
|
|
@ -3,3 +3,4 @@ ai:
|
||||||
ollama:
|
ollama:
|
||||||
endpoint: '%env(string:settings:ai_ollama:endpoint)%'
|
endpoint: '%env(string:settings:ai_ollama:endpoint)%'
|
||||||
api_key: '%env(string:settings:ai_ollama:apiKey)%'
|
api_key: '%env(string:settings:ai_ollama:apiKey)%'
|
||||||
|
http_client: 'app.http_client.ai_ollama'
|
||||||
|
|
|
||||||
|
|
@ -2,3 +2,4 @@ ai:
|
||||||
platform:
|
platform:
|
||||||
openrouter:
|
openrouter:
|
||||||
api_key: '%env(string:settings:ai_openrouter:apiKey)%'
|
api_key: '%env(string:settings:ai_openrouter:apiKey)%'
|
||||||
|
http_client: 'app.http_client.ai_openrouter'
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,28 @@ services:
|
||||||
alias: 'doctrine.migrations.dependency_factory'
|
alias: 'doctrine.migrations.dependency_factory'
|
||||||
|
|
||||||
|
|
||||||
|
####################################################################################################################
|
||||||
|
# AI provider HTTP clients (with configurable timeouts)
|
||||||
|
####################################################################################################################
|
||||||
|
|
||||||
|
app.http_client.ai_ollama:
|
||||||
|
class: Symfony\Contracts\HttpClient\HttpClientInterface
|
||||||
|
factory: ['@http_client', 'withOptions']
|
||||||
|
arguments:
|
||||||
|
- { timeout: '%env(int:settings:ai_ollama:timeout)%' }
|
||||||
|
|
||||||
|
app.http_client.ai_lmstudio:
|
||||||
|
class: Symfony\Contracts\HttpClient\HttpClientInterface
|
||||||
|
factory: ['@http_client', 'withOptions']
|
||||||
|
arguments:
|
||||||
|
- { timeout: '%env(int:settings:ai_lmstudio:timeout)%' }
|
||||||
|
|
||||||
|
app.http_client.ai_openrouter:
|
||||||
|
class: Symfony\Contracts\HttpClient\HttpClientInterface
|
||||||
|
factory: ['@http_client', 'withOptions']
|
||||||
|
arguments:
|
||||||
|
- { timeout: '%env(int:settings:ai_openrouter:timeout)%' }
|
||||||
|
|
||||||
####################################################################################################################
|
####################################################################################################################
|
||||||
# Email
|
# Email
|
||||||
####################################################################################################################
|
####################################################################################################################
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ final class DTOJsonSchemaConverter
|
||||||
public function getJSONSchema(): array
|
public function getJSONSchema(): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'name' => 'clock',
|
'name' => 'part_detail',
|
||||||
'strict' => true,
|
'strict' => true,
|
||||||
'schema' => [
|
'schema' => [
|
||||||
'type' => 'object',
|
'type' => 'object',
|
||||||
|
|
|
||||||
|
|
@ -282,6 +282,10 @@ final class AIWebProvider implements InfoProviderInterface
|
||||||
try {
|
try {
|
||||||
$aiPlatform = $this->AIPlatformRegistry->getPlatform($this->settings->platform ?? throw new \RuntimeException('No AI platform selected') );
|
$aiPlatform = $this->AIPlatformRegistry->getPlatform($this->settings->platform ?? throw new \RuntimeException('No AI platform selected') );
|
||||||
|
|
||||||
|
// AI inference can take much longer than PHP's default max_execution_time (typically 30s).
|
||||||
|
// The HTTP client timeout already enforces the configured limit; disable PHP's constraint here.
|
||||||
|
set_time_limit(0);
|
||||||
|
|
||||||
//'openai/gpt-5-mini'
|
//'openai/gpt-5-mini'
|
||||||
$result = $aiPlatform->invoke($this->settings->model ?? throw new \RuntimeException('No model selected'), $input, [
|
$result = $aiPlatform->invoke($this->settings->model ?? throw new \RuntimeException('No model selected'), $input, [
|
||||||
'response_format' => [
|
'response_format' => [
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,8 @@ class AISettings
|
||||||
{
|
{
|
||||||
use SettingsTrait;
|
use SettingsTrait;
|
||||||
|
|
||||||
|
public const TIMEOUT_LIMIT = 600;
|
||||||
|
|
||||||
#[EmbeddedSettings]
|
#[EmbeddedSettings]
|
||||||
public ?OpenRouterSettings $openRouter = null;
|
public ?OpenRouterSettings $openRouter = null;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,16 +23,17 @@ declare(strict_types=1);
|
||||||
|
|
||||||
namespace App\Settings\AISettings;
|
namespace App\Settings\AISettings;
|
||||||
|
|
||||||
use App\Form\Type\APIKeyType;
|
|
||||||
use App\Services\AI\AIPlatformSettingsInterface;
|
use App\Services\AI\AIPlatformSettingsInterface;
|
||||||
use App\Settings\SettingsIcon;
|
use App\Settings\SettingsIcon;
|
||||||
use Jbtronics\SettingsBundle\Metadata\EnvVarMode;
|
use Jbtronics\SettingsBundle\Metadata\EnvVarMode;
|
||||||
use Jbtronics\SettingsBundle\Settings\Settings;
|
use Jbtronics\SettingsBundle\Settings\Settings;
|
||||||
use Jbtronics\SettingsBundle\Settings\SettingsParameter;
|
use Jbtronics\SettingsBundle\Settings\SettingsParameter;
|
||||||
use Jbtronics\SettingsBundle\Settings\SettingsTrait;
|
use Jbtronics\SettingsBundle\Settings\SettingsTrait;
|
||||||
|
use Symfony\Component\Form\Extension\Core\Type\NumberType;
|
||||||
use Symfony\Component\Form\Extension\Core\Type\UrlType;
|
use Symfony\Component\Form\Extension\Core\Type\UrlType;
|
||||||
use Symfony\Component\Translation\StaticMessage;
|
use Symfony\Component\Translation\StaticMessage;
|
||||||
use Symfony\Component\Translation\TranslatableMessage as TM;
|
use Symfony\Component\Translation\TranslatableMessage as TM;
|
||||||
|
use Symfony\Component\Validator\Constraints as Assert;
|
||||||
|
|
||||||
#[Settings(name: 'ai_lmstudio', label: new TM("settings.ai.lmstudio"))]
|
#[Settings(name: 'ai_lmstudio', label: new TM("settings.ai.lmstudio"))]
|
||||||
#[SettingsIcon("fa-robot")]
|
#[SettingsIcon("fa-robot")]
|
||||||
|
|
@ -46,6 +47,14 @@ class LMStudioSettings implements AIPlatformSettingsInterface
|
||||||
envVar: "AI_LMSTUDIO_HOSTURL", envVarMode: EnvVarMode::OVERWRITE)]
|
envVar: "AI_LMSTUDIO_HOSTURL", envVarMode: EnvVarMode::OVERWRITE)]
|
||||||
public ?string $hostURL = null;
|
public ?string $hostURL = null;
|
||||||
|
|
||||||
|
#[SettingsParameter(label: new TM("settings.ai.timeout"),
|
||||||
|
description: new TM("settings.ai.timeout.help"),
|
||||||
|
formType: NumberType::class,
|
||||||
|
formOptions: ["scale" => 0, "attr" => ["min" => 1]],
|
||||||
|
)]
|
||||||
|
#[Assert\Range(min: 1, max: AISettings::TIMEOUT_LIMIT)]
|
||||||
|
public int $timeout = 180;
|
||||||
|
|
||||||
public function isAIPlatformEnabled(): bool
|
public function isAIPlatformEnabled(): bool
|
||||||
{
|
{
|
||||||
return $this->hostURL !== null && $this->hostURL !== "";
|
return $this->hostURL !== null && $this->hostURL !== "";
|
||||||
|
|
|
||||||
|
|
@ -30,9 +30,11 @@ use Jbtronics\SettingsBundle\Metadata\EnvVarMode;
|
||||||
use Jbtronics\SettingsBundle\Settings\Settings;
|
use Jbtronics\SettingsBundle\Settings\Settings;
|
||||||
use Jbtronics\SettingsBundle\Settings\SettingsParameter;
|
use Jbtronics\SettingsBundle\Settings\SettingsParameter;
|
||||||
use Jbtronics\SettingsBundle\Settings\SettingsTrait;
|
use Jbtronics\SettingsBundle\Settings\SettingsTrait;
|
||||||
|
use Symfony\Component\Form\Extension\Core\Type\NumberType;
|
||||||
use Symfony\Component\Form\Extension\Core\Type\UrlType;
|
use Symfony\Component\Form\Extension\Core\Type\UrlType;
|
||||||
use Symfony\Component\Translation\StaticMessage;
|
use Symfony\Component\Translation\StaticMessage;
|
||||||
use Symfony\Component\Translation\TranslatableMessage as TM;
|
use Symfony\Component\Translation\TranslatableMessage as TM;
|
||||||
|
use Symfony\Component\Validator\Constraints as Assert;
|
||||||
|
|
||||||
#[Settings(name: 'ai_ollama', label: new TM("settings.ai.ollama"))]
|
#[Settings(name: 'ai_ollama', label: new TM("settings.ai.ollama"))]
|
||||||
#[SettingsIcon("fa-robot")]
|
#[SettingsIcon("fa-robot")]
|
||||||
|
|
@ -51,6 +53,14 @@ class OllamaSettings implements AIPlatformSettingsInterface
|
||||||
envVar: "AI_OLLAMA_API_KEY", envVarMode: EnvVarMode::OVERWRITE)]
|
envVar: "AI_OLLAMA_API_KEY", envVarMode: EnvVarMode::OVERWRITE)]
|
||||||
public ?string $apiKey = null;
|
public ?string $apiKey = null;
|
||||||
|
|
||||||
|
#[SettingsParameter(label: new TM("settings.ai.timeout"),
|
||||||
|
description: new TM("settings.ai.timeout.help"),
|
||||||
|
formType: NumberType::class,
|
||||||
|
formOptions: ["scale" => 0, "attr" => ["min" => 1]]
|
||||||
|
)]
|
||||||
|
#[Assert\Range(min: 1, max: AISettings::TIMEOUT_LIMIT)]
|
||||||
|
public int $timeout = 180;
|
||||||
|
|
||||||
public function isAIPlatformEnabled(): bool
|
public function isAIPlatformEnabled(): bool
|
||||||
{
|
{
|
||||||
return $this->endpoint !== null && $this->endpoint !== "";
|
return $this->endpoint !== null && $this->endpoint !== "";
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,9 @@ use Jbtronics\SettingsBundle\Metadata\EnvVarMode;
|
||||||
use Jbtronics\SettingsBundle\Settings\Settings;
|
use Jbtronics\SettingsBundle\Settings\Settings;
|
||||||
use Jbtronics\SettingsBundle\Settings\SettingsParameter;
|
use Jbtronics\SettingsBundle\Settings\SettingsParameter;
|
||||||
use Jbtronics\SettingsBundle\Settings\SettingsTrait;
|
use Jbtronics\SettingsBundle\Settings\SettingsTrait;
|
||||||
|
use Symfony\Component\Form\Extension\Core\Type\NumberType;
|
||||||
use Symfony\Component\Translation\TranslatableMessage as TM;
|
use Symfony\Component\Translation\TranslatableMessage as TM;
|
||||||
|
use Symfony\Component\Validator\Constraints as Assert;
|
||||||
|
|
||||||
#[Settings(name: 'ai_openrouter', label: new TM("settings.ai.openrouter"), description: "settings.ai.openrouter.help")]
|
#[Settings(name: 'ai_openrouter', label: new TM("settings.ai.openrouter"), description: "settings.ai.openrouter.help")]
|
||||||
#[SettingsIcon("fa-robot")]
|
#[SettingsIcon("fa-robot")]
|
||||||
|
|
@ -43,6 +45,14 @@ class OpenRouterSettings implements AIPlatformSettingsInterface
|
||||||
formOptions: ["help_html" => true], envVar: "AI_OPENROUTER_KEY", envVarMode: EnvVarMode::OVERWRITE)]
|
formOptions: ["help_html" => true], envVar: "AI_OPENROUTER_KEY", envVarMode: EnvVarMode::OVERWRITE)]
|
||||||
public ?string $apiKey = null;
|
public ?string $apiKey = null;
|
||||||
|
|
||||||
|
#[SettingsParameter(label: new TM("settings.ai.timeout"),
|
||||||
|
description: new TM("settings.ai.timeout.help"),
|
||||||
|
formType: NumberType::class,
|
||||||
|
formOptions: ["scale" => 0, "attr" => ["min" => 1]],
|
||||||
|
envVar: "int:AI_OPENROUTER_TIMEOUT", envVarMode: EnvVarMode::OVERWRITE)]
|
||||||
|
#[Assert\Range(min: 1, max: AISettings::TIMEOUT_LIMIT)]
|
||||||
|
public int $timeout = 90;
|
||||||
|
|
||||||
public function isAIPlatformEnabled(): bool
|
public function isAIPlatformEnabled(): bool
|
||||||
{
|
{
|
||||||
return $this->apiKey !== null && $this->apiKey !== "";
|
return $this->apiKey !== null && $this->apiKey !== "";
|
||||||
|
|
|
||||||
|
|
@ -13637,6 +13637,18 @@ Buerklin-API Authentication server:
|
||||||
<target>API Key</target>
|
<target>API Key</target>
|
||||||
</segment>
|
</segment>
|
||||||
</unit>
|
</unit>
|
||||||
|
<unit id="VxXEQUD" name="settings.ai.timeout">
|
||||||
|
<segment state="translated">
|
||||||
|
<source>settings.ai.timeout</source>
|
||||||
|
<target>Timeout</target>
|
||||||
|
</segment>
|
||||||
|
</unit>
|
||||||
|
<unit id="vRgtpoJ" name="settings.ai.timeout.help">
|
||||||
|
<segment state="translated">
|
||||||
|
<source>settings.ai.timeout.help</source>
|
||||||
|
<target>Maximum time in seconds to wait for a response. Local AI inference might take multiple minutes, cloud inference is normally faster.</target>
|
||||||
|
</segment>
|
||||||
|
</unit>
|
||||||
<unit id="kuDv.So" name="browser_plugin.recent_pages.title">
|
<unit id="kuDv.So" name="browser_plugin.recent_pages.title">
|
||||||
<segment state="translated">
|
<segment state="translated">
|
||||||
<source>browser_plugin.recent_pages.title</source>
|
<source>browser_plugin.recent_pages.title</source>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue