diff --git a/.codegen.json b/.codegen.json index 111604a5..a7569349 100644 --- a/.codegen.json +++ b/.codegen.json @@ -1 +1 @@ -{ "engineHash": "4ca165c", "specHash": "9919482", "version": "1.0.0" } +{ "engineHash": "4ca165c", "specHash": "871a814", "version": "1.0.0" } diff --git a/Box.Sdk.Gen.Tests.Integration/Test/Ai/AiManagerTests.cs b/Box.Sdk.Gen.Tests.Integration/Test/Ai/AiManagerTests.cs index 6940a484..befe245a 100644 --- a/Box.Sdk.Gen.Tests.Integration/Test/Ai/AiManagerTests.cs +++ b/Box.Sdk.Gen.Tests.Integration/Test/Ai/AiManagerTests.cs @@ -18,7 +18,7 @@ public AiManagerTests() { [TestMethod] public async System.Threading.Tasks.Task TestAskAiSingleItem() { FileFull fileToAsk = await new CommonsManager().UploadNewFileAsync(); - AiResponse response = await client.Ai.CreateAiAskAsync(requestBody: new AiAsk(mode: AiAskModeField.SingleItemQa, prompt: "which direction sun rises", items: Array.AsReadOnly(new [] {new AiAskItemsField(id: fileToAsk.Id, type: AiAskItemsTypeField.File) { Content = "Sun rises in the East" }}))); + AiAskResponse response = await client.Ai.CreateAiAskAsync(requestBody: new AiAsk(mode: AiAskModeField.SingleItemQa, prompt: "which direction sun rises", items: Array.AsReadOnly(new [] {new AiAskItemsField(id: fileToAsk.Id, type: AiAskItemsTypeField.File) { Content = "Sun rises in the East" }}))); Assert.IsTrue(response.Answer.Contains("East")); Assert.IsTrue(response.CompletionReason == "done"); await client.Files.DeleteFileByIdAsync(fileId: fileToAsk.Id); @@ -28,7 +28,7 @@ public async System.Threading.Tasks.Task TestAskAiSingleItem() { public async System.Threading.Tasks.Task TestAskAiMultipleItems() { FileFull fileToAsk1 = await new CommonsManager().UploadNewFileAsync(); FileFull fileToAsk2 = await new CommonsManager().UploadNewFileAsync(); - AiResponse response = await client.Ai.CreateAiAskAsync(requestBody: new AiAsk(mode: AiAskModeField.MultipleItemQa, prompt: "Which direction sun rises?", items: Array.AsReadOnly(new [] {new AiAskItemsField(id: fileToAsk1.Id, type: AiAskItemsTypeField.File) { Content = "Earth goes around the sun" },new AiAskItemsField(id: fileToAsk2.Id, type: AiAskItemsTypeField.File) { Content = "Sun rises in the East in the morning" }}))); + AiAskResponse response = await client.Ai.CreateAiAskAsync(requestBody: new AiAsk(mode: AiAskModeField.MultipleItemQa, prompt: "Which direction sun rises?", items: Array.AsReadOnly(new [] {new AiAskItemsField(id: fileToAsk1.Id, type: AiAskItemsTypeField.File) { Content = "Earth goes around the sun" },new AiAskItemsField(id: fileToAsk2.Id, type: AiAskItemsTypeField.File) { Content = "Sun rises in the East in the morning" }}))); Assert.IsTrue(response.Answer.Contains("East")); Assert.IsTrue(response.CompletionReason == "done"); await client.Files.DeleteFileByIdAsync(fileId: fileToAsk1.Id); @@ -38,7 +38,7 @@ public async System.Threading.Tasks.Task TestAskAiMultipleItems() { [TestMethod] public async System.Threading.Tasks.Task TestAiTextGenWithDialogueHistory() { FileFull fileToAsk = await new CommonsManager().UploadNewFileAsync(); - AiResponse response = await client.Ai.CreateAiTextGenAsync(requestBody: new AiTextGen(prompt: "Parapharse the document.s", items: Array.AsReadOnly(new [] {new AiTextGenItemsField() { Id = fileToAsk.Id, Type = AiTextGenItemsTypeField.File, Content = "The Earth goes around the sun. Sun rises in the East in the morning." }})) { DialogueHistory = Array.AsReadOnly(new [] {new AiTextGenDialogueHistoryField() { Prompt = "What does the earth go around?", Answer = "The sun", CreatedAt = Utils.DateTimeFromString(dateTime: "2021-01-01T00:00:00Z") },new AiTextGenDialogueHistoryField() { Prompt = "On Earth, where does the sun rise?", Answer = "East", CreatedAt = Utils.DateTimeFromString(dateTime: "2021-01-01T00:00:00Z") }}) }); + AiResponse response = await client.Ai.CreateAiTextGenAsync(requestBody: new AiTextGen(prompt: "Parapharse the document.s", items: Array.AsReadOnly(new [] {new AiTextGenItemsField() { Id = fileToAsk.Id, Type = AiTextGenItemsTypeField.File, Content = "The Earth goes around the sun. Sun rises in the East in the morning." }})) { DialogueHistory = Array.AsReadOnly(new [] {new AiDialogueHistory() { Prompt = "What does the earth go around?", Answer = "The sun", CreatedAt = Utils.DateTimeFromString(dateTime: "2021-01-01T00:00:00Z") },new AiDialogueHistory() { Prompt = "On Earth, where does the sun rise?", Answer = "East", CreatedAt = Utils.DateTimeFromString(dateTime: "2021-01-01T00:00:00Z") }}) }); Assert.IsTrue(response.Answer.Contains("sun")); Assert.IsTrue(response.CompletionReason == "done"); await client.Files.DeleteFileByIdAsync(fileId: fileToAsk.Id); diff --git a/Box.Sdk.Gen/Managers/Ai/AiManager.cs b/Box.Sdk.Gen/Managers/Ai/AiManager.cs index 8088cf9e..cc5f002b 100644 --- a/Box.Sdk.Gen/Managers/Ai/AiManager.cs +++ b/Box.Sdk.Gen/Managers/Ai/AiManager.cs @@ -25,11 +25,11 @@ public AiManager(NetworkSession? networkSession = default) { /// /// Token used for request cancellation. /// - public async System.Threading.Tasks.Task CreateAiAskAsync(AiAsk requestBody, CreateAiAskHeaders? headers = default, System.Threading.CancellationToken? cancellationToken = null) { + public async System.Threading.Tasks.Task CreateAiAskAsync(AiAsk requestBody, CreateAiAskHeaders? headers = default, System.Threading.CancellationToken? cancellationToken = null) { headers = headers ?? new CreateAiAskHeaders(); Dictionary headersMap = Utils.PrepareParams(map: DictionaryUtils.MergeDictionaries(new Dictionary() { }, headers.ExtraHeaders)); FetchResponse response = await HttpClientAdapter.FetchAsync(string.Concat(this.NetworkSession.BaseUrls.BaseUrl, "/2.0/ai/ask"), new FetchOptions(networkSession: this.NetworkSession) { Method = "POST", Headers = headersMap, Data = SimpleJsonSerializer.Serialize(requestBody), ContentType = "application/json", ResponseFormat = "json", Auth = this.Auth, CancellationToken = cancellationToken }).ConfigureAwait(false); - return SimpleJsonSerializer.Deserialize(response.Data); + return SimpleJsonSerializer.Deserialize(response.Data); } /// diff --git a/Box.Sdk.Gen/Managers/Ai/IAiManager.cs b/Box.Sdk.Gen/Managers/Ai/IAiManager.cs index 6e15fa6f..05e5efb3 100644 --- a/Box.Sdk.Gen/Managers/Ai/IAiManager.cs +++ b/Box.Sdk.Gen/Managers/Ai/IAiManager.cs @@ -18,7 +18,7 @@ public interface IAiManager { /// /// Token used for request cancellation. /// - public System.Threading.Tasks.Task CreateAiAskAsync(AiAsk requestBody, CreateAiAskHeaders? headers = default, System.Threading.CancellationToken? cancellationToken = null) => throw new System.NotImplementedException("This method needs to be implemented by the derived class before calling it."); + public System.Threading.Tasks.Task CreateAiAskAsync(AiAsk requestBody, CreateAiAskHeaders? headers = default, System.Threading.CancellationToken? cancellationToken = null) => throw new System.NotImplementedException("This method needs to be implemented by the derived class before calling it."); /// /// Sends an AI request to supported LLMs and returns an answer specifically focused on the creation of new text. diff --git a/Box.Sdk.Gen/Schemas/AiAgentAsk/AiAgentAsk.cs b/Box.Sdk.Gen/Schemas/AiAgentAsk/AiAgentAsk.cs index 803c446e..febe890a 100644 --- a/Box.Sdk.Gen/Schemas/AiAgentAsk/AiAgentAsk.cs +++ b/Box.Sdk.Gen/Schemas/AiAgentAsk/AiAgentAsk.cs @@ -10,7 +10,7 @@ public class AiAgentAsk { /// [JsonPropertyName("type")] [JsonConverter(typeof(StringEnumConverter))] - public StringEnum? Type { get; init; } + public StringEnum Type { get; } [JsonPropertyName("long_text")] public AiAgentLongTextTool? LongText { get; init; } @@ -24,8 +24,13 @@ public class AiAgentAsk { [JsonPropertyName("basic_text_multi")] public AiAgentBasicTextToolAsk? BasicTextMulti { get; init; } - public AiAgentAsk() { - + public AiAgentAsk(AiAgentAskTypeField type = AiAgentAskTypeField.AiAgentAsk) { + Type = type; + } + + [JsonConstructorAttribute] + internal AiAgentAsk(StringEnum type) { + Type = AiAgentAskTypeField.AiAgentAsk; } } } \ No newline at end of file diff --git a/Box.Sdk.Gen/Schemas/AiAgentTextGen/AiAgentTextGen.cs b/Box.Sdk.Gen/Schemas/AiAgentTextGen/AiAgentTextGen.cs index f4f8be3b..e4df864b 100644 --- a/Box.Sdk.Gen/Schemas/AiAgentTextGen/AiAgentTextGen.cs +++ b/Box.Sdk.Gen/Schemas/AiAgentTextGen/AiAgentTextGen.cs @@ -10,13 +10,18 @@ public class AiAgentTextGen { /// [JsonPropertyName("type")] [JsonConverter(typeof(StringEnumConverter))] - public StringEnum? Type { get; init; } + public StringEnum Type { get; } [JsonPropertyName("basic_gen")] public AiAgentBasicGenTool? BasicGen { get; init; } - public AiAgentTextGen() { - + public AiAgentTextGen(AiAgentTextGenTypeField type = AiAgentTextGenTypeField.AiAgentTextGen) { + Type = type; + } + + [JsonConstructorAttribute] + internal AiAgentTextGen(StringEnum type) { + Type = AiAgentTextGenTypeField.AiAgentTextGen; } } } \ No newline at end of file diff --git a/Box.Sdk.Gen/Schemas/AiAsk/AiAsk.cs b/Box.Sdk.Gen/Schemas/AiAsk/AiAsk.cs index 5014a6b8..70a284f3 100644 --- a/Box.Sdk.Gen/Schemas/AiAsk/AiAsk.cs +++ b/Box.Sdk.Gen/Schemas/AiAsk/AiAsk.cs @@ -31,6 +31,18 @@ public class AiAsk { [JsonPropertyName("items")] public IReadOnlyList Items { get; } + /// + /// The history of prompts and answers previously passed to the LLM. This provides additional context to the LLM in generating the response. + /// + [JsonPropertyName("dialogue_history")] + public IReadOnlyList? DialogueHistory { get; init; } + + /// + /// A flag to indicate whether citations should be returned. + /// + [JsonPropertyName("include_citations")] + public bool? IncludeCitations { get; init; } + [JsonPropertyName("ai_agent")] public AiAgentAsk? AiAgent { get; init; } diff --git a/Box.Sdk.Gen/Schemas/AiAskResponse/AiAskResponse.cs b/Box.Sdk.Gen/Schemas/AiAskResponse/AiAskResponse.cs new file mode 100644 index 00000000..544a9a44 --- /dev/null +++ b/Box.Sdk.Gen/Schemas/AiAskResponse/AiAskResponse.cs @@ -0,0 +1,39 @@ +using Box.Sdk.Gen; +using System; +using System.Collections.ObjectModel; +using System.Collections.Generic; +using System.Text.Json.Serialization; +using Box.Sdk.Gen.Schemas; + +namespace Box.Sdk.Gen.Schemas { + public class AiAskResponse { + /// + /// The answer provided by the LLM. + /// + [JsonPropertyName("answer")] + public string Answer { get; } + + /// + /// The ISO date formatted timestamp of when the answer to the prompt was created. + /// + [JsonPropertyName("created_at")] + public System.DateTimeOffset CreatedAt { get; } + + /// + /// The reason the response finishes. + /// + [JsonPropertyName("completion_reason")] + public string? CompletionReason { get; init; } + + /// + /// The citations of the LLM's answer reference. + /// + [JsonPropertyName("citations")] + public IReadOnlyList? Citations { get; init; } + + public AiAskResponse(string answer, System.DateTimeOffset createdAt) { + Answer = answer; + CreatedAt = createdAt; + } + } +} \ No newline at end of file diff --git a/Box.Sdk.Gen/Schemas/AiCitation/AiCitation.cs b/Box.Sdk.Gen/Schemas/AiCitation/AiCitation.cs new file mode 100644 index 00000000..7f29d95b --- /dev/null +++ b/Box.Sdk.Gen/Schemas/AiCitation/AiCitation.cs @@ -0,0 +1,36 @@ +using Box.Sdk.Gen; +using System.Text.Json.Serialization; +using Box.Sdk.Gen.Internal; + +namespace Box.Sdk.Gen.Schemas { + public class AiCitation { + /// + /// The specific content from where the answer was referenced. + /// + [JsonPropertyName("content")] + public string? Content { get; init; } + + /// + /// The id of the item. + /// + [JsonPropertyName("id")] + public string? Id { get; init; } + + /// + /// The type of the item. + /// + [JsonPropertyName("type")] + [JsonConverter(typeof(StringEnumConverter))] + public StringEnum? Type { get; init; } + + /// + /// The name of the item. + /// + [JsonPropertyName("name")] + public string? Name { get; init; } + + public AiCitation() { + + } + } +} \ No newline at end of file diff --git a/Box.Sdk.Gen/Schemas/AiCitation/AiCitationTypeField.cs b/Box.Sdk.Gen/Schemas/AiCitation/AiCitationTypeField.cs new file mode 100644 index 00000000..5533020c --- /dev/null +++ b/Box.Sdk.Gen/Schemas/AiCitation/AiCitationTypeField.cs @@ -0,0 +1,8 @@ +using System.ComponentModel; + +namespace Box.Sdk.Gen.Schemas { + public enum AiCitationTypeField { + [Description("file")] + File + } +} \ No newline at end of file diff --git a/Box.Sdk.Gen/Schemas/AiTextGen/AiTextGenDialogueHistoryField.cs b/Box.Sdk.Gen/Schemas/AiDialogueHistory/AiDialogueHistory.cs similarity index 83% rename from Box.Sdk.Gen/Schemas/AiTextGen/AiTextGenDialogueHistoryField.cs rename to Box.Sdk.Gen/Schemas/AiDialogueHistory/AiDialogueHistory.cs index a5097498..d274f90b 100644 --- a/Box.Sdk.Gen/Schemas/AiTextGen/AiTextGenDialogueHistoryField.cs +++ b/Box.Sdk.Gen/Schemas/AiDialogueHistory/AiDialogueHistory.cs @@ -1,10 +1,8 @@ using Box.Sdk.Gen; using System.Text.Json.Serialization; -using Box.Sdk.Gen.Internal; -using Box.Sdk.Gen.Schemas; namespace Box.Sdk.Gen.Schemas { - public class AiTextGenDialogueHistoryField { + public class AiDialogueHistory { /// /// The prompt previously provided by the client and answered by the LLM. /// @@ -23,7 +21,7 @@ public class AiTextGenDialogueHistoryField { [JsonPropertyName("created_at")] public System.DateTimeOffset? CreatedAt { get; init; } - public AiTextGenDialogueHistoryField() { + public AiDialogueHistory() { } } diff --git a/Box.Sdk.Gen/Schemas/AiTextGen/AiTextGen.cs b/Box.Sdk.Gen/Schemas/AiTextGen/AiTextGen.cs index eb8c1517..61efebba 100644 --- a/Box.Sdk.Gen/Schemas/AiTextGen/AiTextGen.cs +++ b/Box.Sdk.Gen/Schemas/AiTextGen/AiTextGen.cs @@ -28,7 +28,7 @@ public class AiTextGen { /// The history of prompts and answers previously passed to the LLM. This provides additional context to the LLM in generating the response. /// [JsonPropertyName("dialogue_history")] - public IReadOnlyList? DialogueHistory { get; init; } + public IReadOnlyList? DialogueHistory { get; init; } [JsonPropertyName("ai_agent")] public AiAgentTextGen? AiAgent { get; init; } diff --git a/docs/Ai.md b/docs/Ai.md index 97e488c9..bfd15be2 100644 --- a/docs/Ai.md +++ b/docs/Ai.md @@ -31,7 +31,7 @@ await client.Ai.CreateAiAskAsync(requestBody: new AiAsk(mode: AiAskModeField.Mul ### Returns -This function returns a value of type `AiResponse`. +This function returns a value of type `AiAskResponse`. A successful response including the answer from the LLM. @@ -47,7 +47,7 @@ See the endpoint docs at ``` -await client.Ai.CreateAiTextGenAsync(requestBody: new AiTextGen(prompt: "Parapharse the document.s", items: Array.AsReadOnly(new [] {new AiTextGenItemsField() { Id = fileToAsk.Id, Type = AiTextGenItemsTypeField.File, Content = "The Earth goes around the sun. Sun rises in the East in the morning." }})) { DialogueHistory = Array.AsReadOnly(new [] {new AiTextGenDialogueHistoryField() { Prompt = "What does the earth go around?", Answer = "The sun", CreatedAt = Utils.DateTimeFromString(dateTime: "2021-01-01T00:00:00Z") },new AiTextGenDialogueHistoryField() { Prompt = "On Earth, where does the sun rise?", Answer = "East", CreatedAt = Utils.DateTimeFromString(dateTime: "2021-01-01T00:00:00Z") }}) }); +await client.Ai.CreateAiTextGenAsync(requestBody: new AiTextGen(prompt: "Parapharse the document.s", items: Array.AsReadOnly(new [] {new AiTextGenItemsField() { Id = fileToAsk.Id, Type = AiTextGenItemsTypeField.File, Content = "The Earth goes around the sun. Sun rises in the East in the morning." }})) { DialogueHistory = Array.AsReadOnly(new [] {new AiDialogueHistory() { Prompt = "What does the earth go around?", Answer = "The sun", CreatedAt = Utils.DateTimeFromString(dateTime: "2021-01-01T00:00:00Z") },new AiDialogueHistory() { Prompt = "On Earth, where does the sun rise?", Answer = "East", CreatedAt = Utils.DateTimeFromString(dateTime: "2021-01-01T00:00:00Z") }}) }); ``` ### Arguments