namespace AIStudio.Provider.OpenAI; /// /// Represents a line of a chat completion annotation stream. /// /// The unique identifier of the chat completion. /// The type of object returned, typically "chat.completion". /// The creation timestamp of the chat completion in Unix epoch format. /// The model used for the chat completion. /// The system fingerprint associated with the chat completion. /// The list of choices returned in the chat completion. public record ChatCompletionAnnotationStreamLine(string Id, string Object, uint Created, string Model, string SystemFingerprint, IList Choices) : IAnnotationStreamLine { #region Implementation of IAnnotationStreamLine /// public bool ContainsSources() => this.Choices.Any(choice => choice.Delta.Annotations is not null && choice.Delta.Annotations.Any(annotation => annotation is not AnnotatingUnknown)); /// public IList GetSources() { var sources = new List(); foreach (var choice in this.Choices) { if (choice.Delta.Annotations is null) continue; // Iterate through all annotations: foreach (var annotation in choice.Delta.Annotations) { // Check if the annotation is of the expected type and extract the source information: if (annotation is ChatCompletionAnnotatingURL urlAnnotation) sources.Add(new Source(urlAnnotation.UrlCitation.Title, urlAnnotation.UrlCitation.URL)); // // Check for the unexpected annotation type of the Responses API. // // This seems weird at first. But there are two possibilities why this could happen: // - Anyone of the open source providers such as ollama, LM Studio, etc. could // implement & use the Responses API data structures for annotations in their // chat completion endpoint. // // - Our custom JSON converter checks for the Responses API data type first. If it // fails, it checks for the chat completion API data type. So, when the Responses // API data type is valid, it will be deserialized into that type, even though // we are calling the chat completion endpoint. // if (annotation is ResponsesAnnotatingUrlCitationData citationData) sources.Add(new Source(citationData.Title, citationData.URL)); } } return sources; } #endregion }