Metadata-Version: 2.4
Name: haystack-brave-search
Version: 0.1.5
Summary: A Haystack component for web search via the Brave Search API
Author: Tasis
Author-email: Tasis <tasis@gaia-labs.eu>
License-Expression: MIT
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Classifier: Programming Language :: Python :: 3
Requires-Dist: brave-search-python-client>=0.4.27
Requires-Dist: haystack-ai>=2.25.2
Requires-Python: >=3.12
Description-Content-Type: text/markdown

# haystack-brave-search

[![PyPI version](https://img.shields.io/pypi/v/haystack-brave-search.svg)](https://pypi.org/project/haystack-brave-search/)
[![Python versions](https://img.shields.io/pypi/pyversions/haystack-brave-search.svg)](https://pypi.org/project/haystack-brave-search/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

A [Haystack](https://haystack.deepset.ai/) component for web search using the [Brave Search API](https://brave.com/search/api/).

## Installation

```bash
pip install haystack-brave-search
```

## Requirements

* Python 3.12+
* A ```Brave Search API key```

## Usage

### Standalone

```python
from haystack_brave_search import BraveWebSearch
import os

# Set the API key using an environment variable
brave_api_key = os.environ["BRAVE_API_KEY"]

# Parameters set at initialisation are used as defaults for every call
searcher = BraveWebSearch(api_key=brave_api_key, top_k=5, country="BE", language="en")
result = searcher.run(query="Haystack AI framework")

# Any parameter can be overridden at run time
result = searcher.run(query="Haystack AI framework", top_k=3, country="US", language="en")

for doc in result["documents"]:
    print(doc.meta["title"])
    print(doc.meta["url"])
    print(doc.content)
```
### In a Haystack Pipeline

```python
from haystack import Pipeline
from haystack.components.builders import PromptBuilder
from haystack_brave_search import BraveWebSearch

prompt_template = """
Given the following search results:
{% for doc in documents %}
- {{ doc.meta.title }}: {{ doc.content }}
{% endfor %}

Answer the question: {{ query }}
"""

pipe = Pipeline()
pipe.add_component("search", BraveWebSearch(api_key="your-api-key", top_k=5))
pipe.add_component("prompt", PromptBuilder(template=prompt_template))

pipe.connect("search.documents", "prompt.documents")

result = pipe.run({
    "search": {"query": "What is RAG?"},
    "prompt": {"query": "What is RAG?"}
})

# Override search parameters at run time without changing the component
result = pipe.run({
    "search": {"query": "What is RAG?", "top_k": 3, "country": "BE", "language": "en"},
    "prompt": {"query": "What is RAG?"}
})

print(result["prompt"]["prompt"])
```

### With AsyncPipeline

```python
from haystack import AsyncPipeline
from haystack_brave_search import BraveWebSearch

pipe = AsyncPipeline()
pipe.add_component("search", BraveWebSearch(api_key="your-api-key"))
```

### Using a Proxy

Pass a `proxy_url` to the constructor to route requests through a proxy. When set, `api_key` is used as the Bearer token and the default `X-Subscription-Token` header is removed.

```python
searcher = BraveWebSearch(api_key="your-token", proxy_url="https://your-proxy-url.com")
```

### Parameters

#### Initialisation (`__init__`)

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `api_key` | `str` | required | Your Brave Search API key (also used as Bearer token when `proxy_url` is set) |
| `proxy_url` | `str` | `None` | Optional proxy URL. When set, overrides the Brave API base URL and uses `api_key` as the Bearer token |
| `top_k` | `int` | `5` | Default number of results to return |
| `country` | `str` | `"ALL"` | Default country code to localise results (e.g. `"BE"`, `"GR"`) |
| `language` | `str` | `"en"` | Default language code using ISO 639-1 (e.g. `"en"`, `"el"`) |

#### Run time (`run`)

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `query` | `str` | required | Search query |
| `top_k` | `int` | `None` | Overrides the initialisation value for this call only |
| `country` | `str` | `None` | Overrides the initialisation value for this call only |
| `language` | `str` | `None` | Overrides the initialisation value for this call only |

Run-time values take precedence over the defaults set at initialisation. Omitting a run-time parameter falls back to the initialisation value.

### Output

The ```run()``` method returns a dict with a ```documents``` key containing a list of Haystack ```Document``` objects:

* ```document.content``` — snippet/description of the result

* ```document.meta["title"]``` — page title

* ```document.meta["url"]``` — page URL

### Environment Variable

You can avoid hardcoding the API key by using an environment variable:

```python
import os
from haystack_brave_search import BraveWebSearch

searcher = BraveWebSearch(api_key=os.environ["BRAVE_API_KEY"])
```

### License

MIT