README.md

# Karn

Karn is an interactive AI assistant for your Elixir codebase, designed to be used within an `IEx` session. It helps you understand and query your code using natural language, leveraging the power of Large Language Models.

## Features

*   **Natural Language Queries**: Ask questions about your code in plain English.
*   **Code Explanations**: Get detailed explanations for specific modules and their functions.
*   **Conversational Context**: Karn remembers the history of your conversation, allowing for follow-up questions.
*   **Context Management**: View the current conversation context or reset it when needed.
*   **Usage Tracking**: Monitor your LLM token usage for the current session.

## Installation

Add `karn` as a dependency to your `mix.exs` file. It is recommended to add it only for the `:dev` environment.
User can change the default model by adding to their dev config 
``` elixir
  config :karn,
    default_model: "anthropic:claude-3-5-haiku-20241022"
```

```elixir
def deps do
  [
    {:karn, "~> 0.1.0", only: [:dev]}
  ]
end
```

One can also install Karn using igniter 
```shell
# uses gemini as default model
mix igniter.install karn

mix igniter.install karn --anthropic
```

Supported options are `--google`, `--anthropic`, `--openai`
You can use any model supported by `ReqLLM`, the supported options are just to get started fast

Then, fetch the dependencies:

```shell
mix deps.get
```

## Setup and Usage

Karn is designed to be used interactively within an `IEx` session.

### 1. Start IEx

Start your project's `IEx` session:

```shell
# phoenix application
iex -S mix phx.server

# generic
iex -S mix run
```

### 2. Configure API Key

Karn uses the `ReqLLM` library to communicate with LLMs. You need to provide an API key for the desired service. The default model is `google:gemini-2.0-flash`, so you'll need a Google AI API key.

You can configure your key in one of two ways:

1.  **Environment Variable (Recommended)**: Export the key in your shell.
    ```shell
    export GOOGLE_API_KEY="your-google-api-key"
    ```
    `ReqLLM` will automatically pick it up when you start `iex`.

2.  **In your `IEx` session**: Configure the key manually.
    ```elixir
    # Replace "your-google-api-key" with your actual key
    ReqLLM.put_key(:google_api_key, "your-google-api-key")
    ```

### 3. Start the Karn Server

Start the server:

```elixir
Karn.start
```

### 4. Use Karn

For a more human-friendly experience, import the `Karn` functions into your `IEx` shell. This allows you to call them directly.

```elixir
iex> import Karn
Karn
```

Now you can interact with the AI.

#### General Query (`q/1`)

Ask any question about Elixir or your project.

```elixir
iex> q "What is the difference between a GenServer and an Agent?"
╭─ assistant ─────────────────────────────────────────────────────────────────╮
│ Okay, Let's clarify the difference between GenServer and Agent in Elixir.   │
│                                                                             │
│ **Agent:**                                                                  │
│                                                                             │
│ *   **Simple State Management:** An Agent is...                             │
│                                                                             │
╰─────────────────────────────────────────────────────────────────────────────╯
```

#### Explain Module (`e/3`)

Get an explanation for a specific module. You can also provide related modules for more context.

```elixir
# Get a general explanation of MyModule
iex> e Karn
╭─ assistant ──────────────────────────────────────────────────────────╮
│ Okay, I've analyzed the `Elixir.Karn` module. Here's a breakdown:    │
│                                                                      │
│ **Purpose:**                                                         │
│                                                                      │
│ The `Karn` module acts as a client...                                │
│ explanation, context management, and usage tracking.                 │
│                                                                      │
╰──────────────────────────────────────────────────────────────────────╯

# Get a specific explanation of MyModule
iex> e MyModule,"How does function b work?"

# only 1 reference
iex> e MyModule,ModuleB,"How are the two modules related"

# multiple references
iex> e MyModule,[ModuleB,ModuleC],"Why is MyModule.function behaving this way ?"

#Ask a specific question about MyModule, providing another module for context
iex> e MyModule, "Write me ecto query to fetch records for xyz schema ?"
```

#### View Conversation Context (`view_context/0`)

See the history of messages (user and assistant) in the current session.

```elixir
iex> view_context()
```

#### Reset Conversation Context (`reset_context/1`)

Clear the current conversation history. You can optionally provide a new system prompt.

```elixir
# Reset to the default system prompt
iex> reset_context()

# Reset with a custom system prompt
iex> reset_context "You are a helpful Elixir assistant."
```

#### View Usage (`usage/0`)

Check the token usage (input, output, and total cost) for the current session.

```elixir
iex> usage()
```

#### Stop Karn (`stop/0`)

Stop the `Karn.Ai.Server`. This will also print the final usage statistics for the session.

```elixir
iex> stop()
```