Una simple biblioteca de clientes C# .NET para OpenAI para usar a través de su API RESTFUL. Desarrollado de forma independiente, esta no es una biblioteca oficial y no estoy afiliado a OpenAI. Se requiere una cuenta API de OpenAI.
Originalmente bifurcado de OpenAI-API-Dotnet. Más contexto en el blog de Roger Pincombe.
Instale el paquete OpenAI-DotNet desde Nuget. Así es como a través de la línea de comandos:
PowerShell:
Install-Package OpenAI-DotNet
Dotnet:
dotnet add package OpenAI-DotNet
¿Busca usar OpenAI-Dotnet en el motor de un juego Unity? Echa un vistazo a nuestro paquete Unity en OpenUpm:
¡Mira nuestros nuevos documentos de API!
https://rageagainstthepixel.github.io/openai-dotnet
Hay 3 formas de proporcionar sus claves API, en orden de precedencia:
Advertencia
Recomendamos usar las variables de entorno para cargar la tecla API en lugar de codificarla en su fuente. No se recomienda usar este método en producción, sino solo para aceptar las credenciales de los usuarios, las pruebas locales y los escenarios de inicio rápido.
Advertencia
Recomendamos usar las variables de entorno para cargar la tecla API en lugar de codificarla en su fuente. No se recomienda usar este método en producción, sino solo para aceptar las credenciales de los usuarios, las pruebas locales y los escenarios de inicio rápido.
using var api = new OpenAIClient ( " sk-apiKey " ) ; O crear un objeto OpenAIAuthentication manualmente
using var api = new OpenAIClient ( new OpenAIAuthentication ( " sk-apiKey " , " org-yourOrganizationId " , " proj_yourProjectId " ) ) ; Intenta cargar las teclas API desde un archivo de configuración, de forma predeterminada .openai en el directorio actual, atravesando opcionalmente el árbol del directorio o en el directorio de inicio del usuario.
Para crear un archivo de configuración, cree un nuevo archivo de texto llamado .openai y contenga la línea:
Nota
Las entradas de ID de organización y proyecto son opcionales.
{
"apiKey" : " sk-aaaabbbbbccccddddd " ,
"organizationId" : " org-yourOrganizationId " ,
"projectId" : " proj_yourProjectId "
}OPENAI_API_KEY=sk-aaaabbbbbccccddddd
OPENAI_ORGANIZATION_ID=org-yourOrganizationId
OPENAI_PROJECT_ID=proj_yourProjectId También puede cargar el archivo de configuración directamente con la ruta conocida llamando a métodos estáticos en OpenAIAuthentication :
.openai predeterminada en el directorio especificado: using var api = new OpenAIClient ( OpenAIAuthentication . LoadFromDirectory ( " path/to/your/directory " ) ) ;.openai siempre que se ajuste al formato JSON: using var api = new OpenAIClient ( OpenAIAuthentication . LoadFromPath ( " path/to/your/file.json " ) ) ; Utilice las variables de entorno de su sistema especifican una clave y organización API para usar.
OPENAI_API_KEY para su tecla API.OPENAI_ORGANIZATION_ID para especificar una organización.OPENAI_PROJECT_ID para especificar un proyecto. using var api = new OpenAIClient ( OpenAIAuthentication . LoadFromEnv ( ) ) ; OpenAIClient implementa IDisposable para administrar el ciclo de vida de los recursos que utiliza, incluido HttpClient . Cuando inicializa OpenAIClient , creará una instancia interna HttpClient si no se proporciona uno. Este HttpClient interno se elimina cuando se elimina OpenAIClient . Si proporciona una instancia externa HttpClient a OpenAIClient , usted es responsable de administrar su eliminación.
OpenAIClient crea su propio HttpClient , también se encargará de eliminarlo cuando elimine OpenAIClient .HttpClient externo a OpenAIClient , no será eliminado por OpenAIClient . Debe administrar la eliminación del HttpClient usted mismo. Asegúrese de deshacerse adecuadamente de OpenAIClient para liberar recursos a tiempo y evitar cualquier posible memoria o filtración de recursos en su aplicación.
Uso típico con un HttpClient interno:
using var api = new OpenAIClient ( ) ; HttpClient personalizado (que debe deshacerse de usted mismo):
using var customHttpClient = new HttpClient ( ) ;
// set custom http client properties here
var api = new OpenAIClient ( client : customHttpClient ) ;También puede optar por usar las implementaciones de Azure OpenAI de Microsoft también.
Puede encontrar la información requerida en el patio de juegos Azure haciendo clic en el botón View Code y ver una URL como esta:
https://{your-resource-name}.openai.azure.com/openai/deployments/{deployment-id}/chat/completions?api-version={api-version}your-resource-name el nombre de su recurso Azure OpenAI.deployment-id El nombre de implementación que eligió cuando implementó el modelo.api-version La versión API para usar para esta operación. Esto sigue el formato YYYY-MM-DD. Para configurar el cliente para usar su implementación, deberá pasar en OpenAIClientSettings al constructor del cliente.
var auth = new OpenAIAuthentication ( " sk-apiKey " ) ;
var settings = new OpenAIClientSettings ( resourceName : " your-resource-name " , deploymentId : " deployment-id " , apiVersion : " api-version " ) ;
using var api = new OpenAIClient ( auth , settings ) ; Autentique con MSAL como de costumbre y obtenga el token de acceso, luego use el token de acceso al crear su OpenAIAuthentication . Luego, asegúrese de establecer USAAZureActiveRectory en verdadero al crear sus OpenAIClientSettings .
Tutorial: aplicación de escritorio que llama API web: adquirir un token
// get your access token using any of the MSAL methods
var accessToken = result . AccessToken ;
var auth = new OpenAIAuthentication ( accessToken ) ;
var settings = new OpenAIClientSettings ( resourceName : " your-resource " , deploymentId : " deployment-id " , apiVersion : " api-version " , useActiveDirectoryAuthentication : true ) ;
using var api = new OpenAIClient ( auth , settings ) ;El uso de los paquetes Operai-Dotnet o Com.openai.unity directamente en su aplicación front-end puede exponer sus claves API y otra información confidencial. Para mitigar este riesgo, se recomienda configurar una API intermedia que solicite a OpenAI en nombre de su aplicación front-end. Esta biblioteca se puede utilizar para configuraciones de host front-end e intermediarios, asegurando una comunicación segura con la API de OpenAI.
En el ejemplo de front -end, deberá autenticar de forma segura a sus usuarios utilizando su proveedor de OAuth preferido. Una vez que el usuario esté autenticado, intercambie su token de autenticación personalizado con su clave API en el backend.
Sigue estos pasos:
OpenAIAuthentication y pase en el token personalizado con el prefijo sess- .OpenAIClientSettings y especifique el dominio donde se encuentra su API intermedia.auth y objetos settings al Constructor OpenAIClient cuando cree la instancia del cliente.Aquí hay un ejemplo de cómo configurar la parte delantera:
var authToken = await LoginAsync ( ) ;
var auth = new OpenAIAuthentication ( $" sess- { authToken } " ) ;
var settings = new OpenAIClientSettings ( domain : " api.your-custom-domain.com " ) ;
using var api = new OpenAIClient ( auth , settings ) ;Esta configuración permite que su aplicación front-end se comunique de forma segura con su backend que utilizará OpenAI-Dotnet-Proxy, que luego reenvía las solicitudes a la API de OpenAI. Esto garantiza que sus claves API de OpenAI y otra información confidencial sigan siendo seguras durante todo el proceso.
En este ejemplo, demostramos cómo configurar y usar OpenAIProxy en una nueva aplicación ASP.NET Core Web. El servidor proxy manejará la autenticación y reenviará las solicitudes a la API de OpenAI, asegurando que sus claves API y otra información confidencial permanezcan seguras.
Install-Package OpenAI-DotNet-Proxydotnet add package OpenAI-DotNet-Proxy<PackageReference Include="OpenAI-DotNet-Proxy" />AbstractAuthenticationFilter y anule el método ValidateAuthentication . Esto implementará el IAuthenticationFilter que usará para verificar el token de sesión de usuario en su servidor interno.Program.cs , cree una nueva aplicación web proxy llamando al método OpenAIProxy.CreateWebApplication , aprobando su AuthenticationFilter personalizado como argumento de tipo.OpenAIAuthentication y OpenAIClientSettings como lo haría normalmente con sus claves API, ID de Org o configuración de Azure. public partial class Program
{
private class AuthenticationFilter : AbstractAuthenticationFilter
{
public override async Task ValidateAuthenticationAsync ( IHeaderDictionary request )
{
await Task . CompletedTask ; // remote resource call to verify token
// You will need to implement your own class to properly test
// custom issued tokens you've setup for your end users.
if ( ! request . Authorization . ToString ( ) . Contains ( TestUserToken ) )
{
throw new AuthenticationException ( " User is not authorized " ) ;
}
}
}
public static void Main ( string [ ] args )
{
var auth = OpenAIAuthentication . LoadFromEnv ( ) ;
var settings = new OpenAIClientSettings ( /* your custom settings if using Azure OpenAI */ ) ;
using var openAIClient = new OpenAIClient ( auth , settings ) ;
OpenAIProxy . CreateWebApplication < AuthenticationFilter > ( args , openAIClient ) . Run ( ) ;
}
}Una vez que haya configurado su servidor proxy, sus usuarios finales ahora pueden realizar solicitudes autenticadas a su API proxy en lugar de directamente a la API de OpenAI. El servidor proxy manejará la autenticación y reenviará las solicitudes a la API de OpenAI, asegurando que sus claves API y otra información confidencial permanezcan seguras.
Lista y describa los diversos modelos disponibles en la API. Puede consultar la documentación de los modelos para comprender qué modelos están disponibles y las diferencias entre ellos.
También consulte la compatibilidad del punto final del modelo para comprender qué modelos funcionan con qué puntos finales.
Para especificar un modelo personalizado no predefinido en esta biblioteca:
var model = new Model ( " model-id " ) ; Se accede a la API de los modelos a través de OpenAIClient.ModelsEndpoint
Enumera los modelos disponibles actualmente y proporciona información básica sobre cada uno, como el propietario y la disponibilidad.
using var api = new OpenAIClient ( ) ;
var models = await api . ModelsEndpoint . GetModelsAsync ( ) ;
foreach ( var model in models )
{
Console . WriteLine ( model . ToString ( ) ) ;
} Recupera una instancia de modelo, proporcionando información básica sobre el modelo, como el propietario y los permisos.
using var api = new OpenAIClient ( ) ;
var model = await api . ModelsEndpoint . GetModelDetailsAsync ( " gpt-4o " ) ;
Console . WriteLine ( model . ToString ( ) ) ; Eliminar un modelo ajustado. Debe tener el papel del propietario en su organización.
using var api = new OpenAIClient ( ) ;
var isDeleted = await api . ModelsEndpoint . DeleteFineTuneModelAsync ( " your-fine-tuned-model " ) ;
Assert . IsTrue ( isDeleted ) ;Advertencia
Característica beta. API sujeta a cambios de ruptura.
La API de tiempo real le permite construir experiencias de conversación multimodal de baja latencia. Actualmente admite texto y audio como entrada y salida, así como llamadas de funciones.
Se accede a la API de Asistentes a través de OpenAIClient.RealtimeEndpoint
Aquí hay un ejemplo simple de cómo crear una sesión en tiempo real y enviar y recibir mensajes del modelo.
using var api = new OpenAIClient ( ) ;
var cancellationTokenSource = new CancellationTokenSource ( ) ;
var tools = new List < Tool >
{
Tool . FromFunc ( " goodbye " , ( ) =>
{
cancellationTokenSource . Cancel ( ) ;
return " Goodbye! " ;
} )
} ;
var options = new Options ( Model . GPT4oRealtime , tools : tools ) ;
using var session = await api . RealtimeEndpoint . CreateSessionAsync ( options ) ;
var responseTask = session . ReceiveUpdatesAsync < IServerEvent > ( ServerEvents , cancellationTokenSource . Token ) ;
await session . SendAsync ( new ConversationItemCreateRequest ( " Hello! " ) ) ;
await session . SendAsync ( new CreateResponseRequest ( ) ) ;
await session . SendAsync ( new InputAudioBufferAppendRequest ( new ReadOnlyMemory < byte > ( new byte [ 1024 * 4 ] ) ) , cancellationTokenSource . Token ) ;
await session . SendAsync ( new ConversationItemCreateRequest ( " GoodBye! " ) ) ;
await session . SendAsync ( new CreateResponseRequest ( ) ) ;
await responseTask ;
void ServerEvents ( IServerEvent @event )
{
switch ( @event )
{
case ResponseAudioTranscriptResponse transcriptResponse :
Console . WriteLine ( transcriptResponse . ToString ( ) ) ;
break ;
case ResponseFunctionCallArgumentsResponse functionCallResponse :
if ( functionCallResponse . IsDone )
{
ToolCall toolCall = functionCallResponse ;
toolCall . InvokeFunction ( ) ;
}
break ;
}
} La biblioteca implementa la interfaz IClientEvent para eventos enviados al cliente saliente.
UpdateSessionRequest : actualice la sesión con nuevas opciones de sesión.InputAudioBufferAppendRequest : Agregar audio al búfer de audio de entrada. (A diferencia de otros eventos de clientes realizados, el servidor no enviará una respuesta de confirmación a este evento).InputAudioBufferCommitRequest : confirme el búfer de audio de entrada. (Cuando está en el modo VAD Server, el cliente no necesita enviar este evento).InputAudioBufferClearRequest : borre el búfer de audio de entrada.ConversationItemCreateRequest : crea un nuevo elemento de conversación. Esta es la forma principal de enviar contenido de usuario al modelo.ConversationItemTruncateRequest : envíe este evento para truncar el audio de un mensaje de asistente anterior.ConversationItemDeleteRequest : elimine un elemento de conversación. Esto es útil cuando desea eliminar un mensaje del historial de conversación.CreateResponseRequest : cree una respuesta del modelo. Envíe este evento después de crear nuevos elementos de conversación o invocar llamadas de herramientas. Esto desencadenará el modelo para generar una respuesta.ResponseCancelRequest -Send este evento para cancelar una respuesta en progreso. Puede enviar eventos del cliente en cualquier momento al servidor llamando al método RealtimeSession.SendAsync en el objeto de sesión. La llamada de envío devolverá un identificador IServerEvent que mejor represente la respuesta apropiada del servidor para ese evento. Esto es útil si desea manejar las respuestas del servidor de una manera más granular.
Idealmente, es posible que desee manejar todas las respuestas del servidor con RealtimeSession.ReceiveUpdatesAsync .
Nota
El servidor no enviará una respuesta de confirmación al evento InputAudioBufferAppendRequest .
Importante
También deberá enviar CreateResponseRequest para activar el modelo para generar una respuesta.
var serverEvent = await session . SendAsync ( new ConversationItemCreateRequest ( " Hello! " ) ) ;
Console . WriteLine ( serverEvent . ToJsonString ( ) ) ;
serverEvent = await session . SendAsync ( new CreateResponseRequest ( ) ) ;
Console . WriteLine ( serverEvent . ToJsonString ( ) ) ; La biblioteca implementa la interfaz IServerEvent para eventos enviados al servidor entrante.
RealtimeEventError : devuelto cuando ocurre un error, que podría ser un problema del cliente o un problema del servidor.SessionResponse : regresó tanto para un evento session.created y session.updated .RealtimeConversationResponse : devuelto cuando se crea un nuevo elemento de conversación.ConversationItemCreatedResponse : regresó cuando se crea un nuevo elemento de conversación.ConversationItemInputAudioTranscriptionResponse : devuelto cuando la transcripción de audio de entrada se completa o falle.ConversationItemTruncatedResponse : devuelto cuando se trunca un elemento de conversación.ConversationItemDeletedResponse : devuelto cuando se elimina un elemento de conversación.InputAudioBufferCommittedResponse : devuelto cuando el cliente comete un búfer de audio de entrada, ya sea por el cliente o automáticamente en el modo VAD del servidor.InputAudioBufferClearedResponse : devuelto cuando se borra un búfer de audio de entrada.InputAudioBufferStartedResponse : enviado por el servidor cuando está en el modo Server_vad para indicar que el habla se ha detectado en el búfer de audio. Esto puede suceder en cualquier momento en que el audio se agrega al búfer (a menos que el discurso ya se detecte). El cliente puede querer usar este evento para interrumpir la reproducción de audio o proporcionar comentarios visuales al usuario.InputAudioBufferStoppedResponse : devuelto en modo server_vad cuando el servidor detecta el final del habla en el búfer de audio.RealtimeResponse : devuelto cuando se crea o se hace una respuesta.ResponseOutputItemResponse : devuelto cuando se agrega o se hace un elemento de salida de respuesta.ResponseContentPartResponse : devuelto cuando se agrega o se hace una parte de contenido de respuesta.ResponseTextResponse : devuelto cuando un texto de respuesta se actualiza o se hace.ResponseAudioTranscriptResponse : devuelto cuando se actualiza o realiza una transcripción de audio de respuesta.ResponseAudioResponse : devuelto cuando un audio de respuesta se actualiza o realiza.ResponseFunctionCallArgumentsResponse : devuelto cuando se actualizan o se realizan argumentos de llamada de función de respuesta de respuesta.RateLimitsResponse : devuelto cuando se actualizan los límites de velocidad. Para recibir eventos del servidor, deberá llamar al método RealtimeSession.ReceiveUpdatesAsync en el objeto de sesión. Este método devolverá una Task o IAsyncEnumerable<T> que se completará cuando la sesión esté cerrada o cuando se active el token de cancelación. Idealmente, este método debe llamarse una vez y ejecutar durante la sesión.
Nota
También puede recibir devoluciones de llamada IClientEvent utilizando la interfaz IRealtimeEvent en lugar de IServerEvent .
await foreach ( var @event in session . ReceiveUpdatesAsync < IServerEvent > ( cts . Token ) )
{
switch ( @event )
{
case RealtimeEventError error :
// raised anytime an error occurs
break ;
case SessionResponse sessionResponse :
// raised when a session is created or updated
break ;
case RealtimeConversationResponse conversationResponse :
// raised when a new conversation is created
break ;
case ConversationItemCreatedResponse conversationItemCreated :
// raised when a new conversation item is created
break ;
case ConversationItemInputAudioTranscriptionResponse conversationItemTranscription :
// raised when the input audio transcription is completed or failed
break ;
case ConversationItemTruncatedResponse conversationItemTruncated :
// raised when a conversation item is truncated
break ;
case ConversationItemDeletedResponse conversationItemDeleted :
// raised when a conversation item is deleted
break ;
case InputAudioBufferCommittedResponse committedResponse :
// raised when an input audio buffer is committed
break ;
case InputAudioBufferClearedResponse clearedResponse :
// raised when an input audio buffer is cleared
break ;
case InputAudioBufferStartedResponse startedResponse :
// raised when speech is detected in the audio buffer
break ;
case InputAudioBufferStoppedResponse stoppedResponse :
// raised when speech stops in the audio buffer
break ;
case RealtimeResponse realtimeResponse :
// raised when a response is created or done
break ;
case ResponseOutputItemResponse outputItemResponse :
// raised when a response output item is added or done
break ;
case ResponseContentPartResponse contentPartResponse :
// raised when a response content part is added or done
break ;
case ResponseTextResponse textResponse :
// raised when a response text is updated or done
break ;
case ResponseAudioTranscriptResponse transcriptResponse :
// raised when a response audio transcript is updated or done
break ;
case ResponseFunctionCallArgumentsResponse functionCallResponse :
// raised when a response function call arguments are updated or done
break ;
case RateLimitsResponse rateLimitsResponse :
// raised when rate limits are updated
break ;
}
}Advertencia
Característica beta. API sujeta a cambios de ruptura.
Cree asistentes que puedan llamar a modelos y usar herramientas para realizar tareas.
Se accede a la API de Asistentes a través de OpenAIClient.AssistantsEndpoint
Devuelve una lista de asistentes.
using var api = new OpenAIClient ( ) ;
var assistantsList = await api . AssistantsEndpoint . ListAssistantsAsync ( ) ;
foreach ( var assistant in assistantsList . Items )
{
Console . WriteLine ( $" { assistant } -> { assistant . CreatedAt } " ) ;
} Cree un asistente con un modelo e instrucciones.
using var api = new OpenAIClient ( ) ;
var request = new CreateAssistantRequest ( Model . GPT4o ) ;
var assistant = await api . AssistantsEndpoint . CreateAssistantAsync ( request ) ; Recupera un asistente.
using var api = new OpenAIClient ( ) ;
var assistant = await api . AssistantsEndpoint . RetrieveAssistantAsync ( " assistant-id " ) ;
Console . WriteLine ( $" { assistant } -> { assistant . CreatedAt } " ) ; Modifica un asistente.
using var api = new OpenAIClient ( ) ;
var createRequest = new CreateAssistantRequest ( Model . GPT4_Turbo ) ;
var assistant = await api . AssistantsEndpoint . CreateAssistantAsync ( createRequest ) ;
var modifyRequest = new CreateAssistantRequest ( Model . GPT4o ) ;
var modifiedAssistant = await api . AssistantsEndpoint . ModifyAssistantAsync ( assistant . Id , modifyRequest ) ;
// OR AssistantExtension for easier use!
var modifiedAssistantEx = await assistant . ModifyAsync ( modifyRequest ) ; Eliminar un asistente.
using var api = new OpenAIClient ( ) ;
var isDeleted = await api . AssistantsEndpoint . DeleteAssistantAsync ( " assistant-id " ) ;
// OR AssistantExtension for easier use!
var isDeleted = await assistant . DeleteAsync ( ) ;
Assert . IsTrue ( isDeleted ) ; Nota
Los eventos de transmisión del asistente se pueden agregar fácilmente a las llamadas de hilos existentes al pasar Func<IServerSentEvent, Task> streamEventHandler a cualquier método existente que admita la transmisión.
Cree hilos con los que los asistentes puedan interactuar.
Se accede a la API de hilos a través de OpenAIClient.ThreadsEndpoint
Crear un hilo.
using var api = new OpenAIClient ( ) ;
var thread = await api . ThreadsEndpoint . CreateThreadAsync ( ) ;
Console . WriteLine ( $" Create thread { thread . Id } -> { thread . CreatedAt } " ) ; Crea un hilo y ejecutarlo en una solicitud.
Ver también: Ejecutar el hilo
using var api = new OpenAIClient ( ) ;
var assistant = await api . AssistantsEndpoint . CreateAssistantAsync (
new CreateAssistantRequest (
name : " Math Tutor " ,
instructions : " You are a personal math tutor. Answer questions briefly, in a sentence or less. " ,
model : Model . GPT4o ) ) ;
var messages = new List < Message > { " I need to solve the equation `3x + 11 = 14`. Can you help me? " } ;
var threadRequest = new CreateThreadRequest ( messages ) ;
var run = await assistant . CreateThreadAndRunAsync ( threadRequest ) ;
Console . WriteLine ( $" Created thread and run: { run . ThreadId } -> { run . Id } -> { run . CreatedAt } " ) ; Cree un hilo y ejecutelo en una solicitud mientras transmite eventos.
using var api = new OpenAIClient ( ) ;
var tools = new List < Tool >
{
Tool . GetOrCreateTool ( typeof ( WeatherService ) , nameof ( WeatherService . GetCurrentWeatherAsync ) )
} ;
var assistantRequest = new CreateAssistantRequest ( tools : tools , instructions : " You are a helpful weather assistant. Use the appropriate unit based on geographical location. " ) ;
var assistant = await api . AssistantsEndpoint . CreateAssistantAsync ( assistantRequest ) ;
ThreadResponse thread = null ;
async Task StreamEventHandler ( IServerSentEvent streamEvent )
{
switch ( streamEvent )
{
case ThreadResponse threadResponse :
thread = threadResponse ;
break ;
case RunResponse runResponse :
if ( runResponse . Status == RunStatus . RequiresAction )
{
var toolOutputs = await assistant . GetToolOutputsAsync ( runResponse ) ;
foreach ( var toolOutput in toolOutputs )
{
Console . WriteLine ( $" Tool Output: { toolOutput } " ) ;
}
await runResponse . SubmitToolOutputsAsync ( toolOutputs , StreamEventHandler ) ;
}
break ;
default :
Console . WriteLine ( streamEvent . ToJsonString ( ) ) ;
break ;
}
}
var run = await assistant . CreateThreadAndRunAsync ( " I'm in Kuala-Lumpur, please tell me what's the temperature now? " , StreamEventHandler ) ;
run = await run . WaitForStatusChangeAsync ( ) ;
var messages = await thread . ListMessagesAsync ( ) ;
foreach ( var response in messages . Items . Reverse ( ) )
{
Console . WriteLine ( $" { response . Role } : { response . PrintContent ( ) } " ) ;
} Recupera un hilo.
using var api = new OpenAIClient ( ) ;
var thread = await api . ThreadsEndpoint . RetrieveThreadAsync ( " thread-id " ) ;
// OR if you simply wish to get the latest state of a thread
thread = await thread . UpdateAsync ( ) ;
Console . WriteLine ( $" Retrieve thread { thread . Id } -> { thread . CreatedAt } " ) ; Modifica un hilo.
Nota: Solo los metadatos pueden modificarse.
using var api = new OpenAIClient ( ) ;
var thread = await api . ThreadsEndpoint . CreateThreadAsync ( ) ;
var metadata = new Dictionary < string , string >
{
{ " key " , " custom thread metadata " }
}
thread = await api . ThreadsEndpoint . ModifyThreadAsync ( thread . Id , metadata ) ;
// OR use extension method for convenience!
thread = await thread . ModifyAsync ( metadata ) ;
Console . WriteLine ( $" Modify thread { thread . Id } -> { thread . Metadata [ " key " ] } " ) ; Eliminar un hilo.
using var api = new OpenAIClient ( ) ;
var isDeleted = await api . ThreadsEndpoint . DeleteThreadAsync ( " thread-id " ) ;
// OR use extension method for convenience!
var isDeleted = await thread . DeleteAsync ( ) ;
Assert . IsTrue ( isDeleted ) ; Crear mensajes dentro de los hilos.
Devuelve una lista de mensajes para un hilo dado.
using var api = new OpenAIClient ( ) ;
var messageList = await api . ThreadsEndpoint . ListMessagesAsync ( " thread-id " ) ;
// OR use extension method for convenience!
var messageList = await thread . ListMessagesAsync ( ) ;
foreach ( var message in messageList . Items )
{
Console . WriteLine ( $" { message . Id } : { message . Role } : { message . PrintContent ( ) } " ) ;
} Crear un mensaje.
using var api = new OpenAIClient ( ) ;
var thread = await api . ThreadsEndpoint . CreateThreadAsync ( ) ;
var request = new CreateMessageRequest ( " Hello world! " ) ;
var message = await api . ThreadsEndpoint . CreateMessageAsync ( thread . Id , request ) ;
// OR use extension method for convenience!
var message = await thread . CreateMessageAsync ( " Hello World! " ) ;
Console . WriteLine ( $" { message . Id } : { message . Role } : { message . PrintContent ( ) } " ) ; Recuperar un mensaje.
using var api = new OpenAIClient ( ) ;
var message = await api . ThreadsEndpoint . RetrieveMessageAsync ( " thread-id " , " message-id " ) ;
// OR use extension methods for convenience!
var message = await thread . RetrieveMessageAsync ( " message-id " ) ;
var message = await message . UpdateAsync ( ) ;
Console . WriteLine ( $" { message . Id } : { message . Role } : { message . PrintContent ( ) } " ) ; Modificar un mensaje.
Nota: Solo se pueden modificar los metadatos del mensaje.
using var api = new OpenAIClient ( ) ;
var metadata = new Dictionary < string , string >
{
{ " key " , " custom message metadata " }
} ;
var message = await api . ThreadsEndpoint . ModifyMessageAsync ( " thread-id " , " message-id " , metadata ) ;
// OR use extension method for convenience!
var message = await message . ModifyAsync ( metadata ) ;
Console . WriteLine ( $" Modify message metadata: { message . Id } -> { message . Metadata [ " key " ] } " ) ; Representa una ejecución de ejecución en un hilo.
Devuelve una lista de ejecuciones pertenecientes a un hilo.
using var api = new OpenAIClient ( ) ;
var runList = await api . ThreadsEndpoint . ListRunsAsync ( " thread-id " ) ;
// OR use extension method for convenience!
var runList = await thread . ListRunsAsync ( ) ;
foreach ( var run in runList . Items )
{
Console . WriteLine ( $" [ { run . Id } ] { run . Status } | { run . CreatedAt } " ) ;
} Crea una carrera.
using var api = new OpenAIClient ( ) ;
var assistant = await api . AssistantsEndpoint . CreateAssistantAsync (
new CreateAssistantRequest (
name : " Math Tutor " ,
instructions : " You are a personal math tutor. Answer questions briefly, in a sentence or less. " ,
model : Model . GPT4o ) ) ;
var thread = await api . ThreadsEndpoint . CreateThreadAsync ( ) ;
var message = await thread . CreateMessageAsync ( " I need to solve the equation `3x + 11 = 14`. Can you help me? " ) ;
var run = await thread . CreateRunAsync ( assistant ) ;
Console . WriteLine ( $" [ { run . Id } ] { run . Status } | { run . CreatedAt } " ) ; Crea una ejecución y transmite los eventos.
using var api = new OpenAIClient ( ) ;
var assistant = await api . AssistantsEndpoint . CreateAssistantAsync (
new CreateAssistantRequest (
name : " Math Tutor " ,
instructions : " You are a personal math tutor. Answer questions briefly, in a sentence or less. Your responses should be formatted in JSON. " ,
model : Model . GPT4o ,
responseFormat : ChatResponseFormat . Json ) ) ;
var thread = await api . ThreadsEndpoint . CreateThreadAsync ( ) ;
var message = await thread . CreateMessageAsync ( " I need to solve the equation `3x + 11 = 14`. Can you help me? " ) ;
var run = await thread . CreateRunAsync ( assistant , async streamEvent =>
{
Console . WriteLine ( streamEvent . ToJsonString ( ) ) ;
await Task . CompletedTask ;
} ) ;
var messages = await thread . ListMessagesAsync ( ) ;
foreach ( var response in messages . Items . Reverse ( ) )
{
Console . WriteLine ( $" { response . Role } : { response . PrintContent ( ) } " ) ;
} Recupera una carrera.
using var api = new OpenAIClient ( ) ;
var run = await api . ThreadsEndpoint . RetrieveRunAsync ( " thread-id " , " run-id " ) ;
// OR use extension method for convenience!
var run = await thread . RetrieveRunAsync ( " run-id " ) ;
var run = await run . UpdateAsync ( ) ;
Console . WriteLine ( $" [ { run . Id } ] { run . Status } | { run . CreatedAt } " ) ; Modifica una ejecución.
Nota: Solo los metadatos pueden modificarse.
using var api = new OpenAIClient ( ) ;
var metadata = new Dictionary < string , string >
{
{ " key " , " custom run metadata " }
} ;
var run = await api . ThreadsEndpoint . ModifyRunAsync ( " thread-id " , " run-id " , metadata ) ;
// OR use extension method for convenience!
var run = await run . ModifyAsync ( metadata ) ;
Console . WriteLine ( $" Modify run { run . Id } -> { run . Metadata [ " key " ] } " ) ; Cuando una ejecución tiene el estado: requires_action y required_action.type es submit_tool_outputs , este punto final se puede usar para enviar las salidas de las llamadas de la herramienta una vez que todos están completados. Todas las salidas deben enviarse en una sola solicitud.
Nota
Consulte Crear hilo y ejecutar el ejemplo de transmisión sobre cómo transmitir eventos de salida de herramientas.
using var api = new OpenAIClient ( ) ;
var tools = new List < Tool >
{
// Use a predefined tool
Tool . Retrieval , Tool . CodeInterpreter ,
// Or create a tool from a type and the name of the method you want to use for function calling
Tool . GetOrCreateTool ( typeof ( WeatherService ) , nameof ( WeatherService . GetCurrentWeatherAsync ) ) ,
// Pass in an instance of an object to call a method on it
Tool . GetOrCreateTool ( api . ImagesEndPoint , nameof ( ImagesEndpoint . GenerateImageAsync ) ) ,
// Define func<,> callbacks
Tool . FromFunc ( " name_of_func " , ( ) => { /* callback function */ } ) ,
Tool . FromFunc < T1 , T2 , TResult > ( " func_with_multiple_params " , ( t1 , t2 ) => { /* logic that calculates return value */ return tResult ; } )
} ;
var assistantRequest = new CreateAssistantRequest ( tools : tools , instructions : " You are a helpful weather assistant. Use the appropriate unit based on geographical location. " ) ;
var testAssistant = await api . AssistantsEndpoint . CreateAssistantAsync ( assistantRequest ) ;
var run = await testAssistant . CreateThreadAndRunAsync ( " I'm in Kuala-Lumpur, please tell me what's the temperature now? " ) ;
// waiting while run is Queued and InProgress
run = await run . WaitForStatusChangeAsync ( ) ;
// Invoke all of the tool call functions and return the tool outputs.
var toolOutputs = await testAssistant . GetToolOutputsAsync ( run . RequiredAction . SubmitToolOutputs . ToolCalls ) ;
foreach ( var toolOutput in toolOutputs )
{
Console . WriteLine ( $" tool call output: { toolOutput . Output } " ) ;
}
// submit the tool outputs
run = await run . SubmitToolOutputsAsync ( toolOutputs ) ;
// waiting while run in Queued and InProgress
run = await run . WaitForStatusChangeAsync ( ) ;
var messages = await run . ListMessagesAsync ( ) ;
foreach ( var message in messages . Items . OrderBy ( response => response . CreatedAt ) )
{
Console . WriteLine ( $" { message . Role } : { message . PrintContent ( ) } " ) ;
} Salidas estructuradas es la evolución del modo JSON. Si bien ambos aseguran que se produzca JSON válido, solo las salidas estructuradas aseguran la adherencia al esquema.
Importante
finish_reason es longitud, lo que indica que la generación excedió Max_Tokens o la conversación excedió el límite de token. Para protegerse contra esto, verifique finish_reason antes de analizar la respuesta.Primero defina la estructura de sus respuestas. Estos se utilizarán como su esquema. Estos son los objetos que deserializará, así que asegúrese de usar modelos de objetos JSON estándar.
public class MathResponse
{
[ JsonInclude ]
[ JsonPropertyName ( " steps " ) ]
public IReadOnlyList < MathStep > Steps { get ; private set ; }
[ JsonInclude ]
[ JsonPropertyName ( " final_answer " ) ]
public string FinalAnswer { get ; private set ; }
}
public class MathStep
{
[ JsonInclude ]
[ JsonPropertyName ( " explanation " ) ]
public string Explanation { get ; private set ; }
[ JsonInclude ]
[ JsonPropertyName ( " output " ) ]
public string Output { get ; private set ; }
} Para usar, simplemente especifique el tipo de MathResponse como una restricción genérica en CreateAssistantAsync , CreateRunAsync o CreateThreadAndRunAsync .
using var api = new OpenAIClient ( ) ;
var assistant = await api . AssistantsEndpoint . CreateAssistantAsync < MathResponse > (
new CreateAssistantRequest (
name : " Math Tutor " ,
instructions : " You are a helpful math tutor. Guide the user through the solution step by step. " ,
model : " gpt-4o-2024-08-06 " ) ) ;
ThreadResponse thread = null ;
try
{
async Task StreamEventHandler ( IServerSentEvent @event )
{
try
{
switch ( @event )
{
case MessageResponse message :
if ( message . Status != MessageStatus . Completed )
{
Console . WriteLine ( @event . ToJsonString ( ) ) ;
break ;
}
var mathResponse = message . FromSchema < MathResponse > ( ) ;
for ( var i = 0 ; i < mathResponse . Steps . Count ; i ++ )
{
var step = mathResponse . Steps [ i ] ;
Console . WriteLine ( $" Step { i } : { step . Explanation } " ) ;
Console . WriteLine ( $" Result: { step . Output } " ) ;
}
Console . WriteLine ( $" Final Answer: { mathResponse . FinalAnswer } " ) ;
break ;
default :
Console . WriteLine ( @event . ToJsonString ( ) ) ;
break ;
}
}
catch ( Exception e )
{
Console . WriteLine ( e ) ;
throw ;
}
await Task . CompletedTask ;
}
var run = await assistant . CreateThreadAndRunAsync ( " how can I solve 8x + 7 = -23 " , StreamEventHandler ) ;
thread = await run . GetThreadAsync ( ) ;
run = await run . WaitForStatusChangeAsync ( ) ;
Console . WriteLine ( $" Created thread and run: { run . ThreadId } -> { run . Id } -> { run . CreatedAt } " ) ;
var messages = await thread . ListMessagesAsync ( ) ;
foreach ( var response in messages . Items . OrderBy ( response => response . CreatedAt ) )
{
Console . WriteLine ( $" { response . Role } : { response . PrintContent ( ) } " ) ;
}
}
finally
{
await assistant . DeleteAsync ( deleteToolResources : thread == null ) ;
if ( thread != null )
{
var isDeleted = await thread . DeleteAsync ( deleteToolResources : true ) ;
}
}También puede crear manualmente el esquema JSON JSON String también, pero será responsable de deserializar sus datos de respuesta:
using var api = new OpenAIClient ( ) ;
var mathSchema = new JsonSchema ( " math_response " , @"
{
""type"": ""object"",
""properties"": {
""steps"": {
""type"": ""array"",
""items"": {
""type"": ""object"",
""properties"": {
""explanation"": {
""type"": ""string""
},
""output"": {
""type"": ""string""
}
},
""required"": [
""explanation"",
""output""
],
""additionalProperties"": false
}
},
""final_answer"": {
""type"": ""string""
}
},
""required"": [
""steps"",
""final_answer""
],
""additionalProperties"": false
}" ) ;
var assistant = await api . AssistantsEndpoint . CreateAssistantAsync (
new CreateAssistantRequest (
name : " Math Tutor " ,
instructions : " You are a helpful math tutor. Guide the user through the solution step by step. " ,
model : " gpt-4o-2024-08-06 " ,
jsonSchema : mathSchema ) ) ;
ThreadResponse thread = null ;
try
{
var run = await assistant . CreateThreadAndRunAsync ( " how can I solve 8x + 7 = -23 " ,
async @event =>
{
Console . WriteLine ( @event . ToJsonString ( ) ) ;
await Task . CompletedTask ;
} ) ;
thread = await run . GetThreadAsync ( ) ;
run = await run . WaitForStatusChangeAsync ( ) ;
Console . WriteLine ( $" Created thread and run: { run . ThreadId } -> { run . Id } -> { run . CreatedAt } " ) ;
var messages = await thread . ListMessagesAsync ( ) ;
foreach ( var response in messages . Items )
{
Console . WriteLine ( $" { response . Role } : { response . PrintContent ( ) } " ) ;
}
}
finally
{
await assistant . DeleteAsync ( deleteToolResources : thread == null ) ;
if ( thread != null )
{
var isDeleted = await thread . DeleteAsync ( deleteToolResources : true ) ;
Assert . IsTrue ( isDeleted ) ;
}
} Devuelve una lista de pasos de ejecución pertenecientes a una ejecución.
using var api = new OpenAIClient ( ) ;
var runStepList = await api . ThreadsEndpoint . ListRunStepsAsync ( " thread-id " , " run-id " ) ;
// OR use extension method for convenience!
var runStepList = await run . ListRunStepsAsync ( ) ;
foreach ( var runStep in runStepList . Items )
{
Console . WriteLine ( $" [ { runStep . Id } ] { runStep . Status } { runStep . CreatedAt } -> { runStep . ExpiresAt } " ) ;
} Recupera un paso de ejecución.
using var api = new OpenAIClient ( ) ;
var runStep = await api . ThreadsEndpoint . RetrieveRunStepAsync ( " thread-id " , " run-id " , " step-id " ) ;
// OR use extension method for convenience!
var runStep = await run . RetrieveRunStepAsync ( " step-id " ) ;
var runStep = await runStep . UpdateAsync ( ) ;
Console . WriteLine ( $" [ { runStep . Id } ] { runStep . Status } { runStep . CreatedAt } -> { runStep . ExpiresAt } " ) ; Cancela una ejecución que está in_progress .
using var api = new OpenAIClient ( ) ;
var isCancelled = await api . ThreadsEndpoint . CancelRunAsync ( " thread-id " , " run-id " ) ;
// OR use extension method for convenience!
var isCancelled = await run . CancelAsync ( ) ;
Assert . IsTrue ( isCancelled ) ; Las tiendas vectoriales se utilizan para almacenar archivos para su uso mediante la herramienta file_search .
Se accede a la API de las tiendas Vector a través de OpenAIClient.VectorStoresEndpoint
Devuelve una lista de tiendas vectoriales.
using var api = new OpenAIClient ( ) ;
var vectorStores = await api . VectorStoresEndpoint . ListVectorStoresAsync ( ) ;
foreach ( var vectorStore in vectorStores . Items )
{
Console . WriteLine ( vectorStore ) ;
} Crea una tienda vectorial.
using var api = new OpenAIClient ( ) ;
var createVectorStoreRequest = new CreateVectorStoreRequest ( " test-vector-store " ) ;
var vectorStore = await api . VectorStoresEndpoint . CreateVectorStoreAsync ( createVectorStoreRequest ) ;
Console . WriteLine ( vectorStore ) ; Recupera una tienda vectorial.
using var api = new OpenAIClient ( ) ;
var vectorStore = await api . VectorStoresEndpoint . GetVectorStoreAsync ( " vector-store-id " ) ;
Console . WriteLine ( vectorStore ) ; Modifica una tienda vectorial.
using var api = new OpenAIClient ( ) ;
var metadata = new Dictionary < string , object > { { " Test " , DateTime . UtcNow } } ;
var vectorStore = await api . VectorStoresEndpoint . ModifyVectorStoreAsync ( " vector-store-id " , metadata : metadata ) ;
Console . WriteLine ( vectorStore ) ; Eliminar una tienda vectorial.
using var api = new OpenAIClient ( ) ;
var isDeleted = await api . VectorStoresEndpoint . DeleteVectorStoreAsync ( " vector-store-id " ) ;
Assert . IsTrue ( isDeleted ) ; Los archivos de la tienda vectorial representan archivos dentro de una tienda vectorial.
Devuelve una lista de archivos de tiendas vectoriales.
using var api = new OpenAIClient ( ) ;
var files = await api . VectorStoresEndpoint . ListVectorStoreFilesAsync ( " vector-store-id " ) ;
foreach ( var file in vectorStoreFiles . Items )
{
Console . WriteLine ( file ) ;
} Cree un archivo de almacenamiento vectorial adjuntando un archivo a una tienda vectorial.
using var api = new OpenAIClient ( ) ;
var file = await api . VectorStoresEndpoint . CreateVectorStoreFileAsync ( " vector-store-id " , " file-id " , new ChunkingStrategy ( ChunkingStrategyType . Static ) ) ;
Console . WriteLine ( file ) ; Recupera un archivo de tienda vectorial.
using var api = new OpenAIClient ( ) ;
var file = await api . VectorStoresEndpoint . GetVectorStoreFileAsync ( " vector-store-id " , " vector-store-file-id " ) ;
Console . WriteLine ( file ) ; Eliminar un archivo de tienda vectorial. Esto eliminará el archivo de la tienda Vector, pero el archivo en sí no se eliminará. Para eliminar el archivo, use el punto final de eliminación del archivo.
using var api = new OpenAIClient ( ) ;
var isDeleted = await api . VectorStoresEndpoint . DeleteVectorStoreFileAsync ( " vector-store-id " , vectorStoreFile ) ;
Assert . IsTrue ( isDeleted ) ; Los archivos de la tienda vectorial representan archivos dentro de una tienda vectorial.
Cree un lote de archivo de tienda vectorial.
using var api = new OpenAIClient ( ) ;
var files = new List < string > { " file_id_1 " , " file_id_2 " } ;
var vectorStoreFileBatch = await api . VectorStoresEndpoint . CreateVectorStoreFileBatchAsync ( " vector-store-id " , files ) ;
Console . WriteLine ( vectorStoreFileBatch ) ; Recupera un lote de archivo vectorial.
using var api = new OpenAIClient ( ) ;
var vectorStoreFileBatch = await api . VectorStoresEndpoint . GetVectorStoreFileBatchAsync ( " vector-store-id " , " vector-store-file-batch-id " ) ;
// you can also use convenience methods!
vectorStoreFileBatch = await vectorStoreFileBatch . UpdateAsync ( ) ;
vectorStoreFileBatch = await vectorStoreFileBatch . WaitForStatusChangeAsync ( ) ; Devuelve una lista de archivos de tiendas vectoriales en un lote.
using var api = new OpenAIClient ( ) ;
var files = await api . VectorStoresEndpoint . ListVectorStoreBatchFilesAsync ( " vector-store-id " , " vector-store-file-batch-id " ) ;
foreach ( var file in files . Items )
{
Console . WriteLine ( file ) ;
} Cancele un lote de archivo vectorial. Esto intenta cancelar el procesamiento de archivos en este lote lo antes posible.
using var api = new OpenAIClient ( ) ;
var isCancelled = await api . VectorStoresEndpoint . CancelVectorStoreFileBatchAsync ( " vector-store-id " , " vector-store-file-batch-id " ) ;Dada una conversación de chat, el modelo devolverá una respuesta de finalización de chat.
Se accede a la API de chat a través de OpenAIClient.ChatEndpoint
Crea una finalización para el mensaje de chat
using var api = new OpenAIClient ( ) ;
var messages = new List < Message >
{
new Message ( Role . System , " You are a helpful assistant. " ) ,
new Message ( Role . User , " Who won the world series in 2020? " ) ,
new Message ( Role . Assistant , " The Los Angeles Dodgers won the World Series in 2020. " ) ,
new Message ( Role . User , " Where was it played? " ) ,
} ;
var chatRequest = new ChatRequest ( messages , Model . GPT4o ) ;
var response = await api . ChatEndpoint . GetCompletionAsync ( chatRequest ) ;
var choice = response . FirstChoice ;
Console . WriteLine ( $" [ { choice . Index } ] { choice . Message . Role } : { choice . Message } | Finish Reason: { choice . FinishReason } " ) ; using var api = new OpenAIClient ( ) ;
var messages = new List < Message >
{
new Message ( Role . System , " You are a helpful assistant. " ) ,
new Message ( Role . User , " Who won the world series in 2020? " ) ,
new Message ( Role . Assistant , " The Los Angeles Dodgers won the World Series in 2020. " ) ,
new Message ( Role . User , " Where was it played? " ) ,
} ;
var chatRequest = new ChatRequest ( messages ) ;
var response = await api . ChatEndpoint . StreamCompletionAsync ( chatRequest , async partialResponse =>
{
Console . Write ( partialResponse . FirstChoice . Delta . ToString ( ) ) ;
await Task . CompletedTask ;
} ) ;
var choice = response . FirstChoice ;
Console . WriteLine ( $" [ { choice . Index } ] { choice . Message . Role } : { choice . Message } | Finish Reason: { choice . FinishReason } " ) ; O si usa IAsyncEnumerable{T} (C# 8.0+)
using var api = new OpenAIClient ( ) ;
var messages = new List < Message >
{
new Message ( Role . System , " You are a helpful assistant. " ) ,
new Message ( Role . User , " Who won the world series in 2020? " ) ,
new Message ( Role . Assistant , " The Los Angeles Dodgers won the World Series in 2020. " ) ,
new Message ( Role . User , " Where was it played? " ) ,
} ;
var cumulativeDelta = string . Empty ;
var chatRequest = new ChatRequest ( messages ) ;
await foreach ( var partialResponse in api . ChatEndpoint . StreamCompletionEnumerableAsync ( chatRequest ) )
{
foreach ( var choice in partialResponse . Choices . Where ( choice => choice . Delta ? . Content != null ) )
{
cumulativeDelta += choice . Delta . Content ;
}
}
Console . WriteLine ( cumulativeDelta ) ; using var api = new OpenAIClient ( ) ;
var messages = new List < Message >
{
new ( Role . System , " You are a helpful weather assistant. Always prompt the user for their location. " ) ,
new Message ( Role . User , " What's the weather like today? " ) ,
} ;
foreach ( var message in messages )
{
Console . WriteLine ( $" { message . Role } : { message } " ) ;
}
// Define the tools that the assistant is able to use:
// 1. Get a list of all the static methods decorated with FunctionAttribute
var tools = Tool . GetAllAvailableTools ( includeDefaults : false , forceUpdate : true , clearCache : true ) ;
// 2. Define a custom list of tools:
var tools = new List < Tool >
{
Tool . GetOrCreateTool ( objectInstance , " TheNameOfTheMethodToCall " ) ,
Tool . FromFunc ( " a_custom_name_for_your_function " , ( ) => { /* Some logic to run */ } )
} ;
var chatRequest = new ChatRequest ( messages , tools : tools , toolChoice : " auto " ) ;
var response = await api . ChatEndpoint . GetCompletionAsync ( chatRequest ) ;
messages . Add ( response . FirstChoice . Message ) ;
Console . WriteLine ( $" { response . FirstChoice . Message . Role } : { response . FirstChoice } | Finish Reason: { response . FirstChoice . FinishReason } " ) ;
var locationMessage = new Message ( Role . User , " I'm in Glasgow, Scotland " ) ;
messages . Add ( locationMessage ) ;
Console . WriteLine ( $" { locationMessage . Role } : { locationMessage . Content } " ) ;
chatRequest = new ChatRequest ( messages , tools : tools , toolChoice : " auto " ) ;
response = await api . ChatEndpoint . GetCompletionAsync ( chatRequest ) ;
messages . Add ( response . FirstChoice . Message ) ;
if ( response . FirstChoice . FinishReason == " stop " )
{
Console . WriteLine ( $" { response . FirstChoice . Message . Role } : { response . FirstChoice } | Finish Reason: { response . FirstChoice . FinishReason } " ) ;
var unitMessage = new Message ( Role . User , " Fahrenheit " ) ;
messages . Add ( unitMessage ) ;
Console . WriteLine ( $" { unitMessage . Role } : { unitMessage . Content } " ) ;
chatRequest = new ChatRequest ( messages , tools : tools , toolChoice : " auto " ) ;
response = await api . ChatEndpoint . GetCompletionAsync ( chatRequest ) ;
}
// iterate over all tool calls and invoke them
foreach ( var toolCall in response . FirstChoice . Message . ToolCalls )
{
Console . WriteLine ( $" { response . FirstChoice . Message . Role } : { toolCall . Function . Name } | Finish Reason: { response . FirstChoice . FinishReason } " ) ;
Console . WriteLine ( $" { toolCall . Function . Arguments } " ) ;
// Invokes function to get a generic json result to return for tool call.
var functionResult = await toolCall . InvokeFunctionAsync ( ) ;
// If you know the return type and do additional processing you can use generic overload
var functionResult = await toolCall . InvokeFunctionAsync < string > ( ) ;
messages . Add ( new Message ( toolCall , functionResult ) ) ;
Console . WriteLine ( $" { Role . Tool } : { functionResult } " ) ;
}
// System: You are a helpful weather assistant.
// User: What's the weather like today?
// Assistant: Sure, may I know your current location? | Finish Reason: stop
// User: I'm in Glasgow, Scotland
// Assistant: GetCurrentWeather | Finish Reason: tool_calls
// {
// "location": "Glasgow, Scotland",
// "unit": "celsius"
// }
// Tool: The current weather in Glasgow, Scotland is 39°C. Advertencia
Característica beta. API sujeta a cambios de ruptura.
using var api = new OpenAIClient ( ) ;
var messages = new List < Message >
{
new Message ( Role . System , " You are a helpful assistant. " ) ,
new Message ( Role . User , new List < Content >
{
" What's in this image? " ,
new ImageUrl ( " https://upload.wikimedia.org/wikipedia/commons/thumb/d/dd/Gfp-wisconsin-madison-the-nature-boardwalk.jpg/2560px-Gfp-wisconsin-madison-the-nature-boardwalk.jpg " , ImageDetail . Low )
} )
} ;
var chatRequest = new ChatRequest ( messages , model : Model . GPT4o ) ;
var response = await api . ChatEndpoint . GetCompletionAsync ( chatRequest ) ;
Console . WriteLine ( $" { response . FirstChoice . Message . Role } : { response . FirstChoice . Message . Content } | Finish Reason: { response . FirstChoice . FinishDetails } " ) ; using var api = new OpenAIClient ( ) ;
var messages = new List < Message >
{
new Message ( Role . System , " You are a helpful assistant. " ) ,
new Message ( Role . User , " Is a golden retriever a good family dog? " )
} ;
var chatRequest = new ChatRequest ( messages , Model . GPT4oAudio , audioConfig : Voice . Alloy ) ;
var response = await api . ChatEndpoint . GetCompletionAsync ( chatRequest ) ;
Console . WriteLine ( $" { response . FirstChoice . Message . Role } : { response . FirstChoice } | Finish Reason: { response . FirstChoice . FinishDetails } " ) ;
// todo play response.FirstChoice.Message.AudioOutput.Data La evolución del modo JSON. Si bien ambos aseguran que se produzca JSON válido, solo las salidas estructuradas aseguran la adherencia al esquema.
Importante
finish_reason es longitud, lo que indica que la generación excedió Max_Tokens o la conversación excedió el límite de token. Para protegerse contra esto, verifique finish_reason antes de analizar la respuesta.Primero defina la estructura de sus respuestas. Estos se utilizarán como su esquema. Estos son los objetos que deserializará, así que asegúrese de usar modelos de objetos JSON estándar.
public class MathResponse
{
[ JsonInclude ]
[ JsonPropertyName ( " steps " ) ]
public IReadOnlyList < MathStep > Steps { get ; private set ; }
[ JsonInclude ]
[ JsonPropertyName ( " final_answer " ) ]
public string FinalAnswer { get ; private set ; }
}
public class MathStep
{
[ JsonInclude ]
[ JsonPropertyName ( " explanation " ) ]
public string Explanation { get ; private set ; }
[ JsonInclude ]
[ JsonPropertyName ( " output " ) ]
public string Output { get ; private set ; }
} Para usar, simplemente especifique el tipo de MathResponse como una restricción genérica al solicitar una finalización.
using var api = new OpenAIClient ( ) ;
var messages = new List < Message >
{
new ( Role . System , " You are a helpful math tutor. Guide the user through the solution step by step. " ) ,
new ( Role . User , " how can I solve 8x + 7 = -23 " )
} ;
var chatRequest = new ChatRequest ( messages , model : " gpt-4o-2024-08-06 " ) ;
var ( mathResponse , chatResponse ) = await api . ChatEndpoint . GetCompletionAsync < MathResponse > ( chatRequest ) ;
for ( var i = 0 ; i < mathResponse . Steps . Count ; i ++ )
{
var step = mathResponse . Steps [ i ] ;
Console . WriteLine ( $" Step { i } : { step . Explanation } " ) ;
Console . WriteLine ( $" Result: { step . Output } " ) ;
}
Console . WriteLine ( $" Final Answer: { mathResponse . FinalAnswer } " ) ;
chatResponse . GetUsage ( ) ; Importante
finish_reason es longitud, lo que indica que la generación excedió Max_Tokens o la conversación excedió el límite de token. Para protegerse contra esto, verifique finish_reason antes de analizar la respuesta. var messages = new List < Message >
{
new Message ( Role . System , " You are a helpful assistant designed to output JSON. " ) ,
new Message ( Role . User , " Who won the world series in 2020? " ) ,
} ;
var chatRequest = new ChatRequest ( messages , Model . GPT4o , responseFormat : ChatResponseFormat . Json ) ;
var response = await api . ChatEndpoint . GetCompletionAsync ( chatRequest ) ;
foreach ( var choice in response . Choices )
{
Console . WriteLine ( $" [ { choice . Index } ] { choice . Message . Role } : { choice } | Finish Reason: { choice . FinishReason } " ) ;
}
response . GetUsage ( ) ;Convierte el audio en texto.
Se accede a la API de audio a través de OpenAIClient.AudioEndpoint
Genera audio a partir del texto de entrada.
using var api = new OpenAIClient ( ) ;
var request = new SpeechRequest ( " Hello World! " ) ;
async Task ChunkCallback ( ReadOnlyMemory < byte > chunkCallback )
{
// TODO Implement audio playback as chunks arrive
await Task . CompletedTask ;
}
var response = await api . AudioEndpoint . CreateSpeechAsync ( request , ChunkCallback ) ;
await File . WriteAllBytesAsync ( " ../../../Assets/HelloWorld.mp3 " , response . ToArray ( ) ) ; Transcribe audio al lenguaje de entrada.
using var api = new OpenAIClient ( ) ;
using var request = new AudioTranscriptionRequest ( Path . GetFullPath ( audioAssetPath ) , language : " en " ) ;
var response = await api . AudioEndpoint . CreateTranscriptionTextAsync ( request ) ;
Console . WriteLine ( response ) ; También puede obtener información detallada utilizando verbose_json para obtener granularidades de marca de tiempo:
using var api = new OpenAIClient ( ) ;
using var request = new AudioTranscriptionRequest ( transcriptionAudio , responseFormat : AudioResponseFormat . Verbose_Json , timestampGranularity : TimestampGranularity . Word , temperature : 0.1f , language : " en " ) ;
var response = await api . AudioEndpoint . CreateTranscriptionTextAsync ( request ) ;
foreach ( var word in response . Words )
{
Console . WriteLine ( $" [ { word . Start } - { word . End } ] " { word . Word } " " ) ;
} Traduce el audio al inglés.
using var api = new OpenAIClient ( ) ;
using var request = new AudioTranslationRequest ( Path . GetFullPath ( audioAssetPath ) ) ;
var response = await api . AudioEndpoint . CreateTranslationTextAsync ( request ) ;
Console . WriteLine ( response ) ;Dado un aviso y/o una imagen de entrada, el modelo generará una nueva imagen.
Se accede a la API de imágenes a través de OpenAIClient.ImagesEndpoint
Crea una imagen dada un aviso.
using var api = new OpenAIClient ( ) ;
var request = new ImageGenerationRequest ( " A house riding a velociraptor " , Models . Model . DallE_3 ) ;
var imageResults = await api . ImagesEndPoint . GenerateImageAsync ( request ) ;
foreach ( var image in imageResults )
{
Console . WriteLine ( image ) ;
// image == url or b64_string
} Crea una imagen editada o extendida dada una imagen original y un aviso.
using var api = new OpenAIClient ( ) ;
var request = new ImageEditRequest ( imageAssetPath , maskAssetPath , " A sunlit indoor lounge area with a pool containing a flamingo " , size : ImageSize . Small ) ;
var imageResults = await api . ImagesEndPoint . CreateImageEditAsync ( request ) ;
foreach ( var image in imageResults )
{
Console . WriteLine ( image ) ;
// image == url or b64_string
} Crea una variación de una imagen dada.
using var api = new OpenAIClient ( ) ;
var request = new ImageVariationRequest ( imageAssetPath , size : ImageSize . Small ) ;
var imageResults = await api . ImagesEndPoint . CreateImageVariationAsync ( request ) ;
foreach ( var image in imageResults )
{
Console . WriteLine ( image ) ;
// image == url or b64_string
}Los archivos se utilizan para cargar documentos que se pueden usar con características como el ajuste fino.
Se accede a la API de archivos a través de OpenAIClient.FilesEndpoint
Devuelve una lista de archivos que pertenecen a la organización del usuario.
using var api = new OpenAIClient ( ) ;
var fileList = await api . FilesEndpoint . ListFilesAsync ( ) ;
foreach ( var file in fileList )
{
Console . WriteLine ( $" { file . Id } -> { file . Object } : { file . FileName } | { file . Size } bytes " ) ;
} Cargue un archivo que se pueda usar en varios puntos finales. El tamaño de todos los archivos cargados por una organización puede ser de hasta 100 GB.
El tamaño de los archivos individuales puede ser un máximo de 512 MB. Consulte la Guía de herramientas de asistentes para obtener más información sobre los tipos de archivos compatibles. La API ajustada solo admite archivos .jsonl.
using var api = new OpenAIClient ( ) ;
var file = await api . FilesEndpoint . UploadFileAsync ( " path/to/your/file.jsonl " , FilePurpose . FineTune ) ;
Console . WriteLine ( file . Id ) ; Eliminar un archivo.
using var api = new OpenAIClient ( ) ;
var isDeleted = await api . FilesEndpoint . DeleteFileAsync ( fileId ) ;
Assert . IsTrue ( isDeleted ) ; Devuelve información sobre un archivo específico.
using var api = new OpenAIClient ( ) ;
var file = await api . FilesEndpoint . GetFileInfoAsync ( fileId ) ;
Console . WriteLine ( $" { file . Id } -> { file . Object } : { file . FileName } | { file . Size } bytes " ) ; Descarga el contenido del archivo al directorio especificado.
using var api = new OpenAIClient ( ) ;
var downloadedFilePath = await api . FilesEndpoint . DownloadFileAsync ( fileId , " path/to/your/save/directory " ) ;
Console . WriteLine ( downloadedFilePath ) ;
Assert . IsTrue ( File . Exists ( downloadedFilePath ) ) ;Administre trabajos de ajuste fino para adaptar un modelo a sus datos de capacitación específicos.
Guía relacionada: modelos de ajuste fino
Se accede a la API de archivos a través de OpenAIClient.FineTuningEndpoint
Crea un trabajo que ajusta un modelo especificado de un conjunto de datos dado.
La respuesta incluye detalles del trabajo enqueado, incluido el estado del trabajo y el nombre de los modelos ajustados una vez completados.
using var api = new OpenAIClient ( ) ;
var fileId = " file-abc123 " ;
var request = new CreateFineTuneRequest ( fileId ) ;
var job = await api . FineTuningEndpoint . CreateJobAsync ( Model . GPT3_5_Turbo , request ) ;
Console . WriteLine ( $" Started { job . Id } | Status: { job . Status } " ) ; Enumere los trabajos de ajuste de su organización.
using var api = new OpenAIClient ( ) ;
var jobList = await api . FineTuningEndpoint . ListJobsAsync ( ) ;
foreach ( var job in jobList . Items . OrderByDescending ( job => job . CreatedAt ) )
{
Console . WriteLine ( $" { job . Id } -> { job . CreatedAt } | { job . Status } " ) ;
} Obtiene información sobre el trabajo de ajuste.
using var api = new OpenAIClient ( ) ;
var job = await api . FineTuningEndpoint . GetJobInfoAsync ( fineTuneJob ) ;
Console . WriteLine ( $" { job . Id } -> { job . CreatedAt } | { job . Status } " ) ; Cancelar inmediatamente un trabajo de ajuste.
using var api = new OpenAIClient ( ) ;
var isCancelled = await api . FineTuningEndpoint . CancelFineTuneJobAsync ( fineTuneJob ) ;
Assert . IsTrue ( isCancelled ) ; Obtenga actualizaciones de estado para un trabajo ajustado.
using var api = new OpenAIClient ( ) ;
var eventList = await api . FineTuningEndpoint . ListJobEventsAsync ( fineTuneJob ) ;
Console . WriteLine ( $" { fineTuneJob . Id } -> status: { fineTuneJob . Status } | event count: { eventList . Events . Count } " ) ;
foreach ( var @event in eventList . Items . OrderByDescending ( @event => @event . CreatedAt ) )
{
Console . WriteLine ( $" { @event . CreatedAt } [ { @event . Level } ] { @event . Message } " ) ;
}Cree grandes lotes de solicitudes de API de procesamiento asincrónico. La API por lotes devuelve las finalizaciones dentro de las 24 horas para un descuento del 50%.
Se accede a la API de lotes a través de OpenAIClient.BatchesEndpoint
Enumere los lotes de su organización.
using var api = new OpenAIClient ( ) ;
var batches = await api . BatchEndpoint . ListBatchesAsync ( ) ;
foreach ( var batch in listResponse . Items )
{
Console . WriteLine ( batch ) ;
} Crea y ejecuta un lote desde un archivo cargado de solicitudes
using var api = new OpenAIClient ( ) ;
var batchRequest = new CreateBatchRequest ( " file-id " , Endpoint . ChatCompletions ) ;
var batch = await api . BatchEndpoint . CreateBatchAsync ( batchRequest ) ; Recupera un lote.
using var api = new OpenAIClient ( ) ;
var batch = await api . BatchEndpoint . RetrieveBatchAsync ( " batch-id " ) ;
// you can also use convenience methods!
batch = await batch . UpdateAsync ( ) ;
batch = await batch . WaitForStatusChangeAsync ( ) ; Cancela un lote en progreso. El lote estará en el estado de cancelación por hasta 10 minutos, antes de cambiar a cancelado, donde tendrá resultados parciales (si los hay) disponibles en el archivo de salida.
using var api = new OpenAIClient ( ) ;
var isCancelled = await api . BatchEndpoint . CancelBatchAsync ( batch ) ;
Assert . IsTrue ( isCancelled ) ;Obtenga una representación vectorial de una entrada dada que puede consumirse fácilmente mediante modelos y algoritmos de aprendizaje automático.
Guía relacionada: incrustaciones
Se accede a la API edits a través de OpenAIClient.EmbeddingsEndpoint
Crea un vector de incrustación que representa el texto de entrada.
using var api = new OpenAIClient ( ) ;
var response = await api . EmbeddingsEndpoint . CreateEmbeddingAsync ( " The food was delicious and the waiter... " , Models . Embedding_Ada_002 ) ;
Console . WriteLine ( response ) ;Dado un texto de entrada, sale si el modelo lo clasifica como violando la política de contenido de OpenAI.
Guía relacionada: moderaciones
Se puede acceder a la API de moderaciones a través de OpenAIClient.ModerationsEndpoint
Clasifica si el texto viola la política de contenido de Openai.
using var api = new OpenAIClient ( ) ;
var isViolation = await api . ModerationsEndpoint . GetModerationAsync ( " I want to kill them. " ) ;
Assert . IsTrue ( isViolation ) ;Además, también puede obtener los puntajes de una entrada dada.
using var api = new OpenAIClient ( ) ;
var response = await api . ModerationsEndpoint . CreateModerationAsync ( new ModerationsRequest ( " I love you " ) ) ;
Assert . IsNotNull ( response ) ;
Console . WriteLine ( response . Results ? [ 0 ] ? . Scores ? . ToString ( ) ) ;