交談歷程

ChatGPT
ChatGPT

今天

  1. Gemini Pro Chat App

昨天

  1. Gemini Pro Chat App

過去 7 天

  1. Gemini Chat App Features

過去 30 天

  1. 代码可读性改进
  2. Firefox Mobile Download Fix
  3. DeepSeek与大语言模型对比
  4. Dutch Height Evolution
  5. 聊天记忆与格式调整
  6. Chat App LLM GitHub
  7. 開發ChatGPT前端應用
  8. 大語言模型聊天應用
  9. 前端聊天應用開發
  10. Chat记忆与格式化
  11. Form input reset fix
  12. 新新聞周刊報導真實性
  13. China AI Analysis
  14. Reasoning Deletion Explanation
  15. 韓劇推薦與簡介
  16. 黑悟空華為DeepSeek分析
  17. 国产科技创新分析

1月

  1. 簡繁標點符號轉換
  2. LINE Bot for Notify
  3. Custom HTML Leaflet Controls
  4. Python 程式範例

2024年

  1. 照片修飾需求
  2. Plot Elevation from GPX
  3. 觀霧行程規劃
  4. 觀霧輕鬆行程規劃
升級方案擁有更多最佳模型的存取權限
你說:
Write a browser-side app that uses google's gemini pro api to chat in a standalone HTML. Requirements are listed as follows: (1) Save my Gemini key in a local storage. (2) Support the conversation history and save it a local storage. Add a button to clear the conversation history so that gemini is aware of the context of previous messages. Allow the user to set the token usage threshold, compare it with tokens used in the metadata of gemini pro api response and alert the user if beyond the thrshold. (3) Use marked.js to display Gemini messages. (4) Use the textarea element for user to paste multi-line text. (5) Use highlight.js to check the code language automatically and highlight its code block if any. (6) Add one feature that uses free Google Translate API (https://translate.googleapis.com/translate_a/single) to translate the Gemini message to any language and append the translated message to the "normal" Gemini message. Provide an HTML element for the user to enable/disable the translation feature. Use select and option elements for the user to select output language which defaults to Simplified Chinese. Languages also support Traditional Chinese, Japanese, English and Spanish. Note that the translated text may not have the same format as the input text and marked.js may not handle it well. (7) Maximize the display window. Maximize the message window and minimize control/config buttons except the send message button.

我正在考虑如何编写一个浏览器端应用,使用 Google 的 Gemini Pro API 来进行聊天。首先,我需要确保可以将 Gemini 密钥保存在本地存储中。接着,应用需要支持保存对话历史并存储在本地存储中。还需要一个功能按钮,允许用户清除对话历史,这样 Gemini 就能保持对先前消息的上下文感知。看来目标并不复杂,但涉及一些细节的实现。

我正在考虑如何实现多个功能。首先,允许用户设置token使用阈值,并在Gemini Pro API响应元数据中比较,超出时提醒用户。接下来,使用marked.js展示Gemini消息,textarea元素支持粘贴多行文本。highlight.js可以自动识别和高亮代码块。此外,利用Google翻译API实现信息翻译功能,支持选择输出语言并提供启用/禁用选项。最后,需要设计最大化显示窗口,最小化控制按钮等。

我需要编写一个独立的HTML文件,能够在浏览器中运行并使用Google的Gemini Pro API。用户输入的token使用阈值需要与API响应中的metadata字段进行比较,超过阈值时提醒用户。Gemini消息可能是API的响应,结果可能是JSON格式。界面需要支持标记文本显示、多行输入、代码高亮、翻译功能和会话历史存储。还包括输入框、按钮和语言选择等HTML元素。需要引入外部库,如marked.js和highlight.js,并模拟调用Gemini API。

我正在设计一个聊天应用,需要在本地存储中保存会话记录并显示聊天历史。每次接收到Gemini的响应后,如果超过用户设定的token阈值,则提醒用户。翻译功能启用时,会调用Google翻译API翻译消息,并将翻译结果附加到原始消息中。为了支持界面,我将使用Marked.js解析消息,并用Highlight.js自动高亮代码块。界面设计将简化控制按钮,同时优化消息显示区域。

Below is an all-in-one HTML file that meets the requirements. (Be sure to replace the Gemini Pro API endpoint and adjust the payload as needed for your production use.)

