{"id":15136519,"url":"https://github.com/ksylvest/omniai-openai","last_synced_at":"2025-10-10T09:51:44.752Z","repository":{"id":243734674,"uuid":"813254836","full_name":"ksylvest/omniai-openai","owner":"ksylvest","description":"An implementation of the OmniAI interface for OpenAI.","archived":false,"fork":false,"pushed_at":"2025-08-25T11:03:59.000Z","size":185,"stargazers_count":10,"open_issues_count":1,"forks_count":3,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-08-25T13:08:48.846Z","etag":null,"topics":["chatgpt","omniai","openai","ruby","whisper"],"latest_commit_sha":null,"homepage":"https://omniai-openai.ksylvest.com","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ksylvest.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2024-06-10T19:15:18.000Z","updated_at":"2025-08-25T11:04:02.000Z","dependencies_parsed_at":"2024-06-24T18:59:16.435Z","dependency_job_id":"8572f91a-70e6-4ccc-aef8-7cde3f8640b9","html_url":"https://github.com/ksylvest/omniai-openai","commit_stats":{"total_commits":56,"total_committers":2,"mean_commits":28.0,"dds":0.125,"last_synced_commit":"09a8eca23771ea5018ef7d14aa08d3bdb1b8d0ff"},"previous_names":["ksylvest/omniai-openai"],"tags_count":38,"template":false,"template_full_name":null,"purl":"pkg:github/ksylvest/omniai-openai","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ksylvest%2Fomniai-openai","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ksylvest%2Fomniai-openai/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ksylvest%2Fomniai-openai/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ksylvest%2Fomniai-openai/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ksylvest","download_url":"https://codeload.github.com/ksylvest/omniai-openai/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ksylvest%2Fomniai-openai/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":275658692,"owners_count":25504776,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-17T02:00:09.119Z","response_time":84,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["chatgpt","omniai","openai","ruby","whisper"],"created_at":"2024-09-26T06:22:22.995Z","updated_at":"2025-09-17T20:31:42.326Z","avatar_url":"https://github.com/ksylvest.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"# OmniAI::OpenAI\n\n[![LICENSE](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/ksylvest/omniai-openai/blob/main/LICENSE)\n[![RubyGems](https://img.shields.io/gem/v/omniai-openai)](https://rubygems.org/gems/omniai-openai)\n[![GitHub](https://img.shields.io/badge/github-repo-blue.svg)](https://github.com/ksylvest/omniai-openai)\n[![Yard](https://img.shields.io/badge/docs-site-blue.svg)](https://omniai-openai.ksylvest.com)\n[![CircleCI](https://img.shields.io/circleci/build/github/ksylvest/omniai-openai)](https://circleci.com/gh/ksylvest/omniai-openai)\n\nAn OpenAI implementation of the [OmniAI](https://github.com/ksylvest/omniai) interface supporting ChatGPT, Whisper, Text-to-Voice, Voice-to-Text, and more. This library is community maintained.\n\n## Installation\n\n```sh\ngem install omniai-openai\n```\n\n## Usage\n\n### Client\n\nA client is setup as follows if `ENV['OPENAI_API_KEY']` exists:\n\n```ruby\nclient = OmniAI::OpenAI::Client.new\n```\n\nA client may also be passed the following options:\n\n- `api_key` (required - default is `ENV['OPENAI_API_KEY']`)\n- `api_prefix` (optional) - used with a host when necessary\n- `organization` (optional)\n- `project` (optional)\n- `host` (optional) useful for usage with Ollama, LocalAI or other OpenAI API compatible services\n\n### Configuration\n\nGlobal configuration is supported for the following options:\n\n```ruby\nOmniAI::OpenAI.configure do |config|\n  config.api_key = 'sk-...' # default: ENV['OPENAI_API_KEY']\n  config.organization = '...' # default: ENV['OPENAI_ORGANIZATION']\n  config.project = '...' # default: ENV['OPENAI_PROJECT']\n  config.host = '...' # default: 'https://api.openai.com' - override for usage with LocalAI / Ollama\nend\n```\n\n#### Usage with [LocalAI](https://localai.io/)\n\nLocalAI offers [built in compatability with the OpenAI specification](https://localai.io/). To initialize a client that points to a Ollama change the host accordingly:\n\n```ruby\nclient = OmniAI::OpenAI::Client.new(host: 'http://localhost:8080', api_key: nil)\n```\n\n_For details on installation or running LocalAI see the [getting started tutorial](https://localai.io/basics/getting_started/)._\n\n#### Usage with [Ollama](https://www.ollama.com/)\n\nOllama offers [built in compatability with the OpenAI specification](https://ollama.com/blog/openai-compatibility). To initialize a client that points to a Ollama change the host accordingly:\n\n```ruby\nclient = OmniAI::OpenAI::Client.new(host: 'http://localhost:11434', api_key: nil)\n```\n\n_For details on installation or running Ollama checkout [the project README](https://github.com/ollama/ollama)._\n\n#### Usage with [OpenRouter](https://open_router.ai/)\n\nOther fee-based systems/services have adopted all or some of the OpenAI API. For example [open_router.ai](https://open_router.ai) is a web-services that provides access to many models and providers using their own as well as an OpenAI API.\n\n```ruby\nclient  = OmniAI::OpenAI::Client.new(\n            host:       'https://open_router.ai',\n            api_key:    ENV['OPENROUTER_API_KEY'],\n            api_prefix: '/api')\n```\n\n### Chat\n\nA chat completion is generated by passing in a simple text prompt:\n\n```ruby\ncompletion = client.chat('Tell me a joke!')\ncompletion.content # 'Why did the chicken cross the road? To get to the other side.'\n```\n\nA chat completion may also be generated by using a prompt builder:\n\n```ruby\ncompletion = client.chat do |prompt|\n  prompt.system('Your are an expert in geography.')\n  prompt.user('What is the capital of Canada?')\nend\ncompletion.content # 'The capital of Canada is Ottawa.'\n```\n\n#### Model\n\n`model` takes an optional string (default is `gpt-4o`):\n\n```ruby\ncompletion = client.chat('How fast is a cheetah?', model: OmniAI::OpenAI::Chat::Model::GPT_3_5_TURBO)\ncompletion.content # 'A cheetah can reach speeds over 100 km/h.'\n```\n\n[OpenAI API Reference `model`](https://platform.openai.com/docs/api-reference/chat/create#chat-create-model)\n\n#### Temperature\n\n`temperature` takes an optional float between `0.0` and `2.0` (defaults is `0.7`):\n\n```ruby\ncompletion = client.chat('Pick a number between 1 and 5', temperature: 2.0)\ncompletion.content # '3'\n```\n\n[OpenAI API Reference `temperature`](https://platform.openai.com/docs/api-reference/chat/create#chat-create-temperature)\n\n#### Stream\n\n`stream` takes an optional a proc to stream responses in real-time chunks instead of waiting for a complete response:\n\n```ruby\nstream = proc do |chunk|\n  print(chunk.content) # 'Better', 'three', 'hours', ...\nend\nclient.chat('Be poetic.', stream:)\n```\n\n[OpenAI API Reference `stream`](https://platform.openai.com/docs/api-reference/chat/create#chat-create-stream)\n\n#### Format\n\n`format` takes an optional symbol (`:json`) and that setes the `response_format` to `json_object`:\n\n```ruby\ncompletion = client.chat(format: :json) do |prompt|\n  prompt.system(OmniAI::Chat::JSON_PROMPT)\n  prompt.user('What is the name of the drummer for the Beatles?')\nend\nJSON.parse(completion.content) # { \"name\": \"Ringo\" }\n```\n\n[OpenAI API Reference `response_format`](https://platform.openai.com/docs/api-reference/chat/create#chat-create-stream)\n\n\u003e When using JSON mode, you must also instruct the model to produce JSON yourself via a system or user message.\n\n### Transcribe\n\nA transcription is generated by passing in a path to a file:\n\n```ruby\ntranscription = client.transcribe(file.path)\ntranscription.text # '...'\n```\n\n#### Prompt\n\n`prompt` is optional and can provide additional context for transcribing:\n\n```ruby\ntranscription = client.transcribe(file.path, prompt: '')\ntranscription.text # '...'\n```\n\n[OpenAI API Reference `prompt`](https://platform.openai.com/docs/api-reference/audio/createTranscription#audio-createtranscription-prompt)\n\n#### Format\n\n`format` is optional and supports `json`, `text`, `srt` or `vtt`:\n\n```ruby\ntranscription = client.transcribe(file.path, format: OmniAI::Transcribe::Format::TEXT)\ntranscription.text # '...'\n```\n\n[OpenAI API Reference `response_format`](https://platform.openai.com/docs/api-reference/audio/createTranscription#audio-createtranscription-response_format)\n\n#### Language\n\n`language` is optional and may improve accuracy and latency:\n\n```ruby\ntranscription = client.transcribe(file.path, language: OmniAI::Transcribe::Language::SPANISH)\ntranscription.text\n```\n\n[OpenAI API Reference `language`](https://platform.openai.com/docs/api-reference/audio/createTranscription#audio-createtranscription-language)\n\n#### Temperature\n\n`temperature` is optional and must be between 0.0 (more deterministic) and 1.0 (less deterministic):\n\n```ruby\ntranscription = client.transcribe(file.path, temperature: 0.2)\ntranscription.text\n```\n\n[OpenAI API Reference `temperature`](https://platform.openai.com/docs/api-reference/audio/createTranscription#audio-createtranscription-temperature)\n\n### Speak\n\nSpeech can be generated by passing text with a block:\n\n```ruby\nFile.open('example.ogg', 'wb') do |file|\n  client.speak('How can a clam cram in a clean cream can?') do |chunk|\n    file \u003c\u003c chunk\n  end\nend\n```\n\nIf a block is not provided then a tempfile is returned:\n\n```ruby\ntempfile = client.speak('Can you can a can as a canner can can a can?')\ntempfile.close\ntempfile.unlink\n```\n\n#### Voice\n\n`voice` is optional and must be one of the supported voices:\n\n```ruby\nclient.speak('She sells seashells by the seashore.', voice: OmniAI::OpenAI::Speak::Voice::SHIMMER)\n```\n\n[OpenAI API Reference `voice`](https://platform.openai.com/docs/api-reference/audio/createSpeech#audio-createspeech-voice)\n\n#### Model\n\n`model` is optional and must be either `tts-1` or `tts-1-hd` (default):\n\n```ruby\nclient.speak('I saw a kitten eating chicken in the kitchen.', format: OmniAI::OpenAI::Speak::Model::TTS_1)\n```\n\n[OpenAI API Refernce `model`](https://platform.openai.com/docs/api-reference/audio/createSpeech#audio-createspeech-model)\n\n#### Speed\n\n`speed` is optional and must be between 0.25 and 0.40:\n\n```ruby\nclient.speak('How much wood would a woodchuck chuck if a woodchuck could chuck wood?', speed: 4.0)\n```\n\n[OmniAI API Reference `speed`](https://platform.openai.com/docs/api-reference/audio/createSpeech#audio-createspeech-speed)\n\n#### Format\n\n`format` is optional and supports `MP3` (default), `OPUS`, `AAC`, `FLAC`, `WAV` or `PCM`:\n\n```ruby\nclient.speak('A pessemistic pest exists amidst us.', format: OmniAI::OpenAI::Speak::Format::FLAC)\n```\n\n[OpenAI API Reference `format`](https://platform.openai.com/docs/api-reference/audio/createSpeech#audio-createspeech-response_format)\n\n## Files\n\n### Finding an File\n\n```ruby\nclient.files.find(id: 'file_...')\n```\n\n### Listing all Files\n\n```ruby\nclient.files.all\n```\n\n### Uploading a File\n\n#### Using a File\n\n```ruby\nfile = client.files.build(io: File.open('demo.pdf', 'wb'))\nfile.save!\n```\n\n#### Using a Path\n\n```ruby\nfile = client.files.build(io: 'demo.pdf'))\nfile.save!\n```\n\n### Downloading a File\n\n```ruby\nfile = client.files.find(id: 'file_...')\nFile.open('...', 'wb') do |file|\n  file.content do |chunk|\n    file \u003c\u003c chunk\n  end\nend\n```\n\n### Destroying a File\n\n```ruby\nclient.files.destroy!('file_...')\n```\n\n## Assistants\n\n### Finding an Assistant\n\n```ruby\nclient.assistants.find(id: 'asst_...')\n```\n\n### Listing all Assistants\n\n```ruby\nclient.assistants.all\n```\n\n### Creating an Assistant\n\n```ruby\nassistant = client.assistants.build\nassistant.name = 'Ringo'\nassistant.model = OmniAI::OpenAI::Chat::Model::GPT_4\nassistant.description = 'The drummer for the Beatles.'\nassistant.save!\n```\n\n### Updating an Assistant\n\n```ruby\nassistant = client.assistants.find(id: 'asst_...')\nassistant.name = 'George'\nassistant.model = OmniAI::OpenAI::Chat::Model::GPT_4\nassistant.description = 'A guitarist for the Beatles.'\nassistant.save!\n```\n\n### Destroying an Assistant\n\n```ruby\nclient.assistants.destroy!('asst_...')\n```\n\n## Threads\n\n### Finding a Thread\n\n```ruby\nclient.threads.find(id: 'thread_...')\n```\n\n### Creating a Thread\n\n```ruby\nthread = client.threads.build\nthread.metadata = { user: 'Ringo' }\nthread.save!\n```\n\n### Updating a Thread\n\n```ruby\nthread = client.threads.find(id: 'thread_...')\nthread.metadata = { user: 'Ringo' }\nthread.save!\n```\n\n### Destroying a Threads\n\n```ruby\nclient.threads.destroy!('thread_...')\n```\n\n### Messages\n\n#### Finding a Message\n\n```ruby\nthread = client.threads.find(id: 'thread_...')\nmessage = thread.messages.find(id: 'msg_...')\nmessage.save!\n```\n\n#### Listing all Messages\n\n```ruby\nthread = client.threads.find(id: 'thread_...')\nthread.messages.all\n```\n\n#### Creating a Message\n\n```ruby\nthread = client.threads.find(id: 'thread_...')\nmessage = thread.messages.build(role: 'user', content: 'Hello?')\nmessage.save!\n```\n\n#### Updating a Message\n\n```ruby\nthread = client.threads.find(id: 'thread_...')\nmessage = thread.messages.build(role: 'user', content: 'Hello?')\nmessage.save!\n```\n\n### Runs\n\n#### Finding a Run\n\n```ruby\nthread = client.threads.find(id: 'thread_...')\nrun = thread.runs.find(id: 'run_...')\nrun.save!\n```\n\n#### Listing all Runs\n\n```ruby\nthread = client.threads.find(id: 'thread_...')\nthread.runs.all\n```\n\n#### Creating a Run\n\n```ruby\nrun = client.runs.find(id: 'thread_...')\nrun = thread.runs.build\nrun.metadata = { user: 'Ringo' }\nrun.save!\n```\n\n#### Updating a Run\n\n```ruby\nthread = client.threads.find(id: 'thread_...')\nrun = thread.messages.find(id: 'run_...')\nrun.metadata = { user: 'Ringo' }\nrun.save!\n```\n\n#### Polling a Run\n\n```ruby\nrun.terminated? # false\nrun.poll!\nrun.terminated? # true\nrun.status # 'cancelled' / 'failed' / 'completed' / 'expired'\n```\n\n#### Cancelling a Run\n\n```ruby\nthread = client.threads.find(id: 'thread_...')\nrun = thread.runs.cancel!(id: 'run_...')\n```\n\n### Embed\n\nText can be converted into a vector embedding for similarity comparison usage via:\n\n```ruby\nresponse = client.embed('The quick brown fox jumps over a lazy dog.')\nresponse.embedding # [0.0, ...]\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fksylvest%2Fomniai-openai","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fksylvest%2Fomniai-openai","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fksylvest%2Fomniai-openai/lists"}