Module: Ask::RAG::Query

Defined in:
lib/ask/rag/query.rb

Overview

High-level RAG query API.

Retrieves relevant documents from a vector store and uses an LLM to answer a question based on those documents.

Examples:

answer = Ask::RAG.query(
  store: my_vector_store,
  question: "What is the default timeout?",
  model: "gpt-4o"
)
puts answer.content

Class Method Summary collapse

Class Method Details

.ask_llm(prompt, model: nil, provider: nil) ⇒ Object

Generate an answer using the LLM.



55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/ask/rag/query.rb', line 55

def ask_llm(prompt, model: nil, provider: nil) # rubocop:disable Metrics/MethodLength
  require "ask/agent" unless defined?(Ask::Agent)

  session_opts = { tools: [] }
  session_opts[:model] = model if model
  session_opts[:provider] = provider if provider

  session = Ask::Agent::Session.new(**session_opts)
  response = session.run(prompt)
  response.to_s
rescue NameError
  # Fallback: use basic Ask::Provider directly if ask-agent isn't available
  fallback_ask(prompt, model)
end

.query(store:, question:, model: nil, limit: 5, system_prompt: nil, provider: nil) ⇒ Ask::Document?

Perform a RAG query: retrieve relevant documents, build a prompt, and ask an LLM for an answer based on those documents.

Parameters:

  • store (Ask::RAG::VectorStore)

    the vector store to search

  • question (String)

    the user's question

  • model (String) (defaults to: nil)

    LLM model to use for answering

  • limit (Integer) (defaults to: 5)

    number of documents to retrieve (default: 5)

  • system_prompt (String, nil) (defaults to: nil)

    custom system prompt override

  • provider (Symbol, nil) (defaults to: nil)

    optional provider override

Returns:

  • (Ask::Document, nil)

    the answer with metadata including sources



31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/ask/rag/query.rb', line 31

def query(store:, question:, model: nil, limit: 5, system_prompt: nil, provider: nil)
  documents = store.similarity_search(question, limit: limit)

  return nil if documents.empty?

  context = documents.map.with_index(1) do |doc, i|
    "[#{i}] #{doc.content}\n"
  end.join("\n")

  prompt = system_prompt || build_default_prompt
  full_prompt = "#{prompt}\n\nContext:\n#{context}\n\nQuestion: #{question}"

  answer = ask_llm(full_prompt, model: model, provider: provider)

  Ask::Document.new(
    content: answer,
    metadata: {
      sources: documents.map { |d| d.[:source] }.compact.uniq,
      model: model
    }
  )
end