Spaces:
Paused
Paused
| <div class="environment-container"> | |
| <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 (isGPTMode()) { | |
| <mat-card class="info-card"> | |
| <mat-card-content> | |
| <mat-icon>info</mat-icon> | |
| <div> | |
| <strong>{{ environment.work_mode === 'gpt4o' ? 'GPT-4o' : 'GPT-4o Mini' }} Mode</strong> | |
| <p>This mode uses OpenAI's API which has usage-based pricing.</p> | |
| <p>Approximate cost: {{ environment.work_mode === 'gpt4o' ? '$0.01-0.03' : '$0.001-0.003' }} per conversation turn.</p> | |
| </div> | |
| </mat-card-content> | |
| </mat-card> | |
| } | |
| <form (ngSubmit)="save()" #envForm="ngForm"> | |
| <mat-form-field appearance="outline" class="full-width"> | |
| <mat-label>Work Mode</mat-label> | |
| <mat-select | |
| name="workMode" | |
| [(ngModel)]="environment.work_mode" | |
| (selectionChange)="onWorkModeChange()" | |
| required | |
| [disabled]="loading" | |
| > | |
| <mat-option value="hfcloud">HF Cloud</mat-option> | |
| <mat-option value="cloud">Cloud</mat-option> | |
| <mat-option value="on-premise">On-Premise</mat-option> | |
| <mat-option value="gpt4o">GPT-4o</mat-option> | |
| <mat-option value="gpt4o-mini">GPT-4o Mini</mat-option> | |
| </mat-select> | |
| <mat-icon matPrefix>cloud</mat-icon> | |
| </mat-form-field> | |
| <mat-form-field appearance="outline" class="full-width"> | |
| <mat-label>{{ getTokenLabel() }}</mat-label> | |
| <input | |
| matInput | |
| type="password" | |
| name="cloudToken" | |
| [(ngModel)]="environment.cloud_token" | |
| [disabled]="loading || environment.work_mode === 'on-premise'" | |
| [placeholder]="getTokenPlaceholder()" | |
| > | |
| <mat-icon matPrefix>vpn_key</mat-icon> | |
| <mat-hint>{{ isGPTMode() ? 'Required for OpenAI API access' : 'Required for HF Cloud and Cloud modes' }}</mat-hint> | |
| </mat-form-field> | |
| <mat-form-field appearance="outline" class="full-width"> | |
| <mat-label>Spark Endpoint</mat-label> | |
| <input | |
| matInput | |
| type="url" | |
| name="sparkEndpoint" | |
| [(ngModel)]="environment.spark_endpoint" | |
| [required]="!isGPTMode()" | |
| [disabled]="loading || isGPTMode()" | |
| placeholder="https://spark-service.example.com" | |
| > | |
| <mat-icon matPrefix>link</mat-icon> | |
| <button | |
| mat-icon-button | |
| matSuffix | |
| type="button" | |
| (click)="testConnection()" | |
| [disabled]="loading || !environment.spark_endpoint || isGPTMode()" | |
| matTooltip="Test Connection" | |
| > | |
| <mat-icon>wifi_tethering</mat-icon> | |
| </button> | |
| @if (isGPTMode()) { | |
| <mat-hint>Not required for GPT mode</mat-hint> | |
| } | |
| </mat-form-field> | |
| <!-- TTS Configuration --> | |
| <div class="engine-row"> | |
| <mat-form-field appearance="outline" class="engine-field"> | |
| <mat-label>TTS Engine</mat-label> | |
| <mat-select | |
| name="ttsEngine" | |
| [(ngModel)]="environment.tts_engine" | |
| (selectionChange)="onTTSEngineChange()" | |
| [disabled]="loading" | |
| > | |
| <mat-option value="no_tts">No TTS</mat-option> | |
| <mat-option value="elevenlabs">ElevenLabs</mat-option> | |
| <mat-option value="blaze">Blaze (Coming Soon)</mat-option> | |
| </mat-select> | |
| <mat-icon matPrefix>record_voice_over</mat-icon> | |
| </mat-form-field> | |
| <mat-form-field appearance="outline" class="api-key-field"> | |
| <mat-label>TTS API Key</mat-label> | |
| <input | |
| matInput | |
| type="password" | |
| name="ttsApiKey" | |
| [(ngModel)]="environment.tts_engine_api_key" | |
| [disabled]="loading || environment.tts_engine === 'no_tts'" | |
| [required]="environment.tts_engine !== 'no_tts'" | |
| placeholder="Enter TTS API key" | |
| > | |
| <mat-icon matPrefix>key</mat-icon> | |
| </mat-form-field> | |
| <mat-checkbox | |
| name="ttsUseSSML" | |
| [(ngModel)]="ttsSettings.use_ssml" | |
| [disabled]="loading || !isTTSProviderSSMLCapable()" | |
| *ngIf="environment.tts_engine !== 'no_tts'"> | |
| Use SSML | |
| </mat-checkbox> | |
| <mat-hint *ngIf="isTTSProviderSSMLCapable() && environment.tts_engine !== 'no_tts'"> | |
| SSML provides better control over pronunciation, pauses, and emphasis | |
| </mat-hint> | |
| </div> | |
| <!-- STT Configuration --> | |
| <div class="engine-row"> | |
| <mat-form-field appearance="outline" class="engine-field"> | |
| <mat-label>STT Engine</mat-label> | |
| <mat-select | |
| name="sttEngine" | |
| [(ngModel)]="environment.stt_engine" | |
| (selectionChange)="onSTTEngineChange()" | |
| [disabled]="loading" | |
| > | |
| <mat-option value="no_stt">No STT</mat-option> | |
| <mat-option value="google">Google Cloud Speech</mat-option> | |
| <mat-option value="azure">Azure Speech (Coming Soon)</mat-option> | |
| <mat-option value="amazon">Amazon Transcribe (Coming Soon)</mat-option> | |
| <mat-option value="flicker">Flicker (Coming Soon)</mat-option> | |
| </mat-select> | |
| <mat-icon matPrefix>mic</mat-icon> | |
| </mat-form-field> | |
| <mat-form-field appearance="outline" class="api-key-field"> | |
| <mat-label>{{ getSTTKeyLabel() }}</mat-label> | |
| <input | |
| matInput | |
| type="password" | |
| name="sttApiKey" | |
| [(ngModel)]="environment.stt_engine_api_key" | |
| [disabled]="loading || environment.stt_engine === 'no_stt'" | |
| [required]="environment.stt_engine !== 'no_stt'" | |
| [placeholder]="getSTTKeyPlaceholder()" | |
| > | |
| <mat-icon matPrefix>key</mat-icon> | |
| <mat-hint>{{ getSTTKeyHint() }}</mat-hint> | |
| </mat-form-field> | |
| </div> | |
| <div> | |
| <!-- STT Settings Panel --> | |
| <mat-expansion-panel class="stt-settings-panel" *ngIf="environment.stt_engine !== 'no_stt'"> | |
| <mat-expansion-panel-header> | |
| <mat-panel-title> | |
| <mat-icon>settings_voice</mat-icon> | |
| STT Settings | |
| </mat-panel-title> | |
| <mat-panel-description> | |
| Advanced speech recognition settings | |
| </mat-panel-description> | |
| </mat-expansion-panel-header> | |
| <div class="stt-settings-content"> | |
| <!-- Language --> | |
| <mat-form-field appearance="outline" class="full-width"> | |
| <mat-label>Language</mat-label> | |
| <mat-select | |
| name="sttLanguage" | |
| [(ngModel)]="sttSettings.language" | |
| [disabled]="loading" | |
| > | |
| <mat-option value="tr-TR">Turkish (tr-TR)</mat-option> | |
| <mat-option value="en-US">English US (en-US)</mat-option> | |
| <mat-option value="en-GB">English UK (en-GB)</mat-option> | |
| <mat-option value="de-DE">German (de-DE)</mat-option> | |
| <mat-option value="fr-FR">French (fr-FR)</mat-option> | |
| <mat-option value="es-ES">Spanish (es-ES)</mat-option> | |
| </mat-select> | |
| <mat-icon matPrefix>language</mat-icon> | |
| </mat-form-field> | |
| <!-- Model --> | |
| <mat-form-field appearance="outline" class="full-width" *ngIf="environment.stt_engine === 'google'"> | |
| <mat-label>Recognition Model</mat-label> | |
| <mat-select | |
| name="sttModel" | |
| [(ngModel)]="sttSettings.model" | |
| [disabled]="loading" | |
| > | |
| <mat-option value="latest_long">Latest Long (Best for long audio)</mat-option> | |
| <mat-option value="latest_short">Latest Short (Best for short audio)</mat-option> | |
| <mat-option value="command_and_search">Command and Search</mat-option> | |
| <mat-option value="phone_call">Phone Call</mat-option> | |
| <mat-option value="video">Video</mat-option> | |
| </mat-select> | |
| <mat-icon matPrefix>model_training</mat-icon> | |
| </mat-form-field> | |
| <!-- Speech Timeout --> | |
| <div class="slider-field"> | |
| <label>Speech Timeout: {{ sttSettings.speech_timeout_ms }}ms</label> | |
| <mat-slider | |
| [min]="500" | |
| [max]="5000" | |
| [step]="100" | |
| [discrete]="true" | |
| [displayWith]="formatMilliseconds" | |
| > | |
| <input matSliderThumb | |
| name="sttSpeechTimeout" | |
| [(ngModel)]="sttSettings.speech_timeout_ms"> | |
| </mat-slider> | |
| <mat-hint>Silence duration to end speech detection</mat-hint> | |
| </div> | |
| <!-- VAD Sensitivity --> | |
| <div class="slider-field"> | |
| <label>Voice Activity Detection Sensitivity: {{ sttSettings.vad_sensitivity }}</label> | |
| <mat-slider | |
| [min]="0" | |
| [max]="1" | |
| [step]="0.1" | |
| [discrete]="true" | |
| > | |
| <input matSliderThumb | |
| name="sttVadSensitivity" | |
| [(ngModel)]="sttSettings.vad_sensitivity"> | |
| </mat-slider> | |
| <mat-hint>Higher values = more sensitive</mat-hint> | |
| </div> | |
| <!-- Noise Reduction Level --> | |
| <div class="slider-field"> | |
| <label>Noise Reduction Level: {{ sttSettings.noise_reduction_level }}</label> | |
| <mat-slider | |
| [min]="0" | |
| [max]="3" | |
| [step]="1" | |
| [discrete]="true" | |
| > | |
| <input matSliderThumb | |
| name="sttNoiseReduction" | |
| [(ngModel)]="sttSettings.noise_reduction_level"> | |
| </mat-slider> | |
| <mat-hint>0 = Off, 3 = Maximum</mat-hint> | |
| </div> | |
| <!-- Checkboxes --> | |
| <div class="checkbox-group"> | |
| <mat-checkbox | |
| name="sttUseEnhanced" | |
| [(ngModel)]="sttSettings.use_enhanced" | |
| [disabled]="loading" | |
| *ngIf="environment.stt_engine === 'google'"> | |
| Use Enhanced Model | |
| </mat-checkbox> | |
| <mat-checkbox | |
| name="sttEnablePunctuation" | |
| [(ngModel)]="sttSettings.enable_punctuation" | |
| [disabled]="loading"> | |
| Enable Automatic Punctuation | |
| </mat-checkbox> | |
| <mat-checkbox | |
| name="sttInterimResults" | |
| [(ngModel)]="sttSettings.interim_results" | |
| [disabled]="loading"> | |
| Show Interim Results | |
| </mat-checkbox> | |
| </div> | |
| </div> | |
| </mat-expansion-panel> | |
| </div> | |
| <mat-expansion-panel class="prompt-panel"> | |
| <mat-expansion-panel-header> | |
| <mat-panel-title> | |
| <mat-icon>psychology</mat-icon> | |
| Internal System Prompt | |
| </mat-panel-title> | |
| <mat-panel-description> | |
| Advanced configuration for LLM | |
| </mat-panel-description> | |
| </mat-expansion-panel-header> | |
| <mat-form-field appearance="outline" class="full-width"> | |
| <mat-label>Internal Prompt</mat-label> | |
| <textarea | |
| matInput | |
| name="internalPrompt" | |
| [(ngModel)]="environment.internal_prompt" | |
| [disabled]="loading" | |
| rows="10" | |
| placeholder="Enter internal system prompt..." | |
| ></textarea> | |
| <mat-hint>This prompt will be prepended to all project prompts</mat-hint> | |
| </mat-form-field> | |
| </mat-expansion-panel> | |
| <!-- Parameter Collection Configuration --> | |
| <mat-expansion-panel class="prompt-panel"> | |
| <mat-expansion-panel-header> | |
| <mat-panel-title> | |
| <mat-icon>psychology</mat-icon> | |
| Parameter Collection Configuration | |
| </mat-panel-title> | |
| <mat-panel-description> | |
| Configure smart parameter collection behavior | |
| </mat-panel-description> | |
| </mat-expansion-panel-header> | |
| <div class="param-collection-content"> | |
| <div class="config-grid"> | |
| <!-- Max Parameters Per Question --> | |
| <div class="slider-field"> | |
| <label>Max Parameters Per Question: {{ parameterCollectionConfig.max_params_per_question }}</label> | |
| <mat-slider | |
| [min]="1" | |
| [max]="5" | |
| [step]="1" | |
| [discrete]="true" | |
| > | |
| <input matSliderThumb | |
| name="maxParamsPerQuestion" | |
| [(ngModel)]="parameterCollectionConfig.max_params_per_question"> | |
| </mat-slider> | |
| <mat-hint>Maximum number of parameters to ask in one question</mat-hint> | |
| </div> | |
| <!-- Smart Grouping --> | |
| <mat-checkbox | |
| name="smartGrouping" | |
| [(ngModel)]="parameterCollectionConfig.smart_grouping" | |
| [disabled]="loading" | |
| class="collection-checkbox"> | |
| Smart Grouping | |
| <mat-hint>Automatically group related parameters (e.g., from/to cities)</mat-hint> | |
| </mat-checkbox> | |
| <!-- Retry Unanswered --> | |
| <mat-checkbox | |
| name="retryUnanswered" | |
| [(ngModel)]="parameterCollectionConfig.retry_unanswered" | |
| [disabled]="loading" | |
| class="collection-checkbox"> | |
| Retry Unanswered Parameters | |
| <mat-hint>Re-ask parameters that the user didn't answer</mat-hint> | |
| </mat-checkbox> | |
| </div> | |
| <!-- Collection Prompt Template --> | |
| <mat-form-field appearance="outline" class="full-width"> | |
| <mat-label>Collection Prompt Template</mat-label> | |
| <textarea | |
| matInput | |
| name="collectionPrompt" | |
| [(ngModel)]="parameterCollectionConfig.collection_prompt" | |
| [disabled]="loading" | |
| rows="12" | |
| placeholder="Enter the prompt template for generating parameter questions..." | |
| class="code-textarea" | |
| ></textarea> | |
| <mat-hint> | |
| Available variables: {{conversation_history}}, {{intent_name}}, {{intent_caption}}, | |
| {{collected_params}}, {{missing_params}}, {{unanswered_params}}, {{max_params}}, {{project_language}} | |
| </mat-hint> | |
| </mat-form-field> | |
| <!-- Template Variables Help --> | |
| <mat-expansion-panel class="help-panel"> | |
| <mat-expansion-panel-header> | |
| <mat-panel-title> | |
| <mat-icon>help_outline</mat-icon> | |
| Template Variables Reference | |
| </mat-panel-title> | |
| </mat-expansion-panel-header> | |
| <mat-list> | |
| <mat-list-item> | |
| <mat-icon matListItemIcon>code</mat-icon> | |
| <div matListItemTitle><code>{{conversation_history}}</code></div> | |
| <div matListItemLine>Recent conversation between user and assistant</div> | |
| </mat-list-item> | |
| <mat-list-item> | |
| <mat-icon matListItemIcon>code</mat-icon> | |
| <div matListItemTitle><code>{{intent_name}}</code></div> | |
| <div matListItemLine>Technical name of the detected intent</div> | |
| </mat-list-item> | |
| <mat-list-item> | |
| <mat-icon matListItemIcon>code</mat-icon> | |
| <div matListItemTitle><code>{{intent_caption}}</code></div> | |
| <div matListItemLine>Human-readable caption of the intent</div> | |
| </mat-list-item> | |
| <mat-list-item> | |
| <mat-icon matListItemIcon>code</mat-icon> | |
| <div matListItemTitle><code>{{collected_params}}</code></div> | |
| <div matListItemLine>Parameters already collected with their values</div> | |
| </mat-list-item> | |
| <mat-list-item> | |
| <mat-icon matListItemIcon>code</mat-icon> | |
| <div matListItemTitle><code>{{missing_params}}</code></div> | |
| <div matListItemLine>Parameters still needed to complete the request</div> | |
| </mat-list-item> | |
| <mat-list-item> | |
| <mat-icon matListItemIcon>code</mat-icon> | |
| <div matListItemTitle><code>{{unanswered_params}}</code></div> | |
| <div matListItemLine>Parameters asked before but not answered by user</div> | |
| </mat-list-item> | |
| <mat-list-item> | |
| <mat-icon matListItemIcon>code</mat-icon> | |
| <div matListItemTitle><code>{{max_params}}</code></div> | |
| <div matListItemLine>Maximum number of parameters to ask in one question</div> | |
| </mat-list-item> | |
| <mat-list-item> | |
| <mat-icon matListItemIcon>code</mat-icon> | |
| <div matListItemTitle><code>{{project_language}}</code></div> | |
| <div matListItemLine>Language setting of the current project</div> | |
| </mat-list-item> | |
| </mat-list> | |
| </mat-expansion-panel> | |
| <!-- Reset to Default Button --> | |
| <button mat-stroked-button type="button" (click)="resetCollectionPrompt()" [disabled]="loading"> | |
| <mat-icon>restore</mat-icon> | |
| Reset to Default Template | |
| </button> | |
| </div> | |
| </mat-expansion-panel> | |
| <div class="form-actions"> | |
| <button | |
| mat-raised-button | |
| color="primary" | |
| type="submit" | |
| [disabled]="loading || !envForm.valid || saving" | |
| > | |
| @if (saving) { | |
| <mat-spinner diameter="20"></mat-spinner> | |
| Saving... | |
| } @else { | |
| <mat-icon>save</mat-icon> | |
| Save | |
| } | |
| </button> | |
| <button | |
| mat-raised-button | |
| type="button" | |
| (click)="reloadFromSpark()" | |
| [disabled]="loading || isGPTMode()" | |
| > | |
| <mat-icon>refresh</mat-icon> | |
| Reload from Spark | |
| </button> | |
| </div> | |
| </form> | |
| </mat-card-content> | |
| </mat-card> | |
| </div> |