|
1 | 1 | # Contributing to RubyLLM
|
2 | 2 |
|
3 |
| -Thank you for considering contributing to RubyLLM! We're aiming to build a high-quality, robust library, and thoughtful contributions are welcome. |
4 |
| - |
5 |
| -## Development Setup and Workflow |
6 |
| - |
7 |
| -Getting started and contributing follows a typical GitHub-based workflow: |
8 |
| - |
9 |
| -1. **Fork & Clone**: Fork the repository to your own GitHub account and then clone it locally. |
10 |
| - ```bash |
11 |
| - gh repo fork crmne/ruby_llm --clone |
12 |
| - cd ruby_llm |
13 |
| - ``` |
14 |
| -2. **Install Dependencies**: |
15 |
| - ```bash |
16 |
| - bundle install |
17 |
| - ``` |
18 |
| -3. **Set Up Git Hooks**: Required. |
19 |
| - ```bash |
20 |
| - overcommit --install |
21 |
| - ``` |
22 |
| -4. **Branch**: Create a new branch for your feature or bugfix. If it relates to an existing issue, you can use the `gh` CLI to help: |
23 |
| - ```bash |
24 |
| - gh issue develop 123 --checkout # Substitute 123 with the relevant issue number |
25 |
| - ``` |
26 |
| -5. **Code & Test**: Make your changes and ensure they are well-tested. (See "Running Tests" section for more details). |
27 |
| -6. **Commit**: Write clear and concise commit messages. |
28 |
| -7. **Pull Request**: Create a Pull Request (PR) against the `main` branch of the `crmne/ruby_llm` repository. |
29 |
| - * **Thoroughly review your own PR before submitting.** Check for any "vibe coding" – unnecessary files, experimental code that doesn't belong, or incomplete work. |
30 |
| - * Write a **clear and detailed PR description** explaining the "what" and "why" of your changes. Link to any relevant issues. |
31 |
| - * Badly/vibe-coded PRs with minimal descriptions will likely be closed or receive extensive review comments, slowing things down for everyone. Follow the existing conventions of RubyLLM. Aim for quality. |
32 |
| - ```bash |
33 |
| - gh pr create --web |
34 |
| - ``` |
35 |
| -
|
36 |
| -## Model Registry (`models.json`) & Aliases (`aliases.json`) |
37 |
| -
|
38 |
| -These files are critical for how RubyLLM identifies and uses AI models. **Both are auto-generated by rake tasks. Do not edit them manually or include manual changes to them in PRs.** |
39 |
| -
|
40 |
| -### `models.json`: The Model Catalog |
41 |
| -
|
42 |
| -* **How it's made**: The `rake models:update` task builds this file. It fetches model data directly from configured provider APIs (processing these details via each provider's `capabilities.rb` file) and also from the [Parsera LLM Specs API](https://api.parsera.org/v1/llm-specs). These lists are then merged, with Parsera's standardized data generally taking precedence for common models, augmented by provider-specific metadata. Models unique to a provider's API (and not yet in Parsera) are also included. |
43 |
| -* **Updating Model Information**: |
44 |
| - * **Incorrect public specs (pricing, context size, etc.)?** Parsera scrapes public provider documentation. If data for a publicly documented model is wrong or missing on Parsera, please [file an issue with Parsera](https://github.com/parsera-labs/api-llm-specs/issues). Once they update, `rake models:update` will fetch the corrections. |
45 |
| - * **Models not in public docs / Provider-specifics**: If a model isn't well-documented publicly by the provider (e.g., older or preview models) or needs provider-specific handling within RubyLLM, update the relevant `lib/ruby_llm/providers/<provider>/capabilities.rb` and potentially `models.rb`. Then run `bundle exec rake models:update`. |
46 |
| - * **New Provider Support**: This involves more in-depth work to create the provider-specific modules and ensure integration with the `models:update` task. |
47 |
| -
|
48 |
| -### `aliases.json`: User-Friendly Shortcuts |
49 |
| -
|
50 |
| -* **Purpose**: Maps common names (e.g., `claude-3-5-sonnet`) to precise, versioned model IDs. |
51 |
| -* **How it's made**: Generated by `rake aliases:generate` using the current `models.json`. Run this task *after* `models.json` is updated. |
52 |
| - |
53 |
| -## Running Tests |
54 |
| - |
55 |
| -Tests are crucial. We use RSpec and VCR. |
| 3 | +Thanks for considering contributing! Here's what you need to know. |
56 | 4 |
|
57 |
| -```bash |
58 |
| -# Run all tests (uses existing VCR cassettes) |
59 |
| -bundle exec rspec |
60 |
| -
|
61 |
| -# Run a specific test file |
62 |
| -bundle exec rspec spec/ruby_llm/chat_spec.rb |
| 5 | +## Philosophy & Scope |
63 | 6 |
|
64 |
| -# To re-record a specific test's cassette, first remove its .yml file: |
65 |
| -rm spec/fixtures/vcr_cassettes/chat_vision_models_*_can_understand_local_images.yml # Adjust file name as needed |
66 |
| -# Then run the specific test or test file that uses this cassette. |
| 7 | +RubyLLM does one thing well: **LLM communication in Ruby**. |
67 | 8 |
|
68 |
| -# Run a specific test by its description string (or part of it) |
69 |
| -bundle exec rspec -e "can understand local images" |
70 |
| -``` |
| 9 | +### ✅ We Want |
| 10 | +- LLM provider integrations and new provider features |
| 11 | +- Convenience that benefits most users (Rails generators, etc.) |
| 12 | +- Performance and API consistency improvements |
71 | 13 |
|
72 |
| -### Testing Philosophy & VCR |
| 14 | +### ❌ We Don't Want |
| 15 | +- Application architecture (testing, persistence, error tracking) |
| 16 | +- One-off solutions you can build in your app |
| 17 | +- Auxiliary features unrelated to LLM communication |
73 | 18 |
|
74 |
| -* New tests should generally be **end-to-end** to verify integration with actual provider APIs (via VCR). |
75 |
| -* Keep tests **minimal and focused**. We don't need to test every single model variant for every feature if the underlying API mechanism is the same. One or two representative models per provider for a given feature is usually sufficient. |
76 |
| -* **API Call Costs**: VCR cassettes are used to avoid hitting live APIs on every test run. However, recording these cassettes costs real money for API calls. Please be mindful of this when adding tests that would require new recordings. If you're adding extensive tests that significantly increase API usage for VCR recording, consider [sponsoring the project on GitHub](https://github.com/sponsors/crmne) to help offset these costs. |
| 19 | +### Requests We'll Close |
| 20 | +- **RAG support** → Use dedicated libraries |
| 21 | +- **Prompt templates** → Use ERB/Mustache in your app |
| 22 | +- **Model data fixes** → File with [Parsera](https://github.com/parsera-labs/api-llm-specs/issues) |
| 23 | +- **Auto-failover** → Use `.with_model()` (works mid-conversation, even across providers) |
| 24 | +- **Tool interface changes** → Handle in your tool's initializer |
| 25 | +- **Testing helpers** → Use dependency injection |
77 | 26 |
|
78 |
| -### Recording VCR Cassettes |
| 27 | +**The rule:** If you can solve it in application code, you should. |
79 | 28 |
|
80 |
| -If your changes affect API interactions, you'll need to re-record the VCR cassettes. |
| 29 | +## Response Times & Paid Work |
81 | 30 |
|
82 |
| -To re-record cassettes for specific providers (e.g., OpenAI and Anthropic): |
83 |
| -
|
84 |
| -```bash |
85 |
| -# Set necessary API keys as environment variables |
86 |
| -export OPENAI_API_KEY="your_openai_key" |
87 |
| -export ANTHROPIC_API_KEY="your_anthropic_key" |
| 31 | +This is unpaid work I do between other priorities. I respond when I can. |
88 | 32 |
|
89 |
| -# Run the rake task, specifying providers |
90 |
| -bundle exec rake vcr:record[openai,anthropic] |
91 |
| -``` |
| 33 | +**Need something fast?** Email **carmine@paolino.work** for paid development. $200/hour, 10-hour minimum ($2000). |
92 | 34 |
|
93 |
| -To re-record all cassettes (requires all relevant API keys to be set): |
| 35 | +## Quick Start |
94 | 36 |
|
95 | 37 | ```bash
|
96 |
| -bundle exec rake vcr:record[all] |
| 38 | +gh repo fork crmne/ruby_llm --clone && cd ruby_llm |
| 39 | +bundle install |
| 40 | +overcommit --install |
| 41 | +gh issue develop 123 --checkout # or create your own branch |
| 42 | +# make changes, add tests |
| 43 | +gh pr create --web |
97 | 44 | ```
|
98 | 45 |
|
99 |
| -The rake task will delete the relevant existing cassettes and re-run the tests to record fresh interactions. |
| 46 | +## Essential Rules |
100 | 47 |
|
101 |
| -**CRITICAL**: After recording new or updated VCR cassettes, **manually inspect the YAML files in `spec/fixtures/vcr_cassettes/`**. Ensure that no sensitive information (API keys, personal data, etc.) has accidentally been recorded. The VCR configuration has filters for common keys, but diligence is required. |
| 48 | +1. **Run `overcommit --install` before doing anything** - it auto-fixes style, runs tests, and updates model files on commit |
| 49 | +2. **Don't edit `models.json` or `aliases.json`** - overcommit regenerates them automatically |
| 50 | +3. **Write clear PR descriptions** - explain what and why |
102 | 51 |
|
103 |
| -## Coding Style |
| 52 | +The git hooks handle style, tests, and file generation for you. No excuses for broken commits. |
104 | 53 |
|
105 |
| -We follow the [Standard Ruby](https://github.com/testdouble/standard) style guide. |
| 54 | +## Testing |
106 | 55 |
|
107 |
| -```bash |
108 |
| -# Check your code style |
109 |
| -bundle exec rubocop |
| 56 | +Run tests: `bundle exec rspec` |
110 | 57 |
|
111 |
| -# Auto-fix style issues where possible |
112 |
| -bundle exec rubocop -A |
| 58 | +**Re-recording VCR cassettes?** Set API keys and run: |
| 59 | +```bash |
| 60 | +bundle exec rake vcr:record[openai,anthropic] # specific providers |
| 61 | +bundle exec rake vcr:record[all] # everything |
113 | 62 | ```
|
114 | 63 |
|
115 |
| -The Overcommit pre-commit hook should help enforce this. |
116 |
| -
|
117 |
| -## Documentation |
118 |
| -
|
119 |
| -If you add new features or change existing behavior, please update the documentation: |
| 64 | +**Then inspect the YAML files** - make sure no API keys leaked. |
120 | 65 |
|
121 |
| -* Update relevant guides in the `docs/guides/` directory. |
122 |
| -* Ensure the `README.md` remains a concise and helpful entry point for new users. |
| 66 | +## Model Registry |
123 | 67 |
|
124 |
| -## Release Process |
| 68 | +**Don't touch these files directly:** |
| 69 | +- `models.json` - auto-generated from provider APIs + [Parsera](https://api.parsera.org/v1/llm-specs) |
| 70 | +- `aliases.json` - auto-generated from models.json |
125 | 71 |
|
126 |
| -Gem versioning follows [Semantic Versioning (SemVer)](https://semver.org/): |
| 72 | +**To update model info:** |
| 73 | +- Public model issues → File with [Parsera](https://github.com/parsera-labs/api-llm-specs/issues) |
127 | 74 |
|
128 |
| -1. **MAJOR** version for incompatible API changes. |
129 |
| -2. **MINOR** version for adding functionality in a backward-compatible manner. |
130 |
| -3. **PATCH** version for backward-compatible bug fixes. |
| 75 | +## Support the Project |
131 | 76 |
|
132 |
| -Releases are handled by the maintainers through the CI/CD pipeline. |
| 77 | +Consider [sponsoring RubyLLM](https://github.com/sponsors/crmne) to help with ongoing costs. Sponsorship supports general maintenance - for priority features, use paid development above. |
133 | 78 |
|
134 | 79 | ---
|
135 | 80 |
|
136 |
| -Thanks for contributing to RubyLLM, |
| 81 | +That's it. Let's make Ruby the best AI development experience possible. |
137 | 82 |
|
138 |
| -Carmine |
| 83 | +— Carmine |
0 commit comments