Current section

Files

Jump to
ash_ai lib ash_ai changes vectorize.ex
Raw

lib/ash_ai/changes/vectorize.ex

defmodule AshAi.Changes.Vectorize do
@moduledoc """
A change that vectorizes the current values of attributes for a given record.
Used by the manual vectorization strategy, so you can decide
later when to run the vectorization action.
"""
use Ash.Resource.Change
def change(changeset, _opts, _context) do
{embedding_model, vector_opts} =
AshAi.Info.vectorize_embedding_model!(changeset.resource)
name = AshAi.Info.vectorize_full_text_name!(changeset.resource)
attrs =
AshAi.Info.vectorize_attributes!(changeset.resource)
changes =
case AshAi.Info.vectorize_full_text_text(changeset.resource) do
{:ok, fun} ->
attrs ++
[{:full_text, name, fun}]
_ ->
attrs
end
|> Enum.flat_map(fn
{source, dest} ->
text = Map.get(changeset.data, source)
[{dest, text}]
{:full_text, name, fun} ->
text = fun.(changeset.data)
[{name, text}]
end)
strings = Enum.map(changes, &elem(&1, 1))
case embedding_model.generate(strings, vector_opts) do
{:ok, vectors} ->
changes =
Enum.zip_with(changes, vectors, fn {k, _}, r ->
{k, r}
end)
Ash.Changeset.change_attributes(changeset, changes)
{:error, error} ->
fields = Enum.map(changes, fn {field, _} -> field end)
Ash.Changeset.add_error(changeset,
fields: fields,
message: "An error occurred while generating embeddings: #{inspect(error)}"
)
end
end
def atomic(changeset, opts, context) do
{:ok, change(changeset, opts, context)}
end
end