12 KiB
Chatproject
Dit chatproject laat zien hoe je een Chat Assistent kunt bouwen met behulp van GitHub Models.
Hier is hoe het uiteindelijke project eruitziet:
Wat context: het bouwen van chatassistenten met generatieve AI is een geweldige manier om te beginnen met leren over AI. In deze les leer je hoe je generatieve AI integreert in een webapplicatie. Laten we beginnen.
Verbinden met generatieve AI
Voor de backend gebruiken we GitHub Models. Dit is een geweldige service waarmee je gratis AI kunt gebruiken. Ga naar de playground en haal de code op die overeenkomt met de door jou gekozen backend-taal. Hier is hoe het eruitziet op GitHub Models Playground
Zoals gezegd, selecteer het tabblad "Code" en jouw gekozen runtime.
Gebruik van Python
In dit geval kiezen we Python, wat betekent dat we deze code selecteren:
"""Run this model in Python
> pip install openai
"""
import os
from openai import OpenAI
# To authenticate with the model you will need to generate a personal access token (PAT) in your GitHub settings.
# Create your PAT token by following instructions here: https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens
client = OpenAI(
base_url="https://models.github.ai/inference",
api_key=os.environ["GITHUB_TOKEN"],
)
response = client.chat.completions.create(
messages=[
{
"role": "system",
"content": "",
},
{
"role": "user",
"content": "What is the capital of France?",
}
],
model="openai/gpt-4o-mini",
temperature=1,
max_tokens=4096,
top_p=1
)
print(response.choices[0].message.content)
Laten we deze code een beetje opschonen zodat het herbruikbaar is:
def call_llm(prompt: str, system_message: str):
response = client.chat.completions.create(
messages=[
{
"role": "system",
"content": system_message,
},
{
"role": "user",
"content": prompt,
}
],
model="openai/gpt-4o-mini",
temperature=1,
max_tokens=4096,
top_p=1
)
return response.choices[0].message.content
Met deze functie call_llm
kunnen we nu een prompt en een systeemprompt doorgeven, en de functie retourneert het resultaat.
AI Assistent aanpassen
Als je de AI-assistent wilt aanpassen, kun je specificeren hoe je wilt dat deze zich gedraagt door de systeemprompt als volgt in te vullen:
call_llm("Tell me about you", "You're Albert Einstein, you only know of things in the time you were alive")
Exposeer het via een Web API
Geweldig, we hebben het AI-gedeelte klaar. Laten we nu kijken hoe we dit kunnen integreren in een Web API. Voor de Web API kiezen we Flask, maar elk webframework zou goed moeten werken. Hier is de code:
Gebruik van Python
# api.py
from flask import Flask, request, jsonify
from llm import call_llm
from flask_cors import CORS
app = Flask(__name__)
CORS(app) # * example.com
@app.route("/", methods=["GET"])
def index():
return "Welcome to this API. Call POST /hello with 'message': 'my message' as JSON payload"
@app.route("/hello", methods=["POST"])
def hello():
# get message from request body { "message": "do this taks for me" }
data = request.get_json()
message = data.get("message", "")
response = call_llm(message, "You are a helpful assistant.")
return jsonify({
"response": response
})
if __name__ == "__main__":
app.run(host="0.0.0.0", port=5000)
Hier maken we een Flask API en definiëren we een standaardroute "/" en "/chat". De laatste is bedoeld om door onze frontend te worden gebruikt om vragen door te geven.
Om llm.py te integreren, moeten we het volgende doen:
-
Importeer de functie
call_llm
:from llm import call_llm from flask import Flask, request
-
Roep het aan vanuit de "/chat"-route:
@app.route("/hello", methods=["POST"]) def hello(): # get message from request body { "message": "do this taks for me" } data = request.get_json() message = data.get("message", "") response = call_llm(message, "You are a helpful assistant.") return jsonify({ "response": response })
Hier parseren we het binnenkomende verzoek om de eigenschap
message
uit de JSON-body te halen. Vervolgens roepen we de LLM aan met deze oproep:response = call_llm(message, "You are a helpful assistant") # return the response as JSON return jsonify({ "response": response })
Geweldig, nu hebben we gedaan wat nodig is.
Cors configureren
We moeten vermelden dat we iets zoals CORS hebben ingesteld, oftewel cross-origin resource sharing. Dit betekent dat, omdat onze backend en frontend op verschillende poorten draaien, we de frontend toegang moeten geven tot de backend.
Gebruik van Python
Er is een stukje code in api.py dat dit instelt:
from flask_cors import CORS
app = Flask(__name__)
CORS(app) # * example.com
Op dit moment is het ingesteld om "*" toe te staan, wat alle origins betekent, en dat is een beetje onveilig. We moeten dit beperken zodra we naar productie gaan.
Voer je project uit
Om je project uit te voeren, moet je eerst je backend starten en daarna je frontend.
Gebruik van Python
Oké, we hebben llm.py en api.py. Hoe kunnen we dit laten werken met een backend? Er zijn twee dingen die we moeten doen:
-
Installeer afhankelijkheden:
cd backend python -m venv venv source ./venv/bin/activate pip install openai flask flask-cors openai
-
Start de API
python api.py
Als je in Codespaces werkt, moet je naar Ports gaan in het onderste deel van de editor, er met de rechtermuisknop op klikken, "Port Visibility" selecteren en "Public" kiezen.
Werk aan een frontend
Nu we een API hebben draaien, laten we een frontend maken. Een minimale frontend die we stap voor stap zullen verbeteren. Maak in een frontend-map het volgende aan:
backend/
frontend/
index.html
app.js
styles.css
Laten we beginnen met index.html:
<html>
<head>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<form>
<textarea id="messages"></textarea>
<input id="input" type="text" />
<button type="submit" id="sendBtn">Send</button>
</form>
<script src="app.js" />
</body>
</html>
Het bovenstaande is het absolute minimum dat je nodig hebt om een chatvenster te ondersteunen. Het bestaat uit een tekstgebied waar berichten worden weergegeven, een invoerveld om berichten te typen en een knop om je bericht naar de backend te sturen. Laten we nu naar de JavaScript kijken in app.js.
app.js
// app.js
(function(){
// 1. set up elements
const messages = document.getElementById("messages");
const form = document.getElementById("form");
const input = document.getElementById("input");
const BASE_URL = "change this";
const API_ENDPOINT = `${BASE_URL}/hello`;
// 2. create a function that talks to our backend
async function callApi(text) {
const response = await fetch(API_ENDPOINT, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ message: text })
});
let json = await response.json();
return json.response;
}
// 3. add response to our textarea
function appendMessage(text, role) {
const el = document.createElement("div");
el.className = `message ${role}`;
el.innerHTML = text;
messages.appendChild(el);
}
// 4. listen to submit events
form.addEventListener("submit", async(e) => {
e.preventDefault();
// someone clicked the button in the form
// get input
const text = input.value.trim();
appendMessage(text, "user")
// reset it
input.value = '';
const reply = await callApi(text);
// add to messages
appendMessage(reply, "assistant");
})
})();
Laten we de code per sectie doornemen:
-
- Hier halen we een referentie op naar alle elementen die we later in de code zullen gebruiken.
-
- In deze sectie maken we een functie die de ingebouwde
fetch
-methode gebruikt om onze backend aan te roepen.
- In deze sectie maken we een functie die de ingebouwde
-
appendMessage
helpt om zowel de antwoorden als wat jij als gebruiker typt toe te voegen.
-
- Hier luisteren we naar het submit-event, lezen we het invoerveld, plaatsen we het bericht van de gebruiker in het tekstgebied, roepen we de API aan en renderen we het antwoord in het tekstgebied.
Laten we nu naar de styling kijken. Hier kun je echt creatief zijn en het eruit laten zien zoals je wilt, maar hier zijn enkele suggesties:
styles.css
.message {
background: #222;
box-shadow: 0 0 0 10px orange;
padding: 10px:
margin: 5px;
}
.message.user {
background: blue;
}
.message.assistant {
background: grey;
}
Met deze drie klassen kun je berichten anders stylen, afhankelijk van of ze van de assistent of van jou als gebruiker komen. Als je inspiratie wilt, bekijk dan de map solution/frontend/styles.css
.
Basis-URL wijzigen
Er is één ding dat we hier niet hebben ingesteld, en dat is BASE_URL
. Dit is niet bekend totdat je backend is gestart. Om dit in te stellen:
- Als je de API lokaal uitvoert, moet het iets zijn zoals
http://localhost:5000
. - Als je het in Codespaces uitvoert, moet het eruitzien als "[name]app.github.dev".
Opdracht
Maak je eigen map project met inhoud zoals hieronder:
project/
frontend/
index.html
app.js
styles.css
backend/
...
Kopieer de inhoud van wat hierboven is uitgelegd, maar voel je vrij om het naar eigen wens aan te passen.
Oplossing
Bonus
Probeer de persoonlijkheid van de AI-assistent te veranderen.
Voor Python
Wanneer je call_llm
aanroept in api.py, kun je het tweede argument wijzigen naar wat je wilt, bijvoorbeeld:
call_llm(message, "You are Captain Picard")
Frontend
Verander ook de CSS en tekst naar jouw smaak, dus voer wijzigingen door in index.html en styles.css.
Samenvatting
Geweldig, je hebt geleerd hoe je vanaf nul een persoonlijke assistent kunt maken met AI. We hebben dit gedaan met behulp van GitHub Models, een backend in Python en een frontend in HTML, CSS en JavaScript.
Instellen met Codespaces
-
Navigeer naar: Web Dev For Beginners repo
-
Maak een template (zorg ervoor dat je bent ingelogd op GitHub) in de rechterbovenhoek:
-
Zodra je in je repo bent, maak je een Codespace aan:
Dit zou een omgeving moeten starten waarin je nu kunt werken.
Disclaimer:
Dit document is vertaald met behulp van de AI-vertalingsservice Co-op Translator. Hoewel we streven naar nauwkeurigheid, dient u zich ervan bewust te zijn dat geautomatiseerde vertalingen fouten of onnauwkeurigheden kunnen bevatten. Het originele document in zijn oorspronkelijke taal moet worden beschouwd als de gezaghebbende bron. Voor cruciale informatie wordt professionele menselijke vertaling aanbevolen. Wij zijn niet aansprakelijk voor misverstanden of verkeerde interpretaties die voortvloeien uit het gebruik van deze vertaling.