Story Mode Perplexity Rules — Free Perplexity Rules Template
    Neura MarketNeura Market/Perplexity
    ChatGPTChatGPTClaudeClaudeGeminiGeminiCursorCursorGrokGrokPerplexityPerplexityDeepSeekDeepSeek
    CoPilotCoPilotStable DiffusionStable DiffusionMidjourneyMidjourney
    View All Directories
    OverviewRulesPromptsMCPsAgentsGamesBlogVideosGuidesCoursesCommunityTrending
    PerplexityRulesStory Mode Perplexity Rules
    Back to Rules

    Story Mode Perplexity Rules

    jebcarter-space July 19, 2026
    0 copies 0 downloads
    Rule Content
    <script lang="ts">
      import type { LLMProfile, LLMViews } from "../../../data/types";
      import { createLLMProfiles } from "../../../data/models/llm-profiles.svelte.ts";
      import { LLMService } from "../../../lib/llm-service";
      import { loadDefaultLLMProfiles } from "../../../lib/default-llm-profiles";
      import { SYSTEM_PROMPT_PRESETS, DEFAULT_SYSTEM_PROMPT, DEFAULT_AUTHOR_NOTE, type SystemPromptPreset } from "../../../lib/system-prompt-presets";
      import SettingPage from "../../ui/SettingPage.svelte";
    
      let profiles = createLLMProfiles();
      let profileList = $derived(profiles.value);
    
      let open: LLMViews = $state('');
      let selectedKey = $state('');
      let importData = $state('');
      let exportData = $state('');
      let testingConnection = $state<string | null>(null);
      let testResults = $state<{ [key: string]: boolean }>({});
      
      // UI state for collapsible sections
      let showAdvanced = $state(false);
      let showExpert = $state(false);
    
      // Default profile template
      let profile: LLMProfile = $state({
        name: '',
        provider: 'openai',
        apiKey: '',
        endpoint: '',
        model: 'gpt-3.5-turbo',
        systemPrompt: '',
        authorNote: '',
        settings: {
          temperature: 0.7,
          maxTokens: 500,
          topP: 1.0,
          frequencyPenalty: 0.0,
          presencePenalty: 0.0,
          // KoboldCPP parameters will be initialized when needed
          tfs: undefined,
          topA: undefined,
          topK: undefined,
          minP: undefined,
          typical: undefined,
          repPen: undefined,
          repPenRange: undefined,
          samplerOrder: undefined,
          dynatempRange: undefined,
          dynatempExponent: undefined,
          smoothingFactor: undefined,
          mirostat: undefined,
          mirostatTau: undefined,
          mirostatEta: undefined,
          dryMultiplier: undefined,
          dryBase: undefined,
          dryAllowedLength: undefined,
          drySequenceBreakers: undefined,
          xtcThreshold: undefined,
          xtcProbability: undefined,
          grammar: undefined,
          bannedTokens: undefined,
          logitBias: undefined,
          memory: undefined,
        },
        includeSystemContent: false,
        maxContextEntries: 10,
        // Context size management
        maxContextSize: undefined,
        autoDetectContextSize: true,
        created: 0,
        updated: 0
      });
    
      function resetProfile() {
        profile = {
          name: '',
          provider: 'openai',
          apiKey: '',
          endpoint: '',
          model: 'gpt-3.5-turbo',
          systemPrompt: '',
          authorNote: '',
          settings: {
            temperature: 0.7,
            maxTokens: 500,
            topP: 1.0,
            frequencyPenalty: 0.0,
            presencePenalty: 0.0,
            // KoboldCPP parameters will be initialized when needed
            tfs: undefined,
            topA: undefined,
            topK: undefined,
            minP: undefined,
            typical: undefined,
            repPen: undefined,
            repPenRange: undefined,
            samplerOrder: undefined,
            dynatempRange: undefined,
            dynatempExponent: undefined,
            smoothingFactor: undefined,
            mirostat: undefined,
            mirostatTau: undefined,
            mirostatEta: undefined,
            dryMultiplier: undefined,
            dryBase: undefined,
            dryAllowedLength: undefined,
            drySequenceBreakers: undefined,
            xtcThreshold: undefined,
            xtcProbability: undefined,
            grammar: undefined,
            bannedTokens: undefined,
            logitBias: undefined,
            memory: undefined,
          },
          includeSystemContent: false,
          maxContextEntries: 10,
          // Context size management
          maxContextSize: undefined,
          autoDetectContextSize: true,
          created: 0,
          updated: 0
        };
      }
    
      function applyPreset(preset: SystemPromptPreset) {
        profile.systemPrompt = preset.systemPrompt;
        profile.authorNote = preset.authorNote;
      }
    
      function saveProfile() {
        if (selectedKey) {
          profiles.update(selectedKey, profile);
        } else {
          profiles.add(profile);
        }
        resetProfile();
        open = '';
        selectedKey = '';
      }
    
      function editProfile(key: string) {
        profile = { ...profileList[key] };
        selectedKey = key;
        open = 'create';
      }
    
      function deleteProfile(key: string) {
        if (confirm('Are you sure you want to delete this profile?')) {
          profiles.remove(key);
          if (selectedKey === key) {
            open = '';
            selectedKey = '';
          }
        }
      }
    
      function duplicateProfile(key: string) {
        const original = profileList[key];
        const newName = `${original.name} Copy`;
        profiles.duplicate(key, newName);
      }
    
      function openImport() {
        importData = '';
        open = 'import';
      }
    
      function importProfiles() {
        try {
          const parsed = JSON.parse(importData);
          profiles.importProfiles(parsed);
          importData = '';
          open = '';
        } catch (error) {
          alert('Invalid JSON format. Please check your data and try again.');
          console.error('Import failed:', error);
        }
      }
    
      function openExport() {
        exportData = JSON.stringify(profiles.exportProfiles(), null, 2);
        open = 'export';
      }
    
      function loadDefaults() {
        loadDefaultLLMProfiles();
        // Force reactive update by reloading from localStorage
        profiles.reload();
      }
    
      function getDefaultEndpoint(provider: string): string {
        switch (provider) {
          case 'openai':
            return 'https://api.openai.com/v1/chat/completions';
          case 'mistral':
            return 'https://api.mistral.ai/v1/chat/completions';
          case 'openrouter':
            return 'https://openrouter.ai/api/v1/chat/completions';
          case 'koboldcpp':
            return 'http://localhost:5001/v1/chat/completions';
          case 'custom':
            return '';
          default:
            return '';
        }
      }
    
      function updateEndpoint() {
        if (profile.provider !== 'custom') {
          profile.endpoint = getDefaultEndpoint(profile.provider);
        }
      }
    
      async function testConnection(key: string) {
        const profileToTest = profileList[key];
        if (!profileToTest) return;
    
        testingConnection = key;
        try {
          const service = new LLMService(profileToTest);
          const result = await service.testConnection();
          testResults[key] = result;
        } catch (error) {
          console.error('Connection test failed:', error);
          testResults[key] = false;
        } finally {
          testingConnection = null;
        }
      }
    
      $effect(() => {
        updateEndpoint();
      });
    </script>
    
    <SettingPage>
      <div class="flex justify-between items-center mb-6">
        <h3 class="text-3xl font-bold">LLM Settings</h3>
        <div class="flex gap-2">
          <button onclick={() => { resetProfile(); open = 'create'; }} class="px-3 py-1 bg-green-500 text-white rounded text-sm">
            Create Profile
          </button>
          <button onclick={openImport} class="px-3 py-1 bg-blue-500 text-white rounded text-sm">
            Import
          </button>
          <button onclick={openExport} class="px-3 py-1 bg-blue-500 text-white rounded text-sm">
            Export
          </button>
          <button onclick={loadDefaults} class="px-3 py-1 bg-green-500 text-white rounded text-sm">
            Load Defaults
          </button>
        </div>
      </div>
    
      <div class="flex flex-col">
        {#if open === 'create'}
          <div class="mb-6 p-4 border rounded">
            <h4 class="text-xl mb-3">{selectedKey ? 'Edit Profile' : 'Create Profile'}</h4>
            <div class="flex flex-col gap-3">
              <div>
                <label class="block text-sm font-medium mb-1">Profile Name</label>
                <input 
                  type="text" 
                  placeholder="e.g., Creative Assistant"
                  bind:value={profile.name} 
                  class="w-full p-2 border rounded"
                />
              </div>
              
              <div>
                <label class="block text-sm font-medium mb-1">Provider</label>
                <select bind:value={profile.provider} class="w-full p-2 border rounded">
                  <option value="openai">OpenAI</option>
                  <option value="mistral">Mistral AI</option>
                  <option value="openrouter">OpenRouter</option>
                  <option value="koboldcpp">KoboldCPP</option>
                  <option value="custom">Custom</option>
                </select>
              </div>
    
              <div>
                <label class="block text-sm font-medium mb-1">API Key</label>
                <input 
                  type="password" 
                  placeholder="Your API key"
                  bind:value={profile.apiKey} 
                  class="w-full p-2 border rounded"
                />
              </div>
    
              <div>
                <label class="block text-sm font-medium mb-1">
                  Endpoint URL
                  {#if profile.provider === 'koboldcpp'}
                    <span class="text-xs text-gray-500">(editable for tunnel/remote access)</span>
                  {/if}
                </label>
                <input 
                  type="url" 
                  placeholder={profile.provider === 'koboldcpp' ? 'e.g., http://localhost:5001/v1/chat/completions or tunnel URL' : 'API endpoint URL'}
                  bind:value={profile.endpoint} 
                  readonly={profile.provider !== 'custom' && profile.provider !== 'koboldcpp'}
                  class="w-full p-2 border rounded {profile.provider !== 'custom' && profile.provider !== 'koboldcpp' ? 'bg-gray-100' : ''}"
                />
                {#if profile.provider === 'koboldcpp'}
                  <div class="text-xs text-gray-600 mt-1">
                    For tunnel access, use your tunnel URL (e.g., https://abc123.ngrok.io/v1/chat/completions)
                  </div>
                {/if}
              </div>
    
              <div>
                <label class="block text-sm font-medium mb-1">Model</label>
                <input 
                  type="text" 
                  placeholder="e.g., gpt-3.5-turbo"
                  bind:value={profile.model} 
                  class="w-full p-2 border rounded"
                />
              </div>
    
              <!-- System Prompt & Author Note Configuration -->
              <div class="mt-4 border-t pt-4">
                <h4 class="text-lg font-medium mb-3">Prompt Configuration</h4>
                
                <!-- Preset Selection -->
                <div class="mb-4">
                  <label class="block text-sm font-medium mb-2">Quick Presets</label>
                  <div class="grid grid-cols-2 md:grid-cols-3 gap-2">
                    {#each SYSTEM_PROMPT_PRESETS as preset}
                      <button 
                        type="button"
                        onclick={() => applyPreset(preset)} 
                        class="px-3 py-2 bg-blue-100 hover:bg-blue-200 text-blue-800 rounded text-sm transition-colors"
                        title={preset.description}
                      >
                        {preset.name}
                      </button>
                    {/each}
                  </div>
                </div>
    
                <!-- System Prompt -->
                <div class="mb-4">
                  <label class="block text-sm font-medium mb-1" title="Custom system prompt sent at the beginning of every conversation. Supports template variables.">
                    System Prompt
                  </label>
                  <textarea 
                    bind:value={profile.systemPrompt} 
                    placeholder="Leave empty to use default storytelling prompt..."
                    class="w-full p-2 border rounded text-sm resize-vertical"
                    rows="4"
                  ></textarea>
                  <div class="text-xs text-gray-600 mt-1">
                    Supports template variables. Leave empty to use the default system prompt.
                  </div>
                </div>
    
                <!-- Author Note -->
                <div class="mb-4">
                  <label class="block text-sm font-medium mb-1" title="Additional instructions sent after the story context but before generation. Supports template variables.">
                    Author Note
                  </label>
                  <textarea 
                    bind:value={profile.authorNote} 
                    placeholder="Optional additional instructions for the AI..."
                    class="w-full p-2 border rounded text-sm resize-vertical"
                    rows="2"
                  ></textarea>
                  <div class="text-xs text-gray-600 mt-1">
                    Sent after story content but before AI generation. Supports template variables.
                  </div>
                </div>
              </div>
    
              <!-- Basic Settings -->
              <div class="grid grid-cols-2 gap-3">
                <div>
                  <label class="block text-sm font-medium mb-1" title="Controls randomness in text generation. Higher values (1.0-2.0) make output more creative but less coherent.">
                    Temperature ({profile.settings.temperature})
                  </label>
                  <input 
                    type="range" 
                    min="0" 
                    max="2" 
                    step="0.1"
                    bind:value={profile.settings.temperature} 
                    class="w-full"
                  />
                </div>
                <div>
                  <label class="block text-sm font-medium mb-1" title="Maximum number of tokens (words/parts) to generate in the response.">
                    Max Tokens
                  </label>
                  <input 
                    type="number" 
                    min="1" 
                    max="4000"
                    bind:value={profile.settings.maxTokens} 
                    class="w-full p-2 border rounded"
                  />
                </div>
              </div>
    
              <div class="grid grid-cols-3 gap-3">
                <div>
                  <label class="block text-sm font-medium mb-1" title="Nucleus sampling. Only considers tokens with cumulative probability up to this value. Lower values (0.1-0.9) make output more focused.">
                    Top P ({profile.settings.topP})
                  </label>
                  <input 
                    type="range" 
                    min="0" 
                    max="1" 
                    step="0.1"
                    bind:value={profile.settings.topP} 
                    class="w-full"
                  />
                </div>
                <div>
                  <label class="block text-sm font-medium mb-1" title="Reduces likelihood of repeating the same words. Positive values discourage repetition.">
                    Freq Penalty ({profile.settings.frequencyPenalty})
                  </label>
                  <input 
                    type="range" 
                    min="-2" 
                    max="2" 
                    step="0.1"
                    bind:value={profile.settings.frequencyPenalty} 
                    class="w-full"
                  />
                </div>
                <div>
                  <label class="block text-sm font-medium mb-1" title="Encourages model to talk about new topics. Positive values promote diverse content.">
                    Pres Penalty ({profile.settings.presencePenalty})
                  </label>
                  <input 
                    type="range" 
                    min="-2" 
                    max="2" 
                    step="0.1"
                    bind:value={profile.settings.presencePenalty} 
                    class="w-full"
                  />
                </div>
              </div>
    
              <!-- KoboldCPP Advanced Settings -->
              {#if profile.provider === 'koboldcpp'}
                <div class="mt-4 border-t pt-4">
                  <button 
                    type="button"
                    onclick={() => showAdvanced = !showAdvanced}
                    class="flex items-center justify-between w-full p-2 bg-gray-100 hover:bg-gray-200 rounded transition-colors"
                  >
                    <span class="font-medium">Advanced Sampling & Repetition Control</span>
                    <span class="transform transition-transform {showAdvanced ? 'rotate-180' : ''}">▼</span>
                  </button>
                  
                  {#if showAdvanced}
                    <div class="mt-3 space-y-3 p-3 bg-gray-50 rounded">
                      <!-- Advanced Sampling -->
                      <div>
                        <h4 class="text-sm font-semibold mb-2 text-gray-700">Advanced Sampling</h4>
                        <div class="grid grid-cols-3 gap-3">
                          <div>
                            <label class="block text-xs font-medium mb-1" title="Tail Free Sampling: Removes tokens from the low probability tail. Lower values make output more focused.">
                              TFS ({profile.settings.tfs ?? 1.0})
                            </label>
                            <input 
                              type="range" 
                              min="0" 
                              max="1" 
                              step="0.05"
                              bind:value={profile.settings.tfs} 
                              class="w-full"
                            />
                          </div>
                          <div>
                            <label class="block text-xs font-medium mb-1" title="Top-A sampling: Removes tokens below a certain probability threshold. 0 = disabled.">
                              Top A ({profile.settings.topA ?? 0})
                            </label>
                            <input 
                              type="range" 
                              min="0" 
                              max="1" 
                              step="0.05"
                              bind:value={profile.settings.topA} 
                              class="w-full"
                            />
                          </div>
                          <div>
                            <label class="block text-xs font-medium mb-1" title="Top-K sampling: Only considers the K most likely tokens. 0 = disabled.">
                              Top K ({profile.settings.topK ?? 0})
                            </label>
                            <input 
                              type="number" 
                              min="0" 
                              max="200" 
                              bind:value={profile.settings.topK} 
                              class="w-full p-1 border rounded text-xs"
                            />
                          </div>
                        </div>
                        <div class="grid grid-cols-2 gap-3 mt-3">
                          <div>
                            <label class="block text-xs font-medium mb-1" title="Minimum probability threshold. Tokens below this are removed.">
                              Min P ({profile.settings.minP ?? 0})
                            </label>
                            <input 
                              type="range" 
                              min="0" 
                              max="1" 
                              step="0.05"
                              bind:value={profile.settings.minP} 
                              class="w-full"
                            />
                          </div>
                          <div>
                            <label class="block text-xs font-medium mb-1" title="Typical sampling: Prefers tokens close to average information density.">
                              Typical ({profile.settings.typical ?? 1.0})
                            </label>
                            <input 
                              type="range" 
                              min="0" 
                              max="1" 
                              step="0.05"
                              bind:value={profile.settings.typical} 
                              class="w-full"
                            />
                          </div>
                        </div>
                      </div>
    
                      <!-- Repetition Control -->
                      <div>
                        <h4 class="text-sm font-semibold mb-2 text-gray-700">Repetition Control</h4>
                        <div class="grid grid-cols-2 gap-3">
                          <div>
                            <label class="block text-xs font-medium mb-1" title="Base repetition penalty. Values > 1.0 discourage repetition.">
                              Rep Penalty ({profile.settings.repPen ?? 1.0})
                            </label>
                            <input 
                              type="range" 
                              min="1" 
                              max="2" 
                              step="0.01"
                              bind:value={profile.settings.repPen} 
                              class="w-full"
                            />
                          </div>
                          <div>
                            <label class="block text-xs font-medium mb-1" title="Number of recent tokens to apply repetition penalty to.">
                              Rep Range ({profile.settings.repPenRange ?? 256})
                            </label>
                            <input 
                              type="number" 
                              min="0" 
                              max="2048" 
                              bind:value={profile.settings.repPenRange} 
                              class="w-full p-1 border rounded text-xs"
                            />
                          </div>
                        </div>
                      </div>
    
                      <!-- Dynamic Temperature -->
                      <div>
                        <h4 class="text-sm font-semibold mb-2 text-gray-700">Dynamic Temperature</h4>
                        <div class="grid grid-cols-3 gap-3">
                          <div>
                            <label class="block text-xs font-medium mb-1" title="Temperature varies between (temp-range) and (temp+range). 0 = static temperature.">
                              Range ({profile.settings.dynatempRange ?? 0})
                            </label>
                            <input 
                              type="range" 
                              min="0" 
                              max="2" 
                              step="0.1"
                              bind:value={profile.settings.dynatempRange} 
                              class="w-full"
                            />
                          </div>
                          <div>
                            <label class="block text-xs font-medium mb-1" title="Exponent for dynamic temperature calculation.">
                              Exponent ({profile.settings.dynatempExponent ?? 1.0})
                            </label>
                            <input 
                              type="range" 
                              min="0.1" 
                              max="5" 
                              step="0.1"
                              bind:value={profile.settings.dynatempExponent} 
                              class="w-full"
                            />
                          </div>
                          <div>
                            <label class="block text-xs font-medium mb-1" title="Temperature smoothing factor. Higher values smooth temperature changes.">
                              Smoothing ({profile.settings.smoothingFactor ?? 0})
                            </label>
                            <input 
                              type="range" 
                              min="0" 
                              max="2" 
                              step="0.1"
                              bind:value={profile.settings.smoothingFactor} 
                              class="w-full"
                            />
                          </div>
                        </div>
                      </div>
                    </div>
                  {/if}
                </div>
    
                <!-- Expert Settings -->
                <div class="mt-4 border-t pt-4">
                  <button 
                    type="button"
                    onclick={() => showExpert = !showExpert}
                    class="flex items-center justify-between w-full p-2 bg-red-50 hover:bg-red-100 rounded transition-colors border border-red-200"
                  >
                    <span class="font-medium text-red-800">Expert Settings (Advanced Users Only)</span>
                    <span class="transform transition-transform {showExpert ? 'rotate-180' : ''} text-red-600">▼</span>
                  </button>
                  
                  {#if showExpert}
                    <div class="mt-3 space-y-3 p-3 bg-red-50 rounded border border-red-200">
                      <!-- Mirostat -->
                      <div>
                        <h4 class="text-sm font-semibold mb-2 text-gray-700">Mirostat</h4>
                        <div class="grid grid-cols-3 gap-3">
                          <div>
                            <label class="block text-xs font-medium mb-1" title="Mirostat mode: 0=disabled, 1=v1, 2=v2. Controls perplexity during generation.">
                              Mode ({profile.settings.mirostat ?? 0})
                            </label>
                            <select bind:value={profile.settings.mirostat} class="w-full p-1 border rounded text-xs">
                              <option value={0}>Disabled</option>
                              <option value={1}>Mirostat v1</option>
                              <option value={2}>Mirostat v2</option>
                            </select>
                          </div>
                          <div>
                            <label class="block text-xs font-medium mb-1" title="Target cross-entropy (perplexity). Higher values allow more variation.">
                              Tau ({profile.settings.mirostatTau ?? 5.0})
                            </label>
                            <input 
                              type="range" 
                              min="0" 
                              max="10" 
                              step="0.1"
                              bind:value={profile.settings.mirostatTau} 
                              class="w-full"
                            />
                          </div>
                          <div>
                            <label class="block text-xs font-medium mb-1" title="Learning rate for mirostat adjustments.">
                              Eta ({profile.settings.mirostatEta ?? 0.1})
                            </label>
                            <input 
                              type="range" 
                              min="0" 
                              max="1" 
                              step="0.01"
                              bind:value={profile.settings.mirostatEta} 
                              class="w-full"
                            />
                          </div>
                        </div>
                      </div>
    
                      <!-- DRY (Don't Repeat Yourself) -->
                      <div>
                        <h4 class="text-sm font-semibold mb-2 text-gray-700">DRY (Don't Repeat Yourself)</h4>
                        <div class="grid grid-cols-3 gap-3">
                          <div>
                            <label class="block text-xs font-medium mb-1" title="DRY multiplier. 0 = disabled. Higher values penalize repetition more.">
                              Multiplier ({profile.settings.dryMultiplier ?? 0})
                            </label>
                            <input 
                              type="range" 
                              min="0" 
                              max="5" 
                              step="0.1"
                              bind:value={profile.settings.dryMultiplier} 
                              class="w-full"
                            />
                          </div>
                          <div>
                            <label class="block text-xs font-medium mb-1" title="Base DRY value.">
                              Base ({profile.settings.dryBase ?? 1.75})
                            </label>
                            <input 
                              type="range" 
                              min="0" 
                              max="5" 
                              step="0.1"
                              bind:value={profile.settings.dryBase} 
                              class="w-full"
                            />
                          </div>
                          <div>
                            <label class="block text-xs font-medium mb-1" title="Minimum sequence length before DRY applies.">
                              Allowed Length ({profile.settings.dryAllowedLength ?? 2})
                            </label>
                            <input 
                              type="number" 
                              min="0" 
                              max="20" 
                              bind:value={profile.settings.dryAllowedLength} 
                              class="w-full p-1 border rounded text-xs"
                            />
                          </div>
                        </div>
                      </div>
    
                      <!-- XTC -->
                      <div>
                        <h4 class="text-sm font-semibold mb-2 text-gray-700">XTC (Exclude Top Choices)</h4>
                        <div class="grid grid-cols-2 gap-3">
                          <div>
                            <label class="block text-xs font-medium mb-1" title="XTC threshold value.">
                              Threshold ({profile.settings.xtcThreshold ?? 0.1})
                            </label>
                            <input 
                              type="range" 
                              min="0" 
                              max="1" 
                              step="0.01"
                              bind:value={profile.settings.xtcThreshold} 
                              class="w-full"
                            />
                          </div>
                          <div>
                            <label class="block text-xs font-medium mb-1" title="XTC probability. Set above 0 to enable XTC sampling.">
                              Probability ({profile.settings.xtcProbability ?? 0})
                            </label>
                            <input 
                              type="range" 
                              min="0" 
                              max="1" 
                              step="0.01"
                              bind:value={profile.settings.xtcProbability} 
                              class="w-full"
                            />
                          </div>
                        </div>
                      </div>
    
                      <!-- Grammar & Constraints -->
                      <div>
                        <h4 class="text-sm font-semibold mb-2 text-gray-700">Grammar & Constraints</h4>
                        <div class="grid grid-cols-1 gap-3">
                          <div>
                            <label class="block text-xs font-medium mb-1" title="GBNF grammar string to constrain output format.">
                              Grammar (GBNF)
                            </label>
                            <textarea 
                              bind:value={profile.settings.grammar} 
                              placeholder="Enter GBNF grammar rules..."
                              class="w-full p-2 border rounded text-xs resize-vertical"
                              rows="3"
                            ></textarea>
                          </div>
                          <div>
                            <label class="block text-xs font-medium mb-1" title="Forced memory insertion at the beginning of prompts.">
                              Memory
                            </label>
                            <textarea 
                              bind:value={profile.settings.memory} 
                              placeholder="Forced memory content..."
                              class="w-full p-2 border rounded text-xs resize-vertical"
                              rows="2"
                            ></textarea>
                          </div>
                        </div>
                      </div>
                    </div>
                  {/if}
                </div>
              {/if}
    
              <div class="grid grid-cols-2 gap-3">
                <div>
                  <label class="block text-sm font-medium mb-1">Max Context Entries</label>
                  <input 
                    type="number" 
                    min="1" 
                    max="50"
                    bind:value={profile.maxContextEntries} 
                    class="w-full p-2 border rounded"
                  />
                </div>
                <div class="flex items-center">
                  <label class="flex items-center">
                    <input 
                      type="checkbox" 
                      bind:checked={profile.includeSystemContent}
                      class="mr-2"
                    />
                    Include System Content
                  </label>
                </div>
              </div>
    
              <!-- Context Size Configuration -->
              <div class="mt-4 border-t pt-4">
                <h4 class="text-sm font-medium mb-3">Context Size Management</h4>
                
                {#if profile.provider === 'koboldcpp'}
                  <div class="space-y-3">
                    <label class="flex items-center">
                      <input 
                        type="checkbox" 
                        bind:checked={profile.autoDetectContextSize}
                        class="mr-2"
                      />
                      Auto-detect context size from KoboldCPP API
                    </label>
                    
                    {#if !profile.autoDetectContextSize}
                      <div>
                        <label class="block text-sm font-medium mb-1">Manual Context Size</label>
                        <input 
                          type="number" 
                          min="512" 
                          max="32768"
                          bind:value={profile.maxContextSize} 
                          placeholder="e.g., 2048"
                          class="w-full p-2 border rounded"
                        />
                        <p class="text-xs text-gray-500 mt-1">
                          Override auto-detection with manual value
                        </p>
                      </div>
                    {/if}
                  </div>
                {:else}
                  <div>
                    <label class="block text-sm font-medium mb-1">Max Context Size (tokens)</label>
                    <input 
                      type="number" 
                      min="512" 
                      max="200000"
                      bind:value={profile.maxContextSize} 
                      placeholder="e.g., 4096 for GPT-3.5, 128000 for GPT-4"
                      class="w-full p-2 border rounded"
                    />
                    <p class="text-xs text-gray-500 mt-1">
                      Set the maximum context size for this model. Token counting will use character-based estimation.
                    </p>
                  </div>
                {/if}
              </div>
            </div>
            
            <div class="flex gap-2 mt-4">
              <button onclick={saveProfile} class="px-4 py-2 bg-green-500 text-white rounded">
                {selectedKey ? 'Update' : 'Create'} Profile
              </button>
              <button onclick={() => { open = ''; selectedKey = ''; resetProfile(); }} class="px-4 py-2 bg-gray-500 text-white rounded">
                Cancel
              </button>
            </div>
          </div>
        {:else if open === 'import'}
          <div class="mb-6 p-4 border rounded">
            <h4 class="text-xl mb-3">Import Profiles</h4>
            <textarea 
              bind:value={importData} 
              placeholder="Paste your JSON profile data here..."
              class="w-full p-2 border rounded h-32"
            ></textarea>
            <div class="flex gap-2 mt-3">
              <button onclick={importProfiles} class="px-4 py-2 bg-blue-500 text-white rounded">
                Import
              </button>
              <button onclick={() => open = ''} class="px-4 py-2 bg-gray-500 text-white rounded">
                Cancel
              </button>
            </div>
          </div>
        {:else if open === 'export'}
          <div class="mb-6 p-4 border rounded">
            <h4 class="text-xl mb-3">Export Profiles</h4>
            <textarea 
              readonly 
              bind:value={exportData} 
              class="w-full p-2 border rounded h-32 bg-gray-50"
            ></textarea>
            <div class="flex gap-2 mt-3">
              <button onclick={() => navigator.clipboard.writeText(exportData)} class="px-4 py-2 bg-blue-500 text-white rounded">
                Copy to Clipboard
              </button>
              <button onclick={() => open = ''} class="px-4 py-2 bg-gray-500 text-white rounded">
                Close
              </button>
            </div>
          </div>
        {/if}
    
        <!-- Profile List -->
        <div class="space-y-3">
          {#each Object.entries(profileList) as [key, prof]}
            <div class="p-4 border rounded flex justify-between items-start">
              <div class="flex-1">
                <div class="flex items-center gap-2 mb-2">
                  <h4 class="text-lg font-medium">{prof.name}</h4>
                  <span class="px-2 py-1 bg-blue-100 text-blue-800 rounded text-xs">{prof.provider}</span>
                  {#if testResults[key] !== undefined}
                    <span class="px-2 py-1 rounded text-xs {testResults[key] ? 'bg-green-100 text-green-800' : 'bg-red-100 text-red-800'}">
                      {testResults[key] ? '✓ Connected' : '✗ Failed'}
                    </span>
                  {/if}
                </div>
                <div class="text-sm text-gray-600 space-y-1">
                  <div><strong>Model:</strong> {prof.model}</div>
                  <div><strong>Context:</strong> {prof.maxContextEntries} entries, {prof.includeSystemContent ? 'includes' : 'excludes'} system content</div>
                  <div><strong>Settings:</strong> temp {prof.settings.temperature}, tokens {prof.settings.maxTokens}</div>
                </div>
              </div>
              <div class="flex gap-2 ml-4">
                <button onclick={() => testConnection(key)} disabled={testingConnection === key} class="px-2 py-1 bg-purple-500 text-white rounded text-xs">
                  {testingConnection === key ? 'Testing...' : 'Test'}
                </button>
                <button onclick={() => editProfile(key)} class="px-2 py-1 bg-blue-500 text-white rounded text-xs">
                  Edit
                </button>
                <button onclick={() => duplicateProfile(key)} class="px-2 py-1 bg-yellow-500 text-white rounded text-xs">
                  Duplicate
                </button>
                <button onclick={() => deleteProfile(key)} class="px-2 py-1 bg-red-500 text-white rounded text-xs">
                  Delete
                </button>
              </div>
            </div>
          {:else}
            <div class="p-8 text-center text-gray-500">
              <p class="mb-4">No LLM profiles configured yet.</p>
              <button onclick={() => { resetProfile(); open = 'create'; }} class="px-4 py-2 bg-green-500 text-white rounded">
                Create Your First Profile
              </button>
            </div>
          {/each}
        </div>
      </div>
    </SettingPage>

    Comments

    More Rules

    View all

    Textbased Predictor Perplexity Rules

    H
    Havcker243

    Intelligent Team Building Recommendation System Perplexity Rules

    R
    royswastik

    Pita Perplexity Rules

    S
    SaratBobbili

    Eskrev Perplexity Rules

    R
    rfmss

    Founder Control Room Perplexity Rules

    J
    jussray

    N8nWorkflows Perplexity Rules

    S
    Samarth-ITM

    Stay up to date

    Get the latest Perplexity prompts, rules, and resources delivered to your inbox weekly.

    Neura Market LogoNeura Market

    Discover the best AI prompts, plugins, and resources for Perplexity and more.

    Content Types

    • Rules
    • Prompts
    • MCPs
    • Agents
    • Guides

    Platforms

    • ChatGPT Directory
    • Claude Directory
    • Gemini Directory
    • Cursor Directory
    • Grok Directory
    • Perplexity Directory
    • DeepSeek Directory
    • CoPilot Directory
    • Stable Diffusion Directory
    • Midjourney Directory
    • All Directories

    Resources

    • Blog
    • Documentation
    • Help Center
    • Marketplace

    Legal

    • Privacy Policy
    • Terms of Service

    © 2026 Neura Market. All rights reserved.

    |

    Not affiliated with any AI platform vendors.

    Neura Market

    Custom AI Systems & Services

    Our team of experienced AI builders will help build custom AI systems, workflows, and solutions for your business.

    Request custom work

    Ready-made automations for this

    Workflows from the Neura Market marketplace related to this Perplexity resource

    • Automated Lead Generation & Contact Enrichment with Hunter.io and Perplexity AIn8n · $24.99 · Related topic
    • Automate SEO-Optimized Blog Creation with GPT-4, Perplexity AI & Multi-Language Supportn8n · $24.99 · Related topic
    • Automate SEO Blog Content Creation with GPT-4, Perplexity AI, and WordPressn8n · $24.99 · Related topic
    • Automate SEO Blog Creation + Social Media with GPT-4, Perplexity, and WordPressn8n · $24.99 · Related topic
    Browse all workflows