mirror of
https://github.com/microsoft/semantic-kernel.git
synced 2026-10-12 11:19:56 +00:00
### Motivation and Context
<!-- Thank you for your contribution to the semantic-kernel repo!
Please help reviewers and future users, providing the following
information:
1. Why is this change required?
2. What problem does it solve?
3. What scenario does it contribute to?
4. If it fixes an open issue, please link to the issue here.
-->
Enable deeper alignment with Open AI features: code-interpreter and
retrieval
### Description
<!-- Describe your changes, the overall approach, the underlying design.
These notes will help understanding how your code works. Thanks! -->
- Add support to enable code-interpreter and retrieval
- Add support to associated uploaded files with agent
- Files must be uploaded outside of the Agent API and then referenced by
identifier
- Added support for message citations
Known issue where Open AI API text includes citation reference and no
corresponding annocations:
```
{
"id": "msg_jCIdC8gdO5yPylbP9JMGCNO0",
"object": "thread.message",
"created_at": 1704872920,
"thread_id": "thread_BQLiJQFVFxfNH2blMROZYDQ2",
"role": "assistant",
"content": [
{
"type": "text",
"text": {
"value": "Sam Marks went on a trip from Seattle to Raleigh/Durham. According to the itinerary, Sam departed from Seattle-Tacoma International Airport (SEA) on Monday, September 11, 2023, at 10:05 AM on Alaska Airlines Flight AS 572 and arrived in Raleigh (RDU) at 06:15 PM【6†source】. Sam stayed for two nights【4†source】 and returned on Wednesday, September 13, 2023, departing from Raleigh (RDU) at 07:15 PM on Alaska Airlines Flight AS 491 and arrived back in Seattle (SEA) at 09:59 PM【7†source】.",
"annotations": []
}
}
],
"file_ids": [],
"assistant_id": "asst_2zdSRjQJCyAKdXvhqw9dNrie",
"run_id": "run_Rn5nJPncHY41nAr5VgOvPeyC",
"metadata": {}
}
```
### Contribution Checklist
<!-- Before submitting this PR, please make sure: -->
- [x] The code builds clean without any errors or warnings
- [x] The PR follows the [SK Contribution
Guidelines](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md)
and the [pre-submission formatting
script](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md#development-scripts)
raises no violations
- [x] All unit tests pass, and I have added new tests where possible
- [x] I didn't break anyone 😄
---------
Co-authored-by: Gil LaHaye <[email protected]>
169 lines
5.2 KiB
C#
169 lines
5.2 KiB
C#
// Copyright (c) Microsoft. All rights reserved.
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Threading.Tasks;
|
|
using Microsoft.SemanticKernel.Experimental.Agents;
|
|
|
|
// ReSharper disable once InconsistentNaming
|
|
/// <summary>
|
|
/// Showcase usage of code_interpreter and retrieval tools.
|
|
/// </summary>
|
|
public static class Example75_AgentTools
|
|
{
|
|
/// <summary>
|
|
/// Specific model is required that supports agents and parallel function calling.
|
|
/// Currently this is limited to Open AI hosted services.
|
|
/// </summary>
|
|
private const string OpenAIFunctionEnabledModel = "gpt-4-1106-preview";
|
|
|
|
// Track agents for clean-up
|
|
private static readonly List<IAgent> s_agents = new();
|
|
|
|
/// <summary>
|
|
/// Show how to utilize code_interpreter and retrieval tools.
|
|
/// </summary>
|
|
public static async Task RunAsync()
|
|
{
|
|
Console.WriteLine("======== Example75_AgentTools ========");
|
|
|
|
if (TestConfiguration.OpenAI.ApiKey == null)
|
|
{
|
|
Console.WriteLine("OpenAI apiKey not found. Skipping example.");
|
|
return;
|
|
}
|
|
|
|
// Run agent with 'code_interpreter' tool
|
|
await RunCodeInterpreterToolAsync();
|
|
|
|
// Run agent with 'retrieval' tool
|
|
await RunRetrievalToolAsync();
|
|
}
|
|
|
|
private static async Task RunCodeInterpreterToolAsync()
|
|
{
|
|
Console.WriteLine("======== Run:CodeInterpreterTool ========");
|
|
|
|
var builder =
|
|
new AgentBuilder()
|
|
.WithOpenAIChatCompletion(OpenAIFunctionEnabledModel, TestConfiguration.OpenAI.ApiKey)
|
|
.WithInstructions("Write only code to solve the given problem without comment.");
|
|
|
|
try
|
|
{
|
|
var defaultAgent =
|
|
Track(
|
|
await builder.BuildAsync());
|
|
|
|
var codeInterpreterAgent =
|
|
Track(
|
|
await builder.WithCodeInterpreter().BuildAsync());
|
|
|
|
await ChatAsync(
|
|
defaultAgent,
|
|
codeInterpreterAgent,
|
|
"What is the solution to `3x + 2 = 14`?",
|
|
"What is the fibinacci sequence until 101?");
|
|
}
|
|
finally
|
|
{
|
|
await Task.WhenAll(s_agents.Select(a => a.DeleteAsync()));
|
|
}
|
|
}
|
|
|
|
private static async Task RunRetrievalToolAsync()
|
|
{
|
|
Console.WriteLine("======== Run:RunRetrievalTool ========");
|
|
|
|
// REQUIRED:
|
|
//
|
|
// Use `curl` to upload document prior to running example and assign the
|
|
// identifier to `fileId`.
|
|
//
|
|
// Powershell:
|
|
// curl https://api.openai.com/v1/files `
|
|
// -H "Authorization: Bearer $Env:OPENAI_APIKEY" `
|
|
// -F purpose="assistants" `
|
|
// -F file="@Resources/travelinfo.txt"
|
|
|
|
var fileId = "<see comment>";
|
|
|
|
var defaultAgent =
|
|
await new AgentBuilder()
|
|
.WithOpenAIChatCompletion(OpenAIFunctionEnabledModel, TestConfiguration.OpenAI.ApiKey)
|
|
.BuildAsync();
|
|
|
|
var retrievalAgent =
|
|
await new AgentBuilder()
|
|
.WithOpenAIChatCompletion(OpenAIFunctionEnabledModel, TestConfiguration.OpenAI.ApiKey)
|
|
.WithRetrieval(fileId)
|
|
.BuildAsync();
|
|
|
|
try
|
|
{
|
|
await ChatAsync(
|
|
defaultAgent,
|
|
retrievalAgent,
|
|
"Where did sam go?",
|
|
"When does the flight leave Seattle?",
|
|
"What is the hotel contact info at the destination?");
|
|
}
|
|
finally
|
|
{
|
|
await Task.WhenAll(s_agents.Select(a => a.DeleteAsync()));
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Common chat loop used for: RunCodeInterpreterToolAsync and RunRetrievalToolAsync.
|
|
/// Processes each question for both "default" and "enabled" agents.
|
|
/// </summary>
|
|
private static async Task ChatAsync(
|
|
IAgent defaultAgent,
|
|
IAgent enabledAgent,
|
|
params string[] questions)
|
|
{
|
|
foreach (var question in questions)
|
|
{
|
|
Console.WriteLine("\nDEFAULT AGENT:");
|
|
await InvokeAgentAsync(defaultAgent, question);
|
|
|
|
Console.WriteLine("\nTOOL ENABLED AGENT:");
|
|
await InvokeAgentAsync(enabledAgent, question);
|
|
}
|
|
|
|
static async Task InvokeAgentAsync(IAgent agent, string question)
|
|
{
|
|
await foreach (var message in agent.InvokeAsync(question))
|
|
{
|
|
string content = message.Content;
|
|
foreach (var annotation in message.Annotations)
|
|
{
|
|
content = content.Replace(annotation.Label, string.Empty, StringComparison.Ordinal);
|
|
}
|
|
|
|
Console.WriteLine($"# {message.Role}: {content}");
|
|
|
|
if (message.Annotations.Count > 0)
|
|
{
|
|
Console.WriteLine("\n# files:");
|
|
foreach (var annotation in message.Annotations)
|
|
{
|
|
Console.WriteLine($"* {annotation.FileId}");
|
|
}
|
|
}
|
|
}
|
|
|
|
Console.WriteLine();
|
|
}
|
|
}
|
|
|
|
private static IAgent Track(IAgent agent)
|
|
{
|
|
s_agents.Add(agent);
|
|
|
|
return agent;
|
|
}
|
|
}
|