Promptimizer

AI-powered prompt optimization tool that works with OpenAI-compatible APIs

目前為 2025-02-24 提交的版本,檢視 最新版本

  1. // ==UserScript==
  2. // @name Promptimizer
  3. // @namespace http://tampermonkey.net/
  4. // @version 1.0
  5. // @license MIT
  6. // @description AI-powered prompt optimization tool that works with OpenAI-compatible APIs
  7. // @author NoahTheGinger
  8. // @match *://*/*
  9. // @grant GM_xmlhttpRequest
  10. // @grant GM_setValue
  11. // @grant GM_getValue
  12. // @grant GM_addStyle
  13. // ==/UserScript==
  14.  
  15. (function() {
  16. 'use strict';
  17.  
  18. // Styles for the UI
  19. GM_addStyle(`
  20. #promptimizer-container {
  21. position: fixed;
  22. bottom: 20px;
  23. right: 20px;
  24. width: 400px;
  25. background: #ffffff;
  26. border-radius: 8px;
  27. box-shadow: 0 2px 10px rgba(0,0,0,0.3);
  28. z-index: 2147483647;
  29. font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
  30. display: none;
  31. color: #000000;
  32. transition: width 0.2s ease, height 0.2s ease;
  33. overflow: hidden;
  34. min-height: 300px;
  35. min-width: 300px;
  36. }
  37.  
  38. #promptimizer-header {
  39. padding: 12px;
  40. background: #2196F3;
  41. border-radius: 8px 8px 0 0;
  42. cursor: move;
  43. display: flex;
  44. justify-content: space-between;
  45. align-items: center;
  46. color: #ffffff;
  47. }
  48.  
  49. #promptimizer-header-controls {
  50. display: flex;
  51. gap: 12px;
  52. align-items: center;
  53. }
  54.  
  55. .header-button {
  56. background: none;
  57. border: none;
  58. color: #ffffff;
  59. cursor: pointer;
  60. font-size: 16px;
  61. padding: 0;
  62. display: flex;
  63. align-items: center;
  64. opacity: 0.8;
  65. transition: opacity 0.2s;
  66. }
  67.  
  68. .header-button:hover {
  69. opacity: 1;
  70. }
  71.  
  72. #promptimizer-title {
  73. margin: 0;
  74. font-size: 16px;
  75. font-weight: bold;
  76. color: #ffffff;
  77. }
  78.  
  79. #promptimizer-toggle {
  80. position: fixed;
  81. bottom: 20px;
  82. right: 20px;
  83. width: 50px;
  84. height: 50px;
  85. background: #2196F3;
  86. border-radius: 25px;
  87. color: white;
  88. display: flex;
  89. align-items: center;
  90. justify-content: center;
  91. cursor: pointer;
  92. font-size: 24px;
  93. box-shadow: 0 2px 5px rgba(0,0,0,0.2);
  94. z-index: 2147483647;
  95. border: 2px solid rgba(255,255,255,0.2);
  96. }
  97.  
  98. #promptimizer-content {
  99. padding: 16px;
  100. background: #ffffff;
  101. border-radius: 0 0 8px 8px;
  102. overflow-y: auto;
  103. max-height: calc(100% - 48px);
  104. }
  105.  
  106. .promptimizer-input {
  107. width: 100%;
  108. padding: 8px;
  109. margin-bottom: 10px;
  110. border: 1px solid #ddd;
  111. border-radius: 4px;
  112. box-sizing: border-box;
  113. background: #ffffff;
  114. color: #000000;
  115. }
  116.  
  117. /* Textarea specific styles */
  118. textarea.promptimizer-input {
  119. resize: none; /* We'll handle resizing through container */
  120. min-height: 100px;
  121. transition: border-color 0.2s ease, box-shadow 0.2s ease;
  122. overflow-y: auto;
  123. }
  124.  
  125. textarea.promptimizer-input:focus {
  126. border-color: #2196F3;
  127. box-shadow: 0 0 0 2px rgba(33, 150, 243, 0.2);
  128. outline: none;
  129. }
  130.  
  131. /* Custom resize handles for the container */
  132. .resize-handle {
  133. position: absolute;
  134. background: transparent;
  135. z-index: 10;
  136. }
  137.  
  138. .resize-handle-right {
  139. cursor: ew-resize;
  140. width: 8px;
  141. height: 100%;
  142. right: 0;
  143. top: 0;
  144. }
  145.  
  146. .resize-handle-bottom {
  147. cursor: ns-resize;
  148. height: 8px;
  149. width: 100%;
  150. bottom: 0;
  151. left: 0;
  152. }
  153.  
  154. .resize-handle-corner {
  155. cursor: nwse-resize;
  156. width: 14px;
  157. height: 14px;
  158. right: 0;
  159. bottom: 0;
  160. }
  161.  
  162. /* Container resize visual feedback */
  163. #promptimizer-container.resizing {
  164. transition: none;
  165. box-shadow: 0 2px 15px rgba(33, 150, 243, 0.4);
  166. }
  167.  
  168. #promptimizer-container.resizing-right {
  169. border-right: 2px solid #2196F3;
  170. }
  171.  
  172. #promptimizer-container.resizing-bottom {
  173. border-bottom: 2px solid #2196F3;
  174. }
  175.  
  176. #promptimizer-container.resizing-corner {
  177. border-right: 2px solid #2196F3;
  178. border-bottom: 2px solid #2196F3;
  179. }
  180.  
  181. .prompt-type-select {
  182. width: 100%;
  183. padding: 8px;
  184. margin-bottom: 10px;
  185. border: 1px solid #ddd;
  186. border-radius: 4px;
  187. background: #ffffff;
  188. color: #000000;
  189. font-size: 14px;
  190. cursor: pointer;
  191. }
  192.  
  193. .prompt-type-select:focus {
  194. border-color: #2196F3;
  195. outline: none;
  196. }
  197.  
  198. .input-group {
  199. margin-bottom: 16px;
  200. }
  201.  
  202. .input-label {
  203. display: block;
  204. margin-bottom: 6px;
  205. color: #000000;
  206. font-size: 14px;
  207. font-weight: 500;
  208. }
  209.  
  210. .promptimizer-button {
  211. background: #2196F3;
  212. color: white;
  213. border: none;
  214. padding: 8px 16px;
  215. border-radius: 4px;
  216. cursor: pointer;
  217. font-size: 14px;
  218. margin-bottom: 10px;
  219. width: 100%;
  220. }
  221.  
  222. .promptimizer-button:hover {
  223. background: #1976D2;
  224. }
  225.  
  226. #promptimizer-response-container {
  227. position: relative;
  228. margin-top: 16px;
  229. }
  230.  
  231. #promptimizer-response {
  232. margin-top: 0;
  233. padding: 12px;
  234. background: #f8f9fa;
  235. border-radius: 4px;
  236. white-space: pre-wrap;
  237. max-height: 300px;
  238. overflow-y: auto;
  239. color: #000000;
  240. border: 1px solid #e9ecef;
  241. }
  242.  
  243. #copy-button {
  244. position: absolute;
  245. top: 8px;
  246. right: 8px;
  247. background: #2196F3;
  248. color: white;
  249. border: none;
  250. border-radius: 4px;
  251. padding: 4px 8px;
  252. font-size: 12px;
  253. cursor: pointer;
  254. opacity: 0;
  255. transition: opacity 0.2s;
  256. z-index: 1;
  257. }
  258.  
  259. #copy-button:hover {
  260. background: #1976D2;
  261. }
  262.  
  263. #copy-button.visible {
  264. opacity: 1;
  265. }
  266.  
  267. #copy-button.copied {
  268. background: #4CAF50;
  269. }
  270.  
  271. .promptimizer-error {
  272. color: #dc3545;
  273. margin-top: 8px;
  274. font-size: 14px;
  275. background: #fff;
  276. padding: 8px;
  277. border-radius: 4px;
  278. }
  279.  
  280. .config-section {
  281. margin-bottom: 15px;
  282. overflow: hidden;
  283. transition: max-height 0.3s ease-out;
  284. }
  285.  
  286. .config-section.collapsed {
  287. max-height: 40px;
  288. }
  289.  
  290. .config-section.expanded {
  291. max-height: 300px;
  292. }
  293.  
  294. .config-header {
  295. display: flex;
  296. justify-content: space-between;
  297. align-items: center;
  298. cursor: pointer;
  299. padding: 8px 0;
  300. }
  301.  
  302. .config-header h3 {
  303. margin: 0;
  304. font-size: 16px;
  305. color: #333;
  306. }
  307.  
  308. .config-toggle {
  309. font-size: 18px;
  310. color: #666;
  311. transition: transform 0.3s;
  312. }
  313.  
  314. .config-toggle.collapsed {
  315. transform: rotate(-90deg);
  316. }
  317.  
  318. .config-content {
  319. transition: opacity 0.3s;
  320. }
  321.  
  322. .config-content.collapsed {
  323. opacity: 0;
  324. height: 0;
  325. overflow: hidden;
  326. }
  327.  
  328. .config-content.expanded {
  329. opacity: 1;
  330. height: auto;
  331. }
  332. `);
  333.  
  334. // Default dimensions for the container
  335. const defaultDimensions = {
  336. width: '400px',
  337. height: 'auto',
  338. right: '20px',
  339. bottom: '20px'
  340. };
  341.  
  342. // Create UI elements
  343. function createUI() {
  344. // Toggle button
  345. const toggle = document.createElement('div');
  346. toggle.id = 'promptimizer-toggle';
  347. toggle.innerHTML = '✨';
  348. toggle.title = 'Toggle Promptimizer';
  349. document.body.appendChild(toggle);
  350.  
  351. // Main container
  352. const container = document.createElement('div');
  353. container.id = 'promptimizer-container';
  354. container.innerHTML = `
  355. <div id="promptimizer-header">
  356. <h2 id="promptimizer-title">Promptimizer</h2>
  357. <div id="promptimizer-header-controls">
  358. <button class="header-button" id="promptimizer-reset" title="Reset UI Position and Size">↺</button>
  359. <button class="header-button" id="promptimizer-minimize" title="Minimize">−</button>
  360. </div>
  361. </div>
  362. <div id="promptimizer-content">
  363. <div class="config-section expanded" id="config-section">
  364. <div class="config-header" id="config-header">
  365. <h3>API Configuration</h3>
  366. <span class="config-toggle">▼</span>
  367. </div>
  368. <div class="config-content expanded">
  369. <input type="text" id="api-url" class="promptimizer-input" placeholder="API URL (e.g., https://api.openai.com/v1)" />
  370. <input type="password" id="api-key" class="promptimizer-input" placeholder="API Key" />
  371. <input type="text" id="model-name" class="promptimizer-input" placeholder="Model name" />
  372. <input type="text" id="provider-name" class="promptimizer-input" placeholder="Provider name (optional, for gpt4free)" />
  373. <button id="save-config" class="promptimizer-button">Save Configuration</button>
  374. </div>
  375. </div>
  376. <div class="input-group">
  377. <label class="input-label" for="prompt-type">Prompt Type:</label>
  378. <select id="prompt-type" class="prompt-type-select">
  379. <option value="user">User Prompt</option>
  380. <option value="system">System Prompt</option>
  381. </select>
  382. </div>
  383. <div class="input-group">
  384. <label class="input-label" for="prompt-input">Enter Your Prompt:</label>
  385. <textarea id="prompt-input" class="promptimizer-input" rows="4" placeholder="Enter your prompt here..."></textarea>
  386. </div>
  387. <button id="optimize-button" class="promptimizer-button">Optimize Prompt</button>
  388. <div id="promptimizer-response-container">
  389. <button id="copy-button" style="display: none;">Copy Enhanced Prompt</button>
  390. <div id="promptimizer-response"></div>
  391. </div>
  392. </div>
  393. <div class="resize-handle resize-handle-right"></div>
  394. <div class="resize-handle resize-handle-bottom"></div>
  395. <div class="resize-handle resize-handle-corner"></div>
  396. `;
  397. document.body.appendChild(container);
  398.  
  399. // Make the container draggable
  400. makeDraggable(container);
  401.  
  402. // Add container resizing
  403. makeResizable(container);
  404.  
  405. // Load saved configuration
  406. loadConfiguration();
  407.  
  408. // Event listeners
  409. toggle.addEventListener('click', () => {
  410. container.style.display = container.style.display === 'none' ? 'block' : 'none';
  411. });
  412.  
  413. document.getElementById('promptimizer-minimize').addEventListener('click', () => {
  414. container.style.display = 'none';
  415. });
  416.  
  417. // Config section toggle
  418. const configHeader = document.getElementById('config-header');
  419. const configSection = document.getElementById('config-section');
  420. const configToggle = configHeader.querySelector('.config-toggle');
  421. const configContent = configSection.querySelector('.config-content');
  422.  
  423. configHeader.addEventListener('click', () => {
  424. const isExpanded = configSection.classList.contains('expanded');
  425.  
  426. if (isExpanded) {
  427. configSection.classList.remove('expanded');
  428. configSection.classList.add('collapsed');
  429. configContent.classList.remove('expanded');
  430. configContent.classList.add('collapsed');
  431. configToggle.classList.add('collapsed');
  432. } else {
  433. configSection.classList.remove('collapsed');
  434. configSection.classList.add('expanded');
  435. configContent.classList.remove('collapsed');
  436. configContent.classList.add('expanded');
  437. configToggle.classList.remove('collapsed');
  438. }
  439. });
  440.  
  441. document.getElementById('save-config').addEventListener('click', saveConfiguration);
  442. document.getElementById('optimize-button').addEventListener('click', optimizePrompt);
  443. document.getElementById('copy-button').addEventListener('click', copyEnhancedPrompt);
  444.  
  445. // Initialize auto-height for textarea
  446. const textarea = document.getElementById('prompt-input');
  447. if (textarea) {
  448. autoResizeTextarea(textarea);
  449. textarea.addEventListener('input', function() {
  450. autoResizeTextarea(this);
  451. });
  452. }
  453. }
  454.  
  455. // Make an element draggable
  456. function makeDraggable(element) {
  457. const header = element.querySelector('#promptimizer-header');
  458. let isDragging = false;
  459. let currentX;
  460. let currentY;
  461. let initialX;
  462. let initialY;
  463. let xOffset = 0;
  464. let yOffset = 0;
  465.  
  466. // Function to reset position and size
  467. function resetPosition() {
  468. element.style.transform = 'translate(0, 0)';
  469. element.style.right = defaultDimensions.right;
  470. element.style.bottom = defaultDimensions.bottom;
  471. element.style.left = '';
  472. element.style.top = '';
  473. // Reset dimensions as well
  474. element.style.width = defaultDimensions.width;
  475. element.style.height = defaultDimensions.height;
  476. xOffset = 0;
  477. yOffset = 0;
  478.  
  479. // Reset any set textarea dimensions
  480. const textarea = document.getElementById('prompt-input');
  481. if (textarea) {
  482. textarea.style.height = '';
  483. autoResizeTextarea(textarea);
  484. }
  485. }
  486.  
  487. // Add reset button event listener
  488. document.getElementById('promptimizer-reset').addEventListener('click', (e) => {
  489. e.stopPropagation(); // Prevent drag start
  490. resetPosition();
  491. });
  492.  
  493. header.addEventListener('mousedown', dragStart);
  494. document.addEventListener('mousemove', drag);
  495. document.addEventListener('mouseup', dragEnd);
  496.  
  497. function dragStart(e) {
  498. if (e.target.closest('.header-button')) {
  499. return; // Don't start drag if clicking a button
  500. }
  501. initialX = e.clientX - xOffset;
  502. initialY = e.clientY - yOffset;
  503.  
  504. if (e.target === header || e.target.closest('#promptimizer-header')) {
  505. isDragging = true;
  506. }
  507. }
  508.  
  509. function drag(e) {
  510. if (isDragging) {
  511. e.preventDefault();
  512. currentX = e.clientX - initialX;
  513. currentY = e.clientY - initialY;
  514. xOffset = currentX;
  515. yOffset = currentY;
  516.  
  517. element.style.transform = `translate(${currentX}px, ${currentY}px)`;
  518. // Clear the default positioning when dragging
  519. element.style.right = '';
  520. element.style.bottom = '';
  521. }
  522. }
  523.  
  524. function dragEnd() {
  525. initialX = currentX;
  526. initialY = currentY;
  527. isDragging = false;
  528. }
  529.  
  530. // Initialize at default position
  531. resetPosition();
  532. }
  533.  
  534. // Make container resizable
  535. function makeResizable(container) {
  536. const rightHandle = container.querySelector('.resize-handle-right');
  537. const bottomHandle = container.querySelector('.resize-handle-bottom');
  538. const cornerHandle = container.querySelector('.resize-handle-corner');
  539.  
  540. let isResizing = false;
  541. let currentResizeType = '';
  542. let startX, startY, startWidth, startHeight;
  543.  
  544. // Function to start resize operation
  545. function startResize(e, type) {
  546. e.preventDefault();
  547. e.stopPropagation();
  548.  
  549. isResizing = true;
  550. currentResizeType = type;
  551.  
  552. // Get current dimensions
  553. const rect = container.getBoundingClientRect();
  554. startWidth = rect.width;
  555. startHeight = rect.height;
  556. startX = e.clientX;
  557. startY = e.clientY;
  558.  
  559. // Add visual feedback classes
  560. container.classList.add('resizing');
  561. container.classList.add(`resizing-${type}`);
  562.  
  563. // Add document listeners
  564. document.addEventListener('mousemove', resize);
  565. document.addEventListener('mouseup', stopResize);
  566. }
  567.  
  568. // Function to handle resize
  569. function resize(e) {
  570. if (!isResizing) return;
  571.  
  572. let newWidth = startWidth;
  573. let newHeight = startHeight;
  574.  
  575. // Calculate new dimensions based on mouse movement
  576. switch (currentResizeType) {
  577. case 'right':
  578. newWidth = startWidth + (e.clientX - startX);
  579. break;
  580. case 'bottom':
  581. newHeight = startHeight + (e.clientY - startY);
  582. break;
  583. case 'corner':
  584. newWidth = startWidth + (e.clientX - startX);
  585. newHeight = startHeight + (e.clientY - startY);
  586. break;
  587. }
  588.  
  589. // Apply minimum dimensions
  590. newWidth = Math.max(300, newWidth);
  591. newHeight = Math.max(300, newHeight);
  592.  
  593. // Apply new dimensions
  594. container.style.width = `${newWidth}px`;
  595. container.style.height = `${newHeight}px`;
  596. }
  597.  
  598. // Function to stop resize
  599. function stopResize() {
  600. isResizing = false;
  601.  
  602. // Remove visual feedback classes
  603. container.classList.remove('resizing');
  604. container.classList.remove(`resizing-${currentResizeType}`);
  605.  
  606. // Remove document listeners
  607. document.removeEventListener('mousemove', resize);
  608. document.removeEventListener('mouseup', stopResize);
  609.  
  610. // Re-enable transitions
  611. container.style.transition = 'width 0.2s ease, height 0.2s ease';
  612. }
  613.  
  614. // Add event listeners to resize handles
  615. rightHandle.addEventListener('mousedown', e => startResize(e, 'right'));
  616. bottomHandle.addEventListener('mousedown', e => startResize(e, 'bottom'));
  617. cornerHandle.addEventListener('mousedown', e => startResize(e, 'corner'));
  618. }
  619.  
  620. // Helper function to auto-resize textarea based on content
  621. function autoResizeTextarea(textarea) {
  622. // Save scroll position
  623. const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
  624.  
  625. // Reset height temporarily to get accurate scrollHeight
  626. textarea.style.height = 'auto';
  627.  
  628. // Set new height based on content (with minimum)
  629. const newHeight = Math.max(textarea.scrollHeight, 100) + 'px';
  630.  
  631. // Apply the new height with transition
  632. textarea.style.transition = 'height 0.15s ease-out';
  633. textarea.style.height = newHeight;
  634.  
  635. // Restore scroll position to prevent page jump
  636. window.scrollTo(0, scrollTop);
  637. }
  638.  
  639. // Save API configuration
  640. function saveConfiguration() {
  641. const apiUrl = document.getElementById('api-url').value;
  642. const apiKey = document.getElementById('api-key').value;
  643. const modelName = document.getElementById('model-name').value;
  644. const providerName = document.getElementById('provider-name').value;
  645.  
  646. GM_setValue('apiUrl', apiUrl);
  647. GM_setValue('apiKey', apiKey);
  648. GM_setValue('modelName', modelName);
  649. GM_setValue('providerName', providerName);
  650.  
  651. showResponse('Configuration saved!');
  652. }
  653.  
  654. // Load saved configuration
  655. function loadConfiguration() {
  656. const apiUrl = GM_getValue('apiUrl', '');
  657. const apiKey = GM_getValue('apiKey', '');
  658. const modelName = GM_getValue('modelName', '');
  659. const providerName = GM_getValue('providerName', '');
  660.  
  661. document.getElementById('api-url').value = apiUrl;
  662. document.getElementById('api-key').value = apiKey;
  663. document.getElementById('model-name').value = modelName;
  664. document.getElementById('provider-name').value = providerName;
  665. }
  666.  
  667. // Show response or error message
  668. function showResponse(message, isError = false) {
  669. const responseDiv = document.getElementById('promptimizer-response');
  670. const copyButton = document.getElementById('copy-button');
  671. responseDiv.textContent = message;
  672. responseDiv.className = isError ? 'promptimizer-error' : '';
  673.  
  674. // Show/hide copy button based on whether there's a successful response
  675. if (!isError && message !== 'Optimizing prompt...') {
  676. copyButton.style.display = 'block';
  677. setTimeout(() => copyButton.classList.add('visible'), 10);
  678. } else {
  679. copyButton.style.display = 'none';
  680. copyButton.classList.remove('visible');
  681. }
  682. }
  683.  
  684. // Extract enhanced prompt from response
  685. function extractEnhancedPrompt(text) {
  686. const match = text.match(/<enhanced_prompt>([\s\S]*?)<\/enhanced_prompt>/);
  687. return match ? match[1].trim() : text;
  688. }
  689.  
  690. // Copy enhanced prompt to clipboard
  691. function copyEnhancedPrompt() {
  692. const responseDiv = document.getElementById('promptimizer-response');
  693. const copyButton = document.getElementById('copy-button');
  694. const textToCopy = extractEnhancedPrompt(responseDiv.textContent);
  695.  
  696. navigator.clipboard.writeText(textToCopy).then(() => {
  697. copyButton.textContent = 'Copied!';
  698. copyButton.classList.add('copied');
  699. setTimeout(() => {
  700. copyButton.textContent = 'Copy Enhanced Prompt';
  701. copyButton.classList.remove('copied');
  702. }, 2000);
  703. }).catch(err => {
  704. console.error('Failed to copy text: ', err);
  705. });
  706. }
  707.  
  708. // Optimize prompt using the API
  709. async function optimizePrompt() {
  710. const apiUrl = GM_getValue('apiUrl', '');
  711. const apiKey = GM_getValue('apiKey', '');
  712. const modelName = GM_getValue('modelName', '');
  713. const providerName = GM_getValue('providerName', '');
  714. const promptType = document.getElementById('prompt-type').value;
  715. const promptInput = document.getElementById('prompt-input').value;
  716.  
  717. if (!apiUrl || !apiKey || !modelName) {
  718. showResponse('Please configure API settings first!', true);
  719. return;
  720. }
  721.  
  722. if (!promptInput.trim()) {
  723. showResponse('Please enter a prompt to optimize!', true);
  724. return;
  725. }
  726.  
  727. showResponse('Optimizing prompt...');
  728.  
  729. const systemPrompt = `You are a specialized prompt optimization AI focused on enhancing both user prompts and system prompts for AI interactions.
  730.  
  731. <instructions>
  732. 1. You will receive prompts marked with either <user_prompt> or <system_prompt> tags
  733. 2. ALWAYS maintain the same type of prompt in your enhancement
  734. 3. NEVER engage in conversation or provide explanations
  735. 4. ONLY return the enhanced prompt within <enhanced_prompt> tags
  736. 5. Apply appropriate prompt engineering techniques based on the prompt type:
  737.  
  738. For User Prompts:
  739. - Maintain conversational context and flow
  740. - Clarify user intent and expectations
  741. - Add specific parameters for the response
  742. - Include relevant context from prior conversation
  743. - Structure multi-part requests clearly
  744.  
  745. For System Prompts:
  746. - Define clear roles and responsibilities
  747. - Establish behavioral boundaries
  748. - Include success criteria and constraints
  749. - Structure hierarchical instructions
  750. - Define interaction patterns
  751. - Specify output formats and preferences
  752. - Include error handling instructions
  753. </instructions>
  754.  
  755. <examples>
  756. <example>
  757. <input_type>user_prompt</input_type>
  758. <input>Thanks for your help! Can you search the web for more information about this topic?</input>
  759. <enhanced_prompt>Please conduct a comprehensive web search on our current topic with the following parameters:
  760. 1. Focus on authoritative sources from the last 2 years
  761. 2. Include academic and expert perspectives
  762. 3. Compare and contrast different viewpoints
  763. 4. Identify emerging trends and developments
  764. 5. Extract key insights and practical applications
  765.  
  766. Format the response with:
  767. - Main findings in bullet points
  768. - Source citations for each major claim
  769. - Relevance assessment for each source
  770. - Synthesis of conflicting information
  771. - Suggestions for further research</enhanced_prompt>
  772. </example>
  773.  
  774. <example>
  775. <input_type>system_prompt</input_type>
  776. <input>You are a web search AI assistant. Your role is to help users find information.</input>
  777. <enhanced_prompt>You are a specialized web search AI assistant designed to provide comprehensive, accurate, and well-structured information retrieval services.
  778.  
  779. Core Responsibilities:
  780. 1. Execute precise web searches based on user queries
  781. 2. Evaluate source credibility and relevance
  782. 3. Synthesize information from multiple sources
  783. 4. Present findings in clear, structured formats
  784.  
  785. Behavioral Guidelines:
  786. - Maintain objectivity in information presentation
  787. - Clearly distinguish between facts and interpretations
  788. - Acknowledge information gaps or uncertainties
  789. - Proactively suggest related topics for exploration
  790.  
  791. Output Requirements:
  792. 1. Structure all responses with:
  793. - Executive summary
  794. - Detailed findings
  795. - Source citations
  796. - Confidence levels
  797. 2. Use formatting for clarity:
  798. - Bullet points for key facts
  799. - Tables for comparisons
  800. - Markdown for emphasis
  801. - Hierarchical headings
  802.  
  803. Error Handling:
  804. - Acknowledge when information is outdated
  805. - Flag potential misinformation
  806. - Suggest alternative search strategies
  807. - Provide confidence levels for findings</enhanced_prompt>
  808. </example>
  809. </examples>
  810.  
  811. <success_criteria>
  812. For User Prompts:
  813. - Enhanced clarity and specificity
  814. - Maintained conversation context
  815. - Clear parameters for response
  816. - Structured multi-part requests
  817. - Defined output preferences
  818.  
  819. For System Prompts:
  820. - Clear role definition
  821. - Comprehensive behavioral guidelines
  822. - Specific output requirements
  823. - Error handling procedures
  824. - Interaction patterns defined
  825. </success_criteria>`;
  826.  
  827. // Wrap the input with appropriate type tags
  828. const taggedInput = `<${promptType}_prompt>${promptInput}</${promptType}_prompt>`;
  829.  
  830. GM_xmlhttpRequest({
  831. method: 'POST',
  832. url: `${apiUrl}/chat/completions`,
  833. headers: {
  834. 'Content-Type': 'application/json',
  835. 'Authorization': `Bearer ${apiKey}`
  836. },
  837. data: JSON.stringify({
  838. model: modelName,
  839. ...(providerName && { provider: providerName }),
  840. messages: [
  841. {
  842. role: 'system',
  843. content: systemPrompt
  844. },
  845. {
  846. role: 'user',
  847. content: taggedInput
  848. }
  849. ],
  850. temperature: 0.7,
  851. max_tokens: 16384
  852. }),
  853. onload: function(response) {
  854. try {
  855. const result = JSON.parse(response.responseText);
  856. if (result.error) {
  857. showResponse(`Error: ${result.error.message}`, true);
  858. } else if (result.choices && result.choices[0]) {
  859. showResponse(result.choices[0].message.content);
  860. } else {
  861. showResponse('Unexpected API response format', true);
  862. }
  863. } catch (error) {
  864. showResponse(`Error processing response: ${error.message}`, true);
  865. }
  866. },
  867. onerror: function(error) {
  868. showResponse(`Network error: ${error.statusText}`, true);
  869. }
  870. });
  871. }
  872.  
  873. // Initialize the UI
  874. createUI();
  875. })();