AIHelpMe.ALLOWED_PACKSConstant
ALLOWED PACKS

Currently available packs are:

  • :julia - Julia documentation, standard library docstrings and a few extras (for Julia v1.10)
  • :tidier - Tidier.jl organization documentation (as of 7th April 2024)
  • :makie - Makie.jl organization documentation (as of 30th March 2024)
AIHelpMe.LOADED_PACKSConstant
LOADED_PACKS

The knowledge packs that are currently loaded in the index.

AIHelpMe.PREFERENCESConstant
PREFERENCES

You can set preferences for AIHelpMe by using the set_preferences!. It will create a LocalPreferences.toml file in your current directory and will reload your prefences from there.

Check your preferences by calling get_preferences(key::String).

Available Preferences (for set_preferences!)

  • MODEL_CHAT: The default model to use for aigenerate and most ai* calls. See PromptingTools.MODEL_REGISTRY for a list of available models or define your own with PromptingTools.register_model!.
  • MODEL_EMBEDDING: The default model to use for aiembed (embedding documents). See PromptingTools.MODEL_REGISTRY for a list of available models or define your own with PromptingTools.register_model!.
  • EMBEDDING_DIMENSION: The dimension of the embedding vector. Defaults to 1024 (truncated OpenAI embedding). Set to 0 to use the maximum allowed dimension.
  • LOADED_PACKS: The knowledge packs that are loaded on restart/refresh (load_index!()).
AIHelpMe.RAG_CONFIGURATIONSConstant
RAG_CONFIGURATIONS

A dictionary of RAG configurations, keyed by a unique symbol (eg, bronze). Each entry contains a dictionary with keys :config and :kwargs, where :config is the RAG configuration object (AbstractRAGConfig) and :kwargs the NamedTuple of corresponding kwargs.

Available Options:

  • :bronze: A simple configuration for a bronze pipeline, using truncated binary embeddings (dimensionality: 1024) and no re-ranking or refinement.
  • :silver: A simple configuration for a bronze pipeline, using truncated binary embeddings (dimensionality: 1024) but also enables re-ranking step.
  • :gold: A more complex configuration, similar to :simpler, but using a standard embeddings (dimensionality: 3072, type: Float32). It also leverages re-ranking and refinement with a web-search.
AIHelpMe.aihelpMethod
aihelp([cfg::RT.AbstractRAGConfig, index::RT.AbstractChunkIndex,]
    question::AbstractString;
    verbose::Integer = 1,
    model = MODEL_CHAT,
    return_all::Bool = false)

Generates a response for a given question using a Retrieval-Augmented Generation (RAG) approach over Julia documentation (or any other knowledge pack).

If you return RAGResult (return_all=true), you can use AIHelpMe.pprint to pretty-print the result and see the sources/"support" scores for each chunk of the answer.

The answer will depend on the knowledge packs loaded, see ?load_index!.

You can also use add docstrings from any package you have loaded (or all of them), see ?update_index and make sure to provide your new updated index explicitly!

Arguments

  • cfg::AbstractRAGConfig: The RAG configuration.
  • index::AbstractChunkIndex: The chunk index (contains chunked and embedded documentation).
  • question::AbstractString: The question to be answered.
  • model::String: A chat/generation model used for generating the final response, default is MODEL_CHAT.
  • return_all::Bool: If true, returns a RAGResult (provides details of the pipeline + allows pretty-printing with pprint(result)).
  • search::Union{Nothing, Bool}: If true, uses TavilySearchRefiner to add web search results to the context. See ?PromptingTools.Experimental.RAGTools.TavilySearchRefiner for details.
  • rerank::Union{Nothing, Bool}: If true, uses CohereReranker to rerank the chunks. See ?PromptingTools.Experimental.RAGTools.CohereReranker for details.

Returns

  • If return_all is false, returns the generated message (msg).
  • If return_all is true, returns a RAGResult (provides details of the pipeline + allows pretty-printing with pprint(result))

Notes

  • Function always saves the last context in global LAST_RESULT for inspection of sources/context regardless of return_all value.

Examples

Using aihelp to get a response for a question:

using AIHelpMe: build_index

index = build_index(...)  # create an index that contains Makie.jl documentation (or any loaded package that you have)

question = "How to make a barplot in Makie.jl?"
msg = aihelp(index, question)

If you want a pretty-printed answer with highlighted sources, you can use the return_all argument and pprint utility:

using AIHelpMe: pprint

result = aihelp(index, question; return_all = true)
pprint(result)

If you loaded a knowledge pack, you do not have to provide the index.

# Load Makie knowledge pack
AIHelpMe.load_index!(:makie)

