Spaces:
Building
Building
<mat-card> | |
<mat-card-header> | |
<mat-card-title> | |
<mat-icon>settings</mat-icon> | |
Environment Configuration | |
</mat-card-title> | |
</mat-card-header> | |
<mat-card-content> | |
@if (loading) { | |
<div class="loading-container"> | |
<mat-spinner></mat-spinner> | |
<p>Loading configuration...</p> | |
</div> | |
} @else { | |
<form [formGroup]="form"> | |
<!-- LLM Provider Section --> | |
<div class="provider-section"> | |
<h3> | |
<mat-icon>smart_toy</mat-icon> | |
LLM Provider | |
</h3> | |
<mat-form-field appearance="outline" class="full-width"> | |
<mat-label>Provider</mat-label> | |
<mat-icon matPrefix>{{ getLLMProviderIcon(currentLLMProviderSafe) }}</mat-icon> | |
<mat-select formControlName="llm_provider_name" | |
(selectionChange)="onLLMProviderChange($event.value)"> | |
@for (provider of llmProviders; track provider.name) { | |
<mat-option [value]="provider.name"> | |
<mat-icon>{{ getLLMProviderIcon(provider) }}</mat-icon> | |
{{ provider.display_name }} | |
</mat-option> | |
} | |
</mat-select> | |
@if (currentLLMProviderSafe?.description) { | |
<mat-hint>{{ currentLLMProviderSafe?.description }}</mat-hint> | |
} | |
</mat-form-field> | |
@if (currentLLMProviderSafe?.requires_api_key) { | |
<mat-form-field appearance="outline" class="full-width"> | |
<mat-label>{{ getApiKeyLabel('llm') }}</mat-label> | |
<mat-icon matPrefix>key</mat-icon> | |
<input matInput | |
type="password" | |
formControlName="llm_provider_api_key" | |
[placeholder]="getApiKeyPlaceholder('llm')"> | |
<mat-error *ngIf="form.get('llm_provider_api_key')?.hasError('required')"> | |
API key is required for {{ currentLLMProviderSafe?.display_name || 'this provider' }} | |
</mat-error> | |
</mat-form-field> | |
} | |
@if (currentLLMProviderSafe?.requires_endpoint) { | |
<mat-form-field appearance="outline" class="full-width"> | |
<mat-label>Endpoint URL</mat-label> | |
<mat-icon matPrefix>link</mat-icon> | |
<input matInput | |
formControlName="llm_provider_endpoint" | |
[placeholder]="getEndpointPlaceholder('llm')"> | |
<button mat-icon-button matSuffix | |
(click)="testConnection()" | |
type="button" | |
matTooltip="Test connection"> | |
<mat-icon>wifi_tethering</mat-icon> | |
</button> | |
<mat-error *ngIf="form.get('llm_provider_endpoint')?.hasError('required')"> | |
Endpoint is required for {{ currentLLMProviderSafe?.display_name || 'this provider' }} | |
</mat-error> | |
</mat-form-field> | |
} | |
<!-- LLM Settings (Internal Prompt & Parameter Collection) --> | |
@if (currentLLMProviderSafe) { | |
<mat-expansion-panel class="settings-panel"> | |
<mat-expansion-panel-header> | |
<mat-panel-title> | |
<mat-icon>psychology</mat-icon> | |
Internal System Prompt | |
</mat-panel-title> | |
<mat-panel-description> | |
Configure the internal prompt for intent detection | |
</mat-panel-description> | |
</mat-expansion-panel-header> | |
<div class="panel-content"> | |
<p class="hint-text"> | |
This prompt is prepended to all intent detection requests. | |
</p> | |
<mat-form-field appearance="outline" class="full-width"> | |
<mat-label>Internal Prompt</mat-label> | |
<textarea matInput | |
[(ngModel)]="internalPrompt" | |
[ngModelOptions]="{standalone: true}" | |
rows="10" | |
placeholder="Enter the system prompt that guides intent detection..."></textarea> | |
<mat-hint>Use clear instructions to guide the LLM's behavior</mat-hint> | |
</mat-form-field> | |
</div> | |
</mat-expansion-panel> | |
<mat-expansion-panel class="settings-panel"> | |
<mat-expansion-panel-header> | |
<mat-panel-title> | |
<mat-icon>tune</mat-icon> | |
Parameter Collection Configuration | |
</mat-panel-title> | |
<mat-panel-description> | |
Fine-tune how parameters are collected from users | |
</mat-panel-description> | |
</mat-expansion-panel-header> | |
<div class="panel-content"> | |
<mat-slide-toggle [(ngModel)]="parameterCollectionConfig.enabled" | |
[ngModelOptions]="{standalone: true}"> | |
Enable Smart Parameter Collection | |
</mat-slide-toggle> | |
<div class="config-item"> | |
<label>Max Parameters per Question</label> | |
<mat-slider min="1" max="5" step="1" discrete> | |
<input matSliderThumb [(ngModel)]="parameterCollectionConfig.max_params_per_question" | |
[ngModelOptions]="{standalone: true}"> | |
</mat-slider> | |
<span class="slider-value">{{ parameterCollectionConfig.max_params_per_question }}</span> | |
</div> | |
<mat-slide-toggle [(ngModel)]="parameterCollectionConfig.show_all_required" | |
[ngModelOptions]="{standalone: true}"> | |
Show All Required Parameters | |
</mat-slide-toggle> | |
<mat-slide-toggle [(ngModel)]="parameterCollectionConfig.ask_optional_params" | |
[ngModelOptions]="{standalone: true}"> | |
Ask for Optional Parameters | |
</mat-slide-toggle> | |
<mat-slide-toggle [(ngModel)]="parameterCollectionConfig.group_related_params" | |
[ngModelOptions]="{standalone: true}"> | |
Group Related Parameters | |
</mat-slide-toggle> | |
<div class="config-item"> | |
<label>Minimum Confidence Score</label> | |
<mat-slider min="0" max="1" step="0.1" discrete> | |
<input matSliderThumb [(ngModel)]="parameterCollectionConfig.min_confidence_score" | |
[ngModelOptions]="{standalone: true}"> | |
</mat-slider> | |
<span class="slider-value">{{ parameterCollectionConfig.min_confidence_score }}</span> | |
</div> | |
<mat-form-field appearance="outline" class="full-width"> | |
<mat-label>Collection Prompt Template</mat-label> | |
<textarea matInput | |
[(ngModel)]="parameterCollectionConfig.collection_prompt" | |
[ngModelOptions]="{standalone: true}" | |
rows="8"></textarea> | |
<button mat-icon-button matSuffix | |
(click)="resetCollectionPrompt()" | |
type="button" | |
matTooltip="Reset to default"> | |
<mat-icon>refresh</mat-icon> | |
</button> | |
</mat-form-field> | |
</div> | |
</mat-expansion-panel> | |
} | |
</div> | |
<mat-divider></mat-divider> | |
<!-- TTS Provider Section --> | |
<div class="provider-section"> | |
<h3> | |
<mat-icon>record_voice_over</mat-icon> | |
TTS Provider | |
</h3> | |
<mat-form-field appearance="outline" class="full-width"> | |
<mat-label>Provider</mat-label> | |
<mat-icon matPrefix>{{ getTTSProviderIcon(currentTTSProviderSafe) }}</mat-icon> | |
<mat-select formControlName="tts_provider_name" | |
(selectionChange)="onTTSProviderChange($event.value)"> | |
@for (provider of ttsProviders; track provider.name) { | |
<mat-option [value]="provider.name"> | |
<mat-icon>{{ getTTSProviderIcon(provider) }}</mat-icon> | |
{{ provider.display_name }} | |
</mat-option> | |
} | |
</mat-select> | |
@if (currentTTSProviderSafe?.description) { | |
<mat-hint>{{ currentTTSProviderSafe?.description }}</mat-hint> | |
} | |
</mat-form-field> | |
@if (currentTTSProviderSafe?.requires_api_key) { | |
<mat-form-field appearance="outline" class="full-width"> | |
<mat-label>API Key</mat-label> | |
<mat-icon matPrefix>key</mat-icon> | |
<input matInput | |
type="password" | |
formControlName="tts_provider_api_key" | |
[placeholder]="getApiKeyPlaceholder('tts')"> | |
<mat-error *ngIf="form.get('tts_provider_api_key')?.hasError('required')"> | |
API key is required for {{ currentTTSProviderSafe?.display_name || 'this provider' }} | |
</mat-error> | |
</mat-form-field> | |
} | |
@if (currentTTSProviderSafe?.requires_endpoint) { | |
<mat-form-field appearance="outline" class="full-width"> | |
<mat-label>Endpoint URL</mat-label> | |
<mat-icon matPrefix>link</mat-icon> | |
<input matInput | |
formControlName="tts_provider_endpoint" | |
[placeholder]="getEndpointPlaceholder('tts')"> | |
</mat-form-field> | |
} | |
</div> | |
<mat-divider></mat-divider> | |
<!-- STT Provider Section --> | |
<div class="provider-section"> | |
<h3> | |
<mat-icon>mic</mat-icon> | |
STT Provider | |
</h3> | |
<mat-form-field appearance="outline" class="full-width"> | |
<mat-label>Provider</mat-label> | |
<mat-icon matPrefix>{{ getSTTProviderIcon(currentSTTProviderSafe) }}</mat-icon> | |
<mat-select formControlName="stt_provider_name" | |
(selectionChange)="onSTTProviderChange($event.value)"> | |
@for (provider of sttProviders; track provider.name) { | |
<mat-option [value]="provider.name"> | |
<mat-icon>{{ getSTTProviderIcon(provider) }}</mat-icon> | |
{{ provider.display_name }} | |
</mat-option> | |
} | |
</mat-select> | |
@if (currentSTTProviderSafe?.description) { | |
<mat-hint>{{ currentSTTProviderSafe?.description }}</mat-hint> | |
} | |
</mat-form-field> | |
@if (currentSTTProviderSafe?.requires_api_key) { | |
<mat-form-field appearance="outline" class="full-width"> | |
<mat-label>{{ getApiKeyLabel('stt') }}</mat-label> | |
<mat-icon matPrefix>key</mat-icon> | |
<input matInput | |
[type]="currentSTTProviderSafe?.name === 'google' ? 'text' : 'password'" | |
formControlName="stt_provider_api_key" | |
[placeholder]="getApiKeyPlaceholder('stt')"> | |
<mat-error *ngIf="form.get('stt_provider_api_key')?.hasError('required')"> | |
{{ currentSTTProviderSafe?.name === 'google' ? 'Credentials path' : 'API key' }} is required for {{ currentSTTProviderSafe?.display_name || 'this provider' }} | |
</mat-error> | |
</mat-form-field> | |
} | |
@if (currentSTTProviderSafe?.requires_endpoint) { | |
<mat-form-field appearance="outline" class="full-width"> | |
<mat-label>Endpoint URL</mat-label> | |
<mat-icon matPrefix>link</mat-icon> | |
<input matInput | |
formControlName="stt_provider_endpoint" | |
[placeholder]="getEndpointPlaceholder('stt')"> | |
</mat-form-field> | |
} | |
</div> | |
<mat-card-actions align="end"> | |
<button mat-raised-button | |
color="primary" | |
(click)="saveEnvironment()" | |
[disabled]="form.invalid || saving"> | |
<mat-icon>save</mat-icon> | |
{{ saving ? 'Saving...' : 'Save Configuration' }} | |
</button> | |
</mat-card-actions> | |
</form> | |
} | |
</mat-card-content> | |
</mat-card> |