Skip to content

Commit

Permalink
OpenAI: TypeSpec representations of new Assistants streaming response…
Browse files Browse the repository at this point in the history
… models (Azure#28555)

* initial commit for models in support of streaming Assistants calls

* merge + pr feedback

* [OpenAI] [Assistants] PR feedback (Azure#28786)

* Adding streaming events and modified class visibilities

* Represented the alias as a union to align better with the swagger and have a class generated

* Adding chunk classes to be included on code emission

* Update specification/ai/OpenAI.Assistants/streaming/events.tsp

* Added usage models for run and runStep (Azure#28864)

* Added usage models for run and runStep

* Added added annotation

* Added warning suppresion for nullable fields

* Compiled with new models and unions

* back ported everything to a past version. Extracted SubmitToolOutputsOptions model

* re-compile

* Removed toolresources for now and added warning supressions

* Brought up to date the classes related to streaming for AssistantStreamEvent

* Making filename mandatory uploadFile operation

* Project compilation

* Re-formated definitiones according to CI instructions

* Added missing documentation

* Reverted nullability of fileName

* re-compiled

* Removed openapi v2 and v3 files generated with the placeholder version

* reformating

* Maded the stream events public to expose types and docs to users

* Made stream events publics

* remove single-use options model, merge into route params directly

* proactively add 2024-05-01-preview label

* Removed 05_01 from service version enum ... for now

* Added string type to AssistantStreamEvent

* tsp validation check

---------

Co-authored-by: Jose Alvarez <jpalvarezl@users.noreply.github.com>
Co-authored-by: Jose Alvarez <josealvar@microsoft.com>
  • Loading branch information
3 people authored and Francisco-Gamino committed Jun 5, 2024
1 parent 93315d4 commit 1fcc627
Show file tree
Hide file tree
Showing 9 changed files with 1,668 additions and 45 deletions.
56 changes: 56 additions & 0 deletions specification/ai/OpenAI.Assistants/client.tsp
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,62 @@ namespace Azure.AI.OpenAI.Assistants {

// Ensure some shared types remain public despite interaction with previously internalized details

// Ensure generator inclusion of streaming "leaf" types not yet referenced by a route

@@usage(MessageDeltaTextFileCitationAnnotation, Usage.output);
@@access(MessageDeltaTextFileCitationAnnotation, Access.public);

@@usage(MessageDeltaTextFilePathAnnotation, Usage.output);
@@access(MessageDeltaTextFilePathAnnotation, Access.public);

@@usage(MessageDeltaImageFileContent, Usage.output);
@@access(MessageDeltaImageFileContent, Access.public);

@@usage(MessageDeltaTextContent, Usage.output);
@@access(MessageDeltaTextContent, Access.public);

@@usage(RunStepDeltaMessageCreationObject, Usage.output);
@@access(RunStepDeltaMessageCreationObject, Access.public);

@@usage(RunStepDeltaFunction, Usage.output);
@@access(RunStepDeltaFunction, Access.public);

@@usage(RunStepDeltaCodeInterpreterLogOutput, Usage.output);
@@access(RunStepDeltaCodeInterpreterLogOutput, Access.public);

@@usage(RunStepDeltaCodeInterpreterImageOutputObject, Usage.output);
@@access(RunStepDeltaCodeInterpreterImageOutputObject, Access.public);

@@usage(RunStepDeltaChunk, Usage.output);
@@access(RunStepDeltaChunk, Access.public);

@@usage(MessageDeltaChunk, Usage.output);
@@access(MessageDeltaChunk, Access.public);

// Stream events : made public to expose documentation and make class casting for strongly typed languages easier

@@usage(AssistantStreamEvent, Usage.output);
@@access(AssistantStreamEvent, Access.public);

@@usage(ThreadStreamEvent, Usage.output);
@@access(ThreadStreamEvent, Access.public);

@@usage(RunStreamEvent, Usage.output);
@@access(RunStreamEvent, Access.public);

@@usage(RunStepStreamEvent, Usage.output);
@@access(RunStepStreamEvent, Access.public);

@@usage(MessageStreamEvent, Usage.output);
@@access(MessageStreamEvent, Access.public);

@@usage(ErrorEvent, Usage.output);
@@access(ErrorEvent, Access.public);

@@usage(DoneEvent, Usage.output);
@@access(DoneEvent, Access.public);

// Ensure some shared types remain public despite interaction with previously internalized details
@@access(MessageTextFilePathAnnotation, Access.public);
@@access(MessageTextFileCitationAnnotation, Access.public);
@@access(ListSortOrder, Access.public);
Expand Down
1 change: 1 addition & 0 deletions specification/ai/OpenAI.Assistants/main.tsp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import "./messages/main.tsp";
import "./runs/main.tsp";
import "./run_steps/main.tsp";
import "./files/main.tsp";
import "./streaming/events.tsp";

using TypeSpec.Http;
using TypeSpec.Versioning;
Expand Down
244 changes: 236 additions & 8 deletions specification/ai/OpenAI.Assistants/messages/models.tsp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,30 @@ model ThreadMessage {
@doc("The ID of the thread that this message belongs to.")
threadId: string;

/** The status of the message. */
@added(ServiceApiVersions.v2024_02_15_preview)
status: MessageStatus;

/** On an incomplete message, details about why the message is incomplete. */
#suppress "@azure-tools/typespec-azure-core/no-nullable" "OpenAI uses explicit nullability, distinct from optionality"
@encodedName("application/json", "incomplete_details")
@added(ServiceApiVersions.v2024_02_15_preview)
incompleteDetails: MessageIncompleteDetailsReason | null;

/** The Unix timestamp (in seconds) for when the message was completed. */
#suppress "@azure-tools/typespec-azure-core/no-nullable" "OpenAI uses explicit nullability, distinct from optionality"
@encode(DateTimeKnownEncoding.unixTimestamp, int32)
@encodedName("application/json", "completed_at")
@added(ServiceApiVersions.v2024_02_15_preview)
completedAt: utcDateTime | null;

/** The Unix timestamp (in seconds) for when the message was marked as incomplete. */
#suppress "@azure-tools/typespec-azure-core/no-nullable" "OpenAI uses explicit nullability, distinct from optionality"
@encode(DateTimeKnownEncoding.unixTimestamp, int32)
@encodedName("application/json", "incomplete_at")
@added(ServiceApiVersions.v2024_02_15_preview)
incompleteAt: utcDateTime | null;

@doc("The role associated with the assistant thread message.")
role: MessageRole;

Expand Down Expand Up @@ -119,14 +143,6 @@ model MessageTextAnnotation {

@doc("The textual content associated with this text annotation item.")
text: string;

@encodedName("application/json", "start_index")
@doc("The first text index associated with this text annotation.")
startIndex: int32;

@encodedName("application/json", "end_index")
@doc("The last text index associated with this text annotation.")
endIndex: int32;
}

// File citation annotation + details
Expand All @@ -143,6 +159,14 @@ model MessageTextFileCitationAnnotation extends MessageTextAnnotation {
Generated when the assistant uses the "retrieval" tool to search files.
""")
fileCitation: MessageTextFileCitationDetails;

@encodedName("application/json", "start_index")
@doc("The first text index associated with this text annotation.")
startIndex?: int32;

@encodedName("application/json", "end_index")
@doc("The last text index associated with this text annotation.")
endIndex?: int32;
}

@doc("A representation of a file-based text citation, as used in a file-based annotation of text thread message content.")
Expand All @@ -167,6 +191,14 @@ model MessageTextFilePathAnnotation extends MessageTextAnnotation {
@encodedName("application/json", "file_path")
@doc("A URL for the file that's generated when the assistant used the code_interpreter tool to generate a file.")
filePath: MessageTextFilePathDetails;

@encodedName("application/json", "start_index")
@doc("The first text index associated with this text annotation.")
startIndex?: int32;

@encodedName("application/json", "end_index")
@doc("The last text index associated with this text annotation.")
endIndex?: int32;
}

@doc("An encapsulation of an image file ID, as used by message image content.")
Expand Down Expand Up @@ -207,3 +239,199 @@ model MessageFile {
@doc("The ID of the message that this file is attached to.")
messageId: string;
}

/** The possible execution status values for a thread message. */
@added(ServiceApiVersions.v2024_02_15_preview)
union MessageStatus {
string,

/** A run is currently creating this message. */
inProgress: "in_progress",

/** This message is incomplete. See incomplete_details for more information. */
incomplete: "incomplete",

/** This message was successfully completed by a run. */
completed: "completed",
}

/** Information providing additional detail about a message entering an incomplete status. */
@added(ServiceApiVersions.v2024_02_15_preview)
model MessageIncompleteDetails {
/** The provided reason describing why the message was marked as incomplete. */
reason: MessageIncompleteDetailsReason;
}

/** A set of reasons describing why a message is marked as incomplete. */
@added(ServiceApiVersions.v2024_02_15_preview)
union MessageIncompleteDetailsReason {
string,

/** The run generating the message was terminated due to content filter flagging. */
contentFilter: "content_filter",

/** The run generating the message exhausted available tokens before completion. */
maxTokens: "max_tokens",

/** The run generating the message was cancelled before completion. */
runCancelled: "run_cancelled",

/** The run generating the message failed. */
runFailed: "run_failed",

/** The run generating the message expired. */
runExpired: "run_expired",
}

//
// These types are specifically used for streaming.
//

/** Represents a message delta i.e. any changed fields on a message during streaming. */
@added(ServiceApiVersions.v2024_02_15_preview)
model MessageDeltaChunk {
/** The identifier of the message, which can be referenced in API endpoints. */
id: string;

/** The object type, which is always `thread.message.delta`. */
object: "thread.message.delta";

/** The delta containing the fields that have changed on the Message. */
delta: MessageDelta;
}

/** Represents the typed 'delta' payload within a streaming message delta chunk. */
@added(ServiceApiVersions.v2024_02_15_preview)
model MessageDelta {
/** The entity that produced the message. */
role: MessageRole;

/** The content of the message as an array of text and/or images. */
content: MessageDeltaContent[];
}

/** The abstract base representation of a partial streamed message content payload. */
@discriminator("type")
@added(ServiceApiVersions.v2024_02_15_preview)
model MessageDeltaContent {
/** The index of the content part of the message. */
index: int32;

/** The type of content for this content part. */
type: string;
}

/** Represents a streamed image file content part within a streaming message delta chunk. */
@added(ServiceApiVersions.v2024_02_15_preview)
model MessageDeltaImageFileContent extends MessageDeltaContent {
/** The type of content for this content part, which is always "image_file." */
type: "image_file";

/** The image_file data. */
@encodedName("application/json", "image_file")
imageFile?: MessageDeltaImageFileContentObject;
}

/** Represents the 'image_file' payload within streaming image file content. */
@added(ServiceApiVersions.v2024_02_15_preview)
model MessageDeltaImageFileContentObject {
/** The file ID of the image in the message content. */
@encodedName("application/json", "file_id")
fileId?: string;
}

/** Represents a streamed text content part within a streaming message delta chunk. */
@added(ServiceApiVersions.v2024_02_15_preview)
model MessageDeltaTextContentObject extends MessageDeltaContent {
/** The type of content for this content part, which is always "text." */
type: "text";

/** The text content details. */
text?: MessageDeltaTextContent;
}

/** Represents the data of a streamed text content part within a streaming message delta chunk. */
@added(ServiceApiVersions.v2024_02_15_preview)
model MessageDeltaTextContent {
/** The data that makes up the text. */
value?: string;

/** Annotations for the text. */
annotations?: MessageDeltaTextAnnotation[];
}

/** The abstract base representation of a streamed text content part's text annotation. */
@discriminator("type")
@added(ServiceApiVersions.v2024_02_15_preview)
model MessageDeltaTextAnnotation {
/** The index of the annotation within a text content part. */
index: int32;

/** The type of the text content annotation. */
type: string;
}

/** Represents a streamed file citation applied to a streaming text content part. */
@added(ServiceApiVersions.v2024_02_15_preview)
model MessageDeltaTextFileCitationAnnotationObject
extends MessageDeltaTextAnnotation {
/** The type of the text content annotation, which is always "file_citation." */
type: "file_citation";

/** The file citation information. */
@encodedName("application/json", "file_citation")
fileCitation?: MessageDeltaTextFileCitationAnnotation;

/** The text in the message content that needs to be replaced */
text?: string;

/** The start index of this annotation in the content text. */
@encodedName("application/json", "start_index")
startIndex?: int32;

/** The end index of this annotation in the content text. */
@encodedName("application/json", "end_index")
endIndex?: int32;
}

/** Represents the data of a streamed file citation as applied to a streaming text content part. */
@added(ServiceApiVersions.v2024_02_15_preview)
model MessageDeltaTextFileCitationAnnotation {
/** The ID of the specific file the citation is from. */
@encodedName("application/json", "file_id")
fileId?: string;

/** The specific quote in the cited file. */
quote?: string;
}

/** Represents a streamed file path annotation applied to a streaming text content part. */
@added(ServiceApiVersions.v2024_02_15_preview)
model MessageDeltaTextFilePathAnnotationObject
extends MessageDeltaTextAnnotation {
/** The type of the text content annotation, which is always "file_path." */
type: "file_path";

/** The file path information. */
@encodedName("application/json", "file_path")
filePath?: MessageDeltaTextFilePathAnnotation;

/** The start index of this annotation in the content text. */
@encodedName("application/json", "start_index")
startIndex?: int32;

/** The end index of this annotation in the content text. */
@encodedName("application/json", "end_index")
endIndex?: int32;

/** The text in the message content that needs to be replaced */
text?: string;
}

/** Represents the data of a streamed file path annotation as applied to a streaming text content part. */
@added(ServiceApiVersions.v2024_02_15_preview)
model MessageDeltaTextFilePathAnnotation {
/** The file ID for the annotation. */
@encodedName("application/json", "file_id")
fileId?: string;
}
Loading

0 comments on commit 1fcc627

Please sign in to comment.