This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import { useMemo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { HelpText } from './HelpText';
|
||||
import { EnvOverrideWarning, FieldLabel, FieldInput } from './formUtils';
|
||||
import { SecretInput } from './SecretInput';
|
||||
@@ -99,6 +100,7 @@ function detectSelfLoop(endpoint: string | undefined): boolean {
|
||||
* endpoint host looks like the current AAO instance
|
||||
*/
|
||||
export function LlmWorkersForm({ config, onChange, overriddenByEnv }: SectionFormProps) {
|
||||
const { t } = useTranslation('settings');
|
||||
const llm: LlmConfigShape = config.llm ?? {};
|
||||
const workers: LlmWorker[] = Array.isArray(llm.workers) ? llm.workers : [];
|
||||
const retry = llm.retry ?? {};
|
||||
@@ -144,21 +146,17 @@ export function LlmWorkersForm({ config, onChange, overriddenByEnv }: SectionFor
|
||||
return (
|
||||
<div className="space-y-5">
|
||||
<div>
|
||||
<h2 className="text-base font-semibold text-slate-800 mb-1">LLM Workers</h2>
|
||||
<h2 className="text-base font-semibold text-slate-800 mb-1">{t('llmWorkers.title')}</h2>
|
||||
<p className="text-xs text-slate-500 leading-relaxed">
|
||||
このセクションは AAO がジョブ実行で <strong>呼び出す</strong> LLM 接続先 (workers)
|
||||
を定義します。AAO 自身を gateway として公開する設定は <em>LLM → Gateway Server</em>
|
||||
にあります。<br />
|
||||
ロール: <code>auto</code> (全 job 候補) / <code>fast</code> · <code>quality</code>
|
||||
(パフォーマンス profile) / <code>reflection</code> (reflection 専用) /{' '}
|
||||
<code>title</code> (タイトル生成専用)。複数指定可。
|
||||
{t('llmWorkers.intro')}<br />
|
||||
{t('llmWorkers.rolesHelp')}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="space-y-3">
|
||||
{workers.length === 0 && (
|
||||
<div className="text-xs text-slate-500 border border-dashed border-slate-200 rounded p-4 text-center">
|
||||
worker が未登録です。最低 1 つ追加してください。
|
||||
{t('llmWorkers.empty')}
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -173,7 +171,7 @@ export function LlmWorkersForm({ config, onChange, overriddenByEnv }: SectionFor
|
||||
<button
|
||||
onClick={() => moveWorker(i, -1)}
|
||||
disabled={i === 0}
|
||||
title="上に移動"
|
||||
title={t('llmWorkers.moveUp')}
|
||||
className="text-slate-400 hover:text-slate-700 text-sm leading-none disabled:opacity-30 disabled:cursor-not-allowed px-1"
|
||||
>
|
||||
↑
|
||||
@@ -181,14 +179,14 @@ export function LlmWorkersForm({ config, onChange, overriddenByEnv }: SectionFor
|
||||
<button
|
||||
onClick={() => moveWorker(i, 1)}
|
||||
disabled={i === workers.length - 1}
|
||||
title="下に移動"
|
||||
title={t('llmWorkers.moveDown')}
|
||||
className="text-slate-400 hover:text-slate-700 text-sm leading-none disabled:opacity-30 disabled:cursor-not-allowed px-1"
|
||||
>
|
||||
↓
|
||||
</button>
|
||||
<button
|
||||
onClick={() => removeWorker(i)}
|
||||
title="この worker を削除"
|
||||
title={t('llmWorkers.removeWorker')}
|
||||
className="text-slate-400 hover:text-red-500 text-lg leading-none px-1"
|
||||
>
|
||||
×
|
||||
@@ -202,7 +200,7 @@ export function LlmWorkersForm({ config, onChange, overriddenByEnv }: SectionFor
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<FieldLabel>Connection type</FieldLabel>
|
||||
<FieldLabel>{t('llmWorkers.connectionType')}</FieldLabel>
|
||||
<select
|
||||
value={w.connectionType ?? (w.proxy === true ? 'aao_gateway' : 'direct')}
|
||||
onChange={e => {
|
||||
@@ -228,7 +226,7 @@ export function LlmWorkersForm({ config, onChange, overriddenByEnv }: SectionFor
|
||||
value={w.endpoint ?? ''}
|
||||
onChange={v => updateWorker(i, { endpoint: v })}
|
||||
disabled={!!endpointOverridden}
|
||||
disabledReason="OLLAMA_BASE_URL 環境変数で上書き中"
|
||||
disabledReason={t('llmWorkers.endpointOverride')}
|
||||
placeholder={
|
||||
isGateway
|
||||
? 'http://gateway.example.com:9876/v1'
|
||||
@@ -238,30 +236,20 @@ export function LlmWorkersForm({ config, onChange, overriddenByEnv }: SectionFor
|
||||
{endpointOverridden && <EnvOverrideWarning />}
|
||||
{showSelfLoop && (
|
||||
<p className="text-2xs text-amber-700 dark:text-amber-300 bg-amber-50 dark:bg-amber-500/15 border border-amber-200 dark:border-amber-500/30 rounded px-2 py-1 mt-1">
|
||||
endpoint は自インスタンスを指しているように見えます (self-loop)。
|
||||
リバースプロキシ越しの場合はこの警告は無視できます。
|
||||
{t('llmWorkers.selfLoopWarn')}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="col-span-2">
|
||||
<FieldLabel>API key{isGateway ? ' (必須)' : ' (任意)'}</FieldLabel>
|
||||
<FieldLabel>{isGateway ? t('llmWorkers.apiKeyRequired') : t('llmWorkers.apiKeyOptional')}</FieldLabel>
|
||||
<SecretInput
|
||||
rawValue={w.apiKey ?? ''}
|
||||
onChange={v => updateWorker(i, { apiKey: v === '' ? '' : v })}
|
||||
placeholder={isGateway ? 'sk-aao-...' : 'sk-... (任意)'}
|
||||
placeholder={isGateway ? 'sk-aao-...' : t('llmWorkers.apiKeyOptionalPlaceholder')}
|
||||
/>
|
||||
<HelpText>
|
||||
{isGateway ? (
|
||||
<>
|
||||
他 AAO の <em>LLM → Gateway Server</em> で発行した{' '}
|
||||
<code>sk-aao-*</code> を貼り付けてください。
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
Bearer 認証が必要な場合のみ設定。Ollama 単体なら空のままで OK。
|
||||
</>
|
||||
)}
|
||||
{isGateway ? t('llmWorkers.apiKeyGatewayHelp') : t('llmWorkers.apiKeyDirectHelp')}
|
||||
</HelpText>
|
||||
</div>
|
||||
|
||||
@@ -275,8 +263,7 @@ export function LlmWorkersForm({ config, onChange, overriddenByEnv }: SectionFor
|
||||
/>
|
||||
{modelOverridden && <EnvOverrideWarning />}
|
||||
<HelpText>
|
||||
endpoint が <code>/models</code> を返せば dropdown に候補が出ます。
|
||||
出ない場合 (auth が必要、proxy 越し等) は直接入力してください。
|
||||
{t('llmWorkers.modelHelp')}
|
||||
</HelpText>
|
||||
</div>
|
||||
|
||||
@@ -290,7 +277,7 @@ export function LlmWorkersForm({ config, onChange, overriddenByEnv }: SectionFor
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<FieldLabel>最大同時実行数</FieldLabel>
|
||||
<FieldLabel>{t('llmWorkers.maxConcurrency')}</FieldLabel>
|
||||
<FieldInput
|
||||
type="number"
|
||||
value={w.maxConcurrency ?? 1}
|
||||
@@ -306,11 +293,11 @@ export function LlmWorkersForm({ config, onChange, overriddenByEnv }: SectionFor
|
||||
onChange={e => updateWorker(i, { enabled: e.target.checked })}
|
||||
className="rounded"
|
||||
/>
|
||||
有効
|
||||
{t('llmWorkers.enabled')}
|
||||
</label>
|
||||
<label
|
||||
className="flex items-center gap-2 text-sm text-slate-600 cursor-pointer"
|
||||
title="VLM 対応モデルの場合、ReadImage が worker 自身のモデルを使用"
|
||||
title={t('llmWorkers.vlmTitle')}
|
||||
>
|
||||
<input
|
||||
type="checkbox"
|
||||
@@ -330,12 +317,12 @@ export function LlmWorkersForm({ config, onChange, overriddenByEnv }: SectionFor
|
||||
onClick={addWorker}
|
||||
className="px-4 py-2 text-sm text-accent border border-accent rounded-lg hover:bg-accent-soft"
|
||||
>
|
||||
+ Worker を追加
|
||||
{t('llmWorkers.addWorker')}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<h3 className="text-sm font-medium text-slate-600 mt-4 pt-3 border-t border-slate-200">
|
||||
Global LLM Settings
|
||||
{t('llmWorkers.globalTitle')}
|
||||
</h3>
|
||||
|
||||
<div>
|
||||
@@ -345,11 +332,11 @@ export function LlmWorkersForm({ config, onChange, overriddenByEnv }: SectionFor
|
||||
value={llm.timeoutMinutes ?? 10}
|
||||
onChange={v => onChange('llm.timeoutMinutes', Number(v))}
|
||||
/>
|
||||
<HelpText>LLM リクエストのタイムアウト (分)。デフォルト: 10</HelpText>
|
||||
<HelpText>{t('llmWorkers.timeoutHelp')}</HelpText>
|
||||
</div>
|
||||
|
||||
<h3 className="text-sm font-medium text-slate-600 mt-4 pt-3 border-t border-slate-200">
|
||||
Retry (per-call HTTP)
|
||||
{t('llmWorkers.retryTitle')}
|
||||
</h3>
|
||||
|
||||
<div>
|
||||
@@ -359,7 +346,7 @@ export function LlmWorkersForm({ config, onChange, overriddenByEnv }: SectionFor
|
||||
value={retry.maxAttempts ?? 3}
|
||||
onChange={v => onChange('llm.retry.maxAttempts', Number(v))}
|
||||
/>
|
||||
<HelpText>1 回の LLM API 呼び出しでの最大試行回数</HelpText>
|
||||
<HelpText>{t('llmWorkers.maxAttemptsHelp')}</HelpText>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
@@ -372,7 +359,7 @@ export function LlmWorkersForm({ config, onChange, overriddenByEnv }: SectionFor
|
||||
}}
|
||||
placeholder="2000"
|
||||
/>
|
||||
<HelpText>各リトライ間の待機時間 (ms)。配列順に消費されます。</HelpText>
|
||||
<HelpText>{t('llmWorkers.backoffHelp')}</HelpText>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
@@ -385,7 +372,7 @@ export function LlmWorkersForm({ config, onChange, overriddenByEnv }: SectionFor
|
||||
}}
|
||||
placeholder="429"
|
||||
/>
|
||||
<HelpText>リトライ対象の HTTP ステータスコード。</HelpText>
|
||||
<HelpText>{t('llmWorkers.retryableStatusHelp')}</HelpText>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user