將OpenAi API與Ruby一起使用! ?❤️
帶有GPT-4O的文字,用耳語轉錄和翻譯音頻,或用dall·e ...創建圖像...
僱用我建造您的軌道+AI應用程序|鐵軌AI | ? Ruby AI Builders Discord | ? X | ?人類寶石| ? Midjourney寶石
將此行添加到您的應用程序的gemfile:
gem "ruby-openai"
然後執行:
$ bundle install
或安裝:
$ gem install ruby-openai
並需要:
require "openai"
對於快速測試,您可以將令牌直接傳遞給新客戶:
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.
)
要進行更強大的設置,您可以使用API鍵配置GEM,例如在openai.rb
初始化文件中。切勿進入代碼庫中的硬碼秘密 - 使用Dotenv之類的東西將鑰匙安全地傳遞到您的環境中。
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
然後,您可以創建這樣的客戶:
client = OpenAI :: Client . new
在建立新客戶端時,您仍然可以覆蓋配置默認值;任何未包含的選項都將返回到帶有OpenAi.configure的任何全局配置集。例如在此示例中
client = OpenAI :: Client . new ( access_token : "access_token_goes_here" )
request_timeout
來更改。 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
}
)
或配置寶石時:
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
您可以動態通過每個客戶端對象的標題,該對象將與openai.configure全球設置的任何標頭合併:
client = OpenAI :: Client . new ( access_token : "access_token_goes_here" )
client . add_headers ( "X-Proxy-TTL" => "43200" )
默認情況下, ruby-openai
在執行網絡請求以避免洩漏數據時遇到的任何Faraday::Error
Faraday::Error
(例如400,500s,SSL錯誤等等)什麼會導致他們)。
如果您想啟用此功能,則可以在配置客戶端時將log_errors
設置為true
:
client = OpenAI :: Client . new ( log_errors : true )
您可以將Faraday中間件傳遞給客戶端,例如。用Ruby的Logger啟用詳細記錄:
client = OpenAI :: Client . new do | f |
f . response :logger , Logger . new ( $stdout ) , bodies : true
end
要使用Azure OpenAI Service API,您可以像這樣配置GEM:
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
哪裡是AZURE_OPENAI_URI
,例如https://custom-domain.openai.azure.com/openai/deployments/gpt-35-turbo
Ollama允許您在本地運行開源LLM,例如Llama 3。它提供與OpenAI API的聊天兼容性。
您可以在這裡下載Ollama。在MacOS上,您可以像這樣安裝和運行Ollama:
brew install ollama
ollama serve
ollama pull llama3:latest # In new terminal tab.
使用您的Ollama服務器和拉動模型創建客戶端,並免費流式傳輸對話:
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?
GROQ API聊天與OpenAI API廣泛兼容,存在一些較小的差異。然後從這裡獲取訪問令牌:
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解析促使文本進入令牌,這是單詞或單詞的一部分。 (這些令牌與您的API Access_Token無關。)計數令牌可以幫助您估計成本。它還可以幫助您確保提示文本大小在模型上下文窗口的最大限制範圍內,並選擇適當的max_tokens
完成參數,以便您的響應也適合。
估計文本的令牌計數:
OpenAI . rough_token_count ( "Your text" )
如果您需要更準確的計數,請嘗試Tiktoken_ruby。
有不同的模型可用於生成文本。有關完整列表並檢索有關單個模型的信息:
client . models . list
client . models . retrieve ( id : "gpt-4o" )
GPT是一種模型,可用於以對話方式生成文本。您可以使用它來生成對一系列消息序列的響應:
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?"
與Rails 7和Hotwire進行流式聊天的快速指南
您可以實時從API流式傳輸,這可以快得多,並用於創建更具吸引力的用戶體驗。將PROC(或具有#call
方法的任何對象)傳遞到stream
參數,以接收生成的完成塊的流。每次收到一個或多個塊時,每個塊都會被調用一次,將其作為哈希解析。如果Openai返回錯誤, ruby-openai
將引起法拉第錯誤。
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..."
注意:為了獲取用法信息,您可以提供stream_options
參數,OpenAI將提供最終的用法。這是一個示例:
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}}
您可以使用GPT-4視覺模型來生成圖像的描述:
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"
您可以將Response_format設置以在JSON中要求響應:
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
# }
您也可以流式傳輸!
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"
# }
# }
# }
您可以描述和傳遞功能,模型將智能選擇輸出包含參數的JSON對象,例如,使用您的方法get_current_weather
來使天氣在給定的位置中獲取天氣。請注意,Tool_Choice是可選的,但是如果將其排除在外,則該模型將選擇是否使用該功能(請參見此處)。
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."
使用其他GPT-3型號擊中OpenAI API進行完成:
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"]
您可以使用嵌入式端點獲取代表輸入的數字向量。然後,您可以比較這些向量的不同輸入,以有效檢查輸入的相似之處。
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
批處理端點使您可以創建和管理大量API請求以異步運行。當前,批處理的受支持的端點是/v1/chat/completions
(聊天完成API)和/v1/embeddings
(嵌入式API)。
要使用批處理端點,您需要先使用文件端點上傳包含批處理請求的JSONL文件。該文件必須在批處理中上傳到batch
。 JSONL文件中的每一行都代表一個請求,應具有以下格式:
{
"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? " }
]
}
}
上傳JSONL文件後,您可以通過提供文件ID,端點和完成窗口來創建新批次:
response = client . batches . create (
parameters : {
input_file_id : "file-abc123" ,
endpoint : "/v1/chat/completions" ,
completion_window : "24h"
}
)
batch_id = response [ "id" ]
您可以使用其ID檢索有關特定批次的信息:
batch = client . batches . retrieve ( id : batch_id )
取消正在進行的批次:
client . batches . cancel ( id : batch_id )
您還可以列出所有批次:
client . batches . list
一旦存在批處理[“已完成_at”],您可以獲取輸出或錯誤文件:
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 )
這些文件的格式為JSONL格式,每行代表單個請求的輸出或錯誤。這些行可以按任何順序:
{
"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. "
}
}
]
}
}
如果請求因非HTTP錯誤而失敗,則錯誤對象將包含有關故障原因的更多信息。
將您的數據放在這樣的.jsonl
文件中:
{ "prompt" : " Overjoyed with my new phone! -> " , "completion" : " positive " }
{ "prompt" : " @lakers disappoint for a third straight night -> " , "completion" : " negative " }
並將路徑(或stringio對象)傳遞給client.files.upload
將其上傳到OpenAI,然後與之交互:
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" )
您可以發送文件路徑:
client . files . upload ( parameters : { file : "path/to/file.pdf" , purpose : "assistants" } )
或文件對象
my_file = File . open ( "path/to/file.pdf" , "rb" )
client . files . upload ( parameters : { file : my_file , purpose : "assistants" } )
請參閱API文檔上的支持文件類型。
將您的微調數據上傳到上述.jsonl
文件中,並獲取其ID:
response = client . files . upload ( parameters : { file : "path/to/sarcasm.jsonl" , purpose : "fine-tune" } )
file_id = JSON . parse ( response . body ) [ "id" ]
然後,您可以使用此文件ID來創建微調作業:
response = client . finetunes . create (
parameters : {
training_file : file_id ,
model : "gpt-4o"
} )
fine_tune_id = response [ "id" ]
這將為您提供微調ID。如果您犯了一個錯誤,則可以在處理之前取消調整模型:
client . finetunes . cancel ( id : fine_tune_id )
您可能需要等待很短的時間才能完成。處理後,您可以使用列表或檢索以獲取微調模型的名稱:
client . finetunes . list
response = client . finetunes . retrieve ( id : fine_tune_id )
fine_tuned_model = response [ "fine_tuned_model" ]
然後可以在聊天完成中使用此微調模型名稱:
response = client . chat (
parameters : {
model : fine_tuned_model ,
messages : [ { role : "user" , content : "I love Mondays!" } ]
}
)
response . dig ( "choices" , 0 , "message" , "content" )
您還可以捕獲工作事件:
client . finetunes . list_events ( id : fine_tune_id )
向量存儲對象使文件搜索工具能夠搜索您的文件。
您可以創建一個新的向量商店:
response = client . vector_stores . create (
parameters : {
name : "my vector store" ,
file_ids : [ "file-abc123" , "file-def456" ]
}
)
vector_store_id = response [ "id" ]
給定一個vector_store_id
您可以retrieve
當前字段值:
client . vector_stores . retrieve ( id : vector_store_id )
您可以獲取組織當前可用的所有矢量商店的list
:
client . vector_stores . list
您可以修改現有矢量存儲,除了file_ids
:
response = client . vector_stores . modify (
id : vector_store_id ,
parameters : {
name : "Modified Test Vector Store" ,
}
)
您可以刪除向量商店:
client . vector_stores . delete ( id : vector_store_id )
向量存儲文件表示矢量存儲中的文件。
您可以通過將文件附加到向量存儲來創建新的矢量存儲文件。
response = client . vector_store_files . create (
vector_store_id : "vector-store-abc123" ,
parameters : {
file_id : "file-abc123"
}
)
vector_store_file_id = response [ "id" ]
給定一個vector_store_file_id
您可以retrieve
當前字段值:
client . vector_store_files . retrieve (
vector_store_id : "vector-store-abc123" ,
id : vector_store_file_id
)
您可以獲取當前在vector商店下可用的矢量存儲文件的list
:
client . vector_store_files . list ( vector_store_id : "vector-store-abc123" )
您可以刪除矢量商店文件:
client . vector_store_files . delete (
vector_store_id : "vector-store-abc123" ,
id : vector_store_file_id
)
注意:這將從矢量存儲中刪除文件,但不會刪除文件本身。要刪除文件,請使用刪除文件端點。
矢量存儲文件批次表示操作,將多個文件添加到矢量存儲中。
您可以通過將多個文件附加到矢量存儲中來創建新的矢量存儲文件批次。
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" ]
給定一個file_batch_id
您可以retrieve
當前字段值:
client . vector_store_file_batches . retrieve (
vector_store_id : "vector-store-abc123" ,
id : file_batch_id
)
您可以在當前在Vector Store下可用的批處理中獲取所有矢量存儲文件的list
:
client . vector_store_file_batches . list (
vector_store_id : "vector-store-abc123" ,
id : file_batch_id
)
您可以取消矢量存儲文件批次(這嘗試盡快取消此批次的文件處理):
client . vector_store_file_batches . cancel (
vector_store_id : "vector-store-abc123" ,
id : file_batch_id
)
助理是有效的參與者,可以進行許多對話並使用工具來執行任務(請參閱助手概述)。
創建一個新助手:
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" ]
給定一個assistant_id
您可以retrieve
當前的字段值:
client . assistants . retrieve ( id : assistant_id )
您可以獲取組織當前可用的所有助手的list
:
client . assistants . list
您可以使用助手的ID修改現有助手(請參閱API文檔):
response = client . assistants . modify (
id : assistant_id ,
parameters : {
name : "Modified Test Assistant for OpenAI-Ruby" ,
metadata : { my_internal_version_id : '1.0.1' }
}
)
您可以刪除助手:
client . assistants . delete ( id : assistant_id )
如上所述創建助手後,您需要準備一條Messages
Thread
供助手進行工作(請參閱《助手的簡介》)。例如,作為初始設置,您可以執行:
# 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 )
不再需要在線程後清理:
# 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
要提交用助手模型評估的線程,請按照以下方式創建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' ]
您可以在塊傳遞時流式傳輸信息:
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
}
)
要獲得運行的狀態:
response = client . runs . retrieve ( id : run_id , thread_id : thread_id )
status = response [ 'status' ]
status
響應可以包括以下字符串queued
, in_progress
, requires_action
, cancelling
, cancelled
, failed
, completed
或expired
,您可以按以下方式處理以下操作:
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
如果status
響應表明run
已completed
,則關聯thread
將附加一條或多個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
您還可以在消息上更新元數據,包括來自助手的消息。
metadata = {
user_id : "abc123"
}
message = client . messages . modify (
id : message_id ,
thread_id : thread_id ,
parameters : { metadata : metadata } ,
)
在任何時候,您都可以列出已在特定線程上執行或正在運行的所有運行:
client . runs . list ( thread_id : thread_id , parameters : { order : "asc" , limit : 3 } )
您還可以創建一個線程並以這樣的呼叫運行:
response = client . runs . create_thread_and_run ( parameters : { assistant_id : assistant_id } )
run_id = response [ 'id' ]
thread_id = response [ 'thread_id' ]
您可以將圖像包含在線程中,將由LLM描述和閱讀。在此示例中,我正在使用此文件:
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."
如果您允許助手訪問function
工具(它們以與聊天完成期間的函數相同的方式定義),那麼當助手希望您評估一個或多個功能工具時,您可能會獲得一定的requires_action
。
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
請注意,在運行到期之前,您有10分鐘的時間提交工具輸出。
深吸一口氣。您可能需要喝一杯。
Openai可以共享其內部RAG管道中使用的塊來創建FileSearch結果。
可以在此處找到一個示例規格,以便您知道這是可能的。
這是如何在文件搜索中使用塊。在此示例中,我正在使用此文件:
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 )
使用dall·e 2或dall·e 3生成圖像!
512x512
dall·e 2,任何生成的圖像的大小都必須是256x256
或1024x1024
如果未指定,則圖像默認為1024x1024
。
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..."
對於dall·e 3,任何生成的圖像的大小都必須是1024x1024
或1792x1024
1024x1792
。另外,圖像的質量可以指定為standard
或hd
。
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..."
填寫圖像的透明部分,或上載帶有透明部分的掩碼,以指示可以根據您的提示更改的圖像部分...
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..."
創建圖像的N變化。
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..."
通過字符串檢查是否違反了OpenAI的內容政策:
response = client . moderations ( parameters : { input : "I'm worried about that." } )
puts response . dig ( "results" , 0 , "category_scores" , "hate" )
# => 5.505014632944949e-05
耳語是對文本模型的語音,可用於基於音頻文件生成文本:
Translations API以任何支持的語言為輸入音頻文件,並將音頻轉錄為英語。
response = client . audio . translate (
parameters : {
model : "whisper-1" ,
file : File . open ( "path_to_file" , "rb" ) ,
}
)
puts response [ "text" ]
# => "Translation of the text"
轉錄API將您要轉錄的音頻文件作為輸入,並以所需的輸出文件格式返回文本。
您可以通過音頻文件的語言來提高轉錄質量。支持的語言在這裡列出。您需要將語言作為ISO-639-1代碼提供,例如。對於尼泊爾人來說,英語或“ ne”的“ en”。您可以在此處查找代碼。
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"
語音API將文本和語音輸入作為輸入,並返回您可以收聽的音頻文件的內容。
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錯誤可能會被捕獲:
begin
OpenAI :: Client . new . models . retrieve ( id : "gpt-4o" )
rescue Faraday :: Error => e
raise "Got a Faraday error: #{ e } "
end
檢查回購後,運行bin/setup
以安裝依賴關係。您可以在交互提示下運行bin/console
,以允許您進行實驗。
要將此GEM安裝到本地計算機上,請運行bundle exec rake install
。
要運行所有測試,請執行Command bundle exec rake
,這也將運行Linter(RuboCop)。該存儲庫使用VCR來記錄API請求。
警告
如果您在ENV
中有OPENAI_ACCESS_TOKEN
,則運行規格將使用它來針對實際的API運行規格,這將很慢,並且花費您的錢 - 2美分或更多!如果您只想根據存儲的VCR響應來運行規格,則會以unset
或類似的方式將其從環境中刪除。
首先在沒有VCR的情況下運行規格,因此它們實際上擊中了API。這將花費2美分或更多。在您的環境中設置OpenAI_ACCESS_TOKEN或這樣的傳遞:
OPENAI_ACCESS_TOKEN=123abc bundle exec rspec
然後更新version.rb
中的版本編號,更新CHANGELOG.md
,運行bundle install
以更新gemfile.lock,然後運行bundle exec rake release
,該版本將為版本創建一個git標籤.gem
文件rubygems.org。
歡迎在https://github.com/alexrudall/ruby-openai的GitHub上的錯誤報告和拉動請求。該項目旨在是一個安全,熱情的協作空間,預計貢獻者將遵守行為準則。
根據MIT許可證的條款,該寶石可作為開源。
在Ruby OpenAI項目的代碼庫,問題跟踪器,聊天室和郵件列表中進行互動的每個人都將遵循《行為守則》。