Använd AI i dina dashboards: Hur du skapar ett enkelt prompt-UI för LlamaIndex
av Vincent de Vries den Apr 14, 2025 3:06:01 PM
Inledning
I en tidigare blogg (Använd AI i dina dashboards: Integrera en lokal LLM med Grafana för bättre insikter) visade vi hur du kan koppla samman Grafana Metrics med en språkmodell (LLM) med hjälp av LlamaIndex. Detta gör det möjligt att ställa frågor till vår LLM baserat på metrics. Men låt oss vara ärliga, vem vill köra ett nytt Python-skript för varje prompt?
I det här inlägget tar vi nästa steg och lägger till ett enkelt, webbaserat gränssnitt som gör interaktionen med både LLM och LlamaIndex mycket smidigare. Gränssnittet eliminerar behovet av att manuellt köra skript varje gång du vill ställa en fråga, vilket gör processen både mindre omständig och betydligt mer användarvänlig. Det är dock viktigt att påpeka att denna implementation är avsedd för experimentellt bruk – inte för produktion.
Förutsättningar
Om du inte redan gjort det, bör du först sätta upp din miljö med LlamaIndex enligt stegen i vårt tidigare inlägg: Använd AI i dina dashboards: Integrera en lokal LLM med Grafana för bättre insikter.
Bygga det webbaserade gränssnittet
För att kunna köra våra Python-skript som en webbserver behöver vi först installera Flask i vår miljö.
pip install flask
Därefter behöver vi skapa en katalog som heter "templates". Detta är där Flask letar efter HTML-filer som ska visas. Skapa mappen i din hemkatalog så att Python-skripten enkelt kan hitta de relativa sökvägarna till dina LlamaIndex-index.
/home/username/
├── web_llamaindex.py
├── templates/
│ ├── index.html
I din hemkatalog skapar du nu en fil med namnet web_llamaindex.py och klistrar in koden nedan:
from flask import Flask, render_template, request, jsonify
import os
from llama_index.core import load_index_from_storage, StorageContext, Settings
from llama_index.core.query_engine import RetrieverQueryEngine
from llama_index.llms.ollama import Ollama
from llama_index.embeddings.huggingface import HuggingFaceEmbedding
app = Flask(__name__)
# Force multi-threading
os.environ["OMP_NUM_THREADS"] = str(os.cpu_count())
os.environ["MKL_NUM_THREADS"] = str(os.cpu_count())
os.environ["OPENBLAS_NUM_THREADS"] = str(os.cpu_count())
os.environ["NUMEXPR_NUM_THREADS"] = str(os.cpu_count())
# Set up LlamaIndex with Ollama
Settings.llm = Ollama(model="mistral", request_timeout=120, num_threads=0) # Use all CPU cores
Settings.embed_model = HuggingFaceEmbedding(model_name="sentence-transformers/all-MiniLM-L6-v2")
# Load storage context before loading the index
storage_context = StorageContext.from_defaults(persist_dir="./mimir_index")
# Load existing index with storage context
index = load_index_from_storage(storage_context=storage_context)
# Create a retriever from the index
retriever = index.as_retriever()
# Create query engine using the retriever
query_engine = RetrieverQueryEngine(retriever=retriever)
@app.route('/')
def home():
return render_template('index.html')
@app.route('/query', methods=['POST'])
def query():
data = request.get_json()
user_query = data.get("query", "")
response = query_engine.query(user_query)
return jsonify({"query": user_query, "response": str(response)})
if __name__ == '__main__':
app.run(host='0.0.0.0', port='5000', debug=True)
Koden i web_llamaindex.py ovan kommer att fungera som ett API för indexsidan.
För att skapa indexsidan, skapa en ny fil med namnet index.html i katalogen templates. Klistra sedan in koden nedan i index.html.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Chatbot</title>
<style>
body {
font-family: Arial, sans-serif;
background-color: #f8f9fa;
color: #333;
margin: 0;
display: flex;
flex-direction: column;
align-items: center;
height: 100vh;
justify-content: center;
}
.chat-container {
width: 40%;
max-width: 600px;
background: white;
border-radius: 8px;
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
padding: 20px;
display: flex;
flex-direction: column;
height: 80vh;
overflow: hidden;
}
.chat-box {
flex-grow: 1;
overflow-y: auto;
padding: 10px;
display: flex;
flex-direction: column;
border-bottom: 1px solid #ddd;
}
.message {
padding: 10px;
border-radius: 8px;
margin-bottom: 10px;
max-width: 80%;
word-wrap: break-word;
}
.user-message {
background: #007bff;
color: white;
align-self: flex-end;
}
.bot-message {
background: #e9ecef;
align-self: flex-start;
}
.input-container {
display: flex;
padding-top: 10px;
}
input {
flex-grow: 1;
padding: 10px;
border: 1px solid #ddd;
border-radius: 4px;
font-size: 16px;
background: white;
color: #333;
outline: none;
}
button {
padding: 10px 20px;
margin-left: 10px;
border: none;
background: #007bff;
color: white;
border-radius: 4px;
cursor: pointer;
font-size: 16px;
}
button:hover {
background: #0056b3;
}
/* Spinner */
.spinner {
display: none;
align-self: center;
width: 24px;
height: 24px;
border: 3px solid #ddd;
border-top: 3px solid #007bff;
border-radius: 50%;
animation: spin 1s linear infinite;
margin-top: 10px;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
</style>
</head>
<body>
<div class="chat-container">
<div class="chat-box" id="chatBox"></div>
<div class="spinner" id="spinner"></div>
<div class="input-container">
<input type="text" id="userInput" placeholder="Type a message..." onkeypress="handleKeyPress(event)">
<button onclick="sendMessage()">Send</button>
</div>
</div>
<script>
function sendMessage() {
let userInput = document.getElementById("userInput");
let message = userInput.value.trim();
if (message === "") return;
let chatBox = document.getElementById("chatBox");
let spinner = document.getElementById("spinner");
let userMsgDiv = document.createElement("div");
userMsgDiv.className = "message user-message";
userMsgDiv.textContent = message;
chatBox.appendChild(userMsgDiv);
userInput.value = "";
chatBox.scrollTop = chatBox.scrollHeight;
spinner.style.display = "block"; // Show spinner
fetch('/query', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ query: message })
})
.then(response => response.json())
.then(data => {
let botMsgDiv = document.createElement("div");
botMsgDiv.className = "message bot-message";
botMsgDiv.textContent = data.response;
chatBox.appendChild(botMsgDiv);
chatBox.scrollTop = chatBox.scrollHeight;
})
.finally(() => {
spinner.style.display = "none"; // Hide spinner
});
}
function handleKeyPress(event) {
if (event.key === "Enter") {
sendMessage();
}
}
</script>
</body>
</html>
Allt du behöver göra nu är att starta servern:
python3 web_llamaindex.py
Om allt gick som det ska, bör du få en utdata som ser ut ungefär så här:
För att använda det webbaserade gränssnittet, surfa till IP-adressen eller FQDN:en på port 5000. Till exempel: http://myhost.local:5000
Du har nu ett enkelt och snyggt gränssnitt som du kan använda för dina prompts:
Sammanfattning
I det här inlägget har vi tagit nästa steg i att kombinera Grafana med AI genom att bygga ett enkelt, webbaserat gränssnitt för att interagera med en lokal LLM via LlamaIndex. Genom att använda Flask kunde vi skapa en lättanvänd UI-lösning som gör det möjligt att ställa frågor direkt i webbläsaren – utan att behöva köra Python-skript för varje prompt.
Vill du prata Grafana med oss?
Du kanske också är intresserad av
Relaterade bloggar

Använd AI i dina dashboards: Integrera en lokal LLM med Grafana för bättre insikter

En introduktion till Grafana Mimir: Skalbar och pålitlig lagring för telemetri

Inga kommentarer än
Berätta vad du tänker