ruby_llm 1.15.0 → 2.0.0.rc1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rdoc_options +25 -0
- data/README.md +87 -33
- data/exe/ruby_llm +8 -0
- data/lib/generators/ruby_llm/agent/templates/agent.rb.tt +0 -1
- data/lib/generators/ruby_llm/chat_ui/chat_ui_generator.rb +3 -43
- data/lib/generators/ruby_llm/chat_ui/templates/controllers/chats_controller.rb.tt +11 -3
- data/lib/generators/ruby_llm/chat_ui/templates/controllers/messages_controller.rb.tt +8 -0
- data/lib/generators/ruby_llm/chat_ui/templates/controllers/models_controller.rb.tt +4 -4
- data/lib/generators/ruby_llm/chat_ui/templates/tailwind/views/chats/_chat.html.erb.tt +1 -1
- data/lib/generators/ruby_llm/chat_ui/templates/tailwind/views/chats/_form.html.erb.tt +1 -1
- data/lib/generators/ruby_llm/chat_ui/templates/tailwind/views/chats/index.html.erb.tt +1 -1
- data/lib/generators/ruby_llm/chat_ui/templates/tailwind/views/chats/show.html.erb.tt +2 -2
- data/lib/generators/ruby_llm/chat_ui/templates/tailwind/views/messages/_assistant.html.erb.tt +1 -1
- data/lib/generators/ruby_llm/chat_ui/templates/tailwind/views/messages/_system.html.erb.tt +1 -1
- data/lib/generators/ruby_llm/chat_ui/templates/tailwind/views/messages/_tool.html.erb.tt +1 -1
- data/lib/generators/ruby_llm/chat_ui/templates/tailwind/views/messages/_tool_calls.html.erb.tt +6 -4
- data/lib/generators/ruby_llm/chat_ui/templates/tailwind/views/messages/_user.html.erb.tt +1 -1
- data/lib/generators/ruby_llm/chat_ui/templates/tailwind/views/messages/tool_calls/_default.html.erb.tt +2 -2
- data/lib/generators/ruby_llm/chat_ui/templates/tailwind/views/models/_model.html.erb.tt +5 -6
- data/lib/generators/ruby_llm/chat_ui/templates/tailwind/views/models/index.html.erb.tt +2 -2
- data/lib/generators/ruby_llm/chat_ui/templates/tailwind/views/models/show.html.erb.tt +5 -5
- data/lib/generators/ruby_llm/chat_ui/templates/views/chats/_chat.html.erb.tt +1 -1
- data/lib/generators/ruby_llm/chat_ui/templates/views/chats/_form.html.erb.tt +1 -1
- data/lib/generators/ruby_llm/chat_ui/templates/views/chats/index.html.erb.tt +1 -1
- data/lib/generators/ruby_llm/chat_ui/templates/views/chats/show.html.erb.tt +2 -2
- data/lib/generators/ruby_llm/chat_ui/templates/views/messages/_assistant.html.erb.tt +1 -1
- data/lib/generators/ruby_llm/chat_ui/templates/views/messages/_system.html.erb.tt +1 -1
- data/lib/generators/ruby_llm/chat_ui/templates/views/messages/_tool.html.erb.tt +1 -1
- data/lib/generators/ruby_llm/chat_ui/templates/views/messages/_tool_calls.html.erb.tt +6 -4
- data/lib/generators/ruby_llm/chat_ui/templates/views/messages/_user.html.erb.tt +1 -1
- data/lib/generators/ruby_llm/chat_ui/templates/views/messages/create.turbo_stream.erb.tt +4 -6
- data/lib/generators/ruby_llm/chat_ui/templates/views/messages/tool_calls/_default.html.erb.tt +2 -2
- data/lib/generators/ruby_llm/chat_ui/templates/views/models/_model.html.erb.tt +5 -6
- data/lib/generators/ruby_llm/chat_ui/templates/views/models/index.html.erb.tt +2 -2
- data/lib/generators/ruby_llm/chat_ui/templates/views/models/show.html.erb.tt +3 -3
- data/lib/generators/ruby_llm/generator_helpers.rb +106 -62
- data/lib/generators/ruby_llm/install/install_generator.rb +3 -11
- data/lib/generators/ruby_llm/install/templates/create_chats_migration.rb.tt +2 -0
- data/lib/generators/ruby_llm/install/templates/create_messages_migration.rb.tt +14 -6
- data/lib/generators/ruby_llm/install/templates/create_ruby_llm_records_migration.rb.tt +117 -0
- data/lib/generators/ruby_llm/install/templates/initializer.rb.tt +0 -8
- data/lib/generators/ruby_llm/provider/cli.rb +175 -0
- data/lib/generators/ruby_llm/provider/scaffold.rb +323 -0
- data/lib/generators/ruby_llm/provider/templates/core/provider.rb.erb +37 -0
- data/lib/generators/ruby_llm/provider/templates/core/provider_spec.rb.erb +34 -0
- data/lib/generators/ruby_llm/provider/templates/gem/archspec.rb.erb +14 -0
- data/lib/generators/ruby_llm/provider/templates/gem/bin/console.erb +15 -0
- data/lib/generators/ruby_llm/provider/templates/gem/bin/setup.erb +5 -0
- data/lib/generators/ruby_llm/provider/templates/gem/chat_schema_spec.rb.erb +30 -0
- data/lib/generators/ruby_llm/provider/templates/gem/chat_spec.rb.erb +35 -0
- data/lib/generators/ruby_llm/provider/templates/gem/chat_streaming_spec.rb.erb +22 -0
- data/lib/generators/ruby_llm/provider/templates/gem/chat_tools_spec.rb.erb +30 -0
- data/lib/generators/ruby_llm/provider/templates/gem/ci.yml.erb +32 -0
- data/lib/generators/ruby_llm/provider/templates/gem/embedding_spec.rb.erb +49 -0
- data/lib/generators/ruby_llm/provider/templates/gem/env.erb +2 -0
- data/lib/generators/ruby_llm/provider/templates/gem/fixtures_gitkeep.erb +1 -0
- data/lib/generators/ruby_llm/provider/templates/gem/flayignore.erb +1 -0
- data/lib/generators/ruby_llm/provider/templates/gem/gemfile.erb +25 -0
- data/lib/generators/ruby_llm/provider/templates/gem/gemspec.erb +28 -0
- data/lib/generators/ruby_llm/provider/templates/gem/gitignore.erb +7 -0
- data/lib/generators/ruby_llm/provider/templates/gem/gitleaks.yml.erb +22 -0
- data/lib/generators/ruby_llm/provider/templates/gem/image_spec.rb.erb +23 -0
- data/lib/generators/ruby_llm/provider/templates/gem/license.erb +21 -0
- data/lib/generators/ruby_llm/provider/templates/gem/models.rb.erb +19 -0
- data/lib/generators/ruby_llm/provider/templates/gem/models_spec.rb.erb +17 -0
- data/lib/generators/ruby_llm/provider/templates/gem/moderation_spec.rb.erb +22 -0
- data/lib/generators/ruby_llm/provider/templates/gem/overcommit.yml.erb +31 -0
- data/lib/generators/ruby_llm/provider/templates/gem/provider.rb.erb +52 -0
- data/lib/generators/ruby_llm/provider/templates/gem/provider_spec.rb.erb +38 -0
- data/lib/generators/ruby_llm/provider/templates/gem/rakefile.erb +38 -0
- data/lib/generators/ruby_llm/provider/templates/gem/readme.md.erb +50 -0
- data/lib/generators/ruby_llm/provider/templates/gem/release.yml.erb +36 -0
- data/lib/generators/ruby_llm/provider/templates/gem/rerank_spec.rb.erb +23 -0
- data/lib/generators/ruby_llm/provider/templates/gem/rspec.erb +2 -0
- data/lib/generators/ruby_llm/provider/templates/gem/rubocop.yml.erb +29 -0
- data/lib/generators/ruby_llm/provider/templates/gem/rubyllm_configuration.rb.erb +14 -0
- data/lib/generators/ruby_llm/provider/templates/gem/spec_helper.rb.erb +26 -0
- data/lib/generators/ruby_llm/provider/templates/gem/speech_spec.rb.erb +25 -0
- data/lib/generators/ruby_llm/provider/templates/gem/vcr_configuration.rb.erb +16 -0
- data/lib/generators/ruby_llm/provider/templates/gem/video_spec.rb.erb +27 -0
- data/lib/generators/ruby_llm/schema/schema_generator.rb +5 -1
- data/lib/generators/ruby_llm/schema/templates/schema.rb.tt +1 -1
- data/lib/generators/ruby_llm/tool/templates/tailwind/tool_call.html.erb.tt +13 -0
- data/lib/generators/ruby_llm/tool/templates/tailwind/tool_result.html.erb.tt +21 -0
- data/lib/generators/ruby_llm/tool/templates/tool.rb.tt +3 -3
- data/lib/generators/ruby_llm/tool/templates/tool_call.html.erb.tt +7 -12
- data/lib/generators/ruby_llm/tool/templates/tool_result.html.erb.tt +5 -2
- data/lib/generators/ruby_llm/tool/tool_generator.rb +25 -59
- data/lib/generators/ruby_llm/upgrade/templates/backfill_v2_data.rb.tt +461 -0
- data/lib/generators/ruby_llm/upgrade/templates/cleanup_v2_upgrade.rb.tt +100 -0
- data/lib/generators/ruby_llm/upgrade/templates/finish_v2_upgrade.rb.tt +215 -0
- data/lib/generators/ruby_llm/upgrade/templates/prepare_v2_upgrade.rb.tt +660 -0
- data/lib/generators/ruby_llm/upgrade/templates/ruby_llm_upgrade.rb.tt +222 -0
- data/lib/generators/ruby_llm/upgrade/templates/upgrade_initializer.rb.tt +13 -0
- data/lib/generators/ruby_llm/upgrade/upgrade_generator.rb +167 -0
- data/lib/generators/ruby_llm/upgrade/upgrade_migration.rb +344 -0
- data/lib/ruby_llm/accounting/usage.rb +245 -0
- data/lib/ruby_llm/active_record/acts_as.rb +94 -136
- data/lib/ruby_llm/active_record/attachment_helpers.rb +180 -0
- data/lib/ruby_llm/active_record/batch.rb +97 -0
- data/lib/ruby_llm/active_record/chat_methods.rb +823 -305
- data/lib/ruby_llm/active_record/message_methods.rb +119 -75
- data/lib/ruby_llm/active_record/model.rb +135 -0
- data/lib/ruby_llm/active_record/payload_helpers.rb +1 -2
- data/lib/ruby_llm/active_record/tool_call.rb +33 -0
- data/lib/ruby_llm/active_record/usage.rb +61 -0
- data/lib/ruby_llm/agent.rb +1065 -150
- data/lib/ruby_llm/aliases.json +338 -167
- data/lib/ruby_llm/attachment.rb +217 -61
- data/lib/ruby_llm/batch.rb +432 -0
- data/lib/ruby_llm/cached_content.rb +112 -0
- data/lib/ruby_llm/chat/tool_concurrency.rb +111 -0
- data/lib/ruby_llm/chat.rb +1208 -150
- data/lib/ruby_llm/chunk.rb +10 -0
- data/lib/ruby_llm/citation.rb +105 -0
- data/lib/ruby_llm/configuration.rb +274 -24
- data/lib/ruby_llm/context.rb +128 -6
- data/lib/ruby_llm/cost.rb +217 -80
- data/lib/ruby_llm/downloaded_file.rb +33 -0
- data/lib/ruby_llm/embedding.rb +141 -7
- data/lib/ruby_llm/embedding_request.rb +53 -0
- data/lib/ruby_llm/error.rb +161 -89
- data/lib/ruby_llm/fallback.rb +133 -0
- data/lib/ruby_llm/files/mime_type.rb +97 -0
- data/lib/ruby_llm/image.rb +155 -32
- data/lib/ruby_llm/message.rb +233 -54
- data/lib/ruby_llm/model/modalities.rb +17 -4
- data/lib/ruby_llm/model/pricing.rb +43 -14
- data/lib/ruby_llm/model/pricing_category.rb +103 -14
- data/lib/ruby_llm/model/pricing_tier.rb +66 -15
- data/lib/ruby_llm/model.rb +244 -2
- data/lib/ruby_llm/models/aliases.rb +41 -0
- data/lib/ruby_llm/models/registry.rb +165 -0
- data/lib/ruby_llm/models/schema.rb +99 -0
- data/lib/ruby_llm/models.json +70380 -33380
- data/lib/ruby_llm/models.rb +528 -201
- data/lib/ruby_llm/moderation.rb +139 -26
- data/lib/ruby_llm/ocr.rb +112 -0
- data/lib/ruby_llm/prompt.rb +79 -0
- data/lib/ruby_llm/protocol/binary_streaming.rb +65 -0
- data/lib/ruby_llm/protocol/stream_accumulator.rb +214 -0
- data/lib/ruby_llm/protocol/streaming.rb +230 -0
- data/lib/ruby_llm/protocol.rb +662 -0
- data/lib/ruby_llm/protocols/anthropic/batches.rb +73 -0
- data/lib/ruby_llm/protocols/anthropic/chat.rb +540 -0
- data/lib/ruby_llm/protocols/anthropic/embeddings.rb +14 -0
- data/lib/ruby_llm/protocols/anthropic/files.rb +38 -0
- data/lib/ruby_llm/protocols/anthropic/media.rb +141 -0
- data/lib/ruby_llm/protocols/anthropic/models.rb +129 -0
- data/lib/ruby_llm/protocols/anthropic/streaming.rb +166 -0
- data/lib/ruby_llm/{providers → protocols}/anthropic/tools.rb +43 -34
- data/lib/ruby_llm/protocols/anthropic.rb +100 -0
- data/lib/ruby_llm/protocols/azure/files.rb +16 -0
- data/lib/ruby_llm/protocols/bedrock/async_videos.rb +109 -0
- data/lib/ruby_llm/protocols/bedrock/batches.rb +129 -0
- data/lib/ruby_llm/protocols/bedrock/files.rb +110 -0
- data/lib/ruby_llm/protocols/bedrock/guardrails.rb +122 -0
- data/lib/ruby_llm/protocols/bedrock/rerank.rb +95 -0
- data/lib/ruby_llm/protocols/chat_completions/batches.rb +32 -0
- data/lib/ruby_llm/protocols/chat_completions/chat.rb +493 -0
- data/lib/ruby_llm/protocols/chat_completions/embedding_batches.rb +35 -0
- data/lib/ruby_llm/protocols/chat_completions/embeddings.rb +60 -0
- data/lib/ruby_llm/protocols/chat_completions/images.rb +127 -0
- data/lib/ruby_llm/protocols/chat_completions/media.rb +121 -0
- data/lib/ruby_llm/protocols/chat_completions/models.rb +39 -0
- data/lib/ruby_llm/protocols/chat_completions/moderation.rb +52 -0
- data/lib/ruby_llm/protocols/chat_completions/rerank.rb +56 -0
- data/lib/ruby_llm/protocols/chat_completions/speech.rb +40 -0
- data/lib/ruby_llm/protocols/chat_completions/streaming.rb +69 -0
- data/lib/ruby_llm/{providers/openai → protocols/chat_completions}/tools.rb +17 -17
- data/lib/ruby_llm/protocols/chat_completions/transcription.rb +150 -0
- data/lib/ruby_llm/protocols/chat_completions.rb +21 -0
- data/lib/ruby_llm/protocols/cohere/batch_requests.rb +75 -0
- data/lib/ruby_llm/protocols/cohere/batches.rb +98 -0
- data/lib/ruby_llm/protocols/cohere/chat.rb +227 -0
- data/lib/ruby_llm/protocols/cohere/datasets.rb +102 -0
- data/lib/ruby_llm/protocols/cohere/embeddings.rb +68 -0
- data/lib/ruby_llm/protocols/cohere/media.rb +77 -0
- data/lib/ruby_llm/protocols/cohere/models.rb +92 -0
- data/lib/ruby_llm/protocols/cohere/ocr.rb +63 -0
- data/lib/ruby_llm/protocols/cohere/rerank.rb +52 -0
- data/lib/ruby_llm/protocols/cohere/streaming.rb +105 -0
- data/lib/ruby_llm/protocols/cohere/tokenization.rb +22 -0
- data/lib/ruby_llm/protocols/cohere/tools.rb +132 -0
- data/lib/ruby_llm/protocols/cohere/transcription.rb +41 -0
- data/lib/ruby_llm/protocols/cohere.rb +21 -0
- data/lib/ruby_llm/protocols/converse/batches.rb +55 -0
- data/lib/ruby_llm/protocols/converse/chat.rb +685 -0
- data/lib/ruby_llm/protocols/converse/media.rb +178 -0
- data/lib/ruby_llm/protocols/converse/streaming.rb +424 -0
- data/lib/ruby_llm/protocols/converse.rb +54 -0
- data/lib/ruby_llm/protocols/deepgram/models.rb +74 -0
- data/lib/ruby_llm/protocols/deepgram/speech.rb +93 -0
- data/lib/ruby_llm/protocols/deepgram/streaming_transcription.rb +89 -0
- data/lib/ruby_llm/protocols/deepgram/transcription.rb +96 -0
- data/lib/ruby_llm/protocols/deepgram.rb +19 -0
- data/lib/ruby_llm/protocols/deepseek/files.rb +31 -0
- data/lib/ruby_llm/protocols/elevenlabs/assets.rb +36 -0
- data/lib/ruby_llm/protocols/elevenlabs/flows/images.rb +74 -0
- data/lib/ruby_llm/protocols/elevenlabs/flows/media.rb +42 -0
- data/lib/ruby_llm/protocols/elevenlabs/flows/videos.rb +93 -0
- data/lib/ruby_llm/protocols/elevenlabs/flows.rb +14 -0
- data/lib/ruby_llm/protocols/elevenlabs/models.rb +64 -0
- data/lib/ruby_llm/protocols/elevenlabs/speech.rb +67 -0
- data/lib/ruby_llm/protocols/elevenlabs/streaming_transcription.rb +127 -0
- data/lib/ruby_llm/protocols/elevenlabs/transcription.rb +61 -0
- data/lib/ruby_llm/protocols/elevenlabs.rb +15 -0
- data/lib/ruby_llm/protocols/files.rb +119 -0
- data/lib/ruby_llm/protocols/gemini/batches.rb +162 -0
- data/lib/ruby_llm/protocols/gemini/caches.rb +59 -0
- data/lib/ruby_llm/protocols/gemini/chat.rb +453 -0
- data/lib/ruby_llm/protocols/gemini/embedding_batches.rb +86 -0
- data/lib/ruby_llm/protocols/gemini/embeddings.rb +70 -0
- data/lib/ruby_llm/protocols/gemini/file_transcription.rb +32 -0
- data/lib/ruby_llm/protocols/gemini/files.rb +115 -0
- data/lib/ruby_llm/protocols/gemini/images.rb +183 -0
- data/lib/ruby_llm/protocols/gemini/live_transcription.rb +140 -0
- data/lib/ruby_llm/{providers → protocols}/gemini/media.rb +33 -20
- data/lib/ruby_llm/protocols/gemini/models.rb +71 -0
- data/lib/ruby_llm/protocols/gemini/speech.rb +56 -0
- data/lib/ruby_llm/protocols/gemini/streaming.rb +96 -0
- data/lib/ruby_llm/protocols/gemini/tools.rb +157 -0
- data/lib/ruby_llm/{providers → protocols}/gemini/transcription.rb +22 -22
- data/lib/ruby_llm/protocols/gemini/videos.rb +103 -0
- data/lib/ruby_llm/protocols/gemini.rb +35 -0
- data/lib/ruby_llm/protocols/gpustack/responses.rb +111 -0
- data/lib/ruby_llm/protocols/gpustack/tokenization.rb +22 -0
- data/lib/ruby_llm/protocols/gpustack/videos.rb +96 -0
- data/lib/ruby_llm/protocols/interactions/chat.rb +145 -0
- data/lib/ruby_llm/protocols/interactions/content.rb +90 -0
- data/lib/ruby_llm/protocols/interactions/streaming.rb +91 -0
- data/lib/ruby_llm/protocols/interactions/tools.rb +51 -0
- data/lib/ruby_llm/protocols/interactions/transcription.rb +58 -0
- data/lib/ruby_llm/protocols/interactions.rb +29 -0
- data/lib/ruby_llm/protocols/invoke_model/cohere_embeddings.rb +51 -0
- data/lib/ruby_llm/protocols/invoke_model/embedding_batches.rb +111 -0
- data/lib/ruby_llm/protocols/invoke_model/nova_embeddings.rb +50 -0
- data/lib/ruby_llm/protocols/invoke_model/stability_images.rb +103 -0
- data/lib/ruby_llm/protocols/invoke_model/titan_multimodal_embeddings.rb +33 -0
- data/lib/ruby_llm/protocols/invoke_model/titan_text_embeddings.rb +44 -0
- data/lib/ruby_llm/protocols/invoke_model.rb +57 -0
- data/lib/ruby_llm/protocols/mistral/content.rb +49 -0
- data/lib/ruby_llm/protocols/mistral/conversations/chat.rb +160 -0
- data/lib/ruby_llm/protocols/mistral/conversations/images.rb +43 -0
- data/lib/ruby_llm/protocols/mistral/conversations/streaming.rb +83 -0
- data/lib/ruby_llm/protocols/mistral/conversations.rb +30 -0
- data/lib/ruby_llm/protocols/mistral/files.rb +36 -0
- data/lib/ruby_llm/protocols/mistral/multi_completion.rb +160 -0
- data/lib/ruby_llm/protocols/openai/batches.rb +126 -0
- data/lib/ruby_llm/protocols/openai/files.rb +42 -0
- data/lib/ruby_llm/protocols/openrouter/batches.rb +147 -0
- data/lib/ruby_llm/protocols/openrouter/files.rb +24 -0
- data/lib/ruby_llm/protocols/openrouter/responses.rb +53 -0
- data/lib/ruby_llm/protocols/openrouter/transcription.rb +51 -0
- data/lib/ruby_llm/protocols/perplexity/files.rb +48 -0
- data/lib/ruby_llm/protocols/perplexity/router.rb +59 -0
- data/lib/ruby_llm/protocols/responses/approvals.rb +32 -0
- data/lib/ruby_llm/protocols/responses/batches.rb +32 -0
- data/lib/ruby_llm/protocols/responses/chat.rb +476 -0
- data/lib/ruby_llm/protocols/responses/compaction.rb +29 -0
- data/lib/ruby_llm/protocols/responses/media.rb +61 -0
- data/lib/ruby_llm/protocols/responses/streaming.rb +117 -0
- data/lib/ruby_llm/protocols/responses/token_counting.rb +26 -0
- data/lib/ruby_llm/protocols/responses/tools.rb +39 -0
- data/lib/ruby_llm/protocols/responses.rb +35 -0
- data/lib/ruby_llm/protocols/vertexai/batch_prediction.rb +155 -0
- data/lib/ruby_llm/protocols/vertexai/embedding_prediction/requests.rb +85 -0
- data/lib/ruby_llm/protocols/vertexai/embedding_prediction/results.rb +74 -0
- data/lib/ruby_llm/protocols/vertexai/embedding_prediction.rb +56 -0
- data/lib/ruby_llm/protocols/vertexai/files.rb +101 -0
- data/lib/ruby_llm/protocols/vertexai/ranking.rb +69 -0
- data/lib/ruby_llm/protocols/vertexai/research.rb +193 -0
- data/lib/ruby_llm/protocols/xai/files.rb +30 -0
- data/lib/ruby_llm/protocols/xai/streaming_transcription.rb +120 -0
- data/lib/ruby_llm/protocols/xai/tokenization.rb +23 -0
- data/lib/ruby_llm/provider.rb +565 -124
- data/lib/ruby_llm/providers/anthropic/capabilities.rb +5 -7
- data/lib/ruby_llm/providers/anthropic.rb +4 -6
- data/lib/ruby_llm/providers/azure/audio.rb +18 -0
- data/lib/ruby_llm/providers/azure/capabilities.rb +16 -0
- data/lib/ruby_llm/providers/azure/chat.rb +2 -9
- data/lib/ruby_llm/providers/azure/chat_completions/batches.rb +29 -0
- data/lib/ruby_llm/providers/azure/chat_completions.rb +80 -0
- data/lib/ruby_llm/providers/azure/cohere.rb +33 -0
- data/lib/ruby_llm/providers/azure/embeddings.rb +3 -2
- data/lib/ruby_llm/providers/azure/images.rb +22 -0
- data/lib/ruby_llm/providers/azure/media.rb +6 -15
- data/lib/ruby_llm/providers/azure/models.rb +35 -0
- data/lib/ruby_llm/providers/azure/responses.rb +26 -0
- data/lib/ruby_llm/providers/azure/videos.rb +64 -0
- data/lib/ruby_llm/providers/azure.rb +77 -78
- data/lib/ruby_llm/providers/bedrock/auth.rb +61 -41
- data/lib/ruby_llm/providers/bedrock/capabilities.rb +18 -0
- data/lib/ruby_llm/providers/bedrock/mantle/anthropic.rb +39 -0
- data/lib/ruby_llm/providers/bedrock/mantle/chat_completions.rb +23 -0
- data/lib/ruby_llm/providers/bedrock/mantle/responses.rb +24 -0
- data/lib/ruby_llm/providers/bedrock/mantle/voxtral.rb +96 -0
- data/lib/ruby_llm/providers/bedrock/mantle.rb +57 -0
- data/lib/ruby_llm/providers/bedrock/models.rb +194 -42
- data/lib/ruby_llm/providers/bedrock.rb +217 -46
- data/lib/ruby_llm/providers/cohere.rb +31 -0
- data/lib/ruby_llm/providers/deepgram.rb +37 -0
- data/lib/ruby_llm/providers/deepseek/capabilities.rb +4 -8
- data/lib/ruby_llm/providers/deepseek/chat.rb +56 -0
- data/lib/ruby_llm/providers/deepseek/responses.rb +68 -0
- data/lib/ruby_llm/providers/deepseek.rb +9 -2
- data/lib/ruby_llm/providers/elevenlabs.rb +35 -0
- data/lib/ruby_llm/providers/gemini/capabilities.rb +8 -107
- data/lib/ruby_llm/providers/gemini.rb +15 -8
- data/lib/ruby_llm/providers/gpustack/chat.rb +2 -9
- data/lib/ruby_llm/providers/gpustack/embeddings.rb +28 -0
- data/lib/ruby_llm/providers/gpustack/media.rb +17 -16
- data/lib/ruby_llm/providers/gpustack/models.rb +72 -60
- data/lib/ruby_llm/providers/gpustack/speech.rb +15 -0
- data/lib/ruby_llm/providers/gpustack/transcription.rb +29 -0
- data/lib/ruby_llm/providers/gpustack.rb +35 -11
- data/lib/ruby_llm/providers/mistral/capabilities.rb +7 -155
- data/lib/ruby_llm/providers/mistral/chat.rb +37 -61
- data/lib/ruby_llm/providers/mistral/chat_completions/batches.rb +120 -0
- data/lib/ruby_llm/providers/mistral/chat_completions.rb +21 -0
- data/lib/ruby_llm/providers/mistral/conversations.rb +12 -0
- data/lib/ruby_llm/providers/mistral/embeddings.rb +6 -4
- data/lib/ruby_llm/providers/mistral/media.rb +43 -0
- data/lib/ruby_llm/providers/mistral/models.rb +57 -21
- data/lib/ruby_llm/providers/mistral/ocr.rb +47 -0
- data/lib/ruby_llm/providers/mistral/speech.rb +51 -0
- data/lib/ruby_llm/providers/mistral/transcription.rb +62 -0
- data/lib/ruby_llm/providers/mistral.rb +18 -6
- data/lib/ruby_llm/providers/ollama/chat.rb +9 -8
- data/lib/ruby_llm/providers/ollama/media.rb +6 -15
- data/lib/ruby_llm/providers/ollama/models.rb +50 -9
- data/lib/ruby_llm/providers/ollama.rb +9 -8
- data/lib/ruby_llm/providers/ollama_cloud/models.rb +14 -0
- data/lib/ruby_llm/providers/ollama_cloud.rb +40 -0
- data/lib/ruby_llm/providers/openai/capabilities.rb +54 -259
- data/lib/ruby_llm/providers/openai/models.rb +23 -23
- data/lib/ruby_llm/providers/openai/responses.rb +13 -0
- data/lib/ruby_llm/providers/openai.rb +92 -11
- data/lib/ruby_llm/providers/openrouter/chat.rb +130 -104
- data/lib/ruby_llm/providers/openrouter/embeddings.rb +51 -0
- data/lib/ruby_llm/providers/openrouter/images.rb +44 -43
- data/lib/ruby_llm/providers/openrouter/media.rb +34 -0
- data/lib/ruby_llm/providers/openrouter/models.rb +50 -11
- data/lib/ruby_llm/providers/openrouter/speech.rb +32 -0
- data/lib/ruby_llm/providers/openrouter/streaming.rb +31 -38
- data/lib/ruby_llm/providers/openrouter/videos.rb +81 -0
- data/lib/ruby_llm/providers/openrouter.rb +78 -20
- data/lib/ruby_llm/providers/perplexity/chat.rb +4 -0
- data/lib/ruby_llm/providers/perplexity/embeddings.rb +32 -0
- data/lib/ruby_llm/providers/perplexity/media.rb +46 -0
- data/lib/ruby_llm/providers/perplexity/models.rb +80 -13
- data/lib/ruby_llm/providers/perplexity.rb +29 -21
- data/lib/ruby_llm/providers/vertexai/anthropic/batches.rb +52 -0
- data/lib/ruby_llm/providers/vertexai/anthropic.rb +34 -0
- data/lib/ruby_llm/providers/vertexai/capabilities.rb +19 -0
- data/lib/ruby_llm/providers/vertexai/chat_completions/batches.rb +54 -0
- data/lib/ruby_llm/providers/vertexai/chat_completions.rb +15 -0
- data/lib/ruby_llm/providers/vertexai/embed_content.rb +42 -0
- data/lib/ruby_llm/providers/vertexai/embeddings.rb +22 -7
- data/lib/ruby_llm/providers/vertexai/gemini/batches.rb +42 -0
- data/lib/ruby_llm/providers/vertexai/gemini.rb +69 -0
- data/lib/ruby_llm/providers/vertexai/live_transcription.rb +24 -0
- data/lib/ruby_llm/providers/vertexai/mistral.rb +28 -0
- data/lib/ruby_llm/providers/vertexai/models.rb +145 -43
- data/lib/ruby_llm/providers/vertexai/transcription.rb +49 -4
- data/lib/ruby_llm/providers/vertexai/videos.rb +61 -0
- data/lib/ruby_llm/providers/vertexai.rb +164 -17
- data/lib/ruby_llm/providers/xai/capabilities.rb +18 -0
- data/lib/ruby_llm/providers/xai/chat.rb +10 -0
- data/lib/ruby_llm/providers/xai/chat_completions/batches.rb +108 -0
- data/lib/ruby_llm/providers/xai/chat_completions.rb +19 -0
- data/lib/ruby_llm/providers/xai/images.rb +91 -0
- data/lib/ruby_llm/providers/xai/models.rb +32 -48
- data/lib/ruby_llm/providers/xai/reported_cost.rb +18 -0
- data/lib/ruby_llm/providers/xai/responses.rb +52 -0
- data/lib/ruby_llm/providers/xai/speech.rb +45 -0
- data/lib/ruby_llm/providers/xai/transcription.rb +48 -0
- data/lib/ruby_llm/providers/xai/videos.rb +87 -0
- data/lib/ruby_llm/providers/xai.rb +17 -7
- data/lib/ruby_llm/railtie.rb +11 -16
- data/lib/ruby_llm/rerank.rb +105 -0
- data/lib/ruby_llm/research_job.rb +241 -0
- data/lib/ruby_llm/search_results.rb +68 -0
- data/lib/ruby_llm/server_tool_call.rb +73 -0
- data/lib/ruby_llm/speech.rb +159 -0
- data/lib/ruby_llm/speech_chunk.rb +33 -0
- data/lib/ruby_llm/support/deprecator.rb +22 -0
- data/lib/ruby_llm/support/inspectable.rb +49 -0
- data/lib/ruby_llm/support/instrumentation.rb +41 -0
- data/lib/ruby_llm/support/utils.rb +147 -0
- data/lib/ruby_llm/thinking.rb +127 -20
- data/lib/ruby_llm/tokenization.rb +59 -0
- data/lib/ruby_llm/tokens.rb +103 -33
- data/lib/ruby_llm/tool.rb +266 -91
- data/lib/ruby_llm/tool_call.rb +36 -3
- data/lib/ruby_llm/tools/server_tools.rb +109 -0
- data/lib/ruby_llm/transcription/wav_audio.rb +62 -0
- data/lib/ruby_llm/transcription.rb +139 -13
- data/lib/ruby_llm/transcription_chunk.rb +68 -0
- data/lib/ruby_llm/transport/connection.rb +193 -0
- data/lib/ruby_llm/transport/error_middleware.rb +131 -0
- data/lib/ruby_llm/transport/usage_middleware.rb +28 -0
- data/lib/ruby_llm/transport/websocket_connection.rb +220 -0
- data/lib/ruby_llm/uploaded_file.rb +144 -0
- data/lib/ruby_llm/version.rb +2 -1
- data/lib/ruby_llm/video.rb +136 -0
- data/lib/ruby_llm/video_job.rb +150 -0
- data/lib/ruby_llm/workflow.rb +91 -0
- data/lib/ruby_llm.rb +385 -4
- data/lib/tasks/ruby_llm.rake +21 -16
- data/skills/rubyllm/SKILL.md +81 -0
- data/skills/rubyllm/agents/openai.yaml +4 -0
- metadata +340 -92
- data/lib/generators/ruby_llm/install/templates/add_references_to_chats_tool_calls_and_messages_migration.rb.tt +0 -9
- data/lib/generators/ruby_llm/install/templates/create_models_migration.rb.tt +0 -39
- data/lib/generators/ruby_llm/install/templates/create_tool_calls_migration.rb.tt +0 -21
- data/lib/generators/ruby_llm/install/templates/model_model.rb.tt +0 -3
- data/lib/generators/ruby_llm/install/templates/tool_call_model.rb.tt +0 -3
- data/lib/generators/ruby_llm/upgrade_to_v1_10/templates/add_v1_10_message_columns.rb.tt +0 -19
- data/lib/generators/ruby_llm/upgrade_to_v1_10/upgrade_to_v1_10_generator.rb +0 -50
- data/lib/generators/ruby_llm/upgrade_to_v1_14/templates/add_v1_14_tool_call_columns.rb.tt +0 -7
- data/lib/generators/ruby_llm/upgrade_to_v1_14/upgrade_to_v1_14_generator.rb +0 -49
- data/lib/generators/ruby_llm/upgrade_to_v1_7/templates/migration.rb.tt +0 -145
- data/lib/generators/ruby_llm/upgrade_to_v1_7/upgrade_to_v1_7_generator.rb +0 -122
- data/lib/generators/ruby_llm/upgrade_to_v1_9/templates/add_v1_9_message_columns.rb.tt +0 -15
- data/lib/generators/ruby_llm/upgrade_to_v1_9/upgrade_to_v1_9_generator.rb +0 -49
- data/lib/ruby_llm/active_record/acts_as_legacy.rb +0 -530
- data/lib/ruby_llm/active_record/model_methods.rb +0 -82
- data/lib/ruby_llm/active_record/tool_call_methods.rb +0 -18
- data/lib/ruby_llm/aliases.rb +0 -38
- data/lib/ruby_llm/connection.rb +0 -130
- data/lib/ruby_llm/content.rb +0 -77
- data/lib/ruby_llm/mime_type.rb +0 -71
- data/lib/ruby_llm/model/info.rb +0 -130
- data/lib/ruby_llm/models_schema.json +0 -171
- data/lib/ruby_llm/providers/anthropic/chat.rb +0 -257
- data/lib/ruby_llm/providers/anthropic/content.rb +0 -44
- data/lib/ruby_llm/providers/anthropic/embeddings.rb +0 -20
- data/lib/ruby_llm/providers/anthropic/media.rb +0 -92
- data/lib/ruby_llm/providers/anthropic/models.rb +0 -57
- data/lib/ruby_llm/providers/anthropic/streaming.rb +0 -69
- data/lib/ruby_llm/providers/bedrock/chat.rb +0 -403
- data/lib/ruby_llm/providers/bedrock/media.rb +0 -90
- data/lib/ruby_llm/providers/bedrock/streaming.rb +0 -322
- data/lib/ruby_llm/providers/gemini/chat.rb +0 -543
- data/lib/ruby_llm/providers/gemini/embeddings.rb +0 -37
- data/lib/ruby_llm/providers/gemini/images.rb +0 -47
- data/lib/ruby_llm/providers/gemini/models.rb +0 -38
- data/lib/ruby_llm/providers/gemini/streaming.rb +0 -96
- data/lib/ruby_llm/providers/gemini/tools.rb +0 -232
- data/lib/ruby_llm/providers/gpustack/capabilities.rb +0 -20
- data/lib/ruby_llm/providers/ollama/capabilities.rb +0 -20
- data/lib/ruby_llm/providers/openai/chat.rb +0 -221
- data/lib/ruby_llm/providers/openai/embeddings.rb +0 -33
- data/lib/ruby_llm/providers/openai/images.rb +0 -90
- data/lib/ruby_llm/providers/openai/media.rb +0 -84
- data/lib/ruby_llm/providers/openai/moderation.rb +0 -34
- data/lib/ruby_llm/providers/openai/streaming.rb +0 -53
- data/lib/ruby_llm/providers/openai/temperature.rb +0 -28
- data/lib/ruby_llm/providers/openai/transcription.rb +0 -70
- data/lib/ruby_llm/providers/perplexity/capabilities.rb +0 -72
- data/lib/ruby_llm/providers/vertexai/chat.rb +0 -14
- data/lib/ruby_llm/providers/vertexai/streaming.rb +0 -14
- data/lib/ruby_llm/stream_accumulator.rb +0 -203
- data/lib/ruby_llm/streaming.rb +0 -175
- data/lib/ruby_llm/utils.rb +0 -91
- data/lib/tasks/models.rake +0 -565
- data/lib/tasks/release.rake +0 -67
- data/lib/tasks/vcr.rake +0 -124
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 3e6a6455ecb1c6bf276d863d9e1f181f1a1d3ea87092800a01522c1fb9be35fc
|
|
4
|
+
data.tar.gz: 39554eb45edfde45e43e0a9eb9afe2a5e07cf6601b9b8076e19065493e62e0fd
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: c92879f31f983745665f2a08db2e9b01a293d40ebd2a0e68ee899e1af4b77f7d4c6767c700bcbdecc85088a43a0fae58a11b617c4409e1b04b73d44a7f59b4da
|
|
7
|
+
data.tar.gz: 853e3cdde61afafbfdff5ff84cdc3c9878002f4da1b81e45e1b105b0caf759587647a03cb05d85d806a5e3c91c48ec426d24e356615914802860cb1cdec9c6cb
|
data/.rdoc_options
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: RubyLLM
|
|
3
|
+
exclude:
|
|
4
|
+
- lib/ruby_llm/providers/
|
|
5
|
+
- lib/ruby_llm/protocols/
|
|
6
|
+
- lib/ruby_llm/protocol/
|
|
7
|
+
- lib/ruby_llm/transport/
|
|
8
|
+
- lib/ruby_llm/support/
|
|
9
|
+
- lib/ruby_llm/accounting/
|
|
10
|
+
- lib/ruby_llm/files/
|
|
11
|
+
- lib/ruby_llm/tools/
|
|
12
|
+
- lib/ruby_llm/models/
|
|
13
|
+
- lib/ruby_llm/chat/tool_concurrency\.rb$
|
|
14
|
+
- lib/ruby_llm/transcription/wav_audio\.rb$
|
|
15
|
+
- lib/tasks/
|
|
16
|
+
- lib/generators/
|
|
17
|
+
- \.json$
|
|
18
|
+
footer_content:
|
|
19
|
+
Documentation:
|
|
20
|
+
Guides: https://rubyllm.com/next/
|
|
21
|
+
Upgrading: https://rubyllm.com/next/upgrading/
|
|
22
|
+
Resources:
|
|
23
|
+
GitHub: https://github.com/crmne/ruby_llm
|
|
24
|
+
Issues: https://github.com/crmne/ruby_llm/issues
|
|
25
|
+
Releases: https://github.com/crmne/ruby_llm/releases
|
data/README.md
CHANGED
|
@@ -5,9 +5,11 @@
|
|
|
5
5
|
<img src="/docs/assets/images/logotype.svg" alt="RubyLLM" height="120" width="250">
|
|
6
6
|
</picture>
|
|
7
7
|
|
|
8
|
-
<strong>
|
|
8
|
+
<strong>Build AI features the Ruby way</strong>
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
<p>The Ruby-native AI framework. Build with chats, tools, agents, images, audio, and video through one consistent API, in plain Ruby or Rails.</p>
|
|
11
|
+
|
|
12
|
+
Battle tested at [<picture><source media="(prefers-color-scheme: dark)" srcset="https://chatwithwork.com/logotype-dark.svg"><img src="https://chatwithwork.com/logotype.svg" alt="Chat with Work" height="30" align="absmiddle"></picture>](https://chatwithwork.com) - *Fully private work AI*
|
|
11
13
|
|
|
12
14
|
[](https://badge.fury.io/rb/ruby_llm)
|
|
13
15
|
[](https://github.com/rubocop/rubocop)
|
|
@@ -22,20 +24,22 @@ Battle tested at [<picture><source media="(prefers-color-scheme: dark)" srcset="
|
|
|
22
24
|
|
|
23
25
|
---
|
|
24
26
|
|
|
25
|
-
|
|
27
|
+
Work with OpenAI, xAI, Anthropic, Google, AWS, local models, and more. Seventeen providers are built in, and you can connect an OpenAI-compatible endpoint directly.
|
|
26
28
|
|
|
27
|
-
##
|
|
29
|
+
## Build a working Ruby AI chat in two minutes
|
|
28
30
|
|
|
29
31
|
https://github.com/user-attachments/assets/65422091-9338-47da-a303-92b918bd1345
|
|
30
32
|
|
|
31
33
|
## Why RubyLLM?
|
|
32
34
|
|
|
33
|
-
|
|
35
|
+
Use the same Ruby methods across providers. Add files to a conversation, give an agent tools, generate media, or build a search feature with embeddings and reranking. Read response text, generated files, and usage through Ruby objects.
|
|
34
36
|
|
|
35
|
-
|
|
37
|
+
In Rails, the API works on your own Chat and Message records, with Active Storage attachments, Hotwire streaming, and background jobs. RubyLLM maintains the supporting model registry, tool calls, usage ledger, and batches. A handful of small dependencies keeps it easy to bring into an existing application.
|
|
36
38
|
|
|
37
39
|
## Show me the code
|
|
38
40
|
|
|
41
|
+
These examples use **2.0.0.rc1**. Follow [Getting Started](https://rubyllm.com/next/getting-started/) to install it and configure the providers you want to try.
|
|
42
|
+
|
|
39
43
|
```ruby
|
|
40
44
|
# Just ask questions
|
|
41
45
|
chat = RubyLLM.chat
|
|
@@ -43,7 +47,8 @@ chat.ask "What's the best way to learn Ruby?"
|
|
|
43
47
|
```
|
|
44
48
|
|
|
45
49
|
```ruby
|
|
46
|
-
#
|
|
50
|
+
# Ask about files with a model that supports their input types
|
|
51
|
+
chat = RubyLLM.chat(model: "gemini-3.7-flash")
|
|
47
52
|
chat.ask "What's in this image?", with: "ruby_conf.jpg"
|
|
48
53
|
chat.ask "What's happening in this video?", with: "video.mp4"
|
|
49
54
|
chat.ask "Describe this meeting", with: "meeting.wav"
|
|
@@ -65,28 +70,56 @@ end
|
|
|
65
70
|
|
|
66
71
|
```ruby
|
|
67
72
|
# Generate images
|
|
68
|
-
RubyLLM.paint "a sunset over mountains in watercolor style"
|
|
73
|
+
image = RubyLLM.paint "a sunset over mountains in watercolor style"
|
|
74
|
+
image.save "sunset.png"
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
```ruby
|
|
78
|
+
# Generate videos
|
|
79
|
+
video = RubyLLM.animate "a paper boat sailing down a rainy gutter"
|
|
80
|
+
video.save "paper_boat.mp4"
|
|
69
81
|
```
|
|
70
82
|
|
|
71
83
|
```ruby
|
|
72
84
|
# Create embeddings
|
|
73
|
-
RubyLLM.embed "Ruby is elegant and expressive"
|
|
85
|
+
embedding = RubyLLM.embed "Ruby is elegant and expressive"
|
|
86
|
+
embedding.vectors
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
```ruby
|
|
90
|
+
# Rank search results
|
|
91
|
+
documents = ["Reset your password in Settings.", "Invoices arrive by email."]
|
|
92
|
+
ranked = RubyLLM.rerank("How do I reset my password?", documents, model: "rerank-v3.5")
|
|
93
|
+
ranked.results.first.document
|
|
74
94
|
```
|
|
75
95
|
|
|
76
96
|
```ruby
|
|
77
97
|
# Transcribe audio to text
|
|
78
|
-
RubyLLM.transcribe "meeting.wav"
|
|
98
|
+
transcript = RubyLLM.transcribe "meeting.wav"
|
|
99
|
+
puts transcript.text
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
```ruby
|
|
103
|
+
# Turn text into speech
|
|
104
|
+
speech = RubyLLM.speak "Hello, welcome to RubyLLM!"
|
|
105
|
+
speech.save "welcome.mp3"
|
|
79
106
|
```
|
|
80
107
|
|
|
81
108
|
```ruby
|
|
82
|
-
#
|
|
83
|
-
RubyLLM.
|
|
109
|
+
# Extract document text as markdown
|
|
110
|
+
document = RubyLLM.ocr "contract.pdf"
|
|
111
|
+
puts document.markdown
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
```ruby
|
|
115
|
+
# Check whether a moderation model flags content
|
|
116
|
+
RubyLLM.moderate("Some user-generated content").flagged?
|
|
84
117
|
```
|
|
85
118
|
|
|
86
119
|
```ruby
|
|
87
120
|
# Let AI use your code
|
|
88
121
|
class Weather < RubyLLM::Tool
|
|
89
|
-
|
|
122
|
+
description "Get current weather"
|
|
90
123
|
|
|
91
124
|
def execute(latitude:, longitude:)
|
|
92
125
|
url = "https://api.open-meteo.com/v1/forecast?latitude=#{latitude}&longitude=#{longitude}¤t=temperature_2m,wind_speed_10m"
|
|
@@ -94,13 +127,13 @@ class Weather < RubyLLM::Tool
|
|
|
94
127
|
end
|
|
95
128
|
end
|
|
96
129
|
|
|
97
|
-
chat.
|
|
130
|
+
chat.with_tools(Weather).ask "What's the weather in Berlin?"
|
|
98
131
|
```
|
|
99
132
|
|
|
100
133
|
```ruby
|
|
101
134
|
# Define an agent with instructions + tools
|
|
102
135
|
class WeatherAssistant < RubyLLM::Agent
|
|
103
|
-
model "gpt-5-
|
|
136
|
+
model "gpt-5.6-luna"
|
|
104
137
|
instructions "Be concise and always use tools for weather."
|
|
105
138
|
tools Weather
|
|
106
139
|
end
|
|
@@ -110,7 +143,7 @@ WeatherAssistant.new.ask "What's the weather in Berlin?"
|
|
|
110
143
|
|
|
111
144
|
```ruby
|
|
112
145
|
# Get structured output
|
|
113
|
-
class ProductSchema <
|
|
146
|
+
class ProductSchema < Schematist::Schema
|
|
114
147
|
string :name
|
|
115
148
|
number :price
|
|
116
149
|
array :features do
|
|
@@ -119,50 +152,71 @@ class ProductSchema < RubyLLM::Schema
|
|
|
119
152
|
end
|
|
120
153
|
|
|
121
154
|
response = chat.with_schema(ProductSchema).ask "Analyze this product", with: "product.txt"
|
|
155
|
+
response.parsed
|
|
122
156
|
```
|
|
123
157
|
|
|
124
158
|
## Features
|
|
125
159
|
|
|
126
160
|
* **Chat:** Conversational AI with `RubyLLM.chat`
|
|
127
161
|
* **Vision:** Analyze images and videos
|
|
128
|
-
* **Audio:** Transcribe and
|
|
129
|
-
* **Documents:**
|
|
162
|
+
* **Audio:** Transcribe speech with `RubyLLM.transcribe` and generate it with `RubyLLM.speak`
|
|
163
|
+
* **Documents:** Ask questions about PDFs, text files, and other supported formats
|
|
164
|
+
* **OCR:** Turn documents into markdown with `RubyLLM.ocr`
|
|
130
165
|
* **Image generation:** Create images with `RubyLLM.paint`
|
|
166
|
+
* **Video generation:** Create videos with `RubyLLM.animate`
|
|
131
167
|
* **Embeddings:** Generate embeddings with `RubyLLM.embed`
|
|
132
|
-
* **
|
|
168
|
+
* **Reranking:** Order retrieval candidates by relevance with `RubyLLM.rerank`
|
|
169
|
+
* **Moderation:** Content flags, categories, and scores with `RubyLLM.moderate`
|
|
133
170
|
* **Tools:** Let AI call your Ruby methods
|
|
171
|
+
* **Tool approval:** Park a run until a human approves with `requires_approval`
|
|
172
|
+
* **The agentic loop:** Drive it yourself with `ask_later`, `step`, and `complete?`
|
|
173
|
+
* **Server tools:** Web search, code execution, and MCP connectors with `with_server_tools`
|
|
134
174
|
* **Agents:** Reusable assistants with `RubyLLM::Agent`
|
|
135
|
-
* **
|
|
175
|
+
* **Prompt templates:** ERB prompts in `app/prompts`, rendered with `RubyLLM.render_prompt`
|
|
176
|
+
* **Workflows:** Correlate multi-agent runs in your telemetry with `RubyLLM.workflow`
|
|
177
|
+
* **Structured output:** Define a Ruby schema and read the result with `response.parsed`
|
|
136
178
|
* **Streaming:** Real-time responses with blocks
|
|
137
|
-
* **Rails:**
|
|
179
|
+
* **Rails:** Active Record persistence, Active Storage attachments, Hotwire streaming, and generators
|
|
180
|
+
* **Files:** Upload once and reuse across chats with `RubyLLM.upload`
|
|
181
|
+
* **Prompt caching:** Turn on the provider's cache with `with_caching` and `cache_until_here`
|
|
182
|
+
* **Fallbacks and cancellation:** Retry on backup models with `with_fallbacks`, stop a run with `cancel`
|
|
183
|
+
* **Cost tracking:** A per-attempt usage ledger behind `chat.tokens` and `chat.cost`
|
|
138
184
|
* **Async:** Fiber-based concurrency
|
|
139
|
-
* **Model registry:**
|
|
185
|
+
* **Model registry:** Browse capabilities, limits, and pricing across providers
|
|
140
186
|
* **Extended thinking:** Control, view, and persist model deliberation
|
|
141
|
-
* **
|
|
187
|
+
* **Citations:** Normalized source citations from documents, search, and grounding
|
|
188
|
+
* **Batches:** Provider-side batch processing with provider-specific discounts via `RubyLLM.batch`
|
|
189
|
+
* **Compaction:** Let providers condense long conversations with `with_compaction`
|
|
190
|
+
* **Token counting:** Count a request before you send it with `count_tokens`
|
|
191
|
+
* **Providers:** OpenAI, Azure, xAI, Anthropic, Gemini, VertexAI, Bedrock, Cohere, DeepSeek, Mistral, Ollama, Ollama Cloud, OpenRouter, Perplexity, GPUStack, ElevenLabs, Deepgram, and any OpenAI-compatible API
|
|
142
192
|
|
|
143
193
|
## Installation
|
|
144
194
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
195
|
+
Install the 2.0 release candidate:
|
|
196
|
+
|
|
197
|
+
```bash
|
|
198
|
+
bundle add ruby_llm --version 2.0.0.rc1
|
|
148
199
|
```
|
|
149
|
-
Then `bundle install`.
|
|
150
200
|
|
|
151
|
-
Configure your
|
|
201
|
+
Configure a provider in your script, or in `config/initializers/ruby_llm.rb` in Rails:
|
|
202
|
+
|
|
152
203
|
```ruby
|
|
153
|
-
|
|
204
|
+
require 'ruby_llm'
|
|
205
|
+
|
|
154
206
|
RubyLLM.configure do |config|
|
|
155
|
-
config.openai_api_key = ENV
|
|
207
|
+
config.openai_api_key = ENV.fetch('OPENAI_API_KEY')
|
|
156
208
|
end
|
|
157
209
|
```
|
|
158
210
|
|
|
211
|
+
Configure the other providers used by the examples as needed: Gemini for files, xAI for video, Mistral for OCR, and Cohere for reranking. [Getting Started](https://rubyllm.com/next/getting-started/) shows each setup beside its example. If your app uses 1.16, follow the [upgrade guide](https://rubyllm.com/next/upgrading/) before deploying 2.0.
|
|
212
|
+
|
|
159
213
|
## Rails
|
|
160
214
|
|
|
161
215
|
```bash
|
|
162
216
|
# Install Rails Integration
|
|
163
217
|
bin/rails generate ruby_llm:install
|
|
164
218
|
bin/rails db:migrate
|
|
165
|
-
bin/rails ruby_llm:load_models
|
|
219
|
+
bin/rails ruby_llm:load_models
|
|
166
220
|
|
|
167
221
|
# Add Chat UI (optional)
|
|
168
222
|
bin/rails generate ruby_llm:chat_ui
|
|
@@ -173,7 +227,7 @@ class Chat < ApplicationRecord
|
|
|
173
227
|
acts_as_chat
|
|
174
228
|
end
|
|
175
229
|
|
|
176
|
-
chat = Chat.create! model: "
|
|
230
|
+
chat = Chat.create! model: "gpt-5.6-luna"
|
|
177
231
|
chat.ask "What's in this file?", with: "report.pdf"
|
|
178
232
|
```
|
|
179
233
|
|
|
@@ -181,7 +235,7 @@ Visit `http://localhost:3000/chats` for a ready-to-use chat interface!
|
|
|
181
235
|
|
|
182
236
|
## Documentation
|
|
183
237
|
|
|
184
|
-
[rubyllm.com](https://rubyllm.com)
|
|
238
|
+
[Guides](https://rubyllm.com/next/getting-started/) · [API reference](https://rubyllm.com/next/api/) · [Models](https://rubyllm.com/available-models/) · [Upgrading](https://rubyllm.com/next/upgrading/)
|
|
185
239
|
|
|
186
240
|
## Contributing
|
|
187
241
|
|
data/exe/ruby_llm
ADDED
|
@@ -28,8 +28,6 @@ module RubyLLM
|
|
|
28
28
|
args = []
|
|
29
29
|
args << "chat:#{chat_model_name}" if chat_model_name != 'Chat'
|
|
30
30
|
args << "message:#{message_model_name}" if message_model_name != 'Message'
|
|
31
|
-
args << "model:#{model_model_name}" if model_model_name != 'Model'
|
|
32
|
-
args << "tool_call:#{tool_call_model_name}" if tool_call_model_name != 'ToolCall'
|
|
33
31
|
arg_string = args.any? ? " #{args.join(' ')}" : ''
|
|
34
32
|
|
|
35
33
|
raise Thor::Error, <<~ERROR
|
|
@@ -37,9 +35,6 @@ module RubyLLM
|
|
|
37
35
|
|
|
38
36
|
Please run the install generator first:
|
|
39
37
|
bin/rails generate ruby_llm:install#{arg_string}
|
|
40
|
-
|
|
41
|
-
Or if upgrading from <= 1.6.x, run the upgrade generator:
|
|
42
|
-
bin/rails generate ruby_llm:upgrade_to_v1_7#{arg_string}
|
|
43
38
|
ERROR
|
|
44
39
|
end
|
|
45
40
|
|
|
@@ -114,6 +109,7 @@ module RubyLLM
|
|
|
114
109
|
return if application_controller.include?('def available_chat_models')
|
|
115
110
|
|
|
116
111
|
inject_into_file path, <<-RUBY, before: /^end\s*\z/
|
|
112
|
+
|
|
117
113
|
private
|
|
118
114
|
|
|
119
115
|
def available_chat_models
|
|
@@ -133,7 +129,7 @@ module RubyLLM
|
|
|
133
129
|
|
|
134
130
|
routes_content = <<~ROUTES.strip
|
|
135
131
|
namespace :#{namespace} do
|
|
136
|
-
resources :#{model_resource}, only: [ :index, :show ] do
|
|
132
|
+
resources :#{model_resource}, only: [ :index, :show ], constraints: { id: /[^\\/]+/ } do
|
|
137
133
|
collection do
|
|
138
134
|
post :refresh
|
|
139
135
|
end
|
|
@@ -146,7 +142,7 @@ module RubyLLM
|
|
|
146
142
|
route routes_content
|
|
147
143
|
else
|
|
148
144
|
model_routes = <<~ROUTES.strip
|
|
149
|
-
resources :#{
|
|
145
|
+
resources :#{model_resource_name}, only: [ :index, :show ], constraints: { id: /[^\\/]+/ } do
|
|
150
146
|
collection do
|
|
151
147
|
post :refresh
|
|
152
148
|
end
|
|
@@ -208,26 +204,6 @@ module RubyLLM
|
|
|
208
204
|
|
|
209
205
|
private
|
|
210
206
|
|
|
211
|
-
def ui_variant
|
|
212
|
-
@ui_variant ||= case options[:ui]
|
|
213
|
-
when 'tailwind'
|
|
214
|
-
:tailwind
|
|
215
|
-
when 'auto'
|
|
216
|
-
tailwind_available? ? :tailwind : :scaffold
|
|
217
|
-
else
|
|
218
|
-
:scaffold
|
|
219
|
-
end
|
|
220
|
-
end
|
|
221
|
-
|
|
222
|
-
def ui_template(template_path)
|
|
223
|
-
return template_path unless ui_variant == :tailwind
|
|
224
|
-
|
|
225
|
-
# Keep Tailwind templates as a separate set so we can mirror Rails/Tailwind
|
|
226
|
-
# scaffold conventions without complicating scaffold templates.
|
|
227
|
-
tailwind_template = "tailwind/#{template_path}"
|
|
228
|
-
File.exist?(File.join(self.class.source_root, "#{tailwind_template}.tt")) ? tailwind_template : template_path
|
|
229
|
-
end
|
|
230
|
-
|
|
231
207
|
def message_helper_module_name
|
|
232
208
|
if message_model_name.include?('::')
|
|
233
209
|
"#{message_model_name.deconstantize}::#{message_model_name.demodulize.pluralize}Helper"
|
|
@@ -235,22 +211,6 @@ module RubyLLM
|
|
|
235
211
|
"#{message_model_name.pluralize}Helper"
|
|
236
212
|
end
|
|
237
213
|
end
|
|
238
|
-
|
|
239
|
-
def tailwind_available?
|
|
240
|
-
Rails.root.join('app/assets/tailwind/application.css').exist? ||
|
|
241
|
-
Rails.root.join('config/tailwind.config.js').exist? ||
|
|
242
|
-
gem_in_bundle?('tailwindcss-rails') ||
|
|
243
|
-
gem_in_bundle?('cssbundling-rails')
|
|
244
|
-
end
|
|
245
|
-
|
|
246
|
-
def gem_in_bundle?(gem_name)
|
|
247
|
-
gemfile_path = Rails.root.join('Gemfile')
|
|
248
|
-
lockfile_path = Rails.root.join('Gemfile.lock')
|
|
249
|
-
|
|
250
|
-
[gemfile_path, lockfile_path].any? do |path|
|
|
251
|
-
path.exist? && path.read.include?(gem_name)
|
|
252
|
-
end
|
|
253
|
-
end
|
|
254
214
|
end
|
|
255
215
|
end
|
|
256
216
|
end
|
|
@@ -7,22 +7,30 @@ class <%= chat_controller_class_name %> < ApplicationController
|
|
|
7
7
|
|
|
8
8
|
def new
|
|
9
9
|
@<%= chat_variable_name %> = <%= chat_model_name %>.new
|
|
10
|
-
@selected_model = params[:model]
|
|
10
|
+
@selected_model = params[:provider] ? [ params[:provider], params[:model] ].join(":") : params[:model]
|
|
11
11
|
@chat_models = available_chat_models
|
|
12
12
|
end
|
|
13
13
|
|
|
14
14
|
def create
|
|
15
15
|
prompt = params.dig(:<%= chat_variable_name %>, :prompt)
|
|
16
16
|
if prompt.present?
|
|
17
|
-
|
|
17
|
+
provider, model = params.dig(:<%= chat_variable_name %>, :model).to_s.split(":", 2)
|
|
18
|
+
@<%= chat_variable_name %> = <%= chat_model_name %>.create!(model: model.presence, provider: provider.presence)
|
|
18
19
|
<%= chat_job_class_name %>.perform_later(@<%= chat_variable_name %>.id, prompt)
|
|
19
20
|
|
|
20
21
|
redirect_to @<%= chat_variable_name %>, notice: "<%= chat_model_name.humanize %> was successfully created."
|
|
22
|
+
else
|
|
23
|
+
@<%= chat_variable_name %> = <%= chat_model_name %>.new
|
|
24
|
+
@<%= chat_variable_name %>.errors.add(:prompt, "can't be blank")
|
|
25
|
+
@selected_model = params.dig(:<%= chat_variable_name %>, :model)
|
|
26
|
+
@chat_models = available_chat_models
|
|
27
|
+
|
|
28
|
+
render :new, status: <%= unprocessable_content_status.inspect %>
|
|
21
29
|
end
|
|
22
30
|
end
|
|
23
31
|
|
|
24
32
|
def show
|
|
25
|
-
@<%= message_variable_name %> =
|
|
33
|
+
@<%= message_variable_name %> = <%= message_model_name %>.new
|
|
26
34
|
end
|
|
27
35
|
|
|
28
36
|
def destroy
|
|
@@ -10,6 +10,14 @@ class <%= message_controller_class_name %> < ApplicationController
|
|
|
10
10
|
format.turbo_stream
|
|
11
11
|
format.html { redirect_to @<%= chat_variable_name %> }
|
|
12
12
|
end
|
|
13
|
+
else
|
|
14
|
+
@<%= message_variable_name %> = @<%= chat_variable_name %>.<%= message_table_name %>.build
|
|
15
|
+
@<%= message_variable_name %>.errors.add(:content, "can't be blank")
|
|
16
|
+
|
|
17
|
+
respond_to do |format|
|
|
18
|
+
format.turbo_stream { render :create, status: <%= unprocessable_content_status.inspect %> }
|
|
19
|
+
format.html { render "<%= chat_model_name.underscore.pluralize %>/show", status: <%= unprocessable_content_status.inspect %> }
|
|
20
|
+
end
|
|
13
21
|
end
|
|
14
22
|
end
|
|
15
23
|
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
class <%= model_controller_class_name %> < ApplicationController
|
|
2
2
|
def index
|
|
3
|
-
@<%=
|
|
3
|
+
@<%= model_resource_name %> = available_chat_models
|
|
4
4
|
end
|
|
5
5
|
|
|
6
6
|
def show
|
|
7
|
-
@<%= model_variable_name %> =
|
|
7
|
+
@<%= model_variable_name %> = RubyLLM.models.find(params[:id], params[:provider])
|
|
8
8
|
end
|
|
9
9
|
|
|
10
10
|
def refresh
|
|
11
|
-
|
|
12
|
-
redirect_to <%=
|
|
11
|
+
RubyLLM.models.refresh
|
|
12
|
+
redirect_to <%= model_resource_name %>_path, notice: "<%= model_model_name.pluralize %> refreshed successfully"
|
|
13
13
|
end
|
|
14
14
|
end
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<div id="<%%= dom_id <%= chat_model_name.demodulize.underscore %> %>" class="w-full sm:w-auto my-5 space-y-3">
|
|
2
2
|
<div>
|
|
3
3
|
<strong class="block font-medium mb-1">Model:</strong>
|
|
4
|
-
<%%= <%= chat_model_name.demodulize.underscore
|
|
4
|
+
<%%= <%= chat_model_name.demodulize.underscore %>.model&.label || default_model_display_name %>
|
|
5
5
|
</div>
|
|
6
6
|
|
|
7
7
|
<div>
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
<div class="my-5">
|
|
15
15
|
<%%= form.label :model, "Select AI model:" %>
|
|
16
16
|
<%%= form.select :model,
|
|
17
|
-
options_for_select(@chat_models.map { |model| [model.label, model.id] }.unshift([default_model_display_name, nil]), @selected_model),
|
|
17
|
+
options_for_select(@chat_models.map { |model| [model.label, [model.provider, model.id].join(":")] }.unshift([default_model_display_name, nil]), @selected_model),
|
|
18
18
|
{},
|
|
19
19
|
class: ["block shadow-sm rounded-md border px-3 py-2 mt-2 w-full", {"border-gray-400 focus:outline-blue-600": <%= chat_variable_name %>.errors[:model].none?, "border-red-400 focus:outline-red-600": <%= chat_variable_name %>.errors[:model].any?}] %>
|
|
20
20
|
</div>
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
<div class="flex justify-between items-center">
|
|
9
9
|
<h1 class="font-bold text-4xl"><%= chat_model_name.pluralize %></h1>
|
|
10
10
|
<div class="flex items-center gap-2">
|
|
11
|
-
<%%= link_to "<%= model_model_name.pluralize %>", <%=
|
|
11
|
+
<%%= link_to "<%= model_model_name.pluralize %>", <%= model_resource_name %>_path, class: "rounded-md px-3.5 py-2.5 bg-gray-100 hover:bg-gray-50 text-gray-900 block font-medium" %>
|
|
12
12
|
<%%= link_to "New <%= chat_table_name.singularize.humanize.downcase %>", new_<%= chat_variable_name %>_path, class: "rounded-md px-3.5 py-2.5 bg-blue-600 hover:bg-blue-500 text-white block font-medium" %>
|
|
13
13
|
</div>
|
|
14
14
|
</div>
|
|
@@ -12,11 +12,11 @@
|
|
|
12
12
|
|
|
13
13
|
<div class="my-5">
|
|
14
14
|
<strong class="block font-medium mb-1">Model:</strong>
|
|
15
|
-
<%%= @<%= chat_variable_name
|
|
15
|
+
<%%= @<%= chat_variable_name %>.model&.label || default_model_display_name %>
|
|
16
16
|
</div>
|
|
17
17
|
|
|
18
18
|
<div id="<%= message_table_name %>" class="min-w-full divide-y divide-gray-200 space-y-5 my-5">
|
|
19
|
-
<%% @<%= chat_variable_name %>.<%= message_table_name %>.
|
|
19
|
+
<%% @<%= chat_variable_name %>.<%= message_table_name %>.each do |<%= message_variable_name %>| %>
|
|
20
20
|
<%%= render <%= message_variable_name %> %>
|
|
21
21
|
<%% end %>
|
|
22
22
|
</div>
|
data/lib/generators/ruby_llm/chat_ui/templates/tailwind/views/messages/_assistant.html.erb.tt
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<%% assistant ||= local_assigns[
|
|
1
|
+
<%% assistant ||= local_assigns[:<%= message_model_name.demodulize.underscore %>] %>
|
|
2
2
|
<div id="<%= message_variable_name %>_<%%= assistant.id %>" class="w-full sm:w-auto my-5 space-y-3 rounded-md px-3 py-2 bg-green-50">
|
|
3
3
|
<div>
|
|
4
4
|
<span class="inline-block rounded px-2 py-0.5 text-xs font-medium bg-green-100 text-green-700">
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<%% system ||= local_assigns[
|
|
1
|
+
<%% system ||= local_assigns[:<%= message_model_name.demodulize.underscore %>] %>
|
|
2
2
|
<div id="<%= message_variable_name %>_<%%= system.id %>" class="w-full sm:w-auto my-5 space-y-3 rounded-md px-3 py-2 bg-gray-50 border border-gray-200">
|
|
3
3
|
<div>
|
|
4
4
|
<span class="inline-block rounded px-2 py-0.5 text-xs font-medium bg-gray-200 text-gray-700">
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
<%% tool ||= local_assigns[
|
|
1
|
+
<%% tool ||= local_assigns[:<%= message_model_name.demodulize.underscore %>] %>
|
|
2
2
|
<%%= render tool_result_partial(tool), tool: tool %>
|
data/lib/generators/ruby_llm/chat_ui/templates/tailwind/views/messages/_tool_calls.html.erb.tt
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
<%%
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
<%% message = local_assigns[:<%= message_model_name.demodulize.underscore %>] || tool_calls %>
|
|
2
|
+
<div id="<%= message_variable_name %>_<%%= message.id %>">
|
|
3
|
+
<%% message.<%= tool_call_variable_name.pluralize %>.each_value do |tool_call| %>
|
|
4
|
+
<%%= render tool_call_partial(tool_call), message: message, tool_call: tool_call %>
|
|
5
|
+
<%% end %>
|
|
6
|
+
</div>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<%% user ||= local_assigns[
|
|
1
|
+
<%% user ||= local_assigns[:<%= message_model_name.demodulize.underscore %>] %>
|
|
2
2
|
<div id="<%= message_variable_name %>_<%%= user.id %>" class="w-full sm:w-auto my-5 space-y-3 rounded-md px-3 py-2 bg-blue-50">
|
|
3
3
|
<div>
|
|
4
4
|
<span class="inline-block rounded px-2 py-0.5 text-xs font-medium bg-blue-100 text-blue-700">
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<div id="<%= message_variable_name %>
|
|
1
|
+
<div id="<%= message_variable_name %>_tool_call_<%%= tool_call.id %>" class="w-full sm:w-auto my-5 space-y-3 rounded-md px-3 py-2 bg-gray-50 border border-gray-200">
|
|
2
2
|
<div>
|
|
3
3
|
<span class="inline-block rounded px-2 py-0.5 text-xs font-medium bg-gray-200 text-gray-700">
|
|
4
4
|
Tool Call
|
|
@@ -8,6 +8,6 @@
|
|
|
8
8
|
<pre class="whitespace-pre-wrap text-gray-700 text-sm overflow-x-auto"><%%= tool_call.name %>(<%%= tool_call.arguments.map { |k, v| "#{k}: #{v.inspect}" }.join(", ") %>)</pre>
|
|
9
9
|
|
|
10
10
|
<div>
|
|
11
|
-
<span class="text-sm text-gray-600"><%%=
|
|
11
|
+
<span class="text-sm text-gray-600"><%%= message.created_at&.strftime("%I:%M %p") %></span>
|
|
12
12
|
</div>
|
|
13
13
|
</div>
|
|
@@ -1,17 +1,16 @@
|
|
|
1
|
-
<%%
|
|
2
|
-
<%% row_id = [<%= model_model_name.demodulize.underscore %>.provider, model_id].join("_").parameterize(separator: "_") %>
|
|
1
|
+
<%% row_id = [<%= model_model_name.demodulize.underscore %>.provider, <%= model_model_name.demodulize.underscore %>.id].join("_").parameterize(separator: "_") %>
|
|
3
2
|
<tr id="model_<%%= row_id %>">
|
|
4
3
|
<td class="px-3 py-2 text-sm text-gray-700"><%%= <%= model_model_name.demodulize.underscore %>.provider_class&.name || <%= model_model_name.demodulize.underscore %>.provider %></td>
|
|
5
|
-
<td class="px-3 py-2 text-sm text-gray-900"><%%= <%= model_model_name.demodulize.underscore %>.
|
|
4
|
+
<td class="px-3 py-2 text-sm text-gray-900"><%%= <%= model_model_name.demodulize.underscore %>.name %></td>
|
|
6
5
|
<td class="px-3 py-2 text-sm text-gray-700"><%%= number_with_delimiter(<%= model_model_name.demodulize.underscore %>.context_window) if <%= model_model_name.demodulize.underscore %>.context_window %></td>
|
|
7
6
|
<td class="px-3 py-2 text-sm text-gray-700">
|
|
8
|
-
<%% input = <%= model_model_name.demodulize.underscore %>.
|
|
9
|
-
<%% output = <%= model_model_name.demodulize.underscore %>.
|
|
7
|
+
<%% input = <%= model_model_name.demodulize.underscore %>.price(:input) %>
|
|
8
|
+
<%% output = <%= model_model_name.demodulize.underscore %>.price(:output) %>
|
|
10
9
|
<%% if input && output %>
|
|
11
10
|
$<%%= "%.2f" % input %> / $<%%= "%.2f" % output %>
|
|
12
11
|
<%% end %>
|
|
13
12
|
</td>
|
|
14
13
|
<td class="px-3 py-2 text-sm">
|
|
15
|
-
<%%= link_to "Start <%= chat_table_name.singularize.humanize.downcase %>", new_<%= chat_variable_name %>_path(model:
|
|
14
|
+
<%%= link_to "Start <%= chat_table_name.singularize.humanize.downcase %>", new_<%= chat_variable_name %>_path(model: [<%= model_model_name.demodulize.underscore %>.provider, <%= model_model_name.demodulize.underscore %>.id].join(":")), class: "text-blue-600 hover:text-blue-500" %>
|
|
16
15
|
</td>
|
|
17
16
|
</tr>
|
|
@@ -9,11 +9,11 @@
|
|
|
9
9
|
<h1 class="font-bold text-4xl"><%= model_model_name.pluralize %></h1>
|
|
10
10
|
<div class="flex items-center gap-2">
|
|
11
11
|
<%%= link_to "<%= chat_model_name.pluralize %>", <%= chat_table_name %>_path, class: "rounded-md px-3.5 py-2.5 bg-gray-100 hover:bg-gray-50 text-gray-900 block font-medium" %>
|
|
12
|
-
<%%= button_to "Refresh <%= model_model_name.pluralize %>", refresh_<%=
|
|
12
|
+
<%%= button_to "Refresh <%= model_model_name.pluralize %>", refresh_<%= model_resource_name %>_path, method: :post, class: "rounded-md px-3.5 py-2.5 bg-blue-600 hover:bg-blue-500 text-white block font-medium cursor-pointer" %>
|
|
13
13
|
</div>
|
|
14
14
|
</div>
|
|
15
15
|
|
|
16
|
-
<div id="<%=
|
|
16
|
+
<div id="<%= model_resource_name %>" class="mt-5 overflow-x-auto">
|
|
17
17
|
<%% if @<%= model_variable_name.pluralize %>.any? %>
|
|
18
18
|
<table class="min-w-full divide-y divide-gray-300 border border-gray-300">
|
|
19
19
|
<thead class="bg-gray-50">
|