Verwenden Sie die OpenAI -API mit Ruby! ? ❤️
Streamen Sie den Text mit GPT-4O, transkribieren und übersetzen Sie Audio mit Flüstern oder erstellen Sie Bilder mit Dall · e ...
Stellen Sie mich ein, um Ihre Schienen+AI -App | zu bauen | Rails ai | ? Ruby AI Builders Discord | ? X | ? Anthropisches Juwel | ? Midjourney Juwel
Fügen Sie diese Zeile der GemFile Ihrer Anwendung hinzu:
gem "ruby-openai"
Und dann ausführen:
$ bundle install
Oder installieren mit:
$ gem install ruby-openai
und erfordern mit:
require "openai"
Für einen kurzen Test können Sie Ihr Token direkt an einen neuen Kunden übergeben:
client = OpenAI :: Client . new (
access_token : "access_token_goes_here" ,
log_errors : true # Highly recommended in development, so you can see what errors OpenAI is returning. Not recommended in production because it could leak private data to your logs.
)
Für ein robusteres Setup können Sie das Edelstein mit Ihren API -Schlüssel konfigurieren, z. B. in einer openai.rb
-Initialisierungsdatei. Niemals Hardcode -Geheimnisse in Ihre Codebasis - verwenden Sie stattdessen so etwas wie dotenv, um die Schlüssel sicher in Ihre Umgebungen zu übergeben.
OpenAI . configure do | config |
config . access_token = ENV . fetch ( "OPENAI_ACCESS_TOKEN" )
config . organization_id = ENV . fetch ( "OPENAI_ORGANIZATION_ID" ) # Optional
config . log_errors = true # Highly recommended in development, so you can see what errors OpenAI is returning. Not recommended in production because it could leak private data to your logs.
end
Dann können Sie einen solchen Kunden erstellen:
client = OpenAI :: Client . new
Sie können die Konfigurationsstandards bei der Herstellung neuer Clients weiterhin überschreiben. Alle nicht enthaltenen Optionen fallen auf eine globale Konfiguration zurück, die mit OpenAi.Configure eingestellt ist. In diesem Beispiel fällt die organisation_id, Request_timeout usw. mit OpenAi.Configure auf einen beliebigen Satz global zurück, wobei nur die Access_Token überschrieben ist:
client = OpenAI :: Client . new ( access_token : "access_token_goes_here" )
request_timeout
übergeben. client = OpenAI :: Client . new (
access_token : "access_token_goes_here" ,
uri_base : "https://oai.hconeai.com/" ,
request_timeout : 240 ,
extra_headers : {
"X-Proxy-TTL" => "43200" , # For https://github.com/6/openai-caching-proxy-worker#specifying-a-cache-ttl
"X-Proxy-Refresh" : "true" , # For https://github.com/6/openai-caching-proxy-worker#refreshing-the-cache
"Helicone-Auth" : "Bearer HELICONE_API_KEY" , # For https://docs.helicone.ai/getting-started/integration-method/openai-proxy
"helicone-stream-force-format" => "true" , # Use this with Helicone otherwise streaming drops chunks # https://github.com/alexrudall/ruby-openai/issues/251
}
)
oder beim Konfigurieren des Edelsteins:
OpenAI . configure do | config |
config . access_token = ENV . fetch ( "OPENAI_ACCESS_TOKEN" )
config . log_errors = true # Optional
config . organization_id = ENV . fetch ( "OPENAI_ORGANIZATION_ID" ) # Optional
config . uri_base = "https://oai.hconeai.com/" # Optional
config . request_timeout = 240 # Optional
config . extra_headers = {
"X-Proxy-TTL" => "43200" , # For https://github.com/6/openai-caching-proxy-worker#specifying-a-cache-ttl
"X-Proxy-Refresh" : "true" , # For https://github.com/6/openai-caching-proxy-worker#refreshing-the-cache
"Helicone-Auth" : "Bearer HELICONE_API_KEY" # For https://docs.helicone.ai/getting-started/integration-method/openai-proxy
} # Optional
end
Sie können Header pro Client -Objekt dynamisch übergeben, die mit allen Headern, die weltweit mit OpenAi.Configure festgelegt sind, zusammengeführt werden:
client = OpenAI :: Client . new ( access_token : "access_token_goes_here" )
client . add_headers ( "X-Proxy-TTL" => "43200" )
Standardmäßig protokolliert ruby-openai
kein Faraday::Error
S, während eine Netzwerkanforderung ausgeführt wird, um Ausspritzdaten zu vermeiden (z. B. 400S, 500S, SSL -Fehler und mehr - hier für eine vollständige Liste der Unterklassen von Faraday::Error
Was kann sie verursachen).
Wenn Sie diese Funktionalität aktivieren möchten, können Sie log_errors
auf true
festlegen, wenn Sie den Client konfigurieren:
client = OpenAI :: Client . new ( log_errors : true )
Sie können Faraday Middleware in einem Block an den Client weitergeben, z. So aktivieren Sie die ausführliche Protokollierung mit Rubys Logger:
client = OpenAI :: Client . new do | f |
f . response :logger , Logger . new ( $stdout ) , bodies : true
end
Um die Azure OpenAI -Service -API zu verwenden, können Sie das Edelstein wie folgt konfigurieren:
OpenAI . configure do | config |
config . access_token = ENV . fetch ( "AZURE_OPENAI_API_KEY" )
config . uri_base = ENV . fetch ( "AZURE_OPENAI_URI" )
config . api_type = :azure
config . api_version = "2023-03-15-preview"
end
wobei AZURE_OPENAI_URI
z. https://custom-domain.openai.azure.com/openai/deployments/gpt-35-turbo
ist
Mit Ollama können Sie Open-Source-LLMs wie Lama 3 vor Ort betreiben. Es bietet Chat -Kompatibilität mit der OpenAI -API.
Sie können Ollama hier herunterladen. Auf macOS können Sie Ollama so installieren und ausführen:
brew install ollama
ollama serve
ollama pull llama3:latest # In new terminal tab.
Erstellen Sie einen Client mit Ihrem Ollama -Server und dem Pulled -Modell und streamen Sie eine Gespräch kostenlos:
client = OpenAI :: Client . new (
uri_base : "http://localhost:11434"
)
client . chat (
parameters : {
model : "llama3" , # Required.
messages : [ { role : "user" , content : "Hello!" } ] , # Required.
temperature : 0.7 ,
stream : proc do | chunk , _bytesize |
print chunk . dig ( "choices" , 0 , "delta" , "content" )
end
}
)
# => Hi! It's nice to meet you. Is there something I can help you with, or would you like to chat?
Der GROQ -API -Chat ist mit der OpenAI -API mit einigen geringfügigen Unterschieden weitgehend kompatibel. Holen Sie sich von hier aus ein Zugangstoken, dann:
client = OpenAI :: Client . new (
access_token : "groq_access_token_goes_here" ,
uri_base : "https://api.groq.com/openai"
)
client . chat (
parameters : {
model : "llama3-8b-8192" , # Required.
messages : [ { role : "user" , content : "Hello!" } ] , # Required.
temperature : 0.7 ,
stream : proc do | chunk , _bytesize |
print chunk . dig ( "choices" , 0 , "delta" , "content" )
end
}
)
OpenAI spricht den Text in Token auf, die Wörter oder Teile der Wörter sind. (Diese Token haben nichts mit Ihrer API Access_Token zu tun.) Tokens zählen können Ihnen helfen, Ihre Kosten abzuschätzen. Es kann Ihnen auch helfen, sicherzustellen, dass Ihre schnelle Textgröße innerhalb der Max-Token-Grenzen des Kontextfensters Ihres Modells liegt, und wählen Sie einen geeigneten Parameter max_tokens
abschließend, damit Ihre Antwort ebenfalls passt.
Um den Token-Count Ihres Textes abzuschätzen:
OpenAI . rough_token_count ( "Your text" )
Wenn Sie eine genauere Anzahl benötigen, versuchen Sie es mit Tiktoken_Ruby.
Es gibt verschiedene Modelle, mit denen Text generiert werden kann. Für eine vollständige Liste und um Informationen zu einem einzelnen Modell abzurufen:
client . models . list
client . models . retrieve ( id : "gpt-4o" )
GPT ist ein Modell, das verwendet werden kann, um Text in einem Konversationsstil zu generieren. Sie können es verwenden, um eine Antwort auf eine Folge von Nachrichten zu generieren:
response = client . chat (
parameters : {
model : "gpt-4o" , # Required.
messages : [ { role : "user" , content : "Hello!" } ] , # Required.
temperature : 0.7 ,
}
)
puts response . dig ( "choices" , 0 , "message" , "content" )
# => "Hello! How may I assist you today?"
Schnellanleitung zum Streaming -Chat mit Rails 7 und Hotwire
Sie können in Echtzeit von der API streamen, was viel schneller sein kann und ein ansprechenderes Benutzererlebnis erstellt. Übergeben Sie einen Proc (oder ein beliebiges Objekt mit einer #call
-Methode) an den stream
-Parameter, um den Strom der Abschlussbrocken zu empfangen, sobald sie generiert werden. Jedes Mal, wenn ein oder mehrere Brocken empfangen werden, wird der Proc mit jedem Stück, das als Hash analysiert wird, einmal aufgerufen. Wenn Openai einen Fehler zurückgibt, erhöht ruby-openai
einen Faraday-Fehler.
client . chat (
parameters : {
model : "gpt-4o" , # Required.
messages : [ { role : "user" , content : "Describe a character called Anna!" } ] , # Required.
temperature : 0.7 ,
stream : proc do | chunk , _bytesize |
print chunk . dig ( "choices" , 0 , "delta" , "content" )
end
}
)
# => "Anna is a young woman in her mid-twenties, with wavy chestnut hair that falls to her shoulders..."
Hinweis: Um Nutzungsinformationen zu erhalten, können Sie den Parameter stream_options
bereitstellen und OpenAI wird einen endgültigen Teil mit der Verwendung bereitstellen. Hier ist ein Beispiel:
stream_proc = proc { | chunk , _bytesize | puts "--------------" ; puts chunk . inspect ; }
client . chat (
parameters : {
model : "gpt-4o" ,
stream : stream_proc ,
stream_options : { include_usage : true } ,
messages : [ { role : "user" , content : "Hello!" } ] ,
}
)
# => --------------
# => {"id"=>"chatcmpl-7bbq05PiZqlHxjV1j7OHnKKDURKaf", "object"=>"chat.completion.chunk", "created"=>1718750612, "model"=>"gpt-4o-2024-05-13", "system_fingerprint"=>"fp_9cb5d38cf7", "choices"=>[{"index"=>0, "delta"=>{"role"=>"assistant", "content"=>""}, "logprobs"=>nil, "finish_reason"=>nil}], "usage"=>nil}
# => --------------
# => {"id"=>"chatcmpl-7bbq05PiZqlHxjV1j7OHnKKDURKaf", "object"=>"chat.completion.chunk", "created"=>1718750612, "model"=>"gpt-4o-2024-05-13", "system_fingerprint"=>"fp_9cb5d38cf7", "choices"=>[{"index"=>0, "delta"=>{"content"=>"Hello"}, "logprobs"=>nil, "finish_reason"=>nil}], "usage"=>nil}
# => --------------
# => ... more content chunks
# => --------------
# => {"id"=>"chatcmpl-7bbq05PiZqlHxjV1j7OHnKKDURKaf", "object"=>"chat.completion.chunk", "created"=>1718750612, "model"=>"gpt-4o-2024-05-13", "system_fingerprint"=>"fp_9cb5d38cf7", "choices"=>[{"index"=>0, "delta"=>{}, "logprobs"=>nil, "finish_reason"=>"stop"}], "usage"=>nil}
# => --------------
# => {"id"=>"chatcmpl-7bbq05PiZqlHxjV1j7OHnKKDURKaf", "object"=>"chat.completion.chunk", "created"=>1718750612, "model"=>"gpt-4o-2024-05-13", "system_fingerprint"=>"fp_9cb5d38cf7", "choices"=>[], "usage"=>{"prompt_tokens"=>9, "completion_tokens"=>9, "total_tokens"=>18}}
Sie können das GPT-4-Vision-Modell verwenden, um eine Beschreibung eines Bildes zu erstellen:
messages = [
{ "type" : "text" , "text" : "What’s in this image?" } ,
{ "type" : "image_url" ,
"image_url" : {
"url" : "https://upload.wikimedia.org/wikipedia/commons/thumb/d/dd/Gfp-wisconsin-madison-the-nature-boardwalk.jpg/2560px-Gfp-wisconsin-madison-the-nature-boardwalk.jpg" ,
} ,
}
]
response = client . chat (
parameters : {
model : "gpt-4-vision-preview" , # Required.
messages : [ { role : "user" , content : messages } ] , # Required.
}
)
puts response . dig ( "choices" , 0 , "message" , "content" )
# => "The image depicts a serene natural landscape featuring a long wooden boardwalk extending straight ahead"
Sie können die Antwort auf Response_Format festlegen, um nach Antworten in JSON zu fragen:
response = client . chat (
parameters : {
model : "gpt-4o" ,
response_format : { type : "json_object" } ,
messages : [ { role : "user" , content : "Hello! Give me some JSON please." } ] ,
temperature : 0.7 ,
} )
puts response . dig ( "choices" , 0 , "message" , "content" )
# =>
# {
# "name": "John",
# "age": 30,
# "city": "New York",
# "hobbies": ["reading", "traveling", "hiking"],
# "isStudent": false
# }
Sie können es auch streamen!
response = client . chat (
parameters : {
model : "gpt-4o" ,
messages : [ { role : "user" , content : "Can I have some JSON please?" } ] ,
response_format : { type : "json_object" } ,
stream : proc do | chunk , _bytesize |
print chunk . dig ( "choices" , 0 , "delta" , "content" )
end
}
)
# =>
# {
# "message": "Sure, please let me know what specific JSON data you are looking for.",
# "JSON_data": {
# "example_1": {
# "key_1": "value_1",
# "key_2": "value_2",
# "key_3": "value_3"
# },
# "example_2": {
# "key_4": "value_4",
# "key_5": "value_5",
# "key_6": "value_6"
# }
# }
# }
Sie können Funktionen beschreiben und übergeben, und das Modell enthält intelligent ein JSON -Objekt, das Argumente enthält, um sie aufzurufen - z. B. um Ihre Methode get_current_weather
zu verwenden, um das Wetter an einem bestimmten Ort zu erhalten. Beachten Sie, dass Tool_Choice optional ist. Wenn Sie es jedoch ausschließen, wählt das Modell, ob die Funktion verwendet wird oder nicht (siehe hier).
def get_current_weather ( location : , unit : "fahrenheit" )
# Here you could use a weather api to fetch the weather.
"The weather in #{ location } is nice ? #{ unit } "
end
messages = [
{
"role" : "user" ,
"content" : "What is the weather like in San Francisco?" ,
} ,
]
response =
client . chat (
parameters : {
model : "gpt-4o" ,
messages : messages , # Defined above because we'll use it again
tools : [
{
type : "function" ,
function : {
name : "get_current_weather" ,
description : "Get the current weather in a given location" ,
parameters : { # Format: https://json-schema.org/understanding-json-schema
type : :object ,
properties : {
location : {
type : :string ,
description : "The city and state, e.g. San Francisco, CA" ,
} ,
unit : {
type : "string" ,
enum : %w[ celsius fahrenheit ] ,
} ,
} ,
required : [ "location" ] ,
} ,
} ,
}
] ,
# Optional, defaults to "auto"
# Can also put "none" or specific functions, see docs
tool_choice : "required"
} ,
)
message = response . dig ( "choices" , 0 , "message" )
if message [ "role" ] == "assistant" && message [ "tool_calls" ]
message [ "tool_calls" ] . each do | tool_call |
tool_call_id = tool_call . dig ( "id" )
function_name = tool_call . dig ( "function" , "name" )
function_args = JSON . parse (
tool_call . dig ( "function" , "arguments" ) ,
{ symbolize_names : true } ,
)
function_response =
case function_name
when "get_current_weather"
get_current_weather ( ** function_args ) # => "The weather is nice ?"
else
# decide how to handle
end
# For a subsequent message with the role "tool", OpenAI requires the preceding message to have a tool_calls argument.
messages << message
messages << {
tool_call_id : tool_call_id ,
role : "tool" ,
name : function_name ,
content : function_response
} # Extend the conversation with the results of the functions
end
second_response = client . chat (
parameters : {
model : "gpt-4o" ,
messages : messages
}
)
puts second_response . dig ( "choices" , 0 , "message" , "content" )
# At this point, the model has decided to call functions, you've called the functions
# and provided the response back, and the model has considered this and responded.
end
# => "It looks like the weather is nice and sunny in San Francisco! If you're planning to go out, it should be a pleasant day."
Drücken Sie die OpenAI-API für eine Fertigstellung mit anderen GPT-3-Modellen:
response = client . completions (
parameters : {
model : "gpt-4o" ,
prompt : "Once upon a time" ,
max_tokens : 5
}
)
puts response [ "choices" ] . map { | c | c [ "text" ] }
# => [", there lived a great"]
Sie können den Endpoint -Emboden -Endpunkt verwenden, um einen Vektor von Zahlen zu erhalten, die einen Eingang darstellen. Sie können diese Vektoren dann für verschiedene Eingänge vergleichen, um effizient zu überprüfen, wie ähnlich die Eingänge sind.
response = client . embeddings (
parameters : {
model : "text-embedding-ada-002" ,
input : "The food was delicious and the waiter..."
}
)
puts response . dig ( "data" , 0 , "embedding" )
# => Vector representation of your embedding
Mit dem Batches -Endpunkt können Sie große Stapel von API -Anfragen erstellen und verwalten, um asynchron auszuführen. Derzeit sind die unterstützten Endpunkte für Stapel /v1/chat/completions
(CHAT -Abschlüsse -API) und /v1/embeddings
(Embettdings -API).
Um den Batches -Endpunkt zu verwenden, müssen Sie zunächst eine JSONL -Datei hochladen, die die Batch -Anforderungen über den Dateienendpunkt enthält. Die Datei muss mit dem für batch
festgelegten Zweck hochgeladen werden. Jede Zeile in der JSONL -Datei stellt eine einzige Anfrage dar und sollte das folgende Format haben:
{
"custom_id" : " request-1 " ,
"method" : " POST " ,
"url" : " /v1/chat/completions " ,
"body" : {
"model" : " gpt-4o " ,
"messages" : [
{ "role" : " system " , "content" : " You are a helpful assistant. " },
{ "role" : " user " , "content" : " What is 2+2? " }
]
}
}
Sobald Sie die JSONL -Datei hochgeladen haben, können Sie eine neue Stapel erstellen, indem Sie das Fenster Datei -ID, Endpunkt und Abschluss angeben:
response = client . batches . create (
parameters : {
input_file_id : "file-abc123" ,
endpoint : "/v1/chat/completions" ,
completion_window : "24h"
}
)
batch_id = response [ "id" ]
Sie können Informationen zu einem bestimmten Stapel mit seiner ID abrufen:
batch = client . batches . retrieve ( id : batch_id )
Um eine Stapel zu stornieren, die im Gange ist:
client . batches . cancel ( id : batch_id )
Sie können auch alle Chargen auflisten:
client . batches . list
Sobald die Batch ["ferast_at"] vorhanden ist, können Sie die Ausgabe- oder Fehlerdateien abrufen:
batch = client . batches . retrieve ( id : batch_id )
output_file_id = batch [ "output_file_id" ]
output_response = client . files . content ( id : output_file_id )
error_file_id = batch [ "error_file_id" ]
error_response = client . files . content ( id : error_file_id )
Diese Dateien befinden sich im JSONL -Format, wobei jede Zeile die Ausgabe oder den Fehler für eine einzelne Anforderung darstellt. Die Linien können in beliebiger Reihenfolge sein:
{
"id" : " response-1 " ,
"custom_id" : " request-1 " ,
"response" : {
"id" : " chatcmpl-abc123 " ,
"object" : " chat.completion " ,
"created" : 1677858242 ,
"model" : " gpt-4o " ,
"choices" : [
{
"index" : 0 ,
"message" : {
"role" : " assistant " ,
"content" : " 2+2 equals 4. "
}
}
]
}
}
Wenn eine Anforderung mit einem Nicht-HTTP-Fehler fehlschlägt, enthält das Fehlerobjekt weitere Informationen über die Ursache des Fehlers.
Legen Sie Ihre Daten in eine .jsonl
-Datei wie folgt ein:
{ "prompt" : " Overjoyed with my new phone! -> " , "completion" : " positive " }
{ "prompt" : " @lakers disappoint for a third straight night -> " , "completion" : " negative " }
und überlasten Sie den Pfad (oder ein Stringio -Objekt) an client.files.upload
, um ihn auf das Öffnen zu laden, und interagieren Sie dann mit ihm:
client . files . upload ( parameters : { file : "path/to/sentiment.jsonl" , purpose : "fine-tune" } )
client . files . list
client . files . retrieve ( id : "file-123" )
client . files . content ( id : "file-123" )
client . files . delete ( id : "file-123" )
Sie können einen Dateipfad senden:
client . files . upload ( parameters : { file : "path/to/file.pdf" , purpose : "assistants" } )
oder ein Dateiobjekt
my_file = File . open ( "path/to/file.pdf" , "rb" )
client . files . upload ( parameters : { file : my_file , purpose : "assistants" } )
Siehe unterstützte Dateitypen in der API -Dokumentation.
Laden Sie Ihre Feinabstimmungsdaten wie oben in eine .jsonl
Datei hoch und erhalten Sie die ID:
response = client . files . upload ( parameters : { file : "path/to/sarcasm.jsonl" , purpose : "fine-tune" } )
file_id = JSON . parse ( response . body ) [ "id" ]
Sie können diese Datei -ID dann verwenden, um einen Feinabstimmungsjob zu erstellen:
response = client . finetunes . create (
parameters : {
training_file : file_id ,
model : "gpt-4o"
} )
fine_tune_id = response [ "id" ]
Das gibt Ihnen die Fein-Tune-ID. Wenn Sie einen Fehler gemacht haben, können Sie das Fein-Tune-Modell abbrechen, bevor es verarbeitet wird:
client . finetunes . cancel ( id : fine_tune_id )
Möglicherweise müssen Sie eine kurze Zeit warten, bis die Verarbeitung abgeschlossen ist. Sobald Sie verarbeitet wurden, können Sie List oder Abruf verwenden, um den Namen des fein abgestimmten Modells zu erhalten:
client . finetunes . list
response = client . finetunes . retrieve ( id : fine_tune_id )
fine_tuned_model = response [ "fine_tuned_model" ]
Dieser fein abgestimmte Modellname kann dann in den Chat-Abschluss verwendet werden:
response = client . chat (
parameters : {
model : fine_tuned_model ,
messages : [ { role : "user" , content : "I love Mondays!" } ]
}
)
response . dig ( "choices" , 0 , "message" , "content" )
Sie können auch die Ereignisse für einen Job erfassen:
client . finetunes . list_events ( id : fine_tune_id )
Vektorspeicherobjekte geben dem Dateisuch -Tool die Möglichkeit, Ihre Dateien zu durchsuchen.
Sie können einen neuen Vektor Store erstellen:
response = client . vector_stores . create (
parameters : {
name : "my vector store" ,
file_ids : [ "file-abc123" , "file-def456" ]
}
)
vector_store_id = response [ "id" ]
Bei einem vector_store_id
können Sie die aktuellen Feldwerte retrieve
:
client . vector_stores . retrieve ( id : vector_store_id )
Sie können eine list
aller Vektor -Stores erhalten, die derzeit unter der Organisation verfügbar sind:
client . vector_stores . list
Sie können einen vorhandenen Vektorspeicher mit Ausnahme der file_ids
ändern:
response = client . vector_stores . modify (
id : vector_store_id ,
parameters : {
name : "Modified Test Vector Store" ,
}
)
Sie können Vektor -Stores löschen:
client . vector_stores . delete ( id : vector_store_id )
Vektorspeicherdateien stellen Dateien in einem Vektorspeicher dar.
Sie können eine neue Vektorspeicherdatei erstellen, indem Sie eine Datei an einen Vektorspeicher anhängen.
response = client . vector_store_files . create (
vector_store_id : "vector-store-abc123" ,
parameters : {
file_id : "file-abc123"
}
)
vector_store_file_id = response [ "id" ]
Bei einem vector_store_file_id
können Sie die aktuellen Feldwerte retrieve
:
client . vector_store_files . retrieve (
vector_store_id : "vector-store-abc123" ,
id : vector_store_file_id
)
Sie erhalten eine list
aller Vektorspeicherdateien, die derzeit im Vektor Store verfügbar sind:
client . vector_store_files . list ( vector_store_id : "vector-store-abc123" )
Sie können eine Vektorspeicherdatei löschen:
client . vector_store_files . delete (
vector_store_id : "vector-store-abc123" ,
id : vector_store_file_id
)
Hinweis: Dadurch wird die Datei aus dem Vektorspeicher entfernt, die Datei selbst wird jedoch nicht gelöscht. Um die Datei zu löschen, verwenden Sie den Endpunkt der Datei löschen.
Vektorspeicherdateistapel stellen Vorgänge dar, um mehrere Dateien zu einem Vektorspeicher hinzuzufügen.
Sie können eine neue Vektorspeicherdatei -Stapel erstellen, indem Sie mehrere Dateien an einen Vektorspeicher anhängen.
response = client . vector_store_file_batches . create (
vector_store_id : "vector-store-abc123" ,
parameters : {
file_ids : [ "file-abc123" , "file-def456" ]
}
)
file_batch_id = response [ "id" ]
Bei einer file_batch_id
können Sie die aktuellen Feldwerte retrieve
:
client . vector_store_file_batches . retrieve (
vector_store_id : "vector-store-abc123" ,
id : file_batch_id
)
Sie können eine list
aller Vektorspeicherdateien in einer Stapel erhalten, die derzeit im Vektor Store verfügbar ist:
client . vector_store_file_batches . list (
vector_store_id : "vector-store-abc123" ,
id : file_batch_id
)
Sie können einen Vektorspeicherdatei -Stapel stornieren (dies wird versucht, die Verarbeitung von Dateien in diesem Stapel so schnell wie möglich zu stornieren):
client . vector_store_file_batches . cancel (
vector_store_id : "vector-store-abc123" ,
id : file_batch_id
)
Assistenten sind staatliche Akteure, die viele Gespräche führen und Tools verwenden können, um Aufgaben auszuführen (siehe Assistantübersicht).
Um einen neuen Assistenten zu erstellen:
response = client . assistants . create (
parameters : {
model : "gpt-4o" ,
name : "OpenAI-Ruby test assistant" ,
description : nil ,
instructions : "You are a Ruby dev bot. When asked a question, write and run Ruby code to answer the question" ,
tools : [
{ type : "code_interpreter" } ,
{ type : "file_search" }
] ,
tool_resources : {
code_interpreter : {
file_ids : [ ] # See Files section above for how to upload files
} ,
file_search : {
vector_store_ids : [ ] # See Vector Stores section above for how to add vector stores
}
} ,
"metadata" : { my_internal_version_id : "1.0.0" }
}
)
assistant_id = response [ "id" ]
Bei einem assistant_id
können Sie die aktuellen Feldwerte retrieve
:
client . assistants . retrieve ( id : assistant_id )
Sie können eine list
aller Assistenten erhalten, die derzeit unter der Organisation verfügbar sind:
client . assistants . list
Sie können einen vorhandenen Assistenten mit der ID des Assistenten ändern (siehe API -Dokumentation):
response = client . assistants . modify (
id : assistant_id ,
parameters : {
name : "Modified Test Assistant for OpenAI-Ruby" ,
metadata : { my_internal_version_id : '1.0.1' }
}
)
Sie können Assistenten löschen:
client . assistants . delete ( id : assistant_id )
Sobald Sie wie oben beschrieben einen Assistenten erstellt haben, müssen Sie einen Messages
Thread
für den Assistenten vorbereiten, an dem Sie arbeiten können (siehe Einführung zu Assistenten). Zum Beispiel können Sie als Erstaufbau:
# Create thread
response = client . threads . create # Note: Once you create a thread, there is no way to list it
# or recover it currently (as of 2023-12-10). So hold onto the `id`
thread_id = response [ "id" ]
# Add initial message from user (see https://platform.openai.com/docs/api-reference/messages/createMessage)
message_id = client . messages . create (
thread_id : thread_id ,
parameters : {
role : "user" , # Required for manually created messages
content : "Can you help me write an API library to interact with the OpenAI API please?"
}
) [ "id" ]
# Retrieve individual message
message = client . messages . retrieve ( thread_id : thread_id , id : message_id )
# Review all messages on the thread
messages = client . messages . list ( thread_id : thread_id )
Nachdem ein Faden aufräumen, wird nicht mehr benötigt:
# To delete the thread (and all associated messages):
client . threads . delete ( id : thread_id )
client . messages . retrieve ( thread_id : thread_id , id : message_id ) # -> Fails after thread is deleted
Um einen Thread einzureichen, der mit dem Modell eines Assistenten bewertet werden soll, erstellen Sie wie folgt einen Run
:
# Create run (will use instruction/model/tools from Assistant's definition)
response = client . runs . create (
thread_id : thread_id ,
parameters : {
assistant_id : assistant_id ,
max_prompt_tokens : 256 ,
max_completion_tokens : 16
}
)
run_id = response [ 'id' ]
Sie können die Nachrichtenbrocken streamen, sobald sie durchkommen:
client . runs . create (
thread_id : thread_id ,
parameters : {
assistant_id : assistant_id ,
max_prompt_tokens : 256 ,
max_completion_tokens : 16 ,
stream : proc do | chunk , _bytesize |
if chunk [ "object" ] == "thread.message.delta"
print chunk . dig ( "delta" , "content" , 0 , "text" , "value" )
end
end
}
)
Um den Status eines Laufs zu erhalten:
response = client . runs . retrieve ( id : run_id , thread_id : thread_id )
status = response [ 'status' ]
Die status
kann die folgenden Zeichenfolgen enthalten, queued
, in_progress
, requires_action
, cancelling
, cancelled
, failed
, completed
oder expired
die Sie wie folgt verarbeiten können:
while true do
response = client . runs . retrieve ( id : run_id , thread_id : thread_id )
status = response [ 'status' ]
case status
when 'queued' , 'in_progress' , 'cancelling'
puts 'Sleeping'
sleep 1 # Wait one second and poll again
when 'completed'
break # Exit loop and report result to user
when 'requires_action'
# Handle tool calls (see below)
when 'cancelled' , 'failed' , 'expired'
puts response [ 'last_error' ] . inspect
break # or `exit`
else
puts "Unknown status response: #{ status } "
end
end
Wenn die status
angibt, dass der run
completed
ist, enthält der zugehörige thread
eine oder mehrere neue messages
:
# Either retrieve all messages in bulk again, or...
messages = client . messages . list ( thread_id : thread_id , parameters : { order : 'asc' } )
# Alternatively retrieve the `run steps` for the run which link to the messages:
run_steps = client . run_steps . list ( thread_id : thread_id , run_id : run_id , parameters : { order : 'asc' } )
new_message_ids = run_steps [ 'data' ] . filter_map do | step |
if step [ 'type' ] == 'message_creation'
step . dig ( 'step_details' , "message_creation" , "message_id" )
end # Ignore tool calls, because they don't create new messages.
end
# Retrieve the individual messages
new_messages = new_message_ids . map do | msg_id |
client . messages . retrieve ( id : msg_id , thread_id : thread_id )
end
# Find the actual response text in the content array of the messages
new_messages . each do | msg |
msg [ 'content' ] . each do | content_item |
case content_item [ 'type' ]
when 'text'
puts content_item . dig ( 'text' , 'value' )
# Also handle annotations
when 'image_file'
# Use File endpoint to retrieve file contents via id
id = content_item . dig ( 'image_file' , 'file_id' )
end
end
end
Sie können die Metadaten auch auf Nachrichten aktualisieren, einschließlich Nachrichten, die vom Assistenten stammen.
metadata = {
user_id : "abc123"
}
message = client . messages . modify (
id : message_id ,
thread_id : thread_id ,
parameters : { metadata : metadata } ,
)
Sie können jederzeit alle Läufe auflisten, die in einem bestimmten Thread durchgeführt wurden oder derzeit ausgeführt werden:
client . runs . list ( thread_id : thread_id , parameters : { order : "asc" , limit : 3 } )
Sie können auch einen Thread erstellen und in einem Anruf wie folgt ausführen:
response = client . runs . create_thread_and_run ( parameters : { assistant_id : assistant_id } )
run_id = response [ 'id' ]
thread_id = response [ 'thread_id' ]
Sie können Bilder in einen Thread aufnehmen und diese werden von der LLM beschrieben und gelesen. In diesem Beispiel verwende ich diese Datei:
require "openai"
# Make a client
client = OpenAI :: Client . new (
access_token : "access_token_goes_here" ,
log_errors : true # Don't log errors in production.
)
# Upload image as a file
file_id = client . files . upload (
parameters : {
file : "path/to/example.png" ,
purpose : "assistants" ,
}
) [ "id" ]
# Create assistant (You could also use an existing one here)
assistant_id = client . assistants . create (
parameters : {
model : "gpt-4o" ,
name : "Image reader" ,
instructions : "You are an image describer. You describe the contents of images." ,
}
) [ "id" ]
# Create thread
thread_id = client . threads . create [ "id" ]
# Add image in message
client . messages . create (
thread_id : thread_id ,
parameters : {
role : "user" , # Required for manually created messages
content : [
{
"type" : "text" ,
"text" : "What's in this image?"
} ,
{
"type" : "image_file" ,
"image_file" : { "file_id" : file_id }
}
]
}
)
# Run thread
run_id = client . runs . create (
thread_id : thread_id ,
parameters : { assistant_id : assistant_id }
) [ "id" ]
# Wait until run in complete
status = nil
until status == "completed" do
sleep ( 0.1 )
status = client . runs . retrieve ( id : run_id , thread_id : thread_id ) [ 'status' ]
end
# Get the response
messages = client . messages . list ( thread_id : thread_id , parameters : { order : 'asc' } )
messages . dig ( "data" , - 1 , "content" , 0 , "text" , "value" )
=> "The image contains a placeholder graphic with a tilted, stylized representation of a postage stamp in the top part, which includes an abstract landscape with hills and a sun. Below the stamp, in the middle of the image, there is italicized text in a light golden color that reads, " This is just an example. " The background is a light pastel shade, and a yellow border frames the entire image."
Falls Sie dem Assistenten erlauben, auf function
zugreifen zu können (er werden auf die gleiche Weise wie Funktionen während der Chat -Fertigstellung definiert), erhalten Sie möglicherweise einen Statuscode von requires_action
, wenn der Assistent möchte, dass Sie eine oder mehrere Funktionstools bewerten:
def get_current_weather ( location : , unit : "celsius" )
# Your function code goes here
if location =~ /San Francisco/i
return unit == "celsius" ? "The weather is nice ? at 27°C" : "The weather is nice ? at 80°F"
else
return unit == "celsius" ? "The weather is icy ? at -5°C" : "The weather is icy ? at 23°F"
end
end
if status == 'requires_action'
tools_to_call = response . dig ( 'required_action' , 'submit_tool_outputs' , 'tool_calls' )
my_tool_outputs = tools_to_call . map { | tool |
# Call the functions based on the tool's name
function_name = tool . dig ( 'function' , 'name' )
arguments = JSON . parse (
tool . dig ( "function" , "arguments" ) ,
{ symbolize_names : true } ,
)
tool_output = case function_name
when "get_current_weather"
get_current_weather ( ** arguments )
end
{
tool_call_id : tool [ 'id' ] ,
output : tool_output ,
}
}
client . runs . submit_tool_outputs (
thread_id : thread_id ,
run_id : run_id ,
parameters : { tool_outputs : my_tool_outputs }
)
end
Beachten Sie, dass Sie 10 Minuten Zeit haben, um Ihre Toolausgabe einzureichen, bevor der Lauf abgelaufen ist.
Atmen Sie tief ein. Möglicherweise brauchen Sie ein Getränk für diesen.
Es ist möglich, dass OpenAI teilen, welche Teile es in seiner internen Lag -Pipeline verwendet hat, um seine Dateisearch -Ergebnisse zu erstellen.
Eine Beispielspezifikation finden Sie hier, die dies tun, nur damit Sie wissen, dass dies möglich ist.
Hier erfahren Sie, wie Sie die Brocken in einer Dateisuche verwenden können. In diesem Beispiel verwende ich diese Datei:
require "openai"
# Make a client
client = OpenAI :: Client . new (
access_token : "access_token_goes_here" ,
log_errors : true # Don't log errors in production.
)
# Upload your file(s)
file_id = client . files . upload (
parameters : {
file : "path/to/somatosensory.pdf" ,
purpose : "assistants"
}
) [ "id" ]
# Create a vector store to store the vectorised file(s)
vector_store_id = client . vector_stores . create ( parameters : { } ) [ "id" ]
# Vectorise the file(s)
vector_store_file_id = client . vector_store_files . create (
vector_store_id : vector_store_id ,
parameters : { file_id : file_id }
) [ "id" ]
# Check that the file is vectorised (wait for status to be "completed")
client . vector_store_files . retrieve ( vector_store_id : vector_store_id , id : vector_store_file_id ) [ "status" ]
# Create an assistant, referencing the vector store
assistant_id = client . assistants . create (
parameters : {
model : "gpt-4o" ,
name : "Answer finder" ,
instructions : "You are a file search tool. Find the answer in the given files, please." ,
tools : [
{ type : "file_search" }
] ,
tool_resources : {
file_search : {
vector_store_ids : [ vector_store_id ]
}
}
}
) [ "id" ]
# Create a thread with your question
thread_id = client . threads . create ( parameters : {
messages : [
{ role : "user" ,
content : "Find the description of a nociceptor." }
]
} ) [ "id" ]
# Run the thread to generate the response. Include the "GIVE ME THE CHUNKS" incantation.
run_id = client . runs . create (
thread_id : thread_id ,
parameters : {
assistant_id : assistant_id
} ,
query_parameters : { include : [ "step_details.tool_calls[*].file_search.results[*].content" ] } # incantation
) [ "id" ]
# Get the steps that happened in the run
steps = client . run_steps . list (
thread_id : thread_id ,
run_id : run_id ,
parameters : { order : "asc" }
)
# Retrieve all the steps. Include the "GIVE ME THE CHUNKS" incantation again.
steps = steps [ "data" ] . map do | step |
client . run_steps . retrieve (
thread_id : thread_id ,
run_id : run_id ,
id : step [ "id" ] ,
parameters : { include : [ "step_details.tool_calls[*].file_search.results[*].content" ] } # incantation
)
end
# Now we've got the chunk info, buried deep. Loop through the steps and find chunks if included:
chunks = steps . flat_map do | step |
included_results = step . dig ( "step_details" , "tool_calls" , 0 , "file_search" , "results" )
next if included_results . nil? || included_results . empty?
included_results . flat_map do | result |
result [ "content" ] . map do | content |
content [ "text" ]
end
end
end . compact
# The first chunk will be the closest match to the prompt. Finally, if you want to view the completed message(s):
client . messages . list ( thread_id : thread_id )
Generieren Sie Bilder mit Dall · e 2 oder dall · e 3!
Für dall · e 2 muss die Größe aller erzeugten Bilder eines von 256x256
, 512x512
oder 1024x1024
sein - wenn nicht angegeben, dass das Bild standardmäßig 1024x1024
ist.
response = client . images . generate (
parameters : {
prompt : "A baby sea otter cooking pasta wearing a hat of some sort" ,
size : "256x256" ,
}
)
puts response . dig ( "data" , 0 , "url" )
# => "https://oaidalleapiprodscus.blob.core.windows.net/private/org-Rf437IxKhh..."
Für dall · e 3 muss die Größe aller erzeugten Bilder eines von 1024x1024
, 1024x1792
oder 1792x1024
sein. Zusätzlich kann die Qualität des Bildes entweder für standard
oder hd
angegeben werden.
response = client . images . generate (
parameters : {
prompt : "A springer spaniel cooking pasta wearing a hat of some sort" ,
model : "dall-e-3" ,
size : "1024x1792" ,
quality : "standard" ,
}
)
puts response . dig ( "data" , 0 , "url" )
# => "https://oaidalleapiprodscus.blob.core.windows.net/private/org-Rf437IxKhh..."
Füllen Sie den transparenten Teil eines Bildes aus oder laden Sie eine Maske mit transparenten Abschnitten hoch, um die Teile eines Bildes anzuzeigen, die gemäß Ihrer Eingabeaufforderung geändert werden können ...
response = client . images . edit (
parameters : {
prompt : "A solid red Ruby on a blue background" ,
image : "image.png" ,
mask : "mask.png" ,
}
)
puts response . dig ( "data" , 0 , "url" )
# => "https://oaidalleapiprodscus.blob.core.windows.net/private/org-Rf437IxKhh..."
Erstellen Sie n Variationen eines Bildes.
response = client . images . variations ( parameters : { image : "image.png" , n : 2 } )
puts response . dig ( "data" , 0 , "url" )
# => "https://oaidalleapiprodscus.blob.core.windows.net/private/org-Rf437IxKhh..."
Überprüfen Sie eine Zeichenfolge, um zu überprüfen, ob sie gegen OpenAIs Inhaltspolitik verstößt:
response = client . moderations ( parameters : { input : "I'm worried about that." } )
puts response . dig ( "results" , 0 , "category_scores" , "hate" )
# => 5.505014632944949e-05
Whisper ist eine Sprache zu Textmodell, mit der Text basierend auf Audiodateien erstellt werden kann:
Die Übersetzungs -API nimmt die Audiodatei in einer der unterstützten Sprachen ein und transkreibt das Audio ins Englische.
response = client . audio . translate (
parameters : {
model : "whisper-1" ,
file : File . open ( "path_to_file" , "rb" ) ,
}
)
puts response [ "text" ]
# => "Translation of the text"
Die Transkriptions -API nimmt die Audiodatei, die Sie transkribieren möchten, als Eingabe ein und gibt den Text im gewünschten Ausgabedateiformat zurück.
Sie können die Sprache der Audiodatei übergeben, um die Transkriptionsqualität zu verbessern. Unterstützte Sprachen sind hier aufgeführt. Sie müssen die Sprache als ISO-639-1 Code angeben, z. "en" für Englisch oder "NE" für Nepali. Hier können Sie die Codes nachschlagen.
response = client . audio . transcribe (
parameters : {
model : "whisper-1" ,
file : File . open ( "path_to_file" , "rb" ) ,
language : "en" , # Optional
}
)
puts response [ "text" ]
# => "Transcription of the text"
Die Sprach -API nimmt den Text und eine Stimme ein und gibt den Inhalt einer Audiodatei zurück, die Sie anhören können.
response = client . audio . speech (
parameters : {
model : "tts-1" ,
input : "This is a speech test!" ,
voice : "alloy" ,
response_format : "mp3" , # Optional
speed : 1.0 , # Optional
}
)
File . binwrite ( 'demo.mp3' , response )
# => mp3 file that plays: "This is a speech test!"
HTTP -Fehler können so erfasst werden:
begin
OpenAI :: Client . new . models . retrieve ( id : "gpt-4o" )
rescue Faraday :: Error => e
raise "Got a Faraday error: #{ e } "
end
Führen Sie bin/setup
nach dem Auschecken des Repo aus, um Abhängigkeiten zu installieren. Sie können bin/console
für eine interaktive Eingabeaufforderung ausführen, mit der Sie experimentieren können.
Um dieses Juwel auf Ihrem lokalen Computer zu installieren, führen Sie bundle exec rake install
aus.
Führen Sie zum Ausführen aller Tests den bundle exec rake
aus, mit dem auch der Rubocop ausgeführt wird. Dieses Repository verwendet VCR, um API -Anforderungen zu protokollieren.
Warnung
Wenn Sie in Ihrer ENV
eine OPENAI_ACCESS_TOKEN
haben, werden die Spezifikationen verwendet, um die Spezifikationen gegen die tatsächliche API auszuführen, die langsam und Sie Geld kosten - 2 Cent oder mehr! Entfernen Sie es aus Ihrer Umgebung mit unset
oder ähnlicher, wenn Sie nur die Spezifikationen mit den gespeicherten VCR -Antworten ausführen möchten.
Führen Sie zuerst die Spezifikationen ohne VCR aus, damit sie tatsächlich die API treffen. Dies kostet 2 Cent oder mehr. Setzen Sie OpenAI_ACCESS_TOOKE in Ihrer Umgebung oder geben Sie sie wie folgt ein:
OPENAI_ACCESS_TOKEN=123abc bundle exec rspec
Aktualisieren bundle exec rake release
dann die Versionsnummer in version.rb
, bundle install
CHANGELOG.md
. Die .gem
-Datei zu Rubygemems.org.
Fehlerberichte und Pull-Anfragen sind auf Github unter https://github.com/alexrudall/ruby-openai willkommen. Dieses Projekt soll ein sicherer, einladender Raum für die Zusammenarbeit sein, und die Mitwirkenden sollen sich an den Verhaltenskodex halten.
Das Edelstein ist unter den Bedingungen der MIT -Lizenz als Open Source erhältlich.
Jeder, der in den Codebasen, Ausgabeträgern, Chatrooms und Mailinglisten des Ruby OpenAI -Projekts interagiert, wird voraussichtlich dem Verhaltenskodex folgen.