-
Notifications
You must be signed in to change notification settings - Fork 1
feat: add citations support #37
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 11 commits
Commits
Show all changes
13 commits
Select commit
Hold shift + click to select a range
8326e17
chore: update editorconfig
StevanFreeborn a9d0dfd
feat: initial pass at citations in request and response
StevanFreeborn d509898
chore: update editor config/fix analyzer suggestions
StevanFreeborn 5b8d88a
feat: add support for citations
StevanFreeborn 74ac1ff
fix: when serializing source use media type to deserialize to image o…
StevanFreeborn 98da138
feat: add support for citations when streaming
StevanFreeborn 0c62a7c
tests: adding missing tests for newly introduced classes
StevanFreeborn d217355
chore: run dotnet format
StevanFreeborn 68e91fc
feat: add unit tests for DocumentContent, CustomSource, PageLocationC…
StevanFreeborn 598eaaa
feat: add serialization tests for CharacterLocationCitation, Citation…
StevanFreeborn 2732ae2
tests: add additional test coverage
StevanFreeborn e351823
fix: address copilot comments
StevanFreeborn bee8fb1
docs: update README.md with citations support information [skip ci]
StevanFreeborn File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| using System.Text.Json; | ||
| using System.Text.Json.Serialization; | ||
|
|
||
| using AnthropicClient.Models; | ||
|
|
||
| namespace AnthropicClient.Json; | ||
|
|
||
| class CitationConverter : JsonConverter<Citation> | ||
| { | ||
| public override Citation Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) | ||
| { | ||
| using var jsonDocument = JsonDocument.ParseValue(ref reader); | ||
| var root = jsonDocument.RootElement; | ||
| var type = root.GetProperty("type").GetString(); | ||
| return type switch | ||
| { | ||
| CitationType.CharacterLocation => JsonSerializer.Deserialize<CharacterLocationCitation>(root.GetRawText(), options)!, | ||
| CitationType.PageLocation => JsonSerializer.Deserialize<PageLocationCitation>(root.GetRawText(), options)!, | ||
| CitationType.ContentBlockLocation => JsonSerializer.Deserialize<ContentBlockLocationCitation>(root.GetRawText(), options)!, | ||
| _ => throw new JsonException($"Unknown content type: {type}") | ||
| }; | ||
| } | ||
|
|
||
| public override void Write(Utf8JsonWriter writer, Citation value, JsonSerializerOptions options) | ||
| { | ||
| JsonSerializer.Serialize(writer, value, value.GetType(), options); | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,59 @@ | ||
| using System.Text.Json; | ||
| using System.Text.Json.Serialization; | ||
|
|
||
| using AnthropicClient.Models; | ||
|
|
||
| namespace AnthropicClient.Json; | ||
|
|
||
| class SourceConverter : JsonConverter<Source> | ||
| { | ||
| public override Source Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) | ||
| { | ||
| using var jsonDocument = JsonDocument.ParseValue(ref reader); | ||
| var root = jsonDocument.RootElement; | ||
| var type = root.GetProperty("type").GetString(); | ||
| return type switch | ||
| { | ||
| SourceType.Text => JsonSerializer.Deserialize<TextSource>(root.GetRawText(), options)!, | ||
| SourceType.Content => JsonSerializer.Deserialize<CustomSource>(root.GetRawText(), options)!, | ||
| SourceType.Base64 => DeserializeBase64Source(root, options), | ||
| _ => throw new JsonException($"Unknown content type: {type}") | ||
StevanFreeborn marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| }; | ||
| } | ||
|
|
||
| private static Source DeserializeBase64Source(JsonElement root, JsonSerializerOptions options) | ||
| { | ||
| var mediaType = root.TryGetProperty("media_type", out var mediaTypeElement) | ||
| ? mediaTypeElement.GetString() ?? throw new JsonException("Missing 'media_type' property") | ||
| : throw new JsonException("Missing 'media_type' property"); | ||
|
|
||
| var isImage = ImageType.IsValidImageType(mediaType); | ||
|
|
||
| return isImage | ||
| ? JsonSerializer.Deserialize<ImageSource>(root.GetRawText(), options)! | ||
| : JsonSerializer.Deserialize<DocumentSource>(root.GetRawText(), options)!; | ||
| } | ||
|
|
||
| public override void Write(Utf8JsonWriter writer, Source value, JsonSerializerOptions options) | ||
| { | ||
| if (value is TextSource textSource) | ||
| { | ||
| JsonSerializer.Serialize(writer, textSource, options); | ||
| return; | ||
| } | ||
|
|
||
| if (value is CustomSource customSource) | ||
| { | ||
| JsonSerializer.Serialize(writer, customSource, options); | ||
| return; | ||
| } | ||
|
|
||
| if (value is Base64Source base64Source) | ||
| { | ||
| JsonSerializer.Serialize(writer, base64Source, options); | ||
| return; | ||
| } | ||
|
|
||
| JsonSerializer.Serialize(writer, value, value.GetType(), options); | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| using System.Text.Json.Serialization; | ||
|
|
||
| using AnthropicClient.Utils; | ||
|
|
||
| namespace AnthropicClient.Models; | ||
|
|
||
| /// <summary> | ||
| /// Represents an base64 source. | ||
StevanFreeborn marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| /// </summary> | ||
| public class Base64Source : Source | ||
| { | ||
| /// <summary> | ||
| /// Gets the media type of the source. | ||
| /// </summary> | ||
| [JsonPropertyName("media_type")] | ||
| public string MediaType { get; init; } = string.Empty; | ||
|
|
||
| /// <summary> | ||
| /// Gets the data of the source. | ||
| /// </summary> | ||
| public string Data { get; init; } = string.Empty; | ||
|
|
||
| /// <summary> | ||
| /// Initializes a new instance of the <see cref="Base64Source"/> class. | ||
| /// </summary> | ||
| /// <param name="mediaType">The media type of the source.</param> | ||
| /// <param name="data">The data of the source.</param> | ||
| /// <exception cref="ArgumentException">Thrown when the media type is invalid.</exception> | ||
| /// <exception cref="ArgumentNullException">Thrown when the media type or data is null.</exception> | ||
| /// <returns>A new instance of the <see cref="Base64Source"/> class.</returns> | ||
| public Base64Source(string mediaType, string data) : base(SourceType.Base64) | ||
| { | ||
| ArgumentValidator.ThrowIfNull(mediaType, nameof(mediaType)); | ||
| ArgumentValidator.ThrowIfNull(data, nameof(data)); | ||
|
|
||
| MediaType = mediaType; | ||
| Data = data; | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| using System.Text.Json.Serialization; | ||
|
|
||
| namespace AnthropicClient.Models; | ||
|
|
||
| /// <summary> | ||
| /// Represents a citation for specific locations within text content. | ||
| /// </summary> | ||
| public class CharacterLocationCitation : Citation | ||
| { | ||
| /// <summary> | ||
| /// Gets the start character index of the citation. | ||
| /// </summary> | ||
| [JsonPropertyName("start_char_index")] | ||
| public int StartCharIndex { get; init; } | ||
|
|
||
| /// <summary> | ||
| /// Gets the end character index of the citation. | ||
| /// </summary> | ||
| [JsonPropertyName("end_char_index")] | ||
| public int EndCharIndex { get; init; } | ||
|
|
||
| /// <summary> | ||
| /// Initializes a new instance of the <see cref="CharacterLocationCitation"/> class. | ||
| /// </summary> | ||
| /// <returns>A new instance of <see cref="CharacterLocationCitation"/>.</returns> | ||
| public CharacterLocationCitation() : base(CitationType.CharacterLocation) | ||
| { | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,42 @@ | ||
| using System.Text.Json.Serialization; | ||
|
|
||
| namespace AnthropicClient.Models; | ||
|
|
||
| /// <summary> | ||
| /// Represents a citation | ||
| /// </summary> | ||
| public abstract class Citation | ||
| { | ||
| /// <summary> | ||
| /// Gets the type of the citation. | ||
| /// </summary> | ||
| public string Type { get; init; } = string.Empty; | ||
|
|
||
| /// <summary> | ||
| /// Gets the text that is cited. | ||
| /// </summary> | ||
| [JsonPropertyName("cited_text")] | ||
| public string CitedText { get; init; } = string.Empty; | ||
|
|
||
| /// <summary> | ||
| /// Gets the document index of the citation. | ||
| /// </summary> | ||
| [JsonPropertyName("document_index")] | ||
| public int DocumentIndex { get; init; } | ||
|
|
||
| /// <summary> | ||
| /// Gets the title of the document from which the citation is made. | ||
| /// </summary> | ||
| [JsonPropertyName("document_title")] | ||
| public string DocumentTitle { get; init; } = string.Empty; | ||
|
|
||
| /// <summary> | ||
| /// Initializes a new instance of the <see cref="Citation"/> class with a specified type. | ||
| /// </summary> | ||
| /// <param name="type">The type of the citation.</param> | ||
| /// <returns>A new instance of <see cref="Citation"/>.</returns> | ||
| protected Citation(string type) | ||
| { | ||
| Type = type; | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| using System.Text.Json.Serialization; | ||
|
|
||
| using AnthropicClient.Utils; | ||
|
|
||
| namespace AnthropicClient.Models; | ||
|
|
||
| /// <summary> | ||
| /// Represents a citation delta. | ||
| /// </summary> | ||
| public class CitationDelta : ContentDelta | ||
| { | ||
| /// <summary> | ||
| /// Gets the citation associated with this delta. | ||
| /// </summary> | ||
| public Citation Citation { get; init; } = new CharacterLocationCitation(); | ||
|
|
||
| [JsonConstructor] | ||
| internal CitationDelta() : base(ContentDeltaType.CitationDelta) | ||
| { | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Initializes a new instance of the <see cref="CitationDelta"/> class. | ||
| /// </summary> | ||
| /// <param name="citation">The citation to associate with this delta.</param> | ||
| /// <exception cref="ArgumentNullException">Thrown when <paramref name="citation"/> is null.</exception> | ||
| /// <returns>A new instance of <see cref="CitationDelta"/>.</returns> | ||
| public CitationDelta(Citation citation) : base(ContentDeltaType.CitationDelta) | ||
| { | ||
| ArgumentValidator.ThrowIfNull(citation, nameof(citation)); | ||
| Citation = citation; | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| namespace AnthropicClient.Models; | ||
|
|
||
| /// <summary> | ||
| /// Represents whether citations are enabled for a document. | ||
| /// </summary> | ||
| public class CitationOption | ||
| { | ||
| /// <summary> | ||
| /// Gets a value indicating whether citations are enabled for the document. | ||
| /// </summary> | ||
| public bool Enabled { get; init; } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| namespace AnthropicClient.Models; | ||
|
|
||
| /// <summary> | ||
| /// The types of citations that can be returned by the Anthropic API. | ||
| /// </summary> | ||
| public static class CitationType | ||
| { | ||
| /// <summary> | ||
| /// A citation that refers to a specific character in the text. | ||
| /// </summary> | ||
| public const string CharacterLocation = "char_location"; | ||
|
|
||
| /// <summary> | ||
| /// A citation that refers to a specific page in the text. | ||
| /// </summary> | ||
| public const string PageLocation = "page_location"; | ||
|
|
||
| /// <summary> | ||
| /// A citation that refers to a specific section in the text. | ||
| /// </summary> | ||
| public const string ContentBlockLocation = "content_block_location"; | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.