Arcana.Config (Arcana v2.0.1)

Copy Markdown View Source

Configuration management for Arcana.

Handles parsing and resolving configuration for embedders, chunkers, and other pluggable components.

Redacting Sensitive Values

Use Arcana.Config.redact/1 to wrap any config value for safe inspection:

config = Application.get_env(:arcana, :llm)
inspect(Arcana.Config.redact(config))
# => {"zai:glm-4.7", [api_key: "[REDACTED]"]}

Embedder Configuration

# Default: Local Bumblebee with bge-small-en-v1.5
config :arcana, embedder: :local

# Local with different model
config :arcana, embedder: {:local, model: "BAAI/bge-large-en-v1.5"}

# OpenAI (requires req_llm and OPENAI_API_KEY)
config :arcana, embedder: :openai
config :arcana, embedder: {:openai, model: "text-embedding-3-large"}

# Custom function
config :arcana, embedder: fn text -> {:ok, embedding} end

# Custom module implementing Arcana.Embedder behaviour
config :arcana, embedder: MyApp.CohereEmbedder
config :arcana, embedder: {MyApp.CohereEmbedder, api_key: "..."}

Chunker Configuration

# Default: text_chunker-based chunking
config :arcana, chunker: :default

# Default chunker with custom options
config :arcana, chunker: {:default, chunk_size: 512, chunk_overlap: 100}

# Custom function (receives text, opts; returns list of chunk maps)
config :arcana, chunker: fn text, _opts ->
  [%{text: text, chunk_index: 0, token_count: 10}]
end

# Custom module implementing Arcana.Chunker behaviour
config :arcana, chunker: MyApp.SemanticChunker
config :arcana, chunker: {MyApp.SemanticChunker, model: "..."}

PDF Parser Configuration

# Default: poppler's pdftotext
config :arcana, pdf_parser: :poppler

# Custom module implementing Arcana.FileParser.PDF behaviour
config :arcana, pdf_parser: MyApp.PDFParser
config :arcana, pdf_parser: {MyApp.PDFParser, some_option: "value"}

Search Defaults

Set defaults for Arcana.search/2. Per-call options override these. Any option accepted by Arcana.Search.search/2 can be set globally.

config :arcana, search: [
  limit: 10,
  threshold: 0.0,
  mode: :vector,              # :vector | :keyword | :hybrid
  vector_weight: 0.5,         # for hybrid mode
  keyword_weight: 0.5,        # for hybrid mode
  rewriter: &MyApp.rewrite/1, # query rewriter function
  # plus any backend-specific opts (e.g. :hnsw_ef_search for pgvector)
]

Ask Defaults

Set defaults for Arcana.ask/2. Per-call options override these. Any option accepted by Arcana.Ask.ask/2 can be set globally.

config :arcana, ask: [
  limit: 5,
  mode: :semantic,
  threshold: 0.0,
  prompt: &MyApp.custom_prompt/3
]

Reranker Configuration

Set a global reranker that will be applied automatically by Arcana.search/2 and Arcana.ask/2. Per-call :reranker options override this. Pass reranker: false per-call to disable for a single request.

# Global reranker module
config :arcana, reranker: Arcana.Reranker.CrossEncoder

# With options (e.g. over_fetch multiplier, threshold)
config :arcana, reranker: {Arcana.Reranker.CrossEncoder, over_fetch: 3}

# Custom function: fn question, chunks, opts -> {:ok, reranked} end
config :arcana, reranker: &MyApp.rerank/3

Summary

Functions

Returns the configured chunker as a {module, opts} tuple.

Returns the current Arcana configuration.

Returns the configured embedder as a {module, opts} tuple.

Returns the value for key from opts, falling back to the global app env.

Returns whether GraphRAG is enabled globally or for specific options.

Merges global keyword-list config under app_key with per-call opts.

Returns the configured PDF parser as a {module, opts} tuple.

Wraps a config value for safe inspection with sensitive data redacted.

Returns the configured reranker, resolving per-call opts and global config.

Resolves chunker from options, falling back to global config.

Functions

chunker()

Returns the configured chunker as a {module, opts} tuple.

current()

Returns the current Arcana configuration.

Useful for logging, debugging, and storing with evaluation runs to track which settings produced which results.

Example

Arcana.Config.current()
# => %{
#   embedding: %{module: Arcana.Embedder.Local, model: "BAAI/bge-small-en-v1.5", dimensions: 384},
#   vector_store: :pgvector
# }

embedder()

Returns the configured embedder as a {module, opts} tuple.

get(opts, key)

Returns the value for key from opts, falling back to the global app env.

Used to thread configuration like :repo and :llm from per-call opts with a fallback to config :arcana, key: value.

Examples

repo = Arcana.Config.get(opts, :repo)
llm = Arcana.Config.get(opts, :llm)

graph_enabled?(opts)

Returns whether GraphRAG is enabled globally or for specific options.

Checks the :graph option in the provided opts first, then falls back to the global configuration.

Examples

# Check global config
Arcana.Config.graph_enabled?([])

# Override with per-call option
Arcana.Config.graph_enabled?(graph: true)

merge_app_opts(opts, app_key)

Merges global keyword-list config under app_key with per-call opts.

Per-call opts override the global config. Used to thread namespace configs like :search, :ask, and :graph.

Examples

# Reads `config :arcana, search: [limit: 10]` and merges
opts = Arcana.Config.merge_app_opts(opts, :search)

# Reads `config :arcana, ask: [limit: 5]` and merges
opts = Arcana.Config.merge_app_opts(opts, :ask)

pdf_parser()

Returns the configured PDF parser as a {module, opts} tuple.

redact(value)

Wraps a config value for safe inspection with sensitive data redacted.

Returns a struct that implements the Inspect protocol and automatically redacts sensitive keys like :api_key, :token, :password, etc.

Example

iex> config = {"zai:glm-4.7", [api_key: "secret123"]}
iex> inspect(Arcana.Config.redact(config))
~s|{"zai:glm-4.7", [api_key: "[REDACTED]"]}|

reranker(opts \\ [])

Returns the configured reranker, resolving per-call opts and global config.

Returns nil if no reranker is set or if explicitly disabled with reranker: false. Otherwise returns {module_or_fun, opts}.

resolve_chunker(opts)

Resolves chunker from options, falling back to global config.