secutorpro commited on
Commit
07ea14f
·
verified ·
1 Parent(s): 057e8b6

🐳 18/08 - 21:05 - cree un systeme pour ree des application ave qwen.     import os from openai import OpenAI client = OpenAI( base_url="https://router.huggingface.co/v1", api_key=os.environ[

Browse files
Files changed (3) hide show
  1. builder.html +151 -0
  2. builder.js +139 -0
  3. index.html +3 -0
builder.html ADDED
@@ -0,0 +1,151 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Qwen App Builder — Memory Void</title>
7
+ <link rel="stylesheet" href="style.css">
8
+ <script src="https://cdn.tailwindcss.com"></script>
9
+ <script>
10
+ tailwind.config = {
11
+ darkMode: 'class',
12
+ theme: {
13
+ extend: {
14
+ colors: {
15
+ 'undefined': {
16
+ 500: '#6366f1',
17
+ 600: '#4f46e5',
18
+ }
19
+ }
20
+ }
21
+ }
22
+ }
23
+ </script>
24
+ <script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script>
25
+ </head>
26
+ <body class="bg-gray-50 text-gray-800 dark:bg-gray-900 dark:text-gray-100 transition-colors duration-300 min-h-screen flex flex-col font-mono">
27
+
28
+ <!-- Navigation -->
29
+ <nav class="border-b border-gray-200 dark:border-gray-800 bg-white/80 dark:bg-gray-900/80 backdrop-blur-md sticky top-0 z-50">
30
+ <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
31
+ <div class="flex justify-between h-16 items-center">
32
+ <div class="flex items-center space-x-2">
33
+ <i data-feather="lock" class="text-undefined-500 w-6 h-6"></i>
34
+ <span class="font-bold text-xl tracking-tight">Memory Void</span>
35
+ <span class="ml-2 text-xs text-gray-500 hidden sm:inline">/ Qwen App Builder</span>
36
+ </div>
37
+ <div class="flex items-center space-x-4">
38
+ <a href="index.html" class="text-sm text-gray-600 dark:text-gray-400 hover:text-undefined-500 transition-colors flex items-center">
39
+ <i data-feather="home" class="w-4 h-4 mr-1"></i> Home
40
+ </a>
41
+ <button id="theme-toggle" class="p-2 rounded-full hover:bg-gray-100 dark:hover:bg-gray-800 transition-colors focus:outline-none focus:ring-2 focus:ring-undefined-500" aria-label="Toggle Theme">
42
+ <i data-feather="moon" class="w-5 h-5 dark:hidden"></i>
43
+ <i data-feather="sun" class="w-5 h-5 hidden dark:block"></i>
44
+ </button>
45
+ </div>
46
+ </div>
47
+ </div>
48
+ </nav>
49
+
50
+ <!-- Main Content -->
51
+ <main class="flex-grow max-w-5xl mx-auto px-4 sm:px-6 lg:px-8 py-8 w-full flex flex-col">
52
+
53
+ <!-- Hero -->
54
+ <div class="text-center mb-8">
55
+ <h1 class="text-3xl md:text-5xl font-extrabold mb-3 bg-clip-text text-transparent bg-gradient-to-r from-undefined-500 to-purple-600">
56
+ Qwen App Builder
57
+ </h1>
58
+ <p class="text-sm text-gray-600 dark:text-gray-400 max-w-2xl mx-auto">
59
+ Generate applications with Qwen via Hugging Face Router. Send text prompts and images to build apps in real-time.
60
+ </p>
61
+ </div>
62
+
63
+ <!-- API Config Bar -->
64
+ <div class="bg-white dark:bg-gray-800 rounded-xl shadow-lg border border-gray-200 dark:border-gray-700 p-4 mb-6">
65
+ <div class="flex flex-col sm:flex-row gap-3 items-stretch sm:items-center">
66
+ <div class="flex items-center gap-2 text-sm font-semibold whitespace-nowrap">
67
+ <i data-feather="key" class="w-4 h-4 text-undefined-500"></i>
68
+ HF_TOKEN
69
+ </div>
70
+ <input id="api-key" type="password" placeholder="hf_xxxxxxxxxxxxxxxxxxxxxx"
71
+ class="flex-grow bg-gray-50 dark:bg-gray-900 border border-gray-300 dark:border-gray-700 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-undefined-500 font-mono"
72
+ value="">
73
+ <select id="model-select" class="bg-gray-50 dark:bg-gray-900 border border-gray-300 dark:border-gray-700 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-undefined-500 font-mono">
74
+ <option value="trohrbaugh/Qwen3.8-27B-heretic-ara:featherless-ai">Qwen3.8-27B-heretic-ara</option>
75
+ <option value="Qwen/Qwen2.5-72B-Instruct">Qwen2.5-72B-Instruct</option>
76
+ <option value="Qwen/Qwen2.5-VL-72B-Instruct">Qwen2.5-VL-72B-Instruct</option>
77
+ <option value="Qwen/Qwen2.5-Coder-32B-Instruct">Qwen2.5-Coder-32B-Instruct</option>
78
+ </select>
79
+ <button id="save-key" class="bg-undefined-500 hover:bg-undefined-600 text-white text-sm font-bold py-2 px-4 rounded-lg transition-colors whitespace-nowrap">
80
+ Save
81
+ </button>
82
+ </div>
83
+ </div>
84
+
85
+ <!-- Chat Container -->
86
+ <div class="flex-grow flex flex-col bg-white dark:bg-gray-800 rounded-xl shadow-lg border border-gray-200 dark:border-gray-700 overflow-hidden">
87
+
88
+ <!-- Messages Area -->
89
+ <div id="chat-messages" class="flex-grow overflow-y-auto p-4 sm:p-6 space-y-4 min-h-[300px] max-h-[55vh]">
90
+ <!-- Welcome message -->
91
+ <div class="flex justify-start">
92
+ <div class="bg-gray-100 dark:bg-gray-700 rounded-2xl rounded-tl-sm px-4 py-3 max-w-[85%]">
93
+ <div class="flex items-center gap-2 mb-1 text-xs text-gray-500">
94
+ <i data-feather="cpu" class="w-3 h-3"></i> Qwen
95
+ </div>
96
+ <p class="text-sm">👋 Hello! I'm your Qwen-powered app builder. Describe the app you want to create, and I'll generate the code for you. You can also attach an image for vision-based tasks!</p>
97
+ </div>
98
+ </div>
99
+ </div>
100
+
101
+ <!-- Image Preview Area -->
102
+ <div id="image-preview" class="hidden px-4 pt-3">
103
+ <div class="inline-flex items-center gap-2 bg-gray-100 dark:bg-gray-700 rounded-lg p-2 pr-3">
104
+ <img id="preview-img" class="w-16 h-16 object-cover rounded-md" alt="preview">
105
+ <div class="text-xs text-gray-500">
106
+ <div id="preview-name">image.jpg</div>
107
+ <button id="remove-image" class="text-red-500 hover:text-red-600 mt-1 flex items-center gap-1">
108
+ <i data-feather="x" class="w-3 h-3"></i> Remove
109
+ </button>
110
+ </div>
111
+ </div>
112
+ </div>
113
+
114
+ <!-- Input Area -->
115
+ <div class="border-t border-gray-200 dark:border-gray-700 p-4">
116
+ <div class="flex items-end gap-2">
117
+ <button id="attach-btn" class="p-3 rounded-lg bg-gray-100 dark:bg-gray-700 hover:bg-gray-200 dark:hover:bg-gray-600 transition-colors flex-shrink-0" title="Attach Image">
118
+ <i data-feather="image" class="w-5 h-5 text-gray-500"></i>
119
+ </button>
120
+ <input type="file" id="file-input" accept="image/*" class="hidden">
121
+ <textarea id="prompt-input" rows="1" placeholder="Describe the app you want to build..."
122
+ class="flex-grow resize-none bg-gray-50 dark:bg-gray-900 border border-gray-300 dark:border-gray-700 rounded-lg px-4 py-3 text-sm focus:outline-none focus:ring-2 focus:ring-undefined-500 max-h-32"></textarea>
123
+ <button id="send-btn" class="p-3 rounded-lg bg-undefined-500 hover:bg-undefined-600 text-white transition-colors flex-shrink-0 shadow-lg shadow-undefined-500/30 disabled:opacity-50 disabled:cursor-not-allowed" title="Send">
124
+ <i data-feather="send" class="w-5 h-5"></i>
125
+ </button>
126
+ </div>
127
+ <div class="flex items-center justify-between mt-2 text-xs text-gray-400">
128
+ <span class="flex items-center gap-1">
129
+ <i data-feather="info" class="w-3 h-3"></i> Press Enter to send, Shift+Enter for new line
130
+ </span>
131
+ <button id="clear-chat" class="hover:text-red-500 transition-colors flex items-center gap-1">
132
+ <i data-feather="trash-2" class="w-3 h-3"></i> Clear
133
+ </button>
134
+ </div>
135
+ </div>
136
+ </div>
137
+
138
+ </main>
139
+
140
+ <!-- Footer -->
141
+ <footer class="border-t border-gray-200 dark:border-gray-800 mt-auto py-6">
142
+ <div class="max-w-7xl mx-auto px-4 text-center text-gray-500 text-sm">
143
+ <p>&copy; 2023 Memory Void. Powered by Qwen on Hugging Face Router.</p>
144
+ </div>
145
+ </footer>
146
+
147
+ <script src="script.js"></script>
148
+ <script src="builder.js"></script>
149
+ <script>feather.replace();</script>
150
+ </body>
151
+ </html>
builder.js ADDED
@@ -0,0 +1,139 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // === Qwen App Builder Logic ===
2
+ document.addEventListener('DOMContentLoaded', () => {
3
+ const chatMessages = document.getElementById('chat-messages');
4
+ const promptInput = document.getElementById('prompt-input');
5
+ const sendBtn = document.getElementById('send-btn');
6
+ const attachBtn = document.getElementById('attach-btn');
7
+ const fileInput = document.getElementById('file-input');
8
+ const imagePreview = document.getElementById('image-preview');
9
+ const previewImg = document.getElementById('preview-img');
10
+ const previewName = document.getElementById('preview-name');
11
+ const removeImageBtn = document.getElementById('remove-image');
12
+ const apiKeyInput = document.getElementById('api-key');
13
+ const saveKeyBtn = document.getElementById('save-key');
14
+ const modelSelect = document.getElementById('model-select');
15
+ const clearChatBtn = document.getElementById('clear-chat');
16
+
17
+ let attachedImage = null; // { base64, name }
18
+ let isStreaming = false;
19
+
20
+ // Load saved API key
21
+ const savedKey = localStorage.getItem('hf_token');
22
+ if (savedKey) apiKeyInput.value = savedKey;
23
+ const savedModel = localStorage.getItem('hf_model');
24
+ if (savedModel) modelSelect.value = savedModel;
25
+
26
+ // Save API key
27
+ saveKeyBtn.addEventListener('click', () => {
28
+ localStorage.setItem('hf_token', apiKeyInput.value.trim());
29
+ localStorage.setItem('hf_model', modelSelect.value);
30
+ saveKeyBtn.textContent = 'Saved!';
31
+ setTimeout(() => { saveKeyBtn.textContent = 'Save'; }, 1500);
32
+ });
33
+
34
+ // Auto-resize textarea
35
+ promptInput.addEventListener('input', () => {
36
+ promptInput.style.height = 'auto';
37
+ promptInput.style.height = Math.min(promptInput.scrollHeight, 128) + 'px';
38
+ });
39
+
40
+ // Enter to send
41
+ promptInput.addEventListener('keydown', (e) => {
42
+ if (e.key === 'Enter' && !e.shiftKey) {
43
+ e.preventDefault();
44
+ sendMessage();
45
+ }
46
+ });
47
+
48
+ sendBtn.addEventListener('click', sendMessage);
49
+
50
+ // Image attachment
51
+ attachBtn.addEventListener('click', () => fileInput.click());
52
+
53
+ fileInput.addEventListener('change', (e) => {
54
+ const file = e.target.files[0];
55
+ if (!file) return;
56
+ if (file.size > 4 * 1024 * 1024) {
57
+ alert('Image too large. Max 4MB for base64 encoding.');
58
+ return;
59
+ }
60
+ const reader = new FileReader();
61
+ reader.onload = (event) => {
62
+ attachedImage = { base64: event.target.result, name: file.name };
63
+ previewImg.src = event.target.result;
64
+ previewName.textContent = file.name;
65
+ imagePreview.classList.remove('hidden');
66
+ feather.replace();
67
+ };
68
+ reader.readAsDataURL(file);
69
+ });
70
+
71
+ removeImageBtn.addEventListener('click', () => {
72
+ attachedImage = null;
73
+ imagePreview.classList.add('hidden');
74
+ fileInput.value = '';
75
+ });
76
+
77
+ // Clear chat
78
+ clearChatBtn.addEventListener('click', () => {
79
+ chatMessages.innerHTML = '';
80
+ addMessage('bot', '👋 Chat cleared. What app shall we build next?');
81
+ });
82
+
83
+ // Add message to chat
84
+ function addMessage(role, content, isCode = false) {
85
+ const wrapper = document.createElement('div');
86
+ wrapper.className = `flex ${role === 'user' ? 'justify-end' : 'justify-start'}`;
87
+
88
+ const bubble = document.createElement('div');
89
+ bubble.className = role === 'user'
90
+ ? 'bg-undefined-500 text-white rounded-2xl rounded-tr-sm px-4 py-3 max-w-[85%]'
91
+ : 'bg-gray-100 dark:bg-gray-700 rounded-2xl rounded-tl-sm px-4 py-3 max-w-[85%]';
92
+
93
+ if (role === 'bot') {
94
+ const header = document.createElement('div');
95
+ header.className = 'flex items-center gap-2 mb-1 text-xs text-gray-500';
96
+ header.innerHTML = '<i data-feather="cpu" class="w-3 h-3"></i> Qwen';
97
+ bubble.appendChild(header);
98
+ }
99
+
100
+ const textDiv = document.createElement('div');
101
+ textDiv.className = 'text-sm whitespace-pre-wrap break-words';
102
+ textDiv.textContent = content;
103
+ bubble.appendChild(textDiv);
104
+
105
+ wrapper.appendChild(bubble);
106
+ chatMessages.appendChild(wrapper);
107
+ chatMessages.scrollTop = chatMessages.scrollHeight;
108
+ feather.replace();
109
+ return textDiv;
110
+ }
111
+
112
+ // Add streaming message (returns the text element to update)
113
+ function addStreamingMessage() {
114
+ const wrapper = document.createElement('div');
115
+ wrapper.className = 'flex justify-start';
116
+
117
+ const bubble = document.createElement('div');
118
+ bubble.className = 'bg-gray-100 dark:bg-gray-700 rounded-2xl rounded-tl-sm px-4 py-3 max-w-[85%]';
119
+
120
+ const header = document.createElement('div');
121
+ header.className = 'flex items-center gap-2 mb-1 text-xs text-gray-500';
122
+ header.innerHTML = '<i data-feather="cpu" class="w-3 h-3"></i> Qwen <span class="animate-pulse">●</span>';
123
+ bubble.appendChild(header);
124
+
125
+ const textDiv = document.createElement('div');
126
+ textDiv.className = 'text-sm whitespace-pre-wrap break-words';
127
+ bubble.appendChild(textDiv);
128
+
129
+ wrapper.appendChild(bubble);
130
+ chatMessages.appendChild(wrapper);
131
+ chatMessages.scrollTop = chatMessages.scrollHeight;
132
+ feather.replace();
133
+ return textDiv;
134
+ }
135
+
136
+ // Format code blocks in text
137
+ function formatContent(element, text) {
138
+ element.innerHTML = '';
139
+ const codeRegex = /
index.html CHANGED
@@ -36,6 +36,9 @@
36
  <span class="font-bold text-xl tracking-tight">Memory Void</span>
37
  </div>
38
  <div class="flex items-center space-x-4">
 
 
 
39
  <button id="theme-toggle" class="p-2 rounded-full hover:bg-gray-100 dark:hover:bg-gray-800 transition-colors focus:outline-none focus:ring-2 focus:ring-undefined-500" aria-label="Toggle Theme">
40
  <i data-feather="moon" class="w-5 h-5 dark:hidden"></i>
41
  <i data-feather="sun" class="w-5 h-5 hidden dark:block"></i>
 
36
  <span class="font-bold text-xl tracking-tight">Memory Void</span>
37
  </div>
38
  <div class="flex items-center space-x-4">
39
+ <a href="builder.html" class="text-sm text-gray-600 dark:text-gray-400 hover:text-undefined-500 transition-colors flex items-center" aria-label="Qwen App Builder">
40
+ <i data-feather="cpu" class="w-4 h-4 mr-1"></i> <span class="hidden sm:inline">App Builder</span>
41
+ </a>
42
  <button id="theme-toggle" class="p-2 rounded-full hover:bg-gray-100 dark:hover:bg-gray-800 transition-colors focus:outline-none focus:ring-2 focus:ring-undefined-500" aria-label="Toggle Theme">
43
  <i data-feather="moon" class="w-5 h-5 dark:hidden"></i>
44
  <i data-feather="sun" class="w-5 h-5 hidden dark:block"></i>