[HN Gopher] RubyLLM: A delightful Ruby way to work with AI
___________________________________________________________________
RubyLLM: A delightful Ruby way to work with AI
Author : ksec
Score : 579 points
Date : 2025-03-11 12:40 UTC (4 days ago)
(HTM) web link (github.com)
(TXT) w3m dump (github.com)
| jatins wrote:
| Such a breath of fresh air compared to poor DX libraries like
| langchain
| nullpoint420 wrote:
| I've found the Ruby community really cares about DUX. Not sure
| why it's not in other language communities
| choxi wrote:
| Matz said he designed Ruby to optimize for developer
| happiness, it's just a core principle of the language since
| it was created
| kuboble wrote:
| Happiness of a developer writing code can be a misery of a
| one having to read / debug it. I worked in ruby for a
| couple years around 2009 and having to deal with a code
| that implemented most of its logic via method missing is
| still one of the strongest negative memories I have about
| coding.
| viraptor wrote:
| Another annoying one from that category is Ruby's
| forwarded methods. Since they're created via generated,
| injected code, you can't query which method it forwards
| to at runtime. Or not easily anyway.
| MatthiasPortzel wrote:
| `binding.irb` and `show_source` have been magical in my
| Ruby debugging experience. `binding.irb` to trigger a
| breakpoint, and `show_source` will find the source code
| for a method name, even in generated code somehow.
| richjdsmith wrote:
| ... I've been using Ruby for years and never thought to
| use show_source like this in a debugger. Thanks kind
| stranger, you just made my day!
| RangerScience wrote:
| Yep yep, that's the whole "sharp knives" thing.
|
| What I advise (and aim for) is only pulling out the sharp
| knives for "library" code, but application code should
| stay "simple" (and this much more easily navigable).
| Otherwise you can absolutely make a bloody mess!
| toasterlovin wrote:
| I don't really mean this to be derogatory toward people who
| enjoy other things, but Ruby is a language and ecosystem by
| and for people who have taste.
| continuational wrote:
| Certainly a taste for global state, it seems.
| atemerev wrote:
| Dogmatically rejecting global state even if it simplifies
| things in some particular case _is_ poor taste.
|
| Even a goto can be elegant sometimes.
| zelphirkalt wrote:
| Usually though it just creates long term issues, putting
| off important work to later.
| bmacho wrote:
| Sometimes later never comes, so it's a net win compared
| to languages where you are forced do this _important
| work_ now.
| lolinder wrote:
| But when later does come, it can take dev-years to fully
| disentangle the global state and allow code reuse. Did
| you gain dev-years in productivity by using it in the
| first place? Probably not.
|
| If you have good reason to believe that an app will stick
| around for more than a year, be maintained by more than 3
| people, or grow to more than 500k lines of code (sub in
| whatever metrics make sense to you), don't put off
| removing global state for later. You _will_ regret it
| eventually, and it doesn 't cost much to do it right the
| first time.
|
| (Also, no mainstream language I'm aware of forces you to
| not use global state. Even Java, famed for its rigidity,
| has global state readily available if you really do need
| it.)
| trevorhinesley wrote:
| You're describing the pain of poor architecture rather
| than the pain of global state. The tool itself is
| neutral. Sharp knives and all that.
| lolinder wrote:
| Global state is a tool that will _almost always_ lead to
| bad architecture in an app where architecture matters. I
| 'm sure you can point to a counterexample or two where a
| set of devs managed to keep disciplined indefinitely, but
| that doesn't change the fact that allowing people to
| reach into a mutable variable from anywhere in the system
| enables trivially accessible spooky action at a distance,
| and spooky action at a distance is a recipe for disaster
| in a medium to large code base.
|
| In a project with more than a few people on it, your
| architecture will decay if it can decay. Avoiding global
| state removes one major source of potential decay.
| trevorhinesley wrote:
| "Almost" is key there. I respect your position, but it's
| an always/never take, and the longer I am in this
| industry, the more I find myself leaning into "it
| depends." Here's a take that articulates this being done
| well on a large codebase better than I can in a short
| comment: https://dev.37signals.com/globals-callbacks-and-
| other-sacril...
| lolinder wrote:
| > it's an always/never take
|
| No, it isn't--I'm the one who inserted the word "almost"
| into that sentence! Where did you get the idea that I
| meant always/never?
|
| Like I said, you can point to exceptions but that doesn't
| change the rule. It's better to teach the rule and break
| it when you really know what you're doing--when you
| _understand_ that you 're breaking a rule and can
| articulate why you need to and why it's okay this time--
| than it is to spread the idea that globals are really
| just fine and you need to weigh the trade-offs. The odds
| are strongly against you being the exception, and you
| should act accordingly, not treat globals as just another
| tool.
|
| Sometimes amputation is the right move to save someone's
| life, but you certainly should not default to that for
| every papercut. It's a tool that comes out in extreme
| circumstances only when a surgeon can thoroughly justify
| it.
| IshKebab wrote:
| Don't forget ungreppable code! And what are type hints
| anyway?
| simpaticoder wrote:
| Global state is wonderful when the world is small.
| Rubyfolk then keep the world small, which has many other
| benefits.
| lolinder wrote:
| Sorry, I like Ruby, but this is nonsense. Rails apps get
| enormous very quickly, like apps written in every other
| framework. In most work you can't just declare that your
| world will be small, your world is as big as your problem
| is.
| techscruggs wrote:
| Well, taste for a Global Interpreter Lock, at least.
| madeofpalk wrote:
| For a certain type of taste.
| rochak wrote:
| Umm, doesn't Go do so as well? Personally, I've had a better
| experience working with Go tooling.
| jatins wrote:
| Go ecosystem is generally good. However, given that Go as a
| language doesn't have any "fancy" (for the lack of a better
| word) syntactical features you can't create DSL's like this
|
| though Ruby's expressiveness comes at a cost and I'd
| personally stick with Go in a team but use something like
| RubyLLM for personal projects
| lolinder wrote:
| I'm wary of equating "ability to create dsls like this"
| with "prioritizing developer experience".
|
| Ruby and go each prioritize different parts of the
| developer experience. Ruby prioritizes the experience of
| the author of the initial code at the expense of the
| experience of the maintainer who comes later. Go
| prioritizes the experience of a maintainer over the
| experience of the initial author. Both prioritize a
| developer, both de-prioritize a different developer, and
| which one makes more sense really depends on the ratio of
| time spent on writing greenfield code versus maintaining
| something another human wrote years ago who's long gone.
| smw wrote:
| I disagree with the idea that Go prioritizes the
| maintainer. More lines of code typically makes
| maintenance more difficult. Go is easy to read line by
| line, but the verbosity makes it more challenging to
| understand the bigger picture.
|
| I find changes in existing Go software often end up
| spreading far deeper into the app than you'd expect.
|
| The runtime is fantastic, though, so I don't see it
| losing it's popularity anytime soon.
| danenania wrote:
| > More lines of code typically makes maintenance more
| difficult.
|
| That's kind of just the surface level of maintenance
| though. Go is not so much focused on making it easy to
| read a single file, but on minimizing the chains of
| abstraction and indirection you need to follow to
| understand exactly how things work.
|
| It's much more likely that all the logic and config to do
| something is right there in that file, or else just one
| or two "Go to definition" clicks away. You end up with
| way more boilerplate and repetition, but also looser
| coupling between files, functions, and components.
|
| Contrast that to a beautiful DSL in Ruby. It's lovely
| until it breaks or you need to extend it, and you realize
| that a small change will require refactoring call sites
| across a dozen different files. Oh and now this other
| thing that reused that logic is broken, and we've got to
| update most of the test suite, and so on.
| lolinder wrote:
| > or else just one or two "Go to definition" clicks away
|
| This is the biggest part of it: maintainers need static
| analysis and/or (preferably and) very good grepability to
| help them navigate foreign code. Ruby by its nature makes
| static analysis essentially impossible to do
| consistently, whereas Go leans to the opposite extreme.
| drdaeman wrote:
| Surely you can have semantically the same API in Go:
| // Must[T](T, error) T is necessary because of Go error
| handling differences chat := Must(gollm.Chat().Wi
| thModel("claude-3-7-sonnet-20250219"))
| resp := Must(chat.Ask("What's the difference between an
| unexported and an exported struct field?")) resp
| = Must(chat.Ask("Could you give me an example?"))
| resp = Must(chat.Ask("Tell me a story about a Go
| programmer")) for chunk := range resp { //
| Requires Go 1.23+ for iterators
| fmt.Print(chunk.Content) } resp =
| Must(chat.WithImages("diagram1.png",
| "diagram2.png").Ask("Compare these diagrams"))
| type Search struct { Query string
| `description:"The search query" required:"true"`
| Limit int `description:"Max results" default:"5"`
| } func (s Search) Execute() ([]string, error) {
| ... } resp =
| Must(chat.WithTool[Search]().Ask("Find documents about Go
| 1.23 features"))
|
| And so on. Syntax is different, of course, but semantics
| (save for language-specific nuances, like error handling
| and lack of optional arguments) are approximately the
| same, biggest difference being WithSomething() having to
| precede Ask()
| danenania wrote:
| I'd say they both optimize for DX, but they come at it from
| very different angles. Ruby is focused on actually writing
| the code: making it feel expressive, intuitive, and fun.
|
| Go is more about making it easier to build fast and robust
| systems. But it really doesn't care if the code itself is
| ugly and full of boilerplate.
|
| As I've gotten more experience, I've come to really
| appreciate Go's tradeoffs. It's not as fun up front, but on
| the other hand, you're less likely to get server alerts at
| 4am. It really depends what you're building though.
| RangerScience wrote:
| Every language prioritizes something (or somethings) because
| every language was made by a person (or people) with a
| reason; python and correctness; Java and splitting up work;
| Go and something like "simplicity" (not that these are the
| only priorities for each language). As another comment points
| out, Matz prioritized developer happiness.
|
| My favorite example of this is the amazing useful and amazing
| whack Ruby array arithmetic; subtraction (`arr1 - arr2`) is
| element-wise removal, but addition (`arr1 + arr2`) is a
| simple append. These are almost always exactly what you want
| to do when you reach for them, but they're completely
| "incorrect" mathematically.
| okeuro49 wrote:
| > python and correctness
|
| I thought it was Python and readability and "one way of
| doing things".
| ekianjo wrote:
| langchain and llamaindex are such garbage libraries: not only
| they never document half of the features they have, but they
| keep breaking their APIs from one version to the next.
| brokegrammer wrote:
| I was about to mention those. I decided a while ago to build
| everything myself instead of relying on these libraries. We
| could use a PythonLLM over here because it seems like nobody
| cares about developer experience in the Python space.
| olegp wrote:
| Would anyone happen to know of a similar library with as good
| DX but for JavaScript or TypeScript?
| mathgeek wrote:
| Perhaps something like https://llmjs.themaximalist.com/
| olegp wrote:
| Great, thank you!
| someothherguyy wrote:
| What about it is a breath of fresh air? What do the other
| libraries do that this doesn't?
| jasongill wrote:
| I was an early contributor to Langchain and it was _great_ at
| first - keep in mind, that 's before chat models even existed,
| not to mention tools, JSON mode, etc.
|
| Langchain really, I think, pushed the LLM makers forward toward
| adding those features but unfortunately it got left in the dust
| and became somewhat of a zombie. Simultaneously, the
| foundational LLM providers kept adding things to turn them more
| into a walled garden, where you no longer needed to connect
| multiple things (like scraping websites with one tool, feeding
| that into the LLM, then storing in a vector datastore - now
| that's all built in).
|
| I think Langchain has tried to pivot (more than once perhaps)
| but had they not taken investor $$ early on (and good for them)
| I suspect that it would have just dried up and the core team
| would have gone on to work at OpenAI, Anthropic, etc.
| SkyPuncher wrote:
| IMO, the samples look great because they're ridiculously
| simple.
|
| It doesn't deal with any of the hard problems you'll routine
| face with implementation.
| earcar wrote:
| Thank you! This is what the Ruby community has always
| prioritized - developer experience. Making complex things
| simple and joyful to use isn't just aesthetic preference, it's
| practical engineering. When your interface matches how
| developers think about the problem domain, you get fewer bugs
| and more productivity.
| freen wrote:
| Wow. So thoughtful.
|
| Ruby: late to the party, brought a keg.
| dismalaf wrote:
| Ruby has a bunch of tools to interact with LLMs already. Also
| has had bindings to stuff like Torch and Tensorflow for years.
| wtf242 wrote:
| been using https://github.com/alexrudall/ruby-openai for years
| with no issues which is a fine gem and works great.
| strudey wrote:
| aw thanks, glad you like it! more good Ruby AI libraries is a
| good thing IMO
| someothherguyy wrote:
| What about it is so thoughtful?
| ilrwbwrkhv wrote:
| Oh just beautiful. Ruby is so expressive and concise.
|
| If you see the typescript options it's like giving yourself a
| water boarding session through your own volition.
| gedy wrote:
| Is it really Ruby or they just made a nice interface? I don't
| see why a hypothetical TypeScript example would be all that
| different. // Just ask questions
| const chat: Chat = LLM.chat; chat.ask("What's the best
| way to learn TypeScript?"); // Analyze images
| chat.ask("What's in this image?", { image: "ts_conf.jpg" });
| // Generate images LLM.paint("a sunset over mountains
| in watercolor style"); // Create vector
| embeddings LLM.embed("TypeScript is powerful and
| scalable"); // Let AI use your code
| class Calculator { description = "Performs
| calculations"; params = { expression: {
| type: "string", desc: "Math expression to evaluate" },
| }; execute(args: { expression: string }):
| string { return eval(args.expression).toString();
| } } chat.withTool(new
| Calculator()).ask("What's 123 * 456?");
| williamcotton wrote:
| It's the extra parens, semi-colons, keywords and type
| annotations. Ruby makes the tradeoff for legibility above all
| else. Yes, you can obviously read the TypeScript, but there's
| an argument to be made that it takes more effort to scan the
| syntax as well as to write the code.
|
| Also: const chat: Chat = LLM.chat;
|
| ...is not instantiating a class, where Ruby is doing so
| behind the scenes. You'd need yet another pair of parens to
| make a factory!
|
| This is mainly a matter of syntactic _style_!
| maleldil wrote:
| chat = RubyLLM.chat
|
| Is ambiguous, though. You can't know if it's an assignment
| or creating a new object. I don't think that's more
| readable.
| shellac wrote:
| What do you mean by 'assignment or creating a new
| object'? It assigns chat to ... whatever RubyLLM.chat
| returns. Do you mean the function could have a clearer
| name?
| maleldil wrote:
| It's unclear whether `chat` is a field/property/member of
| `RubyLLM` or a method being called.
| nickisnoble wrote:
| Ruby only has methods and everything is an object. So...
| that solves that.
| xutopia wrote:
| Rubyists understand it perfectly. It's common practice
| for us.
| drdaeman wrote:
| > It's the extra parens, semi-colons, keywords and type
| annotations.
|
| I always thought such minor syntactic differences are
| unimportant, except for the folks who still learn syntax
| and haven't seen too many languages out there to stop
| caring much about it.
|
| YMMV of course, but whenever I need to jump hoops with some
| API or have things conveniently returned to me in a single
| call matters a lot for my developer happiness. Whenever my
| code needs semicolons or indentation or parens feels such a
| negligibly tiny nuance to me but things like this don't
| even blip on my mental radar... I always think about what
| the code does, and don't even see those details (unless I
| have a typo lol).
|
| Maybe my opinion on this is just the echoes from the
| ancient C vs Pascal vs BASIC syntax holy wars while I was
| still a schoolkid, idk. I mean, when I wrote Scheme or Lisp
| I haven't really "seen" all those parentheses.
|
| Again, YMMV, but `const chat = new LLM.Chat();` and `chat =
| RubyLLM.chat` are exactly the same thing to me - I don't
| remember actual tokens from the screen, I immediately
| mentally process those both as something like "instantiate
| a chat object and assign `chat` to it" (without really
| verbalizing it much, but as an concept/idea). And I don't
| think a little syntactic noise like `const` or `;` is
| making things worse or better for me. Although, to be fair,
| I could be wrong here - I haven't really did any
| experiments in this regards, with properly defined
| methodology and metrics, and my subjective perception could
| be deceptive. Sadly, I'm no scientist and not even sure how
| to set up one correctly...
| ketzo wrote:
| Is this gonna be the thing that finally makes me tried Rails?
| Ruby syntax really is just nice.
| drdaeman wrote:
| I think it's the very nice-looking and clean high-level API
| that should be a pleasure to use (when it fits the job, of
| course).
|
| I'm pretty sure this API semantics (instance builder to
| configure, and then it's ask/paint/embed with language-native
| way to handle streaming and declarative tools) would look
| beautiful and easy to use in many other languages, e.g. I can
| imagine a similar API - save, of course, for the Rails stuff -
| in Python, C# or Erlang. While this level of API may be not
| perfectly sufficient for all possible LLM use cases, it should
| certainly speed up development time when this level of API is
| all that's possible needed.
| Multiplayer wrote:
| Saw this gem of a gem on reddit earlier today and there were some
| trollish comments about no one using ruby anymore blah blah blah
| which quietly bummed me out. Surprised and Delighted to see it as
| #1 here on HN tonight!
| adamtaylor_13 wrote:
| There's a lot of folks who get immense schadenfreude talking
| about things they know nothing about to strangers on the
| internet who also don't know anything.
|
| Don't let it bum you out.
| someothherguyy wrote:
| > some trollish comments about no one using ruby anymore
|
| It is somewhat objectively true:
|
| https://octoverse.github.com/2022/top-programming-languages
|
| https://github.blog/wp-content/uploads/2024/10/GitHub-Octove...
|
| It doesn't mean much, and this library can be reproduced in any
| of those top 10 languages from what I can tell.
| nextos wrote:
| Is position #10 in https://octoverse.github.com/2022/top-
| programming-languages bad?
|
| It ranks right after Shell (#8) and C (#9). Ruby is still a
| mainstream language, and it's fairly easy to find a Ruby job.
| Compare that to Clojure or Haskell.
| someothherguyy wrote:
| It has dropped in popularity and has never regained the
| popularity it once held.
|
| Of the many developers who used to write Ruby (myself
| included), I would wager not many of those same people
| still do.
| vidarh wrote:
| It's dropped in _relative_ popularity, but the demand
| feels like it 's still increasing to me (been doing Ruby
| professionally since 2006), just not as fast as some of
| the other languages.
|
| Keep in mind the number of developers overall is rising
| rapidly still.
| josephg wrote:
| Compare that to Rust. For all the hype it has, very few
| companies are shipping products with it. There are a few,
| but nowhere near as many as are using Ruby.
| simonask wrote:
| That's probably true, but also a poor measure of success.
| I bet there are more companies using Ruby than there are
| companies using C++, too. They fill different niches, and
| different types of companies deliver very different
| products using those languages.
|
| The ratio of people who can code in Python or Ruby to
| people who can code in Rust or C++ is very high.
| jupp0r wrote:
| I don't know why "number of companies using language X"
| is a metric that is used here. Wordpress is serving 43%
| of websites on the internet as of 2025, so we should all
| be learning PHP!
| Lio wrote:
| I get your point but it's a case of right tool for the
| job. Every copy of Ruby now includes YJIT written in Rust
| because Rust is the right tool for that task.
|
| It's easy to forget though that number of lines of code
| required to do something is also a valid metric and Ruby
| beats Rust on that.
|
| So if you're shipping CRUD web apps that might be a more
| important metric than say memory usage or CPU time.
|
| Different job, different tool. More people want to ship
| web apps than write their own JITs.
|
| Engineering is the art of trade offs.
| jupp0r wrote:
| You are probably writing this in a browser with Rust code
| in it.
| meindnoch wrote:
| Safari has Rust?
| WJW wrote:
| That's very nice, but not in itself a good argument for
| language use. If you count using a system written in a
| language, then almost every programmer uses Ruby daily as
| both Github and Gitlab are written in Ruby. Similarly you
| probably interact quite frequently with (banking) systems
| written in COBOL, but nobody would call COBOL a popular
| language.
| IshKebab wrote:
| Yeah but look at the trajectories - Rust is one of the
| fastest growing languages and Ruby is one of the fastest
| declining languages.
| simonask wrote:
| Ruby will always have a special place in my heart. I cut my
| teeth as a young programmer on that language, and I learnt
| its value (as well as the value of using something else)
| along the way.
|
| Ruby code can be downright poetic, for better or worse.
| There's a certain kind of magic to the kind of code it
| enables. That's not always good, but it _is_ beautiful.
|
| I encourage everybody to read the venerable "Why's Poignant
| Guide to Ruby" [1] to see what I'm talking about.
|
| I wish Ruby was cross-platform. It still only works on
| Windows using the MSYS2 emulation layer, and the only reason
| as far as I can tell is that it committed hard and early to
| `fork()` as the main way to use multiple cores.
|
| [1]: https://poignant.guide/
| speleding wrote:
| Over the last 10 years the number of programmers has grown
| enormously. So ruby dropping in position does not necessarily
| imply the absolute number of ruby programmers went down.
| Lio wrote:
| It's worth remembering that the trolls that complain about Ruby
| do so because they care about it.
|
| You'll often see the same names coming back on every post to
| angrily insist that no one is interested in Ruby
|
| ...apart from them obviously because if they didn't they would
| be busy trolling something else. :P
| bmacho wrote:
| > It's worth remembering that the trolls that complain about
| Ruby do so because they care about it.
|
| I don't think so. I mean there are complains about stuff you
| care about like people complaining about Healthcare. ( _edit_
| : there are other forms of caring, see my grandchild comment)
|
| Dissing on Ruby is definitely not this, they are not Ruby
| users wanting Ruby to be better. They don't even know Ruby
| apart from dissing on it is socially accepted, and makes them
| feel good.
| mosselman wrote:
| Usually people get huffed up about stuff they care about.
| Caring doesn't mean wanting it to be better, it could also
| mean get worked up about.
|
| Surely a one-off comment about nobody using Ruby doesn't
| mean you "care", but if it is true that it is the same
| people who keep commenting, they obviously care.
|
| Is it because they are jealous of the beauty of Ruby/Rails,
| as a Rubyist I'd think so, but who is to say really. Maybe
| they worked at a company where they replaced whatever their
| favourite stack is with Rails and they have hated Ruby ever
| since. It could be anything.
|
| You wouldn't keep responding to stuff you don't care about
| at some level.
| bmacho wrote:
| Equating _caring_ and _wanting it to be better_ was a
| mistake on my part. It made my comment not true, and it
| made you worked-up. Sorry for that.
|
| All in all, I don't think that other forms of _caring_
| apply either. I think that parroting "Ruby is dead"
| doesn't mean that they _care_ about Ruby, it 's just a
| thing people like to parrot, without the meaning
| realizing in their heads. A form of bonding, a form of
| distraction, a form of opening to a social interaction, a
| form of self-reassurance etc. It is lot of things, and
| caring about Ruby at all is usually not among those
| (IMO).
| mosselman wrote:
| Haha I am not worked up. I just care it seems.
|
| I agree. Parroting some meme isn't caring per se. But I
| was working under the assumption that the statement that
| it was the same names who keep doing it. If you say "Ruby
| is dead" 5 times a year it isn't necessarily "caring" if
| it becomes 100 times a year there is something else at
| play.
| IshKebab wrote:
| I'm not sure what your point is. I care about Ruby and want
| it to die because I have worked on the Gitlab codebase, which
| is written in Ruby. It's a bad language and it stopped me
| being able to understand behaviours and fix bugs.
|
| In contrast I have also worked on VSCode which is similarly
| huge but written in Typescript. Faaaar easier to work with,
| enough that I've been able to contribute a couple of medium
| sized features and several bug fixes.
|
| So when people say "yeay Ruby" I try to discourage them
| because I don't want more Ruby code in the world that I might
| have the misfortune of having to interact with in future.
| bob1029 wrote:
| IIRC Github was originally written in Ruby as well.
|
| Now that they use something "far easier to work with", the
| UX gets to suffer accordingly.
|
| I've never been in a situation where making the customer
| happy was synonymous with applying best practices to the
| tech stack or otherwise making it so everyone and their dog
| can contribute.
| bullfightonmars wrote:
| Github is still rails, but they have layered in some
| react to the UIs, like the file explorer.
|
| It all seems pretty negative value to me though it's
| terribly slow.
| IshKebab wrote:
| Yeah Codeberg is significantly faster than GitHub,
| presumably in part because it's Go and not Ruby.
| steve_gh wrote:
| I think you are confusing the beauty and elegance of the
| language with the crap thatpeople write.
|
| My experience is that the sort of folks who misuse Ruby's
| powerful features are the sort of idiotes who dont realise
| that because a thing can be done, doesn't mean that it
| should be done. These are the sort of people who are
| capable of misusing most languages.
| elif wrote:
| Was it really idiomatic ruby that "stopped you from being
| unable to understand behaviors"? Or was it unorganized
| monkey patching?
|
| I'm having a hard time thinking that ruby is difficult to
| understand, particularly compared to its opposites lisp,
| erlang, Haskell, e.g. languages that are extremely simple
| to the point where the burden of complexity is shoved into
| code space.
| IshKebab wrote:
| > Was it really idiomatic ruby that "stopped you from
| being unable to understand behaviors"?
|
| I think so. I'm not an expert but the Gitlab codebase
| seems like fairly typical Ruby to me.
| remoroid wrote:
| No, they complain about it because they care about web
| development... That should be obvious.
| JasserInicide wrote:
| Chaotic neutral take: they're Ruby devs that have a vested
| interest in gatekeeping newcomers from the language so they
| have better job security
| jstummbillig wrote:
| Ruby, specially with Rails, is particularly suited for AI
| coding, because of how mature it is and convention over
| configuration: Most of the important stuff is up to date in the
| model, and the entire thing comes with a fairy comprehensive
| set of ideas of how to to be used _cohesively_ to built entire
| apps.
| ksec wrote:
| Interesting cause I submitted this some time ago and I just did
| another one on
|
| https://news.ycombinator.com/item?id=43369977
|
| But it seems hashnode.dev as a domain is blocked entirely.
| Hopefully Ruby gets another chance in AI era.
| init0 wrote:
| One of the most concise APIs to interact with an llm!
|
| Keep going! Happy to see ollama support PR in draft.
| aguynamedben wrote:
| Ruby is alive and well!
| someothherguyy wrote:
| Why does this say it was posted four hours ago on the front page,
| four days ago on Agolia, 3 days ago on /from and the comments are
| all from minutes to hours ago here?
| noodletheworld wrote:
| The threads have presumably been merged; look at the submitters
| in the history.
|
| > 166 points|ksec|4 days ago|21 comments
|
| > 168 points by ksec 4 hours ago
|
| But yes; it's a bit dodgy to resurface old news like this imo
| and pretend it's new news.
|
| I'd go as far as to say that being at #1, under the
| circumstances, means it's been artificially boosted somehow.
|
| I haven't the foggiest why anyone would bother though.
| thinkingemote wrote:
| at least 2 ways.
|
| 1. Moderators can re-submit interesting stories from a second
| chance pool https://news.ycombinator.com/pool (This might
| happen automatically from time to time?) When this happens some
| of the timestamps get updated but others dont.
|
| 2. Moderators can invite users via email to re-submit stories.
| https://news.ycombinator.com/invited
| ripped_britches wrote:
| This is an obviously fishy post!
| neuroelectron wrote:
| What's fishy about wrapping a bunch of APIs?
| ripped_britches wrote:
| Nothing about the library but there was clearly artificial
| boosting when it was first posted
| Finbarr wrote:
| This is a beautiful API. Thanks for the work. Here's hoping for a
| nice ruby agent framework in the near future too!
| armenarmen wrote:
| saw this the other day:
| https://github.com/activeagents/activeagent
|
| haven't tried it yet though
| jiangplus wrote:
| I am writing some LLM-based app scripts, this feels like a
| breeze!
| ultimoo wrote:
| nice job! i miss using ruby.
| makuchaku wrote:
| Abut time that someone built this in ruby! You rock!
| continuational wrote:
| Why is it using a global variable for this?
| t-writescode wrote:
| It's not. The method, RubyLLM.chat creates a new instance of
| the Chat object, as has been copied here:
| module RubyLLM class Error < StandardError; end
| class << self def chat(model: nil)
| Chat.new(model: model) end
|
| https://github.com/crmne/ruby_llm/blob/9825f4fea089b1b974961...
|
| If you're wondering about module RubyLLM. That's just how Ruby
| is often written.
|
| Addendum: Ruby does not require you to put the opening and
| closing parenthesis on a function to run that function, and
| it's not always put there when you have zero or 1 parameter (I
| find it to be cleaner when you have a parameter, but have no
| opinion when there isn't a parameter)
|
| In the example code from the link itself, you'll see:
| chat.ask "What's the best way to learn Ruby?"
|
| which is the same as chat.ask("What's the best
| way to learn Ruby?")
| bmacho wrote:
| > Ruby does not require you to put the opening and closing
| parenthesis on a function to run that function, and it's not
| always put there when you have zero or 1 parameter
|
| mind = blown
|
| I always _liked_ how functionName denotes the function and
| functionName() calls the function, and then it denotes the
| result e.g. in JavaScript or in math. But just saying
| functionName to call a function makes the code read more like
| English. Code that reads like English > code that reads like
| math. (And you can still talk about functions of course.)
| viraptor wrote:
| It comes with the downside that if you want to pass the
| function itself around, you need to do
| f=something.method(:the_function), and then f.call(args).
| It's not a huge deal, but... meh.
| vidarh wrote:
| You might know this, but you can also do f.(args) or
| f[args] in the latter case. It's still a bit meh, but
| slightly less verbose.
| kaiuhl wrote:
| But in general, ruby code only passes anonymous functions
| and, in those cases, the syntax is beautiful.
| tasuki wrote:
| You'd like the ML-family languages, which don't use
| parentheses to call functions.
| kjgkjhfkjf wrote:
| What are some similarly ergonomic packages for other languages?
| tw1984 wrote:
| stone age LLM.
| FailMore wrote:
| This looks amazing, is there anything one can do to change the
| system prompt where it is available?
| antirez wrote:
| The best Ruby always surpasses the elegance of the best Python...
| Unfortunately for practical means at this point I go for Python:
| more libraries, less problems with the C implementation of the
| interpreter (had issues with the GC in the past), better LLMs
| understanding of the code.
| drdaeman wrote:
| Surely you can have the same API elegancy and overall semantics
| in Python? chat = python_llm.Chat() _
| = chat.ask"What's the best way to learn Python?")
| # Analyze images _ = chat.ask("What's in this image?",
| image="python_conf.jpg") # Generate images
| _ = python_llm.paint("a sunset over mountains in watercolor
| style") # Stream responses for chunk in
| chat.ask("Tell me a story about a Python programmer"):
| print(chunk.content) # Can be a class if
| necessary, but for this weather thingy we can probably do with
| a simple callable # Requires Python 3.9+ for
| typing.Annotated def get_weather( latitude:
| Annotated[Decimal, "Latitude of the location"],
| longitude: Annotated[Decimal, "Longitude of the location"]
| ) -> str: """ Gets current weather for
| a location. """ ... _ =
| chat.with_tool(get_weather).ask("What's the weather in Berlin?
| (52.5200, 13.4050)")
|
| (The `_ =` bits are mine, to emphasize we have a meaningful
| result and we're knowingly and willingly discarding it. Just a
| habit, I hope it doesn't bug people.)
|
| Ruby has significantly more capable metaprogramming facilities,
| but they aren't used in RubyLLM, it's all just objects and
| methods (biggest difference being use of iterable in Python vs
| providing a block in Ruby, as I felt an iterable would be more
| Pythonic here), which is nothing Ruby-specific.
|
| And IMHO advanced metaprogramming should be used carefully, as
| it may make code pretty but really hard to comprehend and
| analyze. My largest issue with Rails is difficulty to tell
| where things are coming from and what's available (lack of
| implicit imports and ability to re-open any class or module and
| inject more stuff in there so there's no single place that
| defines it is a double-edged sword that may lead to chaos if
| wielded carelessly - YMMV, of course, I'm merely stating my
| personal preferences here).
| tommica wrote:
| Wow the syntax is beautiful!
| nextaccountic wrote:
| That's my takeaway from Ruby - syntax matters, and good syntax
| makes programmers happier
| dkobia wrote:
| I support software in many languages and ruby has to be the
| most syntactically stimulating.
| brink wrote:
| You're confusing beautiful with simple. There's a lot of
| complexity and magic that's hidden behind the curtains of that
| "beautiful" syntax. Great for scripts and small programs, and
| an absolute nightmare on large projects. It's too simple.
| deedubaya wrote:
| Looks useful.
|
| Allowing ai to eval() code or execute any sql statement would
| scare the crap outta me personally.
| xcskier56 wrote:
| From searching the codebase, I can only find eval() used in the
| markdown and the specs.
|
| You're totally right that eval()'ing unknown code is terrible
| but it doesn't look like the gem itself is doing that.
|
| The usage of eval() is in a user written tool in the docs.
| Definitely a bd example and should probably be changed
| deedubaya wrote:
| Yes, that's exactly what I was referring to. Folks (or llms!)
| never copy/paste doc examples, right?
| hartator wrote:
| Super interesting gem!
|
| `Document.search(query).limit(limit).map(&:title)` how do you
| defined the documents to search on?
| breckenedge wrote:
| That's an example of what your code could look like. For
| example, you might have a Rails app with a Document model and
| have added search to that model via Searchkick. Then this code
| is called by the library to execute a search.
| kyledrake wrote:
| This interface needs to have a better relationship with
| streaming, there is always a lag in response and a lot of people
| are going to want to stream the response in non blocking threads
| instead of hanging the process waiting for the response. Its
| possible this is just a documentation issue, but either way
| streaming is a first class citizen on anything that takes more
| than a couple seconds to finish and uses IO.
|
| Aside from that the DSL is quite excellent.
| joevandyk wrote:
| From https://rubyllm.com/#have-great-conversations
| # Stream responses in real-time chat.ask "Tell me a
| story about a Ruby programmer" do |chunk| print
| chunk.content end
| jupp0r wrote:
| This will synchronously block until 'chat.ask' returns
| though. Be prepared to be paying for the memory of your whole
| app tens/low hundreds of MB of memory being held alive doing
| nothing (other than handling new chunks) until whatever
| streaming API this is using under the hood is finished
| streaming.
| andrewmutz wrote:
| Threads?
| bradgessler wrote:
| There's a whole world of async IO in Ruby that doesn't get
| enough attention.
|
| Checkout the async gem, including async-http, async-websockets,
| and the Falcon web server.
|
| https://github.com/socketry/falcon
| earcar wrote:
| Thank you for your kind words!
|
| Valid point. I'm actually already working on testing better
| streaming using async-http-faraday, which configures the
| default adapter to use async_http with falcon and async-job
| instead of thread-based approaches like puma and SolidQueue.
| This should significantly improve resource efficiency for AI
| workloads in Ruby - something I'm not aware is implemented by
| other major Ruby LLM libraries. The current approach with
| blocks is idiomatic Ruby, but the upcoming async support will
| make the library even better for production use cases. Stay
| tuned!
| ichiwells wrote:
| I run engineering for a venture backed AI-first startup and we
| use Ruby/Rails.
|
| For us, it made sense to leverage one of the best domain modeling
| and ORM frameworks out there. Most of our inference is http calls
| to foundational models, but we can still fine tune and host
| models on GPUs using Python.
|
| Inference matters, but part of building an effective user
| platform are the same old SaaS problems we've had before, and
| Rails just works. Inbound and outbound email done in a day.
| Turning an OCR'd title from ALL CAPS into Title Case is one
| method call and not a whole custom algorithm, etc.
|
| A lot of people seem to think Ruby is slow for some reason but
| it's as fast as Python, and with falcon as fast as node for async
| behavior. Safe to say the application language taking 0.03
| seconds instead of 0.003 seconds when you have to wait 3 seconds
| for first token is absolutely not the bottleneck with LLM heavy
| workflows, anyway.
|
| And yes, metaprogramming is a powerful tool with which you can
| easily shoot yourself in the foot. We culturally just don't write
| any code that's not greppable so don't use method_missing kinds
| of things unless it's in a robust gem like active record. Pretty
| trivial problem to solve really.
|
| PS - We're hiring, if that philosophy aligns with you!
| mattmcknight wrote:
| In terms of LLM code generation as well, the well structured
| nature of a Rails application, where there is a place for
| everything, a structure for tests to be added, really helps
| from the perspective of getting a comprehensible application
| out of it that is easy to modify. In addition to the existence
| of well tested component for most normal web application tasks,
| maybe it helps that a lot of Rails has already been based on
| old-fashioned code generation for 20 years.
| cootsnuck wrote:
| I have this same suspicion. I dusted off a hobby Rails app
| from two years ago I was making with Cursor. I decided to try
| completely changing the main functionality of the app with
| the much better LLMs of today and was shocked how well it did
| with one-shot.
|
| Now compare that to my recent experience with having Cursor
| help me work on a preexisting Node/React app...geez. What a
| pain. (It doesn't help that I wasn't the one that originally
| created the React app though.)
| miki123211 wrote:
| What's a good way to learn the _modern_ Ruby ecosystem
| nowadays?
|
| I played with Ruby when I was a teenager (~2015 or so), and I
| definitely remember enjoying it. I know there's still a vocal
| group of users who love it, so I would be interested in digging
| in again.
| ichiwells wrote:
| I would actually start with the Rails Guides docs, they're
| very good and running the given commands should actually
| work:
|
| https://guides.rubyonrails.org/getting_started.htm
|
| Just have a toy app you want to build in mind
| cootsnuck wrote:
| Yea, just agreeing with the other commenter. Creating a Rails
| app is the way to go to get started with Ruby.
| https://guides.rubyonrails.org/getting_started.html
|
| It's my favorite programming language but I seldom get to use
| it because I'm an AI Engineer. But I just recently went out
| on my own so I guess that can change now, hm...
| luibelgo wrote:
| Rails still the "batteries included" piece of Ruby. Recently
| added parts like Hotwire, SolidQueue etc are pretty
| interesting to know.
|
| Outside of it, you might find interesting libraries like
| sinatra, sequel, roda, dryrb, faraday, sorbet, truffle
| ruby...
| gregmolnar wrote:
| Be careful with the examples though:
| https://github.com/crmne/ruby_llm/issues/25
| soheil wrote:
| bobby drop table, still a thing
| earcar wrote:
| Thanks for flagging this. The eval was only in the docs and
| meant only as an example, but we definitely don't want to
| promote dangerous patterns in the docs. I updated them.
| maleldil wrote:
| I understand it's a Ruby thing, `chat = RubyLLM.chat` looks odd.
| How do I know whether it's a function call returning an object or
| just an assignment? Why not just use `RubyLLM.chat()` and
| eliminate the ambiguity?
| duckworth wrote:
| In Ruby, chat = RubyLLM.chat is a method call since Ruby
| doesn't have properties, only methods. Dropping parentheses is
| standard Ruby style, familiar to Ruby developers. While adding
| parentheses is allowed, it doesn't match Ruby's readability.
| The library aims for a clean style consistent with Ruby
| conventions.
| strudey wrote:
| There's a channel for this on the Ruby AI Builders Discord:
| https://discord.gg/HZTsjFKyy3
| jupp0r wrote:
| The API looks nice on the surface, but this will be expensive to
| operate due to Ruby and Rails' lack of support for concurrency.
| Everything is blocking, which is not a great match for the async
| nature of interacting with these models.
| RangerScience wrote:
| Ruby isn't dead and like all alive things, it grows and
| changes; your expectation is out of date.
|
| https://www.ruby-lang.org/en/news/2020/12/25/ruby-3-0-0-rele...
| igravious wrote:
| https://ruby-concurrency.github.io/concurrent-ruby/1.1.5/Con...
|
| https://thoughtbot.com/blog/my-adventure-with-async-ruby
|
| First two hits on Google.
| Alifatisk wrote:
| Am I dreaming?
| desireco42 wrote:
| I am really impressed and delighted how simple this library is.
|
| I agree that waiting for response can be an issue. I don't think
| this is meant to be for such purposes, but for tools that would
| process and create artifacts based on inputs.
|
| I love Mistral and local LLMs, so this would probably the thing I
| would like to add.
| soheil wrote:
| Feels more useful for something like cli where you want to run
| one-off commands to test something instead of running it in
| production given how non-deterministic the behavior can be for
| example for something like chat.ask "What's being
| said?", with: { audio: "meeting.wav" }
|
| definitely don't want users to get a valid response only 75% of
| the times, maybe?
___________________________________________________________________
(page generated 2025-03-15 23:00 UTC)