In het snelle digitale landschap van vandaag, met de opkomst van Large Language Models (LLM’s), zijn conversatie-applicaties enorm populair geworden. Chatbots hebben de manier waarop we in het dagelijks leven met apps, websites en zelfs klantenservicekanalen omgaan, veranderd.
De mogelijkheid om je eigen chatbot te bouwen is een gamechanger: het stelt bedrijven en individuen in staat om gepersonaliseerde, efficiënte en boeiende conversatie-interfaces te creëren die zijn afgestemd op hun specifieke behoeften.
Dit artikel laat zien hoe je een chatbot in Python bouwt met de kracht van LLM’s. We verkennen hoe we onze eigen chatbot met ChatGPT maken en hoe we die verder optimaliseren met het populaire LangChain-framework.
Ben je nieuw met ChatGPT en LangChain? Bekijk dan hieronder onze Introductie tot Large Language Models met GPT & LangChain AI code-along:
Dit artikel behandelt alle cruciale aspecten van de ontwikkeling van een geoptimaliseerde chatbot die onder de motorkap ChatGPT gebruikt. We werken in een Jupyter Notebook met de libraries openai en langchain geïnstalleerd. Je kunt meekijken in deze DataLab-workbook.
In de volgende secties bekijken we hoe je de OpenAI API gebruikt om basis-API-calls naar ChatGPT te doen als bouwstenen voor onze conversatie. Daarnaast implementeren we contextbewustzijn voor onze chatbot met eenvoudige Python-structuren. Tot slot optimaliseren we zowel de chatbotimplementatie als de gespreksgeschiedenis met LangChain en verkennen we de geheugenfeatures.
Basis-API-calls naar ChatGPT
We gebruiken ChatGPT als het model achter onze chatbot. Daarom bestaat onze eerste hands-on taak uit het schrijven van een eenvoudige maar complete API-call naar ChatGPT, zodat we een eerste interactie kunnen opzetten.
De volgende Python-functie bevat onze gewenste API-call naar ChatGPT met alleen de openai-library.
import os
import openai
openai_api_key = os.environ["OPENAI_API_KEY"]defchatgpt_call(prompt, model="gpt-3.5-turbo"):
response = openai.ChatCompletion.create(
model=model,
messages=[{"role":"user","content": prompt}])return response.choices[0].message["content"]Mogelijk gemaakt door
Merk op dat we in dit geval het gpt-3.5-turbo-model gebruiken, omdat dit het meest capabele GPT-3.5-model is en geoptimaliseerd is voor chat, en bovendien een van de goedkoopste modellen. Meer informatie over de verschillende beschikbare modellen vind je in de OpenAI-documentatie.
Laten we onze implementatie stap voor stap analyseren!
De functie chatgpt_call() is een wrapper rond de oorspronkelijke OpenAI-functiecall ChatCompletion.create die een chatcompletion-verzoek aanmaakt.
Gegeven de gewenste prompt retourneert de functie de bijbehorende ChatGPT-completion. Voor een geslaagde completion-call hoef je alleen de ID van het te gebruiken model (model) en de gewenste prompt (prompt) mee te geven.
De daadwerkelijke completion die ChatGPT terugstuurt, bevat metadata samen met het antwoord zelf. De completion zelf staat echter altijd in het veld response.choices[0].message[“content”]. Meer informatie over de volledige completion-inhoud vind je in de OpenAI-documentatie.
Met deze implementatie kunnen we ChatGPT in één regel prompten:
prompt ="My name is Andrea"
response = chatgpt_call(prompt)print(response)# Output: Nice to meet you, Andrea! How can I assist you today?Mogelijk gemaakt door
De call als op zichzelf staande interactie
Zie je een addertje onder het gras in de bovenstaande implementatie?
Om je een hint te geven, doen we een vervolginteractie:
prompt ="Do you remember my name?"
response = chatgpt_call(prompt)print(response)# Output: I'm sorry, as an AI language model, I don't have the ability to remember specific information about individual users.Mogelijk gemaakt door
Precies, zoals we zien, is elke API-call een op zichzelf staande interactie. Dit betekent dat het model geen geheugen heeft van eerdere inputprompts of gegeven completions. Telkens wanneer we de functie chatgpt_call() aanroepen, beginnen we een compleet nieuw gesprek.
Dat is natuurlijk een probleem als je een chatbot wilt bouwen, want het is onmogelijk om een gesprek te voeren als het model niet onthoudt waar we het over hebben gehad. Daarom is onze volgende stap om het model bewust te maken van onze eerdere interacties.
Contextbewustzijn
Contextbewustzijn stelt chatbots in staat om op basis van een lopend gesprek te begrijpen en passend te reageren.
Door een context op te bouwen, kunnen toekomstige interacties worden gepersonaliseerd op basis van eerdere, blijft de samenhang in het gesprek behouden en worden herhalingen vermeden. Bovendien kan de gebruiker met contextbewuste chatbots proactief verduidelijkende vragen stellen of suggesties doen om misverstanden recht te zetten.
Al met al verhoogt contextbewustzijn de natuurlijkheid, effectiviteit en gebruikerservaring van chatbots. Vanaf nu verwijzen we naar de verzameling van eerdere interacties als gespreksgeschiedenis of geheugen.
De originele OpenAI API voor ChatGPT biedt al een manier om onze gespreksgeschiedenis samen met elke nieuwe prompt naar het model te sturen. Daarnaast biedt het LangChain-framework ook een manier om het geheugen van ChatGPT effectiever en kostengeoptimaliseerd te beheren.
System-, Assistant- en User-berichten begrijpen
Structuur van ChatGPT’s gespreksgeschiedenis
Op dit punt kunnen we de methode chatgpt_call() direct gebruiken door alleen de gewenste prompt mee te geven. Als we beter naar de implementatie kijken, zien we dat de inputprompt is opgemaakt als onderdeel van de messages-lijst. Deze lijst is bedoeld om de gespreksgeschiedenis bij te houden en moet daarom op een heel specifieke manier worden geformatteerd.
Laten we eens beter kijken!
Tot nu toe hebben we de berichtenlijst in chatgpt_call() als volgt opgemaakt:
De messages-lijst slaat de gespreksgeschiedenis op als een verzameling dictionaries. Elke dictionary in de lijst staat voor een bericht in het gesprek en gebruikt twee key-valueparen.
De sleutel role met de waarde user geeft aan dat het bericht door de gebruiker is verstuurd.
De sleutel content met de waarde prompt bevat de daadwerkelijke gebruikersprompt.
Dit is een heel eenvoudig voorbeeld dat slechts één interactie bevat. Hoewel de sleutel content altijd ofwel de gebruikersprompt of de completion van de chatbot bevat, is de sleutel role veel veelzijdiger.
System-, Assistant- en User-rollen
De sleutel role geeft de eigenaar van het bericht in content aan. Bij ChatGPT kunnen we tot drie rollen hebben:
User. Zoals we al bespraken, komt de rol user overeen met de daadwerkelijke gebruiker die met de chatbot interageert.
Assistant. De rol assistant komt overeen met de chatbot.
System. De rol system wordt gebruikt om instructies, richtlijnen en context aan de chatbot te geven. Systemberichten helpen gebruikersinteracties te sturen, het gedrag van de chatbot te bepalen, contextuele informatie te bieden en specifieke interacties in het gesprek af te handelen. Je kunt systemberichten zien als hoog-niveau-instructies voor de chatbot, transparant voor de gebruiker.
ZELFGEMAAKTE afbeelding. Interactie van de verschillende rollen in de conversatieketen bij het bouwen van een chatbot met chatGPT.
Een gespreksgeschiedenis opbouwen
We kunnen onze gespreksgeschiedenis opbouwen met gebruik van de drie rollen user, assistant en system in onze messages-lijst.
Gegeven onze testinteracties zou een correct geformatteerde gespreksgeschiedenis met gebruik van de drie genoemde rollen er als volgt uit kunnen zien:
messages =[{'role':'system','content':'You are friendly chatbot.'},{'role':'user','content':'Hi, my name is Andrea'},{'role':'assistant','content':"Nice to meet you, Andrea! How can I assist you today?"},{'role':'user','content':'Do you remember my name?'}]Mogelijk gemaakt door
We kunnen onze functie call_chatgpt() licht aanpassen om de gespreksgeschiedenis als invoerparameter op te nemen:
defcall_chatgpt_with_memory(messages, model="gpt-3.5-turbo"):
response = openai.ChatCompletion.create(
model=model,
messages=messages,)return response.choices[0].message["content"]Mogelijk gemaakt door
Laten we deze nieuwe implementatie proberen!
messages =[{'role':'system','content':'You are friendly chatbot.'},{'role':'user','content':'Hi, my name is Andrea'},{'role':'assistant','content':"Nice to meet you, Andrea! How can I assist you today?"},{'role':'user','content':'Do you remember my name?'}]
response = call_chatgpt_with_memory(messages)print(response)# Output: Yes, your name is Andrea.Mogelijk gemaakt door
Mooi! We hebben het model bewust kunnen houden van onze eerdere interacties zodat we daadwerkelijk een gesprek kunnen voeren. We moeten echter nog een manier vinden om onze messages-lijst automatisch bij te werken.
Automatische gespreksgeschiedenis
We kunnen het automatisch verzamelen van berichten bereiken door onze API-callfunctie iets verder uit te werken:
defchatgpt_conversation(prompt):
context.append({'role':'user','content':f"{prompt}"})
response = call_chatgpt_with_memory(context)
context.append({'role':'assistant','content':f"{response}"})return response
Mogelijk gemaakt door
Proberen maar!
chatgpt_conversation("Hello, my name is Andrea")# Output: 'Nice to meet you, Andrea! How can I assist you today?'Mogelijk gemaakt door
En een vervolginteractie:
chatgpt_conversation("Do you remember my name?")# Output: 'Yes, your name is Andrea.'Mogelijk gemaakt door
Nu wordt de gespreksgeschiedenis automatisch bijgewerkt. Tot slot: je kunt de gespreksgeschiedenis — en de structuur ervan — op elk moment bekijken door de lijst messages te printen.
print(messages)# Output:[{'role':'user','content':'Hello, my name is Andrea'},{'role':'assistant','content':'Nice to meet you, Andrea! How can I assist you today?'},{'role':'user','content':'Do you remember my name?'},{'role':'assistant','content':'Yes, your name is Andrea.'}]Mogelijk gemaakt door
Het LangChain-framework
Tot nu toe zullen we het erover eens zijn dat onze implementatie leidt tot een bruikbare chatbot, maar waarschijnlijk niet de meest geoptimaliseerde versie.
Het continu meesturen van elk eerder bericht en elke completion kan snel leiden tot een enorme hoeveelheid tokens, die ChatGPT allemaal moet verwerken voordat de nieuwste completion wordt teruggestuurd.
Tot nu toe hebben we .append-operaties gebruikt om eerdere interacties te bundelen zodat de chatbot een soort geheugen heeft. Het geheugenbeheer kan echter effectiever worden gedaan met speciale pakketten zoals LangChain.
LangChain is een framework voor het ontwikkelen van applicaties die worden aangedreven door taalmodellen. Omdat chatbots tegenwoordig een van de populairste toepassingen zijn, biedt LangChain een schonere implementatie om de gespreksgeschiedenis van de chatbot op te bouwen en alternatieven om die efficiënter te behandelen.
In deze sectie verkennen we hoe je in plaats daarvan het LangChain-framework gebruikt om een chatbot te bouwen.
De langchain-library fungeert als vervanging voor de hierboven gebruikte openai-library, omdat de module langchain.llms je al in staat stelt om in twee regels code met ChatGPT te communiceren:
# OpenAI key from environmentfrom langchain.llms import OpenAI
llm = OpenAI()Mogelijk gemaakt door
Zodra het llm-model is geladen, importeren we het memory-object dat onze gespreksgeschiedenis zal opslaan. Voor het opslaan van elke eerdere interactie met de chatbot biedt LangChain de zogenaamde ConversationBufferMemory:
from langchain.memory import ConversationBufferMemory
memory = ConversationBufferMemory()Mogelijk gemaakt door
Nu is het tijd om de zogenaamde ConversationChain te importeren, een wrapper die llm en memory gebruikt om de gebruikersprompt aan ChatGPT te voeren en de completions terug te geven:
from langchain.chains import ConversationChain
conversation = ConversationChain(
llm=llm,
memory=memory
)Mogelijk gemaakt door
Tot slot kunnen we om een gebruikersprompt naar ChatGPT te sturen, de methode .predict als volgt gebruiken:
conversation.predict(input="Hello, my name is Andrea")# Output: "Hi Andrea, I'm an AI created to help you with whatever you may need. What can I do for you today?"Mogelijk gemaakt door
Laten we verbose=True instellen om te zien welke informatie het model in overweging neemt om een completion te geven. Laten we het proberen in een vervolginteractie:
Schermafbeelding van de context die beschikbaar is voor ChatGPT bij het maken van een completion. Verbose-uitvoer in groen.
Controleer tot slot dat eerdere interacties perfect worden onthouden:
Schermafbeelding van de context die beschikbaar is voor ChatGPT bij het maken van een completion. Verbose-uitvoer in groen.
De gespreksgeschiedenis vullen
We kunnen extra context aan de chatbot meegeven met de methode memory.save_context(). Zo kunnen we onze chatbot bewust maken van gewenste inhoud zonder deze informatie in een gesprek te hoeven aanreiken. In LangChain zijn de sleutelwoorden hiervoor input en output. Bijvoorbeeld,
memory.save_context({"input":"Hi"},{"output":"What's up"})
memory.save_context({"input":"Not much, just hanging"},{"output":"Cool"})Mogelijk gemaakt door
Daarnaast kunnen we de geheugeninhoud op elk moment raadplegen door print(memory.buffer) of memory.load_memory_variables({}) uit te voeren.
LangChain-geheugentypen
LangChain implementeert verschillende soorten geheugen voor ChatGPT. De hierboven gebruikte ConversationBufferMemory houdt elke afzonderlijke interactie met ChatGPT bij. We hebben echter al besproken dat het prompten van ChatGPT met de volledige gespreksgeschiedenis snel kan oplopen tot een groot aantal tokens die bij elke nieuwe interactie verwerkt moeten worden.
Houd er rekening mee dat ChatGPT naast een tokenlimiet per interactie ook kosten rekent op basis van het aantal tokens. Het telkens verwerken van de volledige gespreksgeschiedenis zal na verloop van tijd waarschijnlijk duur worden.
Om het continue verwerken van de gespreksgeschiedenis te voorkomen, implementeert LangChain andere geoptimaliseerde manieren om het geheugen van ChatGPT te beheren. We verkennen in de volgende sectie een van de meest geavanceerde typen.
Geavanceerde gespreksgeschiedenis met LangChain
Een geavanceerde manier om het geheugen te beheren zonder elke eerdere interactie op te slaan, is door in plaats daarvan een samenvatting van de interacties op te slaan.
Dit type geheugen is mijn favoriet, omdat het echt kan leiden tot geoptimaliseerd geheugenbeheer zonder ook maar één eerdere interactie te verliezen.
Gaan we doen!
# OpenAI key from environmentfrom langchain.llms import OpenAI
llm = OpenAI()from langchain.memory import ConversationSummaryBufferMemory
memory = ConversationSummaryBufferMemory(llm=llm, max_token_limit=100)Mogelijk gemaakt door
Let er wel op dat dit geheugentype het gedefinieerde llm gebruikt om de samenvatting van eerdere interacties te genereren.
Daarnaast kan dit geheugen volledige interacties opslaan tot een maximum aantal tokens (max_token_limit). Boven deze limiet verwerkt het de informatie van die berichten in de samenvatting.
Om het te testen maken we een interactie met een groot aantal tokens. Neem de volgende schedule:
schedule = "There is a meeting at 8am with your product team. \
You will need your powerpoint presentation prepared. \
9am-12pm have time to work on your LangChain \
project which will go quickly because Langchain is such a powerful tool. \
At Noon, lunch at the italian resturant with a customer who is driving \
from over an hour away to meet you to understand the latest in AI. \
Be sure to bring your laptop to show the latest LLM demo."
memory = ConversationSummaryBufferMemory(llm=llm, max_token_limit=100)
memory.save_context({"input":"Hello"},{"output":"What's up"})
memory.save_context({"input":"Not much, just hanging"},{"output":"Cool"})
memory.save_context({"input":"What is on the schedule today?"},{"output":f"{schedule}"})Mogelijk gemaakt door
Nu hoeven we alleen nog een nieuwe conversatieketen te declareren met het llm en het memory, zoals in de vorige voorbeelden.
conversation = ConversationChain(
llm=llm,
memory=memory,
verbose=True)Mogelijk gemaakt door
We kunnen .predict gebruiken om ChatGPT te prompten:
Schermafbeelding van de context die beschikbaar is voor ChatGPT bij het maken van een completion. Verbose-uitvoer in groen.
Zoals we zien, houdt de chatbot een samenvatting bij van de oorspronkelijke gespreksgeschiedenis, waardoor het aantal tokens dat ChatGPT bij elke vervolginteractie verwerkt, afneemt.
Dat was het! Nu kunnen we urenlang met onze geoptimaliseerde chatbot praten!
Zet verbose=False voor een prettigere vraag-en-antwoord-ervaring in je notebook.
Conclusie
In dit artikel hebben we gezien hoe je een contextbewuste chatbot bouwt met het bekende ChatGPT-model.
We hebben gezien hoe het bouwen van je eigen contextbewuste chatbot kan leiden tot doorlopende interacties. Deze iteratieve aanpak zorgt voor een constante feedbacklus, waardoor je behoeften en voorkeuren van gebruikers gaandeweg in het gesprek kunt meenemen.
We hebben twee hoofdbenaderingen gezien om de gespreksgeschiedenis van de chatbot te beheren. Ten eerste met de originele ChatGPT API, wat leidt tot een functionele, native chatbot. Ten tweede met het speciale LangChain-framework en een geoptimaliseerde geheugenimplementatie.
Nu is het jouw beurt! Het is tijd om met de bouwstenen uit dit artikel een chatbot te maken die is afgestemd op jouw specifieke usecase!
Andrea Valenzuela werkt momenteel aan het CMS-experiment bij de deeltjesversneller (CERN) in Genève, Zwitserland. Met zes jaar ervaring in data-engineering en -analyse omvatten haar taken data-analyse en softwareontwikkeling. Ze zet zich nu in voor het democratiseren van het leren van datagerelateerde technologieën via de Medium-publicatie ForCode'Sake.
Ze behaalde een bachelor in Engineering Physics aan de Polytechnische Universiteit van Catalonië en een master in Intelligent Interactive Systems aan de Pompeu Fabra Universiteit. Haar onderzoekservaring omvat professioneel werk met eerdere OpenAI-algoritmes voor beeldgeneratie, zoals Normalizing Flows.
In het snelle digitale landschap van vandaag, met de opkomst van Large Language Models (LLM’s), zijn conversatie-applicaties enorm populair geworden. Chatbots hebben de manier waarop we in het dagelijks leven met apps, websites en zelfs klantenservicekanalen omgaan, veranderd.
De mogelijkheid om je eigen chatbot te bouwen is een gamechanger: het stelt bedrijven en individuen in staat om gepersonaliseerde, efficiënte en boeiende conversatie-interfaces te creëren die zijn afgestemd op hun specifieke behoeften.
Dit artikel laat zien hoe je een chatbot in Python bouwt met de kracht van LLM’s. We verkennen hoe we onze eigen chatbot met ChatGPT maken en hoe we die verder optimaliseren met het populaire LangChain-framework.
Ben je nieuw met ChatGPT en LangChain? Bekijk dan hieronder onze Introductie tot Large Language Models met GPT & LangChain AI code-along:
Dit artikel behandelt alle cruciale aspecten van de ontwikkeling van een geoptimaliseerde chatbot die onder de motorkap ChatGPT gebruikt. We werken in een Jupyter Notebook met de libraries
openaienlangchaingeïnstalleerd. Je kunt meekijken in deze DataLab-workbook.In de volgende secties bekijken we hoe je de OpenAI API gebruikt om basis-API-calls naar ChatGPT te doen als bouwstenen voor onze conversatie. Daarnaast implementeren we contextbewustzijn voor onze chatbot met eenvoudige Python-structuren. Tot slot optimaliseren we zowel de chatbotimplementatie als de gespreksgeschiedenis met LangChain en verkennen we de geheugenfeatures.
Basis-API-calls naar ChatGPT
We gebruiken ChatGPT als het model achter onze chatbot. Daarom bestaat onze eerste hands-on taak uit het schrijven van een eenvoudige maar complete API-call naar ChatGPT, zodat we een eerste interactie kunnen opzetten.
De volgende Python-functie bevat onze gewenste API-call naar ChatGPT met alleen de
openai-library.Merk op dat we in dit geval het
gpt-3.5-turbo-model gebruiken, omdat dit het meest capabele GPT-3.5-model is en geoptimaliseerd is voor chat, en bovendien een van de goedkoopste modellen. Meer informatie over de verschillende beschikbare modellen vind je in de OpenAI-documentatie.Hulp nodig bij het verkrijgen van je OpenAI API-sleutels? Dan is de training Getting Started with the OpenAI API and ChatGPT iets voor jou.
Laten we onze implementatie stap voor stap analyseren!
De functie
chatgpt_call()is een wrapper rond de oorspronkelijke OpenAI-functiecallChatCompletion.createdie een chatcompletion-verzoek aanmaakt.Gegeven de gewenste prompt retourneert de functie de bijbehorende ChatGPT-completion. Voor een geslaagde completion-call hoef je alleen de ID van het te gebruiken model (
model) en de gewenste prompt (prompt) mee te geven.De daadwerkelijke completion die ChatGPT terugstuurt, bevat metadata samen met het antwoord zelf. De completion zelf staat echter altijd in het veld
response.choices[0].message[“content”]. Meer informatie over de volledige completion-inhoud vind je in de OpenAI-documentatie.Met deze implementatie kunnen we ChatGPT in één regel prompten:
De call als op zichzelf staande interactie
Zie je een addertje onder het gras in de bovenstaande implementatie?
Om je een hint te geven, doen we een vervolginteractie:
Precies, zoals we zien, is elke API-call een op zichzelf staande interactie. Dit betekent dat het model geen geheugen heeft van eerdere inputprompts of gegeven completions. Telkens wanneer we de functie
chatgpt_call()aanroepen, beginnen we een compleet nieuw gesprek.Dat is natuurlijk een probleem als je een chatbot wilt bouwen, want het is onmogelijk om een gesprek te voeren als het model niet onthoudt waar we het over hebben gehad. Daarom is onze volgende stap om het model bewust te maken van onze eerdere interacties.
Contextbewustzijn
Contextbewustzijn stelt chatbots in staat om op basis van een lopend gesprek te begrijpen en passend te reageren.
Door een context op te bouwen, kunnen toekomstige interacties worden gepersonaliseerd op basis van eerdere, blijft de samenhang in het gesprek behouden en worden herhalingen vermeden. Bovendien kan de gebruiker met contextbewuste chatbots proactief verduidelijkende vragen stellen of suggesties doen om misverstanden recht te zetten.
Al met al verhoogt contextbewustzijn de natuurlijkheid, effectiviteit en gebruikerservaring van chatbots. Vanaf nu verwijzen we naar de verzameling van eerdere interacties als gespreksgeschiedenis of geheugen.
De originele OpenAI API voor ChatGPT biedt al een manier om onze gespreksgeschiedenis samen met elke nieuwe prompt naar het model te sturen. Daarnaast biedt het LangChain-framework ook een manier om het geheugen van ChatGPT effectiever en kostengeoptimaliseerd te beheren.
System-, Assistant- en User-berichten begrijpen
Structuur van ChatGPT’s gespreksgeschiedenis
Op dit punt kunnen we de methode
chatgpt_call()direct gebruiken door alleen de gewenste prompt mee te geven. Als we beter naar de implementatie kijken, zien we dat de inputprompt is opgemaakt als onderdeel van demessages-lijst. Deze lijst is bedoeld om de gespreksgeschiedenis bij te houden en moet daarom op een heel specifieke manier worden geformatteerd.Laten we eens beter kijken!
Tot nu toe hebben we de berichtenlijst in
chatgpt_call()als volgt opgemaakt:De
messages-lijst slaat de gespreksgeschiedenis op als een verzameling dictionaries. Elke dictionary in de lijst staat voor een bericht in het gesprek en gebruikt twee key-valueparen.rolemet de waardeusergeeft aan dat het bericht door de gebruiker is verstuurd.contentmet de waardepromptbevat de daadwerkelijke gebruikersprompt.Dit is een heel eenvoudig voorbeeld dat slechts één interactie bevat. Hoewel de sleutel
contentaltijd ofwel de gebruikersprompt of de completion van de chatbot bevat, is de sleutelroleveel veelzijdiger.System-, Assistant- en User-rollen
De sleutel
rolegeeft de eigenaar van het bericht incontentaan. Bij ChatGPT kunnen we tot drie rollen hebben:userovereen met de daadwerkelijke gebruiker die met de chatbot interageert.assistantkomt overeen met de chatbot.systemwordt gebruikt om instructies, richtlijnen en context aan de chatbot te geven. Systemberichten helpen gebruikersinteracties te sturen, het gedrag van de chatbot te bepalen, contextuele informatie te bieden en specifieke interacties in het gesprek af te handelen. Je kunt systemberichten zien als hoog-niveau-instructies voor de chatbot, transparant voor de gebruiker.ZELFGEMAAKTE afbeelding. Interactie van de verschillende rollen in de conversatieketen bij het bouwen van een chatbot met chatGPT.
Een gespreksgeschiedenis opbouwen
We kunnen onze gespreksgeschiedenis opbouwen met gebruik van de drie rollen
user,assistantensystemin onzemessages-lijst.Gegeven onze testinteracties zou een correct geformatteerde gespreksgeschiedenis met gebruik van de drie genoemde rollen er als volgt uit kunnen zien:
We kunnen onze functie
call_chatgpt()licht aanpassen om de gespreksgeschiedenis als invoerparameter op te nemen:Laten we deze nieuwe implementatie proberen!
Mooi! We hebben het model bewust kunnen houden van onze eerdere interacties zodat we daadwerkelijk een gesprek kunnen voeren. We moeten echter nog een manier vinden om onze
messages-lijst automatisch bij te werken.Automatische gespreksgeschiedenis
We kunnen het automatisch verzamelen van berichten bereiken door onze API-callfunctie iets verder uit te werken:
Proberen maar!
En een vervolginteractie:
Nu wordt de gespreksgeschiedenis automatisch bijgewerkt. Tot slot: je kunt de gespreksgeschiedenis — en de structuur ervan — op elk moment bekijken door de lijst
messageste printen.Het LangChain-framework
Tot nu toe zullen we het erover eens zijn dat onze implementatie leidt tot een bruikbare chatbot, maar waarschijnlijk niet de meest geoptimaliseerde versie.
Het continu meesturen van elk eerder bericht en elke completion kan snel leiden tot een enorme hoeveelheid tokens, die ChatGPT allemaal moet verwerken voordat de nieuwste completion wordt teruggestuurd.
Tot nu toe hebben we
.append-operaties gebruikt om eerdere interacties te bundelen zodat de chatbot een soort geheugen heeft. Het geheugenbeheer kan echter effectiever worden gedaan met speciale pakketten zoals LangChain.LangChain is een framework voor het ontwikkelen van applicaties die worden aangedreven door taalmodellen. Omdat chatbots tegenwoordig een van de populairste toepassingen zijn, biedt LangChain een schonere implementatie om de gespreksgeschiedenis van de chatbot op te bouwen en alternatieven om die efficiënter te behandelen.
Voor meer informatie over het LangChain-framework zelf raad ik het introductieartikel Introduction to LangChain for Data Engineering & Data Applications echt aan.
Eenvoudige gespreksgeschiedenis met LangChain
In deze sectie verkennen we hoe je in plaats daarvan het LangChain-framework gebruikt om een chatbot te bouwen.
De
langchain-library fungeert als vervanging voor de hierboven gebruikteopenai-library, omdat de modulelangchain.llmsje al in staat stelt om in twee regels code met ChatGPT te communiceren:Zodra het
llm-model is geladen, importeren we het memory-object dat onze gespreksgeschiedenis zal opslaan. Voor het opslaan van elke eerdere interactie met de chatbot biedt LangChain de zogenaamdeConversationBufferMemory:Nu is het tijd om de zogenaamde
ConversationChainte importeren, een wrapper diellmenmemorygebruikt om de gebruikersprompt aan ChatGPT te voeren en de completions terug te geven:Tot slot kunnen we om een gebruikersprompt naar ChatGPT te sturen, de methode
.predictals volgt gebruiken:Laten we
verbose=Trueinstellen om te zien welke informatie het model in overweging neemt om een completion te geven. Laten we het proberen in een vervolginteractie:Schermafbeelding van de context die beschikbaar is voor ChatGPT bij het maken van een completion. Verbose-uitvoer in groen.
Controleer tot slot dat eerdere interacties perfect worden onthouden:
Schermafbeelding van de context die beschikbaar is voor ChatGPT bij het maken van een completion. Verbose-uitvoer in groen.
De gespreksgeschiedenis vullen
We kunnen extra context aan de chatbot meegeven met de methode
memory.save_context(). Zo kunnen we onze chatbot bewust maken van gewenste inhoud zonder deze informatie in een gesprek te hoeven aanreiken. In LangChain zijn de sleutelwoorden hiervoorinputenoutput. Bijvoorbeeld,Daarnaast kunnen we de geheugeninhoud op elk moment raadplegen door
print(memory.buffer)ofmemory.load_memory_variables({})uit te voeren.LangChain-geheugentypen
LangChain implementeert verschillende soorten geheugen voor ChatGPT. De hierboven gebruikte
ConversationBufferMemoryhoudt elke afzonderlijke interactie met ChatGPT bij. We hebben echter al besproken dat het prompten van ChatGPT met de volledige gespreksgeschiedenis snel kan oplopen tot een groot aantal tokens die bij elke nieuwe interactie verwerkt moeten worden.Houd er rekening mee dat ChatGPT naast een tokenlimiet per interactie ook kosten rekent op basis van het aantal tokens. Het telkens verwerken van de volledige gespreksgeschiedenis zal na verloop van tijd waarschijnlijk duur worden.
Om het continue verwerken van de gespreksgeschiedenis te voorkomen, implementeert LangChain andere geoptimaliseerde manieren om het geheugen van ChatGPT te beheren. We verkennen in de volgende sectie een van de meest geavanceerde typen.
Geavanceerde gespreksgeschiedenis met LangChain
Een geavanceerde manier om het geheugen te beheren zonder elke eerdere interactie op te slaan, is door in plaats daarvan een samenvatting van de interacties op te slaan.
Dit type geheugen is mijn favoriet, omdat het echt kan leiden tot geoptimaliseerd geheugenbeheer zonder ook maar één eerdere interactie te verliezen.
Gaan we doen!
Let er wel op dat dit geheugentype het gedefinieerde
llmgebruikt om de samenvatting van eerdere interacties te genereren.Daarnaast kan dit geheugen volledige interacties opslaan tot een maximum aantal tokens (
max_token_limit). Boven deze limiet verwerkt het de informatie van die berichten in de samenvatting.Om het te testen maken we een interactie met een groot aantal tokens. Neem de volgende
schedule:Nu hoeven we alleen nog een nieuwe conversatieketen te declareren met het
llmen hetmemory, zoals in de vorige voorbeelden.We kunnen
.predictgebruiken om ChatGPT te prompten:Schermafbeelding van de context die beschikbaar is voor ChatGPT bij het maken van een completion. Verbose-uitvoer in groen.
Zoals we zien, houdt de chatbot een samenvatting bij van de oorspronkelijke gespreksgeschiedenis, waardoor het aantal tokens dat ChatGPT bij elke vervolginteractie verwerkt, afneemt.
Dat was het! Nu kunnen we urenlang met onze geoptimaliseerde chatbot praten!
Zet
verbose=Falsevoor een prettigere vraag-en-antwoord-ervaring in je notebook.Conclusie
In dit artikel hebben we gezien hoe je een contextbewuste chatbot bouwt met het bekende ChatGPT-model.
We hebben gezien hoe het bouwen van je eigen contextbewuste chatbot kan leiden tot doorlopende interacties. Deze iteratieve aanpak zorgt voor een constante feedbacklus, waardoor je behoeften en voorkeuren van gebruikers gaandeweg in het gesprek kunt meenemen.
We hebben twee hoofdbenaderingen gezien om de gespreksgeschiedenis van de chatbot te beheren. Ten eerste met de originele ChatGPT API, wat leidt tot een functionele, native chatbot. Ten tweede met het speciale LangChain-framework en een geoptimaliseerde geheugenimplementatie.
Nu is het jouw beurt! Het is tijd om met de bouwstenen uit dit artikel een chatbot te maken die is afgestemd op jouw specifieke usecase!
Ben je geïnteresseerd in het bouwen van andere applicaties met zowel LangChain als ChatGPT, bekijk dan het webinar Building AI Applications with LangChain and GPT. Wil je snel up-to-speed komen met NLP? Bekijk dan de modules over Natural Language Processing in Python!