| <script lang="ts"> |
| import { |
| modelPhase, |
| baseline, |
| prompt, |
| sampling, |
| algoParams, |
| generateBaseline, |
| } from '../lib/stores/app-state'; |
| |
| let showAdvanced = $state(false); |
| const busy = $derived($baseline.status === 'running'); |
| </script> |
| |
| <div class="panel"> |
| <textarea |
| rows="2" |
| bind:value={$prompt} |
| placeholder="Enter a prompt. The same prompt drives the baseline and every watermark." |
| ></textarea> |
| |
| <div class="controls"> |
| <button |
| class="primary" |
| disabled={$modelPhase !== 'ready' || busy || $prompt.trim().length === 0} |
| onclick={generateBaseline} |
| > |
| {busy ? 'Generating baseline…' : $baseline.result ? 'Regenerate baseline' : 'Generate baseline'} |
| </button> |
| <button onclick={() => (showAdvanced = !showAdvanced)}> |
| {showAdvanced ? 'Hide' : 'Advanced'} settings |
| </button> |
| {#if $modelPhase !== 'ready'} |
| <span class="dim small">Load the model first.</span> |
| {:else if !$baseline.result && !busy} |
| <span class="dim small">The baseline is the control every watermark is compared against.</span> |
| {/if} |
| </div> |
| |
| {#if showAdvanced} |
| <div class="advanced"> |
| <fieldset> |
| <legend>Sampling (shared by every run)</legend> |
| <label>temperature <input type="number" step="0.05" min="0.05" max="2" bind:value={$sampling.temperature} /></label> |
| <label>top-p <input type="number" step="0.01" min="0.1" max="1" bind:value={$sampling.topP} /></label> |
| <label>max new tokens <input type="number" step="8" min="16" max="512" bind:value={$sampling.maxNewTokens} /></label> |
| <label>base RNG seed <input type="number" bind:value={$sampling.baseSeed} /></label> |
| </fieldset> |
| <fieldset> |
| <legend>Algorithm parameters (also editable inside each stage)</legend> |
| <label>Kirchenbauer γ <input type="number" step="0.05" min="0.05" max="0.9" bind:value={$algoParams.kirchenbauer.gamma} /></label> |
| <label>Kirchenbauer δ <input type="number" step="0.5" min="0" max="10" bind:value={$algoParams.kirchenbauer.delta} /></label> |
| <label>k-SemStamp margin <input type="number" step="0.005" min="0" max="0.2" bind:value={$algoParams.ksemstamp.margin} /></label> |
| <label>k-SemStamp max trials <input type="number" min="1" max="40" bind:value={$algoParams.ksemstamp.maxTrials} /></label> |
| <label>TextSeal context k <input type="number" min="1" max="8" bind:value={$algoParams.textseal.contextWidth} /></label> |
| <label>TextSeal α <input type="number" step="0.05" min="0" max="0.5" bind:value={$algoParams.textseal.alpha} /></label> |
| </fieldset> |
| </div> |
| {/if} |
| </div> |
| |
| <style> |
| .controls { |
| display: flex; |
| align-items: center; |
| gap: 12px; |
| margin-top: 10px; |
| flex-wrap: wrap; |
| } |
| .advanced { |
| display: grid; |
| grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); |
| gap: 12px; |
| margin-top: 12px; |
| } |
| fieldset { |
| border: 1px solid var(--border); |
| border-radius: 8px; |
| } |
| legend { |
| color: var(--text-dim); |
| font-size: 12.5px; |
| padding: 0 6px; |
| } |
| fieldset label { |
| display: flex; |
| align-items: center; |
| justify-content: space-between; |
| gap: 8px; |
| margin: 5px 0; |
| font-size: 13.5px; |
| } |
| fieldset input { |
| width: 92px; |
| } |
| </style> |
| |