Files
api7-demo/web/templates/llm.html
d.viti ed660dce5a
Some checks failed
Helm Chart Build / lint-only (push) Has been skipped
Helm Chart Build / build-helm (push) Successful in 9s
Build and Deploy / build-api (push) Successful in 33s
Build and Deploy / build-web (push) Failing after 41s
Add LLM endpoints, web frontend, and rate limiting config
- Added OpenAI-compatible LLM endpoints to API backend - Introduced web
frontend with Jinja2 templates and static assets - Implemented API proxy
routes in web service - Added sample db.json data for items, users,
orders, reviews, categories, llm_requests - Updated ADC and Helm configs
for separate AI and standard rate limiting - Upgraded FastAPI, Uvicorn,
and added httpx, Jinja2, python-multipart dependencies - Added API
configuration modal and client-side JS for web app
2025-10-07 17:29:12 +02:00

136 lines
4.2 KiB
HTML

{% extends "base.html" %} {% block title %}LLM Chat - API Demo{% endblock %} {%
block content %}
<div class="page-header">
<h1>🤖 AI Chat - Videogame Expert</h1>
<p>Chat with our AI assistant (Rate limited: 100 tokens/60s)</p>
</div>
<div class="chat-container">
<div class="chat-messages" id="chat-messages">
<div class="system-message">
Welcome! Ask me anything about videogames. I'm powered by the
videogame-expert model.
</div>
</div>
<div class="chat-input-container">
<textarea
id="chat-input"
placeholder="Type your message here..."
rows="3"
></textarea>
<button id="send-btn" class="btn btn-primary" onclick="sendMessage()">
Send Message
</button>
</div>
<div class="chat-info">
<small>
Model: <strong>videogame-expert</strong> | Status:
<span id="status">Ready</span> | Rate Limit:
<strong>100 tokens/60s</strong>
</small>
</div>
</div>
{% endblock %} {% block scripts %}
<script src="https://cdn.jsdelivr.net/npm/marked@11.1.1/marked.min.js"></script>
<script>
const API_BASE = "/api";
let isProcessing = false;
function addMessage(content, isUser = false) {
const messagesDiv = document.getElementById("chat-messages");
const messageDiv = document.createElement("div");
messageDiv.className = isUser ? "user-message" : "assistant-message";
if (isUser) {
messageDiv.textContent = content;
} else {
// Parse markdown for assistant messages
messageDiv.innerHTML = marked.parse(content);
}
messagesDiv.appendChild(messageDiv);
messagesDiv.scrollTop = messagesDiv.scrollHeight;
}
function setStatus(text, isError = false) {
const statusSpan = document.getElementById("status");
statusSpan.textContent = text;
statusSpan.style.color = isError ? "#f44336" : "#4CAF50";
}
async function sendMessage() {
if (isProcessing) return;
const input = document.getElementById("chat-input");
const prompt = input.value.trim();
if (!prompt) {
alert("Please enter a message");
return;
}
// Add user message
addMessage(prompt, true);
input.value = "";
// Set processing state
isProcessing = true;
document.getElementById("send-btn").disabled = true;
setStatus("Processing...");
try {
const response = await fetch(`${API_BASE}/llm/chat`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
prompt: prompt,
max_tokens: 150,
temperature: 0.7,
model: "videogame-expert",
}),
});
if (!response.ok) {
const error = await response.json();
throw new Error(error.detail || "API request failed");
}
const data = await response.json();
// Add assistant response
addMessage(data.response, false);
// Show tokens used
const tokensInfo = `Tokens used: ${data.tokens_used}`;
const infoDiv = document.createElement("div");
infoDiv.className = "system-message";
infoDiv.textContent = tokensInfo;
document.getElementById("chat-messages").appendChild(infoDiv);
setStatus("Ready");
} catch (error) {
console.error("Error:", error);
addMessage(`Error: ${error.message}`, false);
setStatus("Error", true);
} finally {
isProcessing = false;
document.getElementById("send-btn").disabled = false;
}
}
// Allow Enter to send (Shift+Enter for newline)
document
.getElementById("chat-input")
.addEventListener("keydown", function (e) {
if (e.key === "Enter" && !e.shiftKey) {
e.preventDefault();
sendMessage();
}
});
</script>
{% endblock %}