Use this file to discover all available pages before exploring further.
Get from zero to a working RAG application with this complete tutorial. You’ll ingest documents, search for relevant content, and ask questions powered by AI.
This tutorial walks through building a simple RAG system for Elixir documentation. Copy and run each step in your IEx session.
1
Start your application
Open an IEx session with your Phoenix app:
iex -S mix
2
Ingest some documents
Add content to your vector store. We’ll ingest a few facts about Elixir:
# Ingest documents about Elixir{:ok, doc1} = Arcana.ingest( "Elixir is a dynamic, functional programming language designed for building scalable and maintainable applications. It runs on the Erlang VM (BEAM), which is known for creating low-latency, distributed, and fault-tolerant systems.", repo: MyApp.Repo, metadata: %{"topic" => "basics", "source" => "elixir-lang.org"}, collection: "elixir-docs"){:ok, doc2} = Arcana.ingest( "Phoenix is a web framework written in Elixir that enables building rich, interactive web applications with server-side rendering, real-time features using LiveView, and excellent performance.", repo: MyApp.Repo, metadata: %{"topic" => "phoenix", "source" => "phoenixframework.org"}, collection: "elixir-docs"){:ok, doc3} = Arcana.ingest( "OTP (Open Telecom Platform) is a set of libraries and design principles for building concurrent, distributed systems in Erlang and Elixir. GenServer is the most commonly used OTP behavior for implementing server processes.", repo: MyApp.Repo, metadata: %{"topic" => "otp", "source" => "elixir-lang.org"}, collection: "elixir-docs")
Behind the scenes, Arcana is chunking the text, generating embeddings, and storing them in PostgreSQL with pgvector.
3
Search for relevant content
Now search for content using semantic similarity:
# Semantic search - finds content by meaning{:ok, results} = Arcana.search( "What is Phoenix used for?", repo: MyApp.Repo, limit: 3)# Inspect the resultsEnum.each(results, fn chunk -> IO.puts("Score: #{chunk.similarity}") IO.puts("Text: #{chunk.text}\n")end)
Expected output:
Score: 0.89Text: Phoenix is a web framework written in Elixir that enables building rich, interactive web applications...Score: 0.72Text: Elixir is a dynamic, functional programming language designed for building scalable...
4
Ask a question
Use RAG to answer questions based on your documents:
# Configure your LLM (requires OPENAI_API_KEY environment variable){:ok, answer} = Arcana.ask( "What is Phoenix and what can I build with it?", repo: MyApp.Repo, llm: "openai:gpt-4o-mini")IO.puts(answer)
Expected output:
Phoenix is a web framework written in Elixir that enables you to build rich, interactive web applications. You can create applications with server-side rendering, add real-time features using LiveView, and benefit from excellent performance characteristics.
The ask/2 function retrieves relevant chunks via semantic search, then sends them to the LLM as context for generating the answer.
Here’s a complete working script you can save and run:
complete_example.exs
# Start with a clean slate (optional - deletes existing documents)# Arcana.Document |> MyApp.Repo.delete_all()# Ingest a small knowledge basedocuments = [ {"Elixir is a functional language that runs on the BEAM VM, known for concurrency and fault tolerance.", "elixir-basics"}, {"Phoenix Framework enables building real-time web applications with LiveView and channels.", "phoenix-intro"}, {"GenServer is an OTP behavior for implementing server processes that maintain state.", "otp-genserver"}, {"Ecto is the database wrapper for Elixir, providing schemas, queries, and migrations.", "ecto-intro"}]Enum.each(documents, fn {text, source} -> {:ok, _doc} = Arcana.ingest( text, repo: MyApp.Repo, collection: "elixir-docs", metadata: %{"source" => source} ) IO.puts("✓ Ingested: #{source}")end)# Search for relevant contentIO.puts("\n=== Semantic Search Results ==="){:ok, search_results} = Arcana.search( "How do I build real-time web apps?", repo: MyApp.Repo, limit: 2)Enum.each(search_results, fn chunk -> IO.puts("Score: #{Float.round(chunk.similarity, 2)} | #{String.slice(chunk.text, 0..80)}...")end)# Ask a question with RAGIO.puts("\n=== RAG Answer ==="){:ok, answer} = Arcana.ask( "What is Phoenix Framework and what are its main features?", repo: MyApp.Repo, llm: "openai:gpt-4o-mini")IO.puts(answer)