I denne oppgaven skal du sette opp en Web-app med HTML og CSS og Python, med en KI-chatbot som vi kommuniserer med via tjenesten HuggingFace.
.txt
data/
Test i VS Code Terminal (Ctrl+ø):
python –version
Får du et versjonsnummer, er alt klart.
I VS Code, opprett en ny mappe ved å bruke Explorer:
flask-schoolbot
flask-schoolbot/ app.py .env data/ (mappe) templates/ (mappe) index.html static/ (mappe) style.css
pwd
I VS Code Terminal:
python -m venv venv
.\venv\Scripts\activate
pip install flask python-dotenv requests
Du skal se (venv) foran prompten.
(venv)
skolerute.txt
ordensreglement.txt
fravær.txt
Informasjon til disse filene må du hente fra skolens hjemmeside.
Kun .txt støttes i denne første versjonen.
Åpne .env og fyll inn:
.env
HF_TOKEN=DIN_HF_TOKEN_HER MODEL=meta-llama/Meta-Llama-3-8B-Instruct
MERK:
MODEL
Åpne templates/index.html. Du bestemmer tittel, head, CSS‑kobling osv. Men disse delene må ligge i dokumentet:
templates/index.html
<form method="POST"> <input type="text" name="question" placeholder="Skriv spørsmålet ditt..." /> <button type="submit">Send</button> </form>
Legg gjerne til egen CSS i static/style.css for utseende.
static/style.css
app.py
(oppdatert 26.2.2026 kl 15:20)
# app.py # ------------------------------- # En enkel Flask-basert skoleassistent. # Leser .txt-filer fra ./data og kaller en språkmodell via Hugging Face Inference API. # Viser chatlogg (bruker-spørsmål og modell-svar). # ------------------------------- from flask import Flask, request, render_template from dotenv import load_dotenv import os import requests import markdown # Laster miljøvariabler fra .env (HF_TOKEN og MODEL) # override=True sikrer at vi bruker ny verdi selv om gammel henger igjen load_dotenv(override=True) app = Flask(__name__) # REGISTRER MARKDOWN-FILTER @app.template_filter('markdown') def render_markdown(text): return markdown.markdown(text) # HENTER API-NØKKEL OG MODELLNAVN FRA .env HF_TOKEN = os.getenv("HF_TOKEN") MODEL = os.getenv("MODEL") # SJEKKER AT NØKKEL FINNES if not HF_TOKEN: raise RuntimeError("HF_TOKEN mangler i .env. Legg inn din Hugging Face API-nøkkel.") # ENKEL FUNKSJON SOM LESER ALLE .txt-FILER I ./data VED OPPSTART def load_documents(): docs = "" data_dir = "data" if not os.path.isdir(data_dir): return docs for filename in os.listdir(data_dir): if filename.endswith(".txt"): path = os.path.join(data_dir, filename) try: with open(path, "r", encoding="utf-8") as f: content = f.read().strip() # Legg til filnavn som skille for tydeligere kontekst docs += f"\n\n### FIL: {filename}\n{content}" except Exception as e: print(f"Kunne ikke lese {filename}: {e}") print(f"DEBUG: Lastet {len(docs)} tegn med dokumentasjon.") if len(docs) == 0: print("ADVARSEL: Ingen dokumenter lastet funnet i data-mappen!") return docs # LASTER DOKUMENTER EN GANG (VED OPPSTART) DOCUMENTS = load_documents() # CHATLOGG I MINNET (LISTE AV DIKTIONARIES) # MERK: DENNE TØMMES HVIS APPEN STARTES PÅ NYTT. FOR VEDVARENDE LAGRING MÅ DU BRUKE DATABASE. chatlog = [] def build_messages(question: str, chat_history: list) -> list: """ Bygger meldingsliste til språkmodellen. - System-melding: Instruksjoner og dokumentkontekst. - Historikk: Tidligere spørsmål og svar. - Siste melding: Brukerens nye spørsmål. """ # 1. System-instruksjon med dokumenter system_content = f""" Du er en hjelpsom skoleassistent for Charlottenlund vgs. Din oppgave er å svare på spørsmål basert på informasjonen gitt i "DOKUMENTER" nedenfor. VIKTIGE REGLER: 1. Bruk KUN informasjonen i dokumentene for å svare. 2. Hvis du ikke finner svaret i dokumentene, svar høflig at du ikke vet det basert på tilgjengelig info. Ikke finn på ting. 3. Vær kortfattet, presis og hyggelig. 4. Svar på norsk. DOKUMENTER: {DOCUMENTS} """ messages = [{"role": "system", "content": system_content.strip()}] # 2. Legg til historikk for entry in chat_history: messages.append({"role": "user", "content": entry['user']}) messages.append({"role": "assistant", "content": entry['bot']}) # 3. Legg til brukerens nye spørsmål messages.append({"role": "user", "content": question}) return messages def ask_model(messages: list) -> str: """ Ringer Hugging Face Inference API med en liste av meldinger. Forventer HF_TOKEN og MODEL fra .env. """ headers = { "Authorization": f"Bearer {HF_TOKEN}", "Content-Type": "application/json" } # Bruker OpenAI-kompatibelt format for chat-modeller body = { "model": MODEL, "messages": messages, "max_tokens": 500, "temperature": 0.3 } try: # Peke mot den nye routeren som bruker OpenAI-format url = "https://router.huggingface.co/v1/chat/completions" resp = requests.post( url, headers=headers, json=body, timeout=60 ) if resp.status_code != 200: return f"Feil: API returnerte statuskode {resp.status_code}. Svar: {resp.text}" data = resp.json() # Sjekk om svaret er i OpenAI format (choices -> message -> content) if "choices" in data and len(data["choices"]) > 0: return data["choices"][0]["message"]["content"] return str(data) except Exception as e: return f"Feil ved kall til modellen: {e}" @app.route("/", methods=["GET", "POST"]) def index(): """ Viser forsiden og håndterer innsending av skjema (POST). Oppdaterer chatlogg og rendrer index.html med chat-listen. """ global chatlog if request.method == "POST": user_question = request.form.get("question", "").strip() if user_question: messages = build_messages(user_question, chatlog) answer = ask_model(messages) chatlog.append({"user": user_question, "bot": answer}) # RENDERER siden med dagens chatlogg return render_template("index.html", chat=chatlog) if __name__ == "__main__": # KJØRER FLASK I UTVIKLINGSMODUS # DU KAN ENDRE 'debug=False' HVIS DU IKKE VIL SE RESTART/FEILLOGG I TERMINALEN. app.run(debug=True)
Hva kan du endre i app.py etter kopiering:
temperature
max_new_tokens
ask_model
build_prompt
python app.py
http://127.0.0.1:5000
HF_TOKEN
venv/
load_documents()
.md
.pdf
pdfplumber
.docx
mammoth
extract_raw_text
Lag en webapp med KIagent
© 2024 • Contents under CC-BY-NC • Maintained by Karl Arne Dalsaune