client side for the win!
rendering llm markdown as html
This commit is contained in:
parent
afce79f776
commit
880c09bc86
1 changed files with 148 additions and 0 deletions
148
index.html
148
index.html
|
|
@ -24,6 +24,9 @@
|
|||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.10.0/styles/a11y-dark.min.css" />
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.6.0/highlight.min.js"></script>
|
||||
|
||||
<!-- Needed by LLM to do realtime markdown rendering into HTML -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
|
||||
|
||||
<!-- Theme Switcher Script -->
|
||||
<script>
|
||||
function switchTheme(theme) {
|
||||
|
|
@ -199,6 +202,151 @@ pip install vllm
|
|||
python -m vllm.entrypoints.openai.api_server --model NousResearch/Hermes-3-Llama-3.1-8B --host 0.0.0.0 --port 18888 --max-model-len 16000
|
||||
</code></pre>
|
||||
|
||||
|
||||
<h2 id="client-side">Client Side Only Example, chat with this page.</h2>
|
||||
|
||||
<p>view page source, it's _all_ there!</p>
|
||||
|
||||
<div id="chat-container">
|
||||
<div id="chat-box"></div>
|
||||
<div></div>
|
||||
</div>
|
||||
<div>
|
||||
<input type="text" id="user-input" placeholder="Ask about this page...">
|
||||
<button onclick="handleUserInput()">Send</button>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// LLM Webpage Client
|
||||
|
||||
// Configuration
|
||||
const API_URL = "https://hermes.ai.unturf.com/v1/chat/completions";
|
||||
const API_KEY = "dummy-api-key";
|
||||
const MODEL = "NousResearch/Hermes-3-Llama-3.1-8B";
|
||||
|
||||
// Initialize chat history
|
||||
let chatHistory = [
|
||||
{
|
||||
role: "system",
|
||||
content: "You are an AI assistant embedded in a webpage. Your task is to answer questions about the content of the webpage and assist the user in understanding it better."
|
||||
}
|
||||
];
|
||||
|
||||
// Function to extract text content from the webpage
|
||||
function extractWebpageContent() {
|
||||
return document.body.innerText;
|
||||
}
|
||||
|
||||
// Generator function to send a message to the LLM and yield responses
|
||||
async function* sendMessage(message) {
|
||||
chatHistory.push({ role: "user", content: message });
|
||||
|
||||
const response = await fetch(API_URL, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': `Bearer ${API_KEY}`
|
||||
},
|
||||
body: JSON.stringify({
|
||||
model: MODEL,
|
||||
messages: chatHistory,
|
||||
temperature: 0.5,
|
||||
max_tokens: 5600,
|
||||
stream: true
|
||||
})
|
||||
});
|
||||
|
||||
const reader = response.body.getReader();
|
||||
const decoder = new TextDecoder();
|
||||
let buffer = '';
|
||||
|
||||
while (true) {
|
||||
const { done, value } = await reader.read();
|
||||
if (done) break;
|
||||
|
||||
buffer += decoder.decode(value, { stream: true });
|
||||
const lines = buffer.split('\n');
|
||||
|
||||
for (let i = 0; i < lines.length - 1; i++) {
|
||||
const line = lines[i].trim();
|
||||
if (line.startsWith('data: ')) {
|
||||
const jsonData = line.slice(6);
|
||||
if (jsonData === '[DONE]') continue;
|
||||
|
||||
try {
|
||||
const parsedData = JSON.parse(jsonData);
|
||||
const content = parsedData.choices[0].delta.content;
|
||||
if (content) {
|
||||
yield content;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error parsing JSON:', error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
buffer = lines[lines.length - 1];
|
||||
}
|
||||
}
|
||||
|
||||
// Function to handle user input and display responses
|
||||
async function handleUserInput() {
|
||||
const userInput = document.getElementById('user-input').value;
|
||||
document.getElementById('user-input').value = '';
|
||||
|
||||
const chatBox = document.getElementById('chat-box');
|
||||
chatBox.innerHTML += `<p><strong>You:</strong> ${userInput}</p>`;
|
||||
|
||||
chatBox.innerHTML += `<p><strong>AI:</strong> `;
|
||||
const messageElement = chatBox.lastElementChild;
|
||||
|
||||
let accumulatedContent = '';
|
||||
for await (const chunk of sendMessage(userInput)) {
|
||||
accumulatedContent += chunk;
|
||||
const parsedChunk = marked.parse(accumulatedContent);
|
||||
messageElement.innerHTML = parsedChunk;
|
||||
|
||||
// Apply syntax highlighting to code blocks
|
||||
messageElement.querySelectorAll('pre code').forEach((block) => {
|
||||
hljs.highlightElement(block);
|
||||
});
|
||||
}
|
||||
|
||||
chatBox.scrollTop = chatBox.scrollHeight;
|
||||
}
|
||||
|
||||
// Function to initialize the chat interface
|
||||
function initializeChatInterface() {
|
||||
const pageContent = extractWebpageContent();
|
||||
chatHistory.push({
|
||||
role: "system",
|
||||
content: `Here's the content of the webpage: ${pageContent}`
|
||||
});
|
||||
|
||||
// Set up marked.js options
|
||||
marked.setOptions({
|
||||
highlight: function(code, lang) {
|
||||
const language = hljs.getLanguage(lang) ? lang : 'plaintext';
|
||||
return hljs.highlight(code, { language }).value;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
document.getElementById("user-input").addEventListener("keypress", function(event) {
|
||||
if (event.key === "Enter") {
|
||||
event.preventDefault();
|
||||
handleUserInput();
|
||||
}
|
||||
});
|
||||
|
||||
// Initialize the chat interface when the page loads
|
||||
window.onload = initializeChatInterface;
|
||||
|
||||
// Expose handleUserInput to the global scope
|
||||
window.handleUserInput = handleUserInput;
|
||||
|
||||
</script>
|
||||
|
||||
<h2>Questions, Comments, Discussions</h2>
|
||||
<div id="remarkbox-div">
|
||||
<noscript>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue