Skip to content

Commit

Permalink
fix: Fixed Generator.
Browse files Browse the repository at this point in the history
  • Loading branch information
HavenDV committed Mar 19, 2024
1 parent 9e423f4 commit 5f6b861
Show file tree
Hide file tree
Showing 16 changed files with 409 additions and 433 deletions.
7 changes: 7 additions & 0 deletions OpenAI.sln
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenAI.Generators.SnapshotT
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenAI.Constants", "src\libs\OpenAI.Constants\OpenAI.Constants.csproj", "{74A51E6E-2955-4909-A075-13D8E620FBFE}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeAsOpenApi", "src\libs\CodeAsOpenApi\CodeAsOpenApi.csproj", "{77577208-38DE-4F6E-B5E0-ECD500F7D94F}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -62,6 +64,10 @@ Global
{74A51E6E-2955-4909-A075-13D8E620FBFE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{74A51E6E-2955-4909-A075-13D8E620FBFE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{74A51E6E-2955-4909-A075-13D8E620FBFE}.Release|Any CPU.Build.0 = Release|Any CPU
{77577208-38DE-4F6E-B5E0-ECD500F7D94F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{77577208-38DE-4F6E-B5E0-ECD500F7D94F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{77577208-38DE-4F6E-B5E0-ECD500F7D94F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{77577208-38DE-4F6E-B5E0-ECD500F7D94F}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -73,6 +79,7 @@ Global
{83CBA1D2-8424-4925-9F55-BEB64C7E3EE6} = {AAA11B78-2764-4520-A97E-46AA7089A588}
{4F534836-40A3-4E75-8B71-C46CD4FBE137} = {AAA11B78-2764-4520-A97E-46AA7089A588}
{74A51E6E-2955-4909-A075-13D8E620FBFE} = {61E7E11E-4558-434C-ACE8-06316A3097B3}
{77577208-38DE-4F6E-B5E0-ECD500F7D94F} = {61E7E11E-4558-434C-ACE8-06316A3097B3}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {CED9A020-DBA5-4BE6-8096-75E528648EC1}
Expand Down
2 changes: 1 addition & 1 deletion src/libs/Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
</ItemGroup>

<PropertyGroup Label="Nuget">
<Version>2.0.0-alpha.10</Version>
<Version>2.0.0</Version>
<GeneratePackageOnBuild Condition=" '$(Configuration)' == 'Release' ">true</GeneratePackageOnBuild>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<Authors>tryAGI and contributors</Authors>
Expand Down
19 changes: 7 additions & 12 deletions src/libs/OpenAI.Generators/SourceGenerationHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -110,23 +110,18 @@ public static (string Name, string Description, Dictionary<string, object> Dicti
}}
").Inject()}
public static global::System.Collections.Generic.ICollection<global::tryAGI.OpenAI.ChatCompletionFunctions> AsFunctions(this {@interface.Name} functions)
public static global::System.Collections.Generic.ICollection<global::OpenAI.Function> AsFunctions(this {@interface.Name} functions)
{{
{@interface.Methods.Select((method, i) => $@"
var function{i} = functions.{method.Name}AsDictionary();").Inject()}
var (name{i}, description{i}, jsonNode{i}) = functions.{method.Name}AsParametersJsonNode();").Inject()}
return new global::System.Collections.Generic.List<global::tryAGI.OpenAI.ChatCompletionFunctions>
return new global::System.Collections.Generic.List<global::OpenAI.Function>
{{
{@interface.Methods.Select((_, i) => $@"
new global::tryAGI.OpenAI.ChatCompletionFunctions()
{{
Name = function{i}.Name,
Description = function{i}.Description,
Parameters = new global::tryAGI.OpenAI.ChatCompletionFunctionParameters
{{
AdditionalProperties = function{i}.Dictionary,
}},
}},
new global::OpenAI.Function(
name: name{i},
description: description{i},
parameters: jsonNode{i}),
").Inject()}
}};
}}
Expand Down
6 changes: 3 additions & 3 deletions src/libs/OpenAI/Client/Chat/Message.cs
Original file line number Diff line number Diff line change
Expand Up @@ -88,18 +88,18 @@ public Message(Tool tool, IEnumerable<Content> content)
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
public dynamic Content { get; private set; }

private List<Tool> toolCalls;
private List<Tool>? toolCalls;

/// <summary>
/// The tool calls generated by the model, such as function calls.
/// </summary>
[JsonInclude]
[JsonPropertyName("tool_calls")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public IReadOnlyList<Tool> ToolCalls
public IReadOnlyList<Tool>? ToolCalls
{
get => toolCalls;
private set => toolCalls = value.ToList();
private set => toolCalls = value?.ToList();
}

[JsonInclude]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,25 +1,26 @@
// using System.Threading;
// using System.Threading.Tasks;
// using tryAGI.OpenAI;
//
// namespace H.Ipc.Generator.IntegrationTests;
//
// [OpenAiFunctions]
// public interface IMaintenanceFunctions
// {
// [System.ComponentModel.Description("Get the tasks to extract from a contract")]
// public Task<ExtractTasksRequest> GetContractTasksAsync([System.ComponentModel.Description("The tasks extracted from the contract")] ExtractTasksRequest tasks, CancellationToken cancellationToken = default);
// }
//
// public class MaintenanceService : IMaintenanceFunctions
// {
// public Task<ExtractTasksRequest> GetContractTasksAsync(ExtractTasksRequest tasks, CancellationToken cancellationToken = default)
// {
// return Task.FromResult(tasks);
// }
// }
//
// public class ExtractTasksRequest
// {
// public string[] Tasks { get; set; }
// }
using System;
using System.Threading;
using System.Threading.Tasks;
using tryAGI.OpenAI;

namespace H.Ipc.Generator.IntegrationTests;

[OpenAiFunctions]
public interface IMaintenanceFunctions
{
[System.ComponentModel.Description("Get the tasks to extract from a contract")]
public Task<ExtractTasksRequest> GetContractTasksAsync([System.ComponentModel.Description("The tasks extracted from the contract")] ExtractTasksRequest tasks, CancellationToken cancellationToken = default);
}

public class MaintenanceService : IMaintenanceFunctions
{
public Task<ExtractTasksRequest> GetContractTasksAsync(ExtractTasksRequest tasks, CancellationToken cancellationToken = default)
{
return Task.FromResult(tasks);
}
}

public class ExtractTasksRequest
{
public string[] Tasks { get; set; } = Array.Empty<string>();
}
227 changes: 112 additions & 115 deletions src/tests/OpenAI.Generators.IntegrationTests/Tests.Functions.cs
Original file line number Diff line number Diff line change
@@ -1,131 +1,128 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text.Json;
using System.Threading.Tasks;
using OpenAI;
using OpenAI.Chat;
using OpenAI.Constants;
using tryAGI.OpenAI;

namespace H.Ipc.Generator.IntegrationTests;

[TestClass]
public partial class Tests
{
// [TestMethod]
// [Ignore]
// public async Task SimpleMethod()
// {
// var messages = new List<Message>
// {
// "You are a helpful weather assistant.".AsSystemMessage(),
// "What's the weather like today?".AsUserMessage(),
// };
//
// try
// {
// var apiKey =
// Environment.GetEnvironmentVariable("OPENAI_API_KEY") ??
// throw new AssertInconclusiveException("OPENAI_API_KEY is not set.");
// var api = new OpenAIClient(apiKey);
// var service = new WeatherService();
// var functions = service.AsFunctions();
// var result = await api.CreateChatCompletionAsync(new CreateChatCompletionRequest
// {
// Messages = messages,
// Functions = functions,
// Function_call = Function_call4.Auto,
// Model = ModelIds.Gpt35Turbo_0613,
// });
// var resultMessage = result.GetFirstChoiceMessage();
// messages.Add(resultMessage.AsRequestMessage());
//
// messages.Add("Dubai, UAE".AsUserMessage());
// result = await api.CreateChatCompletionAsync(new CreateChatCompletionRequest
// {
// Messages = messages,
// Functions = functions,
// Function_call = Function_call4.Auto,
// Model = ModelIds.Gpt35Turbo_0613,
// });
// resultMessage = result.GetFirstChoiceMessage();
// messages.Add(resultMessage.AsRequestMessage());
//
// // It's possible that the assistant will also ask you which units you want the temperature in.
// if (!string.IsNullOrWhiteSpace(resultMessage.Content))
// {
// messages.Add("celsius".AsUserMessage());
// result = await api.CreateChatCompletionAsync(new CreateChatCompletionRequest
// {
// Messages = messages,
// Functions = functions,
// Function_call = Function_call4.Auto,
// Model = ModelIds.Gpt35Turbo_0613,
// });
// resultMessage = result.GetFirstChoiceMessage();
// messages.Add(resultMessage.AsRequestMessage());
// }
//
// if (resultMessage.Function_call == null)
// {
// throw new InvalidOperationException("Expected a function call.");
// }
//
// var json = await service.CallAsync(
// functionName: resultMessage.Function_call.Name ?? string.Empty,
// argumentsAsJson: resultMessage.Function_call.Arguments ?? string.Empty);
// messages.Add(json.AsFunctionMessage(resultMessage.Function_call?.Name ?? string.Empty));
//
// result = await api.CreateChatCompletionAsync(new CreateChatCompletionRequest
// {
// Messages = messages,
// Functions = functions,
// Function_call = Function_call4.Auto,
// Model = ModelIds.Gpt35Turbo_0613,
// });
// resultMessage = result.GetFirstChoiceMessage();
// messages.Add(resultMessage.AsRequestMessage());
// }
// finally
// {
// PrintMessages(messages);
// }
// }
//
// private static void PrintMessages(List<ChatCompletionRequestMessage> messages)
// {
// foreach (var message in messages)
// {
// if (message.Function_call != null)
// {
// Console.WriteLine($"{message.Role}(FunctionCall): {message.Function_call.Name}");
// Console.WriteLine($"{message.Function_call.Arguments}");
// continue;
// }
//
// Console.WriteLine($"{message.Role}: {message.Content}");
// }
// }
//
// [TestMethod]
// public async Task Call()
// {
// var json = /* lang=json */ """
// {
// "location": "Dubai, UAE"
// }
// """;
// var result = new WeatherService().CallGetCurrentWeather(json);
//
// result.Should().Be(/* lang=json */ """
// {"location":"Dubai, UAE","temperature":22,"unit":"celsius","description":"Sunny"}
// """);
//
// var result2 = await new WeatherService().CallAsync("GetCurrentWeather", json);
// result2.Should().Be(/* lang=json */ """
// {"location":"Dubai, UAE","temperature":22,"unit":"celsius","description":"Sunny"}
// """);
// }
//
[TestMethod]
//[Ignore]
public async Task SimpleMethod()
{
var messages = new List<Message>
{
"You are a helpful weather assistant.".AsSystemMessage(),
"What's the weather like today?".AsUserMessage(),
};

try
{
var apiKey =
Environment.GetEnvironmentVariable("OPENAI_API_KEY") ??
throw new AssertInconclusiveException("OPENAI_API_KEY is not set.");
var api = new OpenAIClient(apiKey);
var service = new WeatherService();
var tools = service.AsFunctions().Select(static x => new Tool(x)).ToArray();
var result = await api.ChatEndpoint.GetCompletionAsync(new ChatRequest(
new[]
{
"You are a helpful weather assistant.".AsSystemMessage(),
"What's the weather like today?".AsUserMessage(),
},
model: ChatModels.Gpt35Turbo,
tools: tools));
var resultMessage = result.GetFirstChoiceMessage();
messages.Add(resultMessage);

messages.Add("Dubai, UAE".AsUserMessage());
result = await api.ChatEndpoint.GetCompletionAsync(new ChatRequest(
messages,
model: ChatModels.Gpt35Turbo,
tools: tools));
resultMessage = result.GetFirstChoiceMessage();
messages.Add(resultMessage);

// It's possible that the assistant will also ask you which units you want the temperature in.
if (!string.IsNullOrWhiteSpace(resultMessage.Content))
{
messages.Add("celsius".AsUserMessage());
result = await api.ChatEndpoint.GetCompletionAsync(new ChatRequest(
messages,
model: ChatModels.Gpt35Turbo,
tools: tools));
resultMessage = result.GetFirstChoiceMessage();
messages.Add(resultMessage);
}

if (resultMessage.ToolCalls.Count == 0)
{
throw new InvalidOperationException("Expected a function call.");
}

foreach (var call in resultMessage.ToolCalls)
{
var json = await service.CallAsync(
functionName: call.Function.Name,
argumentsAsJson: call.Function.Arguments.ToString());
messages.Add(json.AsFunctionMessage(call.Function.Name));
}

result = await api.ChatEndpoint.GetCompletionAsync(new ChatRequest(
messages,
model: ChatModels.Gpt35Turbo,
tools: tools));
resultMessage = result.GetFirstChoiceMessage();
messages.Add(resultMessage);
}
finally
{
PrintMessages(messages);
}
}

private static void PrintMessages(List<Message> messages)
{
foreach (var message in messages)
{
foreach (var tool in message.ToolCalls ?? Array.Empty<Tool>())
{
Console.WriteLine($"{message.Role}(FunctionCall): {tool.Function.Name}");
Console.WriteLine($"{tool.Function.Arguments}");
}

Console.WriteLine($"{message.Role}: {message.Content}");
}
}

[TestMethod]
public async Task Call()
{
var json = /* lang=json */ """
{
"location": "Dubai, UAE"
}
""";
var result = new WeatherService().CallGetCurrentWeather(json);

result.Should().Be(/* lang=json */ """
{"location":"Dubai, UAE","temperature":22,"unit":"celsius","description":"Sunny"}
""");

var result2 = await new WeatherService().CallAsync("GetCurrentWeather", json);
result2.Should().Be(/* lang=json */ """
{"location":"Dubai, UAE","temperature":22,"unit":"celsius","description":"Sunny"}
""");
}

// [TestMethod]
// [Ignore]
// public async Task UpdateCode()
Expand Down
Loading

0 comments on commit 5f6b861

Please sign in to comment.