Chatgeschiedenis
Het chatgeschiedenisobject wordt gebruikt om een record van berichten in een chatsessie bij te houden. Het wordt gebruikt voor het opslaan van berichten van verschillende auteurs, zoals gebruikers, assistenten, hulpprogramma's of het systeem. Als primair mechanisme voor het verzenden en ontvangen van berichten is het chatgeschiedenisobject essentieel voor het onderhouden van context en continuïteit in een gesprek.
Een chatgeschiedenisobject maken
Een chatgeschiedenisobject is een lijst onder de schermen, zodat u eenvoudig berichten kunt maken en eraan kunt toevoegen.
using Microsoft.SemanticKernel.ChatCompletion;
// Create a chat history object
ChatHistory chatHistory = [];
chatHistory.AddSystemMessage("You are a helpful assistant.");
chatHistory.AddUserMessage("What's available to order?");
chatHistory.AddAssistantMessage("We have pizza, pasta, and salad available to order. What would you like to order?");
chatHistory.AddUserMessage("I'd like to have the first option, please.");
# Create a chat history object
chat_history = ChatHistory()
chat_history.add_system_message("You are a helpful assistant.")
chat_history.add_user_message("What's available to order?")
chat_history.add_assistant_message("We have pizza, pasta, and salad available to order. What would you like to order?")
chat_history.add_user_message("I'd like to have the first option, please.")
import com.microsoft.semantickernel.services.chatcompletion.ChatHistory;
// Create a chat history object
ChatHistory chatHistory = new ChatHistory();
chatHistory.addSystemMessage("You are a helpful assistant.");
chatHistory.addUserMessage("What's available to order?");
chatHistory.addAssistantMessage("We have pizza, pasta, and salad available to order. What would you like to order?");
chatHistory.addUserMessage("I'd like to have the first option, please.");
Uitgebreidere berichten toevoegen aan een chatgeschiedenis
De eenvoudigste manier om berichten toe te voegen aan een chatgeschiedenisobject is door de bovenstaande methoden te gebruiken. U kunt echter ook handmatig berichten toevoegen door een nieuw ChatMessage
object te maken. Hiermee kunt u aanvullende informatie opgeven, zoals namen en afbeeldingen.
using Microsoft.SemanticKernel.ChatCompletion;
// Add system message
chatHistory.Add(
new() {
Role = AuthorRole.System,
Content = "You are a helpful assistant"
}
);
// Add user message with an image
chatHistory.Add(
new() {
Role = AuthorRole.User,
AuthorName = "Laimonis Dumins",
Items = [
new TextContent { Text = "What available on this menu" },
new ImageContent { Uri = new Uri("https://example.com/menu.jpg") }
]
}
);
// Add assistant message
chatHistory.Add(
new() {
Role = AuthorRole.Assistant,
AuthorName = "Restaurant Assistant",
Content = "We have pizza, pasta, and salad available to order. What would you like to order?"
}
);
// Add additional message from a different user
chatHistory.Add(
new() {
Role = AuthorRole.User,
AuthorName = "Ema Vargova",
Content = "I'd like to have the first option, please."
}
);
from semantic_kernel.contents.chat_history import ChatHistory
from semantic_kernel.contents import ChatMessageContent, TextContent, ImageContent
from semantic_kernel.contents.utils.author_role import AuthorRole
# Add system message
chat_history.add_message(
ChatMessage(
role=AuthorRole.System,
content="You are a helpful assistant"
)
)
# Add user message with an image
chat_history.add_message(
ChatMessageContent(
role=AuthorRole.USER,
name="Laimonis Dumins",
items=[
TextContent(text="What available on this menu"),
ImageContent(uri="https://example.com/menu.jpg")
]
)
)
# Add assistant message
chat_history.add_message(
ChatMessageContent(
role=AuthorRole.ASSISTANT,
name="Restaurant Assistant",
content="We have pizza, pasta, and salad available to order. What would you like to order?"
)
)
# Add additional message from a different user
chat_history.add_message(
ChatMessageContent(
role=AuthorRole.USER,
name="Ema Vargova",
content="I'd like to have the first option, please."
)
)
import com.microsoft.semantickernel.services.chatcompletion.message.ChatMessageImageContent;
import com.microsoft.semantickernel.services.chatcompletion.message.ChatMessageTextContent;
// Add system message
chatHistory.addSystemMessage(
"You are a helpful assistant"
);
// Add user message with an image
chatHistory.addUserMessage(
"What available on this menu"
);
chatHistory.addMessage(
ChatMessageImageContent.builder()
.withImageUrl("https://example.com/menu.jpg")
.build()
);
// Add assistant message
chatHistory.addAssistantMessage(
"We have pizza, pasta, and salad available to order. What would you like to order?"
);
// Add additional message from a different user
chatHistory.addUserMessage(
"I'd like to have the first option, please."
);
Functie-aanroepen simuleren
Naast gebruikers-, assistent- en systeemrollen kunt u ook berichten uit de functie hulpprogramma toevoegen om functieaanroepen te simuleren. Dit is handig voor het leren van ai over het gebruik van invoegtoepassingen en het bieden van extra context aan het gesprek.
Als u bijvoorbeeld informatie wilt injecteren over de huidige gebruiker in de chatgeschiedenis zonder dat de gebruiker de informatie hoeft op te geven of de LLM-tijd te vragen, kunt u de functie van het hulpprogramma gebruiken om de informatie rechtstreeks op te geven.
Hieronder ziet u een voorbeeld van hoe we allergieën van gebruikers aan de assistent kunnen bieden door een functieaanroep naar de User
invoegtoepassing te simuleren.
Tip
Gesimuleerde functieaanroepen zijn met name handig voor het verstrekken van details over de huidige gebruiker(en). De LLM's van vandaag zijn getraind om bijzonder gevoelig te zijn voor gebruikersgegevens. Zelfs als u gebruikersgegevens in een systeembericht opgeeft, kan de LLM er nog steeds voor kiezen om deze te negeren. Als u het opgeeft via een gebruikersbericht of hulpprogrammabericht, is de LLM waarschijnlijker dat deze wordt gebruikt.
// Add a simulated function call from the assistant
chatHistory.Add(
new() {
Role = AuthorRole.Assistant,
Items = [
new FunctionCallContent(
functionName: "get_user_allergies",
pluginName: "User",
id: "0001",
arguments: new () { {"username", "laimonisdumins"} }
),
new FunctionCallContent(
functionName: "get_user_allergies",
pluginName: "User",
id: "0002",
arguments: new () { {"username", "emavargova"} }
)
]
}
);
// Add a simulated function results from the tool role
chatHistory.Add(
new() {
Role = AuthorRole.Tool,
Items = [
new FunctionResultContent(
functionName: "get_user_allergies",
pluginName: "User",
id: "0001",
result: "{ \"allergies\": [\"peanuts\", \"gluten\"] }"
)
]
}
);
chatHistory.Add(
new() {
Role = AuthorRole.Tool,
Items = [
new FunctionResultContent(
functionName: "get_user_allergies",
pluginName: "User",
id: "0002",
result: "{ \"allergies\": [\"dairy\", \"soy\"] }"
)
]
}
);
from semantic_kernel.contents import ChatMessageContent, FunctionCallContent, FunctionResultContent
# Add a simulated function call from the assistant
chat_history.add_message(
ChatMessageContent(
role=AuthorRole.ASSISTANT,
items=[
FunctionCallContent(
name="get_user_allergies-User",
id="0001",
arguments=str({"username": "laimonisdumins"})
),
FunctionCallContent(
name="get_user_allergies-User",
id="0002",
arguments=str({"username": "emavargova"})
)
]
)
)
# Add a simulated function results from the tool role
chat_history.add_message(
ChatMessageContent(
role=AuthorRole.TOOL,
items=[
FunctionResultContent(
name="get_user_allergies-User",
id="0001",
result="{ \"allergies\": [\"peanuts\", \"gluten\"] }"
)
]
)
)
chat_history.add_message(
ChatMessageContent(
role=AuthorRole.TOOL,
items=[
FunctionResultContent(
name="get_user_allergies-User",
id="0002",
result="{ \"allergies\": [\"dairy\", \"gluten\"] }"
)
]
)
)
This functionality is not supported in the current version of Semantic Kernel for Java.
Belangrijk
Bij het simuleren van de resultaten van het hulpprogramma moet u altijd de id
functie-aanroep opgeven waarop het resultaat overeenkomt. Dit is belangrijk voor de AI om inzicht te hebben in de context van het resultaat. Sommige LLM's, zoals OpenAI, veroorzaken een fout als het id
ontbreekt of als de id
niet overeenkomt met een functieaanroep.
Een chatgeschiedenisobject controleren
Wanneer u een chatgeschiedenisobject doorgeeft aan een chat-voltooiingsservice waarvoor automatisch functieaanroepen zijn ingeschakeld, wordt het chatgeschiedenisobject zodanig gemanipuleerd dat het de functieaanroepen en resultaten bevat. Hierdoor hoeft u deze berichten niet handmatig toe te voegen aan het chatgeschiedenisobject en kunt u ook het chatgeschiedenisobject inspecteren om de functie-aanroepen en resultaten te bekijken.
U moet echter nog steeds de uiteindelijke berichten toevoegen aan het chatgeschiedenisobject. Hieronder ziet u een voorbeeld van hoe u het chatgeschiedenisobject kunt inspecteren om de functieaanroepen en resultaten te bekijken.
using Microsoft.SemanticKernel.ChatCompletion;
ChatHistory chatHistory = [
new() {
Role = AuthorRole.User,
Content = "Please order me a pizza"
}
];
// Get the current length of the chat history object
int currentChatHistoryLength = chatHistory.Count;
// Get the chat message content
ChatMessageContent results = await chatCompletionService.GetChatMessageContentAsync(
chatHistory,
kernel: kernel
);
// Get the new messages added to the chat history object
for (int i = currentChatHistoryLength; i < chatHistory.Count; i++)
{
Console.WriteLine(chatHistory[i]);
}
// Print the final message
Console.WriteLine(results);
// Add the final message to the chat history object
chatHistory.Add(results);
from semantic_kernel.contents import ChatMessageContent
chat_history = ChatHistory([
ChatMessageContent(
role=AuthorRole.USER,
content="Please order me a pizza"
)
])
# Get the current length of the chat history object
current_chat_history_length = len(chat_history)
# Get the chat message content
results = await chat_completion.get_chat_message_content(
chat_history=history,
settings=execution_settings,
kernel=kernel,
)
# Get the new messages added to the chat history object
for i in range(current_chat_history_length, len(chat_history)):
print(chat_history[i])
# Print the final message
print(results)
# Add the final message to the chat history object
chat_history.add_message(results)
import com.microsoft.semantickernel.services.chatcompletion.ChatHistory;
ChatHistory chatHistory = new ChatHistory();
chatHistory.addUserMessage("Please order me a pizza");
// Get the chat message content
List<ChatMessageContent> results = chatCompletionService.getChatMessageContentsAsync(
chatHistory,
kernel,
null
).block();
results.forEach(result -> System.out.println(result.getContent());
// Get the new messages added to the chat history object. By default,
// the ChatCompletionService returns new messages only.
chatHistory.addAll(results);
Chatgeschiedenis verminderen
Het beheren van de chatgeschiedenis is essentieel voor het onderhouden van contextbewuste gesprekken en het garanderen van efficiënte prestaties. Naarmate een gesprek vordert, kan het geschiedenisobject groter worden dan de grenzen van het contextvenster van een model, wat van invloed is op de responskwaliteit en het vertragen van de verwerking. Een gestructureerde benadering om de chatgeschiedenis te verminderen zorgt ervoor dat de meest relevante informatie beschikbaar blijft zonder onnodige overhead.
Waarom chatgeschiedenis verminderen?
- Prestatieoptimalisatie: de verwerkingstijd voor grote chatgeschiedenissen wordt verhoogd. Door hun grootte te verkleinen, kunnen snelle en efficiënte interacties worden onderhouden.
- Contextvensterbeheer: taalmodellen hebben een vast contextvenster. Wanneer de geschiedenis deze limiet overschrijdt, gaan oudere berichten verloren. Het beheren van de chatgeschiedenis zorgt ervoor dat de belangrijkste context toegankelijk blijft.
- Geheugenefficiëntie: In omgevingen met beperkte resources, zoals mobiele toepassingen of ingesloten systemen, kan een niet-gebonden chatgeschiedenis leiden tot overmatig geheugengebruik en trage prestaties.
- Privacy en beveiliging: het behouden van onnodige gespreksgeschiedenis verhoogt het risico op het blootstellen van gevoelige informatie. Een gestructureerd reductieproces minimaliseert het bewaren van gegevens terwijl relevante context behouden blijft.
Strategieën voor het verminderen van chatgeschiedenis
Verschillende benaderingen kunnen worden gebruikt om de chatgeschiedenis beheersbaar te houden en essentiële informatie te behouden:
- Afkapping: de oudste berichten worden verwijderd wanneer de geschiedenis een vooraf gedefinieerde limiet overschrijdt, zodat alleen recente interacties worden bewaard.
- Samenvatting: Oudere berichten worden samengevat in een samenvatting, waarbij belangrijke details behouden blijven terwijl het aantal opgeslagen berichten wordt verminderd.
- Op token gebaseerd: Op tokens gebaseerde reductie zorgt ervoor dat de chatgeschiedenis binnen de tokenlimiet van een model blijft door het totale aantal token te meten en oudere berichten te verwijderen of samen te vatten wanneer de limiet wordt overschreden.
Een Reducer voor chatgeschiedenis automatiseert deze strategieën door de grootte van de geschiedenis te evalueren en te verminderen op basis van configureerbare parameters zoals het aantal doelen (het gewenste aantal berichten dat moet worden bewaard) en het aantal drempelwaarden (het punt waarop vermindering wordt geactiveerd). Door deze reductietechnieken te integreren, kunnen chattoepassingen responsief en performant blijven zonder de gesprekscontext in gevaar te brengen.
In de .NET-versie van Semantic Kernel wordt de abstractie Chatgeschiedenis Reducer gedefinieerd door de IChatHistoryReducer
-interface:
namespace Microsoft.SemanticKernel.ChatCompletion;
[Experimental("SKEXP0001")]
public interface IChatHistoryReducer
{
Task<IEnumerable<ChatMessageContent>?> ReduceAsync(IReadOnlyList<ChatMessageContent> chatHistory, CancellationToken cancellationToken = default);
}
Met deze interface kunnen aangepaste implementaties voor het verminderen van chatgeschiedenis worden gebruikt.
Daarnaast biedt Semantische kernel ingebouwde reducers:
-
ChatHistoryTruncationReducer
: kapt de chatgeschiedenis af naar een opgegeven grootte en verwijdert de verwijderde berichten. De vermindering wordt geactiveerd wanneer de lengte van de chatgeschiedenis de limiet overschrijdt. -
ChatHistorySummarizationReducer
- kapt de chatgeschiedenis af, vat de verwijderde berichten samen en voegt het overzicht weer toe aan de chatgeschiedenis als één bericht.
Beide reducers bewaren altijd systeemberichten om essentiële context voor het model te behouden.
In het volgende voorbeeld ziet u hoe u alleen de laatste twee gebruikersberichten bewaart terwijl de gespreksstroom wordt gehandhaafd:
using Microsoft.SemanticKernel.ChatCompletion;
using Microsoft.SemanticKernel.Connectors.OpenAI;
var chatService = new OpenAIChatCompletionService(
modelId: "<model-id>",
apiKey: "<api-key>");
var reducer = new ChatHistoryTruncationReducer(targetCount: 2); // Keep system message and last user message
var chatHistory = new ChatHistory("You are a librarian and expert on books about cities");
string[] userMessages = [
"Recommend a list of books about Seattle",
"Recommend a list of books about Dublin",
"Recommend a list of books about Amsterdam",
"Recommend a list of books about Paris",
"Recommend a list of books about London"
];
int totalTokenCount = 0;
foreach (var userMessage in userMessages)
{
chatHistory.AddUserMessage(userMessage);
Console.WriteLine($"\n>>> User:\n{userMessage}");
var reducedMessages = await reducer.ReduceAsync(chatHistory);
if (reducedMessages is not null)
{
chatHistory = new ChatHistory(reducedMessages);
}
var response = await chatService.GetChatMessageContentAsync(chatHistory);
chatHistory.AddAssistantMessage(response.Content!);
Console.WriteLine($"\n>>> Assistant:\n{response.Content!}");
if (response.InnerContent is OpenAI.Chat.ChatCompletion chatCompletion)
{
totalTokenCount += chatCompletion.Usage?.TotalTokenCount ?? 0;
}
}
Console.WriteLine($"Total Token Count: {totalTokenCount}");
Meer voorbeelden vindt u in de Semantische kernel opslagplaats.
In deze sectie behandelen we de implementatiedetails van het verminderen van chatgeschiedenis in Python. De aanpak omvat het maken van een ChatHistoryReducer die naadloos kan worden geïntegreerd met het ChatHistory-object, zodat deze kan worden gebruikt en doorgegeven waar een chatgeschiedenis vereist is.
- Integratie: In Python is de
ChatHistoryReducer
ontworpen als een subklasse van hetChatHistory
-object. Met deze overerving kan de reducer worden uitgewisseld met standaardinstances van chatgeschiedenis. - Reductielogica: gebruikers kunnen de methode
reduce
aanroepen in het chatgeschiedenisobject. De reducer evalueert of het huidige aantal berichten groter is dantarget_count
plusthreshold_count
(indien ingesteld). Als dit het geval is, wordt de geschiedenis gereduceerd tottarget_count
door afkapping of samenvatting. - Configuratie: Het reductiegedrag kan worden geconfigureerd via parameters zoals
target_count
(het gewenste aantal berichten dat moet worden bewaard) en threshold_count (het aantal berichten dat het reductieproces activeert).
De ondersteunde Semantic Kernel Python-geschiedenis reducers zijn ChatHistorySummarizationReducer
en ChatHistoryTruncationReducer
. Als onderdeel van de reducerconfiguratie kan auto_reduce
worden ingeschakeld om geschiedenisreductie automatisch toe te passen wanneer deze wordt gebruikt met add_message_async
, zodat de chatgeschiedenis binnen de geconfigureerde limieten blijft.
In het volgende voorbeeld ziet u hoe u ChatHistoryTruncationReducer gebruikt om alleen de laatste twee berichten te behouden terwijl de gespreksstroom behouden blijft.
import asyncio
from semantic_kernel.connectors.ai.open_ai import AzureChatCompletion
from semantic_kernel.contents import ChatHistoryTruncationReducer
from semantic_kernel.kernel import Kernel
async def main():
kernel = Kernel()
kernel.add_service(AzureChatCompletion())
# Keep the last two messages
truncation_reducer = ChatHistoryTruncationReducer(
target_count=2,
)
truncation_reducer.add_system_message("You are a helpful chatbot.")
is_reduced = False
while True:
user_input = input("User:> ")
if user_input.lower() == "exit":
print("\n\nExiting chat...")
break
is_reduced = await truncation_reducer.reduce()
if is_reduced:
print(f"@ History reduced to {len(truncation_reducer.messages)} messages.")
response = await kernel.invoke_prompt(
prompt="{{$chat_history}}{{$user_input}}", user_input=user_input, chat_history=truncation_reducer
)
if response:
print(f"Assistant:> {response}")
truncation_reducer.add_user_message(str(user_input))
truncation_reducer.add_message(response.value[0])
if is_reduced:
for msg in truncation_reducer.messages:
print(f"{msg.role} - {msg.content}\n")
print("\n")
if __name__ == "__main__":
asyncio.run(main())
Chatgeschiedenisreductie is momenteel niet beschikbaar in Java.
Volgende stappen
Nu u weet hoe u een chatgeschiedenisobject maakt en beheert, vindt u meer informatie over het aanroepen van functies in het onderwerp Functie-aanroepen .