html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Gemini Pro Chat</title> <!-- Marked.js for Markdown rendering --> <script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script> <!-- Highlight.js for code block syntax highlighting --> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/styles/default.min.css"> <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/highlight.min.js"></script> <style> /* Reset margins and set full height */ html, body { margin: 0; padding: 0; height: 100%; font-family: Arial, sans-serif; } /* Flex container for the entire app */ #container { display: flex; flex-direction: column; height: 100%; } /* Minimal controls container (you may later hide this via a toggle if desired) */ #controls { background: #f0f0f0; padding: 5px 10px; display: flex; flex-wrap: wrap; align-items: center; gap: 10px; font-size: 0.9em; } /* The message display area fills available space */ #messageDisplay { flex: 1; overflow-y: auto; padding: 10px; background: #fff; } /* Input area at the bottom */ #inputArea { display: flex; padding: 5px; background: #f9f9f9; border-top: 1px solid #ccc; } #inputArea textarea { flex: 1; resize: vertical; padding: 5px; font-size: 1em; } #inputArea button { margin-left: 5px; padding: 5px 10px; font-size: 1em; } /* Message styling */ .message { margin-bottom: 15px; } .assistant { background: #e7f3fe; padding: 10px; border-radius: 5px; white-space: pre-wrap; } .user { background: #e2e2e2; padding: 10px; border-radius: 5px; white-space: pre-wrap; text-align: right; } </style> </head> <body> <div id="container"> <!-- Control/config panel (small height so that most of the screen is free for messages) --> <div id="controls"> <label> Gemini API Key: <input type="password" id="geminiKeyInput" placeholder="Enter your Gemini API key"> </label> <button id="saveKeyButton">Save Key</button> <label> Token Threshold: <input type="number" id="tokenThresholdInput" placeholder="Token threshold"> </label> <button id="clearHistoryButton">Clear History</button> <label> <input type="checkbox" id="enableTranslation" checked> Enable Translation </label> <label> Translate to: <select id="languageSelect"> <option value="zh-CN" selected>Simplified Chinese</option> <option value="zh-TW">Traditional Chinese</option> <option value="ja">Japanese</option> <option value="en">English</option> <option value="es">Spanish</option> </select> </label> </div> <!-- Message display area --> <div id="messageDisplay"></div> <!-- Input area (always visible) --> <div id="inputArea"> <textarea id="userInput" rows="3" placeholder="Type your message here..."></textarea> <button id="sendButton">Send</button> </div> </div> <script> // Local storage keys const STORAGE_KEY = 'conversationHistory'; const GEMINI_KEY_STORAGE = 'geminiKey'; const TOKEN_THRESHOLD_STORAGE = 'tokenThreshold'; // DOM elements const geminiKeyInput = document.getElementById('geminiKeyInput'); const tokenThresholdInput = document.getElementById('tokenThresholdInput'); const messageDisplay = document.getElementById('messageDisplay'); const userInput = document.getElementById('userInput'); const enableTranslation = document.getElementById('enableTranslation'); const languageSelect = document.getElementById('languageSelect'); // Load Gemini API key from local storage if it exists if (localStorage.getItem(GEMINI_KEY_STORAGE)) { geminiKeyInput.value = localStorage.getItem(GEMINI_KEY_STORAGE); } // Load token threshold if set previously if (localStorage.getItem(TOKEN_THRESHOLD_STORAGE)) { tokenThresholdInput.value = localStorage.getItem(TOKEN_THRESHOLD_STORAGE); } // Load conversation history from local storage let conversationHistory = []; if (localStorage.getItem(STORAGE_KEY)) { conversationHistory = JSON.parse(localStorage.getItem(STORAGE_KEY)); conversationHistory.forEach(displayMessage); } // Save API key to local storage document.getElementById('saveKeyButton').addEventListener('click', () => { localStorage.setItem(GEMINI_KEY_STORAGE, geminiKeyInput.value.trim()); alert('Gemini API Key saved.'); }); // Save token threshold to local storage when changed tokenThresholdInput.addEventListener('change', () => { localStorage.setItem(TOKEN_THRESHOLD_STORAGE, tokenThresholdInput.value); }); // Clear conversation history (and thus the context) when requested document.getElementById('clearHistoryButton').addEventListener('click', () => { if (confirm('Clear conversation history? This will reset the context for Gemini.')) { conversationHistory = []; localStorage.removeItem(STORAGE_KEY); messageDisplay.innerHTML = ''; } }); // Send message to Gemini Pro API when the send button is clicked document.getElementById('sendButton').addEventListener('click', async () => { const messageContent = userInput.value.trim(); if (!messageContent) return; // Create and display the user's message const userMessage = { role: 'user', content: messageContent }; conversationHistory.push(userMessage); saveHistory(); displayMessage(userMessage); userInput.value = ''; // Get the saved Gemini API key const geminiKey = geminiKeyInput.value.trim(); if (!geminiKey) { alert('Please enter your Gemini API key.'); return; } // Build the payload for Gemini Pro API. // Adjust this payload structure to match the actual API. const payload = { conversation: conversationHistory }; try { // Replace the endpoint URL with your actual Gemini Pro API endpoint const response = await fetch('https://gemini.googleapis.com/v1/chat:complete', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer ' + geminiKey }, body: JSON.stringify(payload) }); if (!response.ok) { throw new Error('API request failed with status ' + response.status); } const data = await response.json(); // Assume the response includes an "answer" and a "metadata" field containing token usage. const assistantMessage = { role: 'assistant', content: data.answer, metadata: data.metadata }; conversationHistory.push(assistantMessage); saveHistory(); displayMessage(assistantMessage); // Check token usage threshold const threshold = parseInt(tokenThresholdInput.value); if (threshold && data.metadata && data.metadata.total_tokens > threshold) { alert(`Token usage (${data.metadata.total_tokens}) exceeds the threshold of ${threshold}.`); } // If translation is enabled, translate the Gemini answer and display the translated text if (enableTranslation.checked) { const translatedText = await translateText(data.answer, languageSelect.value); if (translatedText) { // Here we prepend a header to denote that this is a translation. const translationMessage = { role: 'assistant', content: '**Translation:**\n\n' + translatedText }; // Optionally, you can also store the translation in conversationHistory. displayMessage(translationMessage); } } } catch (error) { console.error(error); alert('Error: ' + error.message); } }); // Save the conversation history to local storage function saveHistory() { localStorage.setItem(STORAGE_KEY, JSON.stringify(conversationHistory)); } // Display a message using marked.js for Markdown and highlight.js for code blocks function displayMessage(message) { const messageDiv = document.createElement('div'); messageDiv.classList.add('message', message.role); messageDiv.innerHTML = marked.parse(message.content); messageDisplay.appendChild(messageDiv); // Automatically highlight any code blocks inside the message messageDiv.querySelectorAll('pre code').forEach((block) => { hljs.highlightElement(block); }); // Scroll to the bottom of the message display messageDisplay.scrollTop = messageDisplay.scrollHeight; } // Translate text using the free Google Translate API async function translateText(text, targetLang) { try { const encodedText = encodeURIComponent(text); const url = `https://translate.googleapis.com/translate_a/single?client=gtx&sl=auto&tl=${targetLang}&dt=t&q=${encodedText}`; const res = await fetch(url); if (!res.ok) { throw new Error('Translation API error: ' + res.status); } const result = await res.json(); // The result is a nested array; join the segments to form the translated text. let translated = ''; result[0].forEach(segment => { if (segment[0]) { translated += segment[0]; } }); return translated; } catch (error) { console.error('Translation error:', error); return null; } } </script> </body> </html>

How This App Works

  • Gemini API Key & Conversation History:
    The API key is entered and saved in local storage. Conversation history is maintained (and can be cleared with a button) so that Gemini can use previous messages for context.

  • Token Threshold:
    You can set a token usage threshold. When a Gemini response returns, its metadata is checked and an alert is shown if the total token usage exceeds your threshold.

  • Markdown & Code Highlighting:
    The Gemini responses (and their translations) are rendered with marked.js so that Markdown is processed. Code blocks are auto-detected and highlighted using highlight.js.

  • Translation Feature:
    When enabled, the Gemini response is sent to the free Google Translate API, and the translated text (in your chosen language) is appended below the original answer.

  • Layout:
    The message display area uses most of the window while the controls (API key, threshold, clear history, translation options) take up minimal space at the top, and the send button (with a multi‑line textarea) stays fixed at the bottom.

Simply open this HTML file in your browser, set your API key and other options, and start chatting!

Note: The Gemini Pro API endpoint and payload may need to be adjusted for your actual API usage.


O
ChatGPT 可能會發生錯誤。請查核重要資訊。