question = "How to make a barplot in Makie.jl?"
msg = aihelp(question)

If you know it's a hard question, you can use the search and rerank arguments to add web search results to the context and rerank the chunks.

using AIHelpMe: pprint

question = "How to make a barplot in Makie.jl?"
result = aihelp(question; search = true, rerank = true, return_all = true)
pprint(result) # nicer display with sources for each chunk/sentences (look for square brackets)
AIHelpMe.docextractFunction
docextract(d::DocStr, sep::AbstractString = "

")

Extracts the documentation from a DocStr record. Separates the individual docs within DocStr with sep.

AIHelpMe.docextractFunction
docextract(modules::Vector{Module} = Base.Docs.modules)

Extracts the documentation from a vector of modules.

AIHelpMe.docextractFunction
docextract(d::MultiDoc, sep::AbstractString = "

")

Extracts the documentation from a MultiDoc record (separates the individual docs within DocStr with sep)

AIHelpMe.docextractMethod
docextract(mod::Module)

Extracts the documentation from a given (loaded) module.

AIHelpMe.find_new_chunksMethod
find_new_chunks(old_chunks::AbstractVector{<:AbstractString},
    new_chunks::AbstractVector{<:AbstractString})

Identifies the new chunks in new_chunks that are not present in old_chunks.

Returns a mask of chunks that are new (not present in old_chunks).

Uses SHA256 hashes to dedupe the strings quickly and effectively.

AIHelpMe.get_config_keyFunction

Returns the configuration key for the given cfg and kwargs to use the relevant artifacts.

AIHelpMe.get_preferencesMethod
get_preferences(key::String)

Get preferences for AIHelpMe. See ?PREFERENCES for more information.

See also: set_preferences!

Example

AIHelpMe.get_preferences("MODEL_CHAT")
AIHelpMe.last_resultMethod
last_result()

Returns the RAGResult from the last aihelp call. It can be useful to see the sources/references used by the AI model to generate the response.

If you're using aihelp() make sure to set return_all = true to return the RAGResult.

AIHelpMe.load_index!Function
load_index!(packs::Vector{Symbol}=LOADED_PACKS[]; verbose::Bool = true, kwargs...)
load_index!(pack::Symbol; verbose::Bool = true, kwargs...)

Loads one or more packs into the main index from our pre-built artifacts.

Availability of packs might vary depending on your pipeline configuration (ie, whether we have the correct embeddings for it). See AIHelpMe.ALLOWED_PACKS

Example

load_index!(:julia)

Or multiple packs

load_index!([:julia, :makie,:tidier])
AIHelpMe.load_index!Method
load_index!(file_path::AbstractString;
    verbose::Bool = true, kwargs...)

Loads the serialized index in file_path into the global variable MAIN_INDEX.

Supports .jls (serialized Julia object) and .hdf5 (HDF5.jl) files.

AIHelpMe.load_index!Method
load_index!(index::RT.AbstractChunkIndex;
    verbose::Bool = 1, kwargs...)

Loads the provided index into the global variable MAIN_INDEX.

If you don't have an index yet, use build_index to build one from your currently loaded packages (see ?build_index)

Example

# build an index from some modules, keep empty to embed all loaded modules (eg, `build_index()`) 
index = AIH.build_index([DataFramesMeta, DataFrames, CSV])
AIH.load_index!(index)
AIHelpMe.load_index_hdf5Method

Hacky function to load a HDF5 file into a ChunkIndex object. Only bare-bone ChunkIndex is supported right now.

AIHelpMe.set_preferences!Method
set_preferences!(pairs::Pair{String, <:Any}...)

Set preferences for AIHelpMe. See ?PREFERENCES for more information.

See also: get_preferences

Example

Change your API key and default model:

# EMBEDDING_DIMENSION of 0 means the maximum allowed
AIHelpMe.set_preferences!("MODEL_CHAT" => "llama3", "MODEL_EMBEDDING" => "nomic-embed-text", "EMBEDDING_DIMENSION" => 0)
AIHelpMe.update_indexFunction
update_index(index::RT.AbstractChunkIndex = MAIN_INDEX[],
    modules::Vector{Module} = Base.Docs.modules;
    verbose::Integer = 1,
    kwargs...)

Updates the provided index with the documentation of the provided modules.

Deduplicates against the index.sources and embeds only the new document chunks (as measured by a hash).

Returns the updated index (new instance).

For available configurations and customizations, see the corresponding modules and functions of PromptingTools.Experimental.RAGTools (eg, build_index).

Example

If you loaded some new packages and want to add them to your MAIN_INDEX (or any index you use), run:

# To update the MAIN_INDEX as well
AIHelpMe.update_index() |> AHM.load_index!

# To update an explicit index
index = AIHelpMe.update_index(index)
AIHelpMe.update_pipeline!Function
update_pipeline!(option::Symbol = :bronze; model_chat = MODEL_CHAT,
    model_embedding = MODEL_EMBEDDING, verbose::Bool = true, embedding_dimension::Integer = EMBEDDING_DIMENSION)

Updates the default RAG pipeline to one of the pre-configuration options and sets the requested chat and embedding models.

This is a good way to update model types to change between OpenAI models and Ollama models.

See available pipeline options via keys(RAG_CONFIGURATIONS).

Logic:

  • Updates the global MODEL_CHAT and MODEL_EMBEDDING to the requested models.
  • Update the global EMBEDDING_DIMENSION for the requested embedding dimensionality after truncation (embedding_dimension).
  • Updates the global RAG_CONFIG and RAG_KWARGS to the requested option.
  • Updates the global LOADED_CONFIG_KEY to the configuration key for the given option and kwargs (used by the artifact system to download the correct knowledge packs).

Example

update_pipeline!(:bronze; model_chat = "gpt4t")

You don't need to re-load your index if you just change the chat model.

You can switch the pipeline to Ollama models: Note: only 1 Ollama embedding model is supported for embeddings now! You must select "nomic-embed-text" and if you do, set embedding_dimension=0 (maximum dimension available)

update_pipeline!(:bronze; model_chat = "llama3", model_embedding="nomic-embed-text", embedding_dimension=0)

# You must download the corresponding knowledge packs via `load_index!` (because you changed the embedding model)
load_index!()
PromptingTools.Experimental.RAGTools.build_indexFunction
RT.build_index(modules::Vector{Module} = Base.Docs.modules; verbose::Int = 1,
    kwargs...)

Build index from the documentation of the currently loaded modules. If modules is empty, it will use all currently loaded modules.

AIHelpMe.@aihelp!_strMacro
aihelp!"user_question"[model_alias] -> AIMessage

The aihelp!"" string macro is used to continue a previous conversation with the AI model.

It appends the new user prompt to the last conversation in the tracked history (in AIHelpMe.CONV_HISTORY) and generates a response based on the entire conversation context. If you want to see the previous conversation, you can access it via AIHelpMe.CONV_HISTORY, which keeps at most last PromptingTools.MAX_HISTORY_LENGTH conversations.

It does NOT provide new context from the documentation. To do that, start a new conversation with aihelp"<question>".

Arguments

  • user_question (String): The follow up question to be added to the existing conversation.
  • model_alias (optional, any): Specify the model alias of the AI model to be used (see PT.MODEL_ALIASES). If not provided, the default model is used.

Returns

AIMessage corresponding to the new user prompt, considering the entire conversation history.

Example

To continue a conversation:

# start conversation as normal
aihelp"How to create a dictionary?" 

# ... wait for reply and then react to it:

# continue the conversation (notice that you can change the model, eg, to more powerful one for better answer)
aihelp!"Can you create it from named tuple?"gpt4t
# AIMessage("Yes, you can create a dictionary from a named tuple ...")

Usage Notes

  • This macro should be used when you want to maintain the context of an ongoing conversation (ie, the last ai"" message).
  • It automatically accesses and updates the global conversation history.
  • If no conversation history is found, it raises an assertion error, suggesting to initiate a new conversation using ai"" instead.

Important

Ensure that the conversation history is not too long to maintain relevancy and coherence in the AI's responses. The history length is managed by MAX_HISTORY_LENGTH.

AIHelpMe.@aihelp_strMacro
aihelp"user_question"[model_alias] -> AIMessage

The aihelp"" string macro generates an AI response to a given user question by using aihelp under the hood. It will automatically try to provide the most relevant bits of the documentation (from the index) to the LLM to answer the question.

See also aihelp!"" if you want to reply to the provided message / continue the conversation.

Arguments

  • user_question (String): The question to be answered by the AI model.
  • model_alias (optional, any): Provide model alias of the AI model (see MODEL_ALIASES).

Returns

AIMessage corresponding to the input prompt.

Example

result = aihelp"Hello, how are you?"
# AIMessage("Hello! I'm an AI assistant, so I don't have feelings, but I'm here to help you. How can I assist you today?")

If you want to interpolate some variables or additional context, simply use string interpolation:

a=1
result = aihelp"What is `$a+$a`?"
# AIMessage("The sum of `1+1` is `2`.")

If you want to use a different model, eg, GPT-3.5 Turbo, you can provide its alias as a flag:

result = aihelp"What is `1.23 * 100 + 1`?"gpt3t
# AIMessage("The answer is 124.")