Spaces:
Running
Running
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>DeepSeek AI Server</title> | |
<script src="https://cdn.tailwindcss.com"></script> | |
<script src="https://js.puter.com/v2/"></script> | |
<style> | |
body { | |
font-family: 'Inter', sans-serif; | |
background-color: #f3f4f6; | |
} | |
#output { | |
white-space: pre-wrap; | |
word-wrap: break-word; | |
} | |
#apiResponse { | |
font-family: monospace; | |
white-space: pre; | |
overflow-x: auto; | |
} | |
</style> | |
</head> | |
<body class="min-h-screen flex flex-col items-center justify-center p-4"> | |
<div class="w-full max-w-4xl bg-white shadow-lg rounded-lg p-6"> | |
<h1 class="text-2xl font-bold text-gray-800 mb-4 text-center">DeepSeek AI Server</h1> | |
<!-- Web Interface Tab --> | |
<div class="mb-6" id="webInterface"> | |
<div class="mb-4"> | |
<input | |
type="text" | |
id="query" | |
placeholder="Enter your query (e.g., Explain dark matter)" | |
class="w-full p-3 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500" | |
> | |
<button | |
id="submit" | |
class="mt-2 w-full bg-blue-600 text-white p-3 rounded-lg hover:bg-blue-700 transition" | |
> | |
Get AI Response | |
</button> | |
</div> | |
<div id="output" class="bg-gray-100 p-4 rounded-lg text-gray-800 min-h-32"></div> | |
</div> | |
<!-- API Tester Tab --> | |
<div class="mb-6 hidden" id="apiTester"> | |
<div class="mb-4"> | |
<h2 class="text-lg font-semibold mb-2">Test API Endpoint</h2> | |
<div class="grid grid-cols-1 md:grid-cols-2 gap-4"> | |
<div> | |
<label class="block text-sm font-medium text-gray-700 mb-1">API Request</label> | |
<textarea | |
id="apiRequest" | |
class="w-full p-3 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 h-32" | |
placeholder='{"query": "Your question here", "model": "gpt-4o"}' | |
></textarea> | |
<button | |
id="apiSubmit" | |
class="mt-2 w-full bg-green-600 text-white p-3 rounded-lg hover:bg-green-700 transition" | |
> | |
Send API Request | |
</button> | |
</div> | |
<div> | |
<label class="block text-sm font-medium text-gray-700 mb-1">API Response</label> | |
<div id="apiResponse" class="w-full p-3 border rounded-lg bg-gray-100 h-32 overflow-auto"></div> | |
</div> | |
</div> | |
</div> | |
<div class="bg-gray-100 p-4 rounded-lg"> | |
<h2 class="text-lg font-semibold mb-2">API Documentation</h2> | |
<div class="space-y-3"> | |
<div> | |
<h3 class="font-medium">Endpoint</h3> | |
<code class="bg-gray-200 p-1 rounded text-sm">POST /api/ask</code> | |
</div> | |
<div> | |
<h3 class="font-medium">Request Body</h3> | |
<pre class="bg-gray-200 p-2 rounded text-sm overflow-x-auto"> | |
{ | |
"query": "string", // Required | |
"model": "string" // Optional (default: "gpt-4o") | |
}</pre> | |
</div> | |
<div> | |
<h3 class="font-medium">Example Usage</h3> | |
<pre class="bg-gray-200 p-2 rounded text-sm overflow-x-auto"> | |
fetch('/api/ask', { | |
method: 'POST', | |
headers: { | |
'Content-Type': 'application/json' | |
}, | |
body: JSON.stringify({ | |
query: "Explain quantum computing", | |
model: "gpt-4o" | |
}) | |
}) | |
.then(response => response.text()) | |
.then(data => console.log(data));</pre> | |
</div> | |
</div> | |
</div> | |
</div> | |
<!-- Tab Navigation --> | |
<div class="flex border-b"> | |
<button | |
class="px-4 py-2 font-medium text-blue-600 border-b-2 border-blue-600" | |
onclick="showTab('webInterface')" | |
> | |
Web Interface | |
</button> | |
<button | |
class="px-4 py-2 font-medium text-gray-500 hover:text-gray-700" | |
onclick="showTab('apiTester')" | |
> | |
API Tester | |
</button> | |
</div> | |
</div> | |
<script> | |
// Tab navigation | |
function showTab(tabId) { | |
document.getElementById('webInterface').classList.add('hidden'); | |
document.getElementById('apiTester').classList.add('hidden'); | |
document.getElementById(tabId).classList.remove('hidden'); | |
// Update active tab styling | |
const tabs = document.querySelectorAll('.flex.border-b button'); | |
tabs.forEach(tab => { | |
tab.classList.remove('text-blue-600', 'border-b-2', 'border-blue-600'); | |
tab.classList.add('text-gray-500', 'hover:text-gray-700'); | |
}); | |
event.currentTarget.classList.add('text-blue-600', 'border-b-2', 'border-blue-600'); | |
event.currentTarget.classList.remove('text-gray-500', 'hover:text-gray-700'); | |
} | |
// Web Interface Functionality | |
async function streamResponse(query) { | |
const outputDiv = document.getElementById('output'); | |
outputDiv.innerHTML = ''; // Clear previous output | |
const submitButton = document.getElementById('submit'); | |
submitButton.disabled = true; // Disable button during processing | |
try { | |
outputDiv.innerHTML += '<h2 class="text-lg font-semibold text-blue-600">AI Response:</h2>'; | |
// Using Puter SDK directly (client-side) | |
const chatResponse = await puter.ai.chat( | |
query, | |
{ | |
model: 'gpt-4o', | |
stream: true | |
} | |
); | |
for await (const part of chatResponse) { | |
if (part?.text) { | |
outputDiv.innerHTML += part.text; | |
outputDiv.scrollTop = outputDiv.scrollHeight; // Auto-scroll to bottom | |
} | |
} | |
} catch (error) { | |
outputDiv.innerHTML += `<p class="text-red-600">Error: ${error.message}</p>`; | |
} finally { | |
submitButton.disabled = false; // Re-enable button | |
} | |
} | |
// API Tester Functionality | |
async function testApi() { | |
const apiRequest = document.getElementById('apiRequest').value.trim(); | |
const apiResponseDiv = document.getElementById('apiResponse'); | |
const apiSubmitButton = document.getElementById('apiSubmit'); | |
apiResponseDiv.textContent = ''; | |
apiSubmitButton.disabled = true; | |
try { | |
if (!apiRequest) { | |
throw new Error('Please enter a valid JSON request'); | |
} | |
const requestObj = JSON.parse(apiRequest); | |
if (!requestObj.query) { | |
throw new Error('Request must include a "query" field'); | |
} | |
// Using Puter SDK directly (client-side) | |
const response = await puter.ai.chat( | |
requestObj.query, | |
{ | |
model: requestObj.model || 'gpt-4o', | |
stream: false | |
} | |
); | |
apiResponseDiv.textContent = JSON.stringify(response, null, 2); | |
} catch (error) { | |
apiResponseDiv.textContent = `Error: ${error.message}`; | |
} finally { | |
apiSubmitButton.disabled = false; | |
} | |
} | |
// Event listeners | |
document.getElementById('submit').addEventListener('click', () => { | |
const query = document.getElementById('query').value.trim(); | |
if (query) { | |
streamResponse(query); | |
} else { | |
document.getElementById('output').innerHTML = '<p class="text-red-600">Please enter a query.</p>'; | |
} | |
}); | |
document.getElementById('query').addEventListener('keypress', (e) => { | |
if (e.key === 'Enter') { | |
document.getElementById('submit').click(); | |
} | |
}); | |
document.getElementById('apiSubmit').addEventListener('click', testApi); | |
document.getElementById('apiRequest').addEventListener('keypress', (e) => { | |
if (e.key === 'Enter' && e.ctrlKey) { | |
testApi(); | |
} | |
}); | |
// Initialize with web interface shown | |
showTab('webInterface'); | |
</script> | |
</body> | |
</html> |