vkryukov
Hello,
I hope someone can clarify the semantics of calculation return value. The following calculation of a last response from an LLM that is stored in a relationship works:
calculations do
calculate :llm_response, :string do
calculation fn llm_response, _context ->
[llm_response] = Ash.load!(llm_response, run: [:messages])
last_message = llm_response.run.messages |> Enum.at(-1)
[last_message.content]
end
end
end
It loads a nested relationship and extract the content of the last message. After the definitions above, calling
{:ok, run} = LLMRun |> Ash.get("27face7e-6443-43bd-bb69-e7529eedd20c", load: [:llm_response])
will return a run resource where run.llm_response is a string, as expected.
However, I don’t fully understand why I should wrap the content (which is a string) in a list, given that I defined the return type as a :string in calculate :llm_response, :string? (If I don’t wrap it in a list, I get (Protocol.UndefinedError) protocol Enumerable not implemented for type BitString.; I decided to experiment with wrapping the return value in a list and it worked, to my surprise).
I’m using AshSqlite.DataLayer (not sure if that matters or not).
Thank you!
Trending in Questions
Other Trending Topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #elixirconf
- #channels
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #blog-post
- #ai
- #elixirconf-us
- #phoenix_html
- #iex
- #graphql
- #genstage
- #websockets
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #hex
- #security
- #metaprogramming










Showing Posts 1 to 9- Show Best Posts
- Show All (oldest first)
- Show All (newest first)
ahey
Calculations operate on a list of records for efficiency reasons. The calculate function is passed in a list of records and must return a list of calculated terms.
For example, if you were selecting 100 records, and needed to load some associated data from the database for each record, this could be done in a single load instead of 100.
zachdaniel
Also worth pointing out that that only works correctly because you are using
Ash.getand so only have a single record.If you did
a_list_of_records |> Ash.load(:llm_response)your[single_thing] = ...match would fail.vkryukov
Thank you both, it’s very clear now!
vkryukov
Indeed, I changed my code (after refactoring some attribute names) to
and now the above
Ash.getas well aswork as expected.
zachdaniel
You can optimize this further:
Furthermore, if you break it out into a module-based calculation, you can take advantage of the more optimized dependency loading for calculations.
Then you can do
calculate :llm_response, :string, MyApp.MyDomain.MyResource.Calculations.LastRunvkryukov
Great suggestion, thank you! Reading the documentation more closely, I see that anonymous lambdas are not recommended, and I should be really using module-based approach everywhere.
vkryukov
And while we are on this topic: I assume that I cannot use expressions here because of the need to refer to (nested) relationships?
zachdaniel
In this case, actually, you can
Something like that should work.
vkryukov
Wow! I keep getting impressed by Ash.