piclets / qwen.html
Fraser's picture
working qwen demo
836962d
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Qwen3 Demo</title>
<style>
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
max-width: 800px;
margin: 0 auto;
padding: 20px;
background: #f5f5f5;
}
.container {
background: white;
border-radius: 12px;
padding: 30px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
h1 {
color: #333;
text-align: center;
margin-bottom: 30px;
}
.form-group {
margin-bottom: 20px;
}
label {
display: block;
margin-bottom: 8px;
font-weight: 600;
color: #555;
}
textarea {
width: 100%;
min-height: 120px;
padding: 12px;
border: 2px solid #e1e5e9;
border-radius: 8px;
font-size: 14px;
resize: vertical;
box-sizing: border-box;
}
textarea:focus {
outline: none;
border-color: #007aff;
}
button {
background: #007aff;
color: white;
border: none;
padding: 12px 24px;
border-radius: 8px;
font-size: 16px;
cursor: pointer;
transition: background 0.2s;
}
button:hover:not(:disabled) {
background: #0056b3;
}
button:disabled {
background: #ccc;
cursor: not-allowed;
}
.status {
margin: 20px 0;
padding: 12px;
border-radius: 6px;
font-weight: 500;
}
.status.connecting {
background: #fff3cd;
color: #856404;
border: 1px solid #ffeaa7;
}
.status.connected {
background: #d4edda;
color: #155724;
border: 1px solid #c3e6cb;
}
.status.error {
background: #f8d7da;
color: #721c24;
border: 1px solid #f5c6cb;
}
.response {
margin-top: 20px;
padding: 20px;
background: #f8f9fa;
border-radius: 8px;
border-left: 4px solid #007aff;
white-space: pre-wrap;
font-family: 'SF Mono', Monaco, 'Cascadia Code', monospace;
font-size: 14px;
line-height: 1.5;
}
.hidden {
display: none;
}
</style>
</head>
<body>
<div class="container">
<h1>Qwen3 Demo</h1>
<div id="status" class="status connecting">
Connecting to Qwen/Qwen3-Demo...
</div>
<div class="form-group">
<label for="prompt">Enter your prompt:</label>
<textarea
id="prompt"
placeholder="Ask Qwen3 anything... For example: 'Explain quantum computing in simple terms' or 'Write a short story about a robot learning to paint'"
></textarea>
</div>
<button id="submitBtn" onclick="generateResponse()" disabled>
Generate Response
</button>
<div id="response" class="response hidden"></div>
</div>
<script type="module">
// Import Gradio client using the same CDN pattern as your project
import { Client } from "https://cdn.jsdelivr.net/npm/@gradio/client/dist/index.min.js";
let qwenClient = null;
const statusEl = document.getElementById('status');
const submitBtn = document.getElementById('submitBtn');
const promptEl = document.getElementById('prompt');
const responseEl = document.getElementById('response');
// Initialize connection to Qwen/Qwen3-Demo
async function initializeClient() {
try {
qwenClient = await Client.connect("Qwen/Qwen3-Demo");
statusEl.textContent = "✅ Connected to Qwen/Qwen3-Demo";
statusEl.className = "status connected";
submitBtn.disabled = false;
console.log("Successfully connected to Qwen/Qwen3-Demo");
console.log("API Map:", qwenClient.api_map);
} catch (error) {
console.error("Failed to connect:", error);
statusEl.textContent = `❌ Failed to connect: ${error.message}`;
statusEl.className = "status error";
}
}
// Generate response using Qwen3
window.generateResponse = async function() {
if (!qwenClient) {
alert("Not connected to Qwen service");
return;
}
const prompt = promptEl.value.trim();
if (!prompt) {
alert("Please enter a prompt");
return;
}
submitBtn.disabled = true;
submitBtn.textContent = "Generating...";
responseEl.className = "response hidden";
try {
// Based on the source code analysis:
// add_message: 13 is the correct function
// It expects [input, settings_form, thinking_btn_state, state] parameters
console.log("Using add_message function (fn_index 13) from API map");
// Create the required state structure based on app.py
const defaultState = {
"conversation_contexts": {},
"conversations": [],
"conversation_id": "",
};
// Create default settings based on config.py
const defaultSettings = {
"model": "qwen3-235b-a22b", // DEFAULT_MODEL from config.py
"sys_prompt": "You are a helpful and harmless assistant.", // DEFAULT_SYS_PROMPT
"thinking_budget": 38 // DEFAULT_THINKING_BUDGET
};
// Create thinking button state
const thinkingBtnState = {
"enable_thinking": true
};
console.log("Calling add_message with parameters:", {
input: prompt,
settings: defaultSettings,
thinking: thinkingBtnState,
state: defaultState
});
// Call the add_message function (fn_index 13)
const output = await qwenClient.predict(13, [
prompt, // input_value
defaultSettings, // settings_form_value
thinkingBtnState, // thinking_btn_state_value
defaultState // state_value
]);
console.log("add_message response:", output);
console.log("Chatbot data (index 5):", output.data[5]);
if (output.data[5] && output.data[5].value) {
console.log("Chat history:", output.data[5].value);
}
// Extract the chatbot response from the output
let responseText = "";
if (output && output.data && Array.isArray(output.data)) {
// The add_message function returns multiple updates
// The chatbot response is at index 5 in the outputs array
const chatbotUpdate = output.data[5]; // chatbot is at index 5 in the outputs array
if (chatbotUpdate && chatbotUpdate.value && Array.isArray(chatbotUpdate.value)) {
// The value array contains the chat history
const chatHistory = chatbotUpdate.value;
if (chatHistory.length > 0) {
// Get the last message (assistant's response)
const lastMessage = chatHistory[chatHistory.length - 1];
if (lastMessage && lastMessage.content && Array.isArray(lastMessage.content)) {
// Extract text content from the message
const textContents = lastMessage.content
.filter(item => item.type === "text")
.map(item => item.content)
.join("\n");
responseText = textContents || "Response received but no text content found";
} else if (lastMessage && lastMessage.role === "assistant") {
// Fallback - if content structure is different
responseText = JSON.stringify(lastMessage, null, 2);
} else {
responseText = "Last message structure unexpected: " + JSON.stringify(lastMessage, null, 2);
}
} else {
responseText = "No messages in chat history";
}
} else {
responseText = "No chatbot value found in response: " + JSON.stringify(chatbotUpdate, null, 2);
}
} else {
responseText = "Unexpected response format: " + JSON.stringify(output, null, 2);
}
responseEl.textContent = responseText;
responseEl.className = "response";
} catch (error) {
console.error("Generation error:", error);
responseEl.textContent = `Error: ${error.message}`;
responseEl.className = "response";
} finally {
submitBtn.disabled = false;
submitBtn.textContent = "Generate Response";
}
};
// Handle Enter key in textarea (Shift+Enter for new line, Enter to submit)
promptEl.addEventListener('keydown', function(e) {
if (e.key === 'Enter' && !e.shiftKey) {
e.preventDefault();
if (!submitBtn.disabled) {
generateResponse();
}
}
});
// Initialize the client when the page loads
initializeClient();
</script>
</body>
</html>