Live data from Hacker News

RubyLLM: A delightful Ruby way to work with AI

github.com

151–160 of 182 posts

Re: RubyLLM: A delightful Ruby way to work with AI

#151

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…

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!

Re: RubyLLM: A delightful Ruby way to work with AI

#152

Earlier quoted context omitted.

I’ve found the Ruby community really cares about DUX. Not sure why it’s not in other language communities

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 a…

> python and correctness

I thought it was Python and readability and "one way of doing things".

Re: RubyLLM: A delightful Ruby way to work with AI

#153
post #2

Such a breath of fresh air compared to poor DX libraries like langchain

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.

Re: RubyLLM: A delightful Ruby way to work with AI

#154
post #135

Earlier quoted context omitted.

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 anyti…

> 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…

> 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.

Re: RubyLLM: A delightful Ruby way to work with AI

#155
post #37
post #35

Earlier quoted context omitted.

Umm, doesn’t Go do so as well? Personally, I’ve had a better experience working with Go tooling.

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

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().WithModel("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()

Re: RubyLLM: A delightful Ruby way to work with AI

#156
post #36

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!

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

Chaotic neutral take: they're Ruby devs that have a vested interest in gatekeeping newcomers from the language so they have better job security

Re: RubyLLM: A delightful Ruby way to work with AI

#157
post #56

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.

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).

Re: RubyLLM: A delightful Ruby way to work with AI

#158
post #69

Wow the syntax is beautiful!

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.

Re: RubyLLM: A delightful Ruby way to work with AI

#159
post #102

Earlier quoted context omitted.

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 embedding…

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 par…

> 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 (but then, I just checked some Lisp code and syntax looks off and takes time to get through, since I haven't practiced it in a long while and it's pretty different from anything I've used any recently).

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...

Re: RubyLLM: A delightful Ruby way to work with AI

#160

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 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

That looks good, I didn't see that earlier.
Post reply on HN