|
1 | | -# Custom Component Template |
| 1 | +# Context.dev for Haystack |
2 | 2 |
|
3 | | -A template repository for creating custom [Haystack](https://haystack.deepset.ai/) components and publishing them as standalone Python packages. |
| 3 | +[](https://pypi.org/project/context-dev-haystack/) |
| 4 | +[](https://pypi.org/project/context-dev-haystack/) |
| 5 | +[](https://github.com/context-dot-dev/context-haystack/actions/workflows/test.yml) |
| 6 | +[](LICENSE) |
4 | 7 |
|
5 | | -For more details, see the Haystack documentation on [creating custom components](https://docs.haystack.deepset.ai/docs/custom-components) and [creating custom document stores](https://docs.haystack.deepset.ai/docs/creating-custom-document-stores). |
| 8 | +Haystack components for live web search, webpage and YouTube transcript retrieval, and bounded website crawling with [Context.dev](https://context.dev). |
6 | 9 |
|
7 | | -## How to use this template |
| 10 | +## Installation |
8 | 11 |
|
9 | | -1. Click **[Use this template](https://github.com/deepset-ai/custom-component/generate)** to create a new repository. |
| 12 | +```bash |
| 13 | +pip install context-dev-haystack |
| 14 | +``` |
10 | 15 |
|
11 | | -2. **Rename the package directory** from `src/haystack_integrations/components/example/` to match your integration. See [Namespace convention](#namespace-convention) below for the correct path. |
| 16 | +Create an API key in the [Context.dev dashboard](https://context.dev/dashboard/api-keys), then export it: |
12 | 17 |
|
13 | | -3. **Update `pyproject.toml`** — search for `TODO` comments and replace: |
14 | | - - `name`: your package name, following the `<technology>-haystack` convention (e.g. `opensearch-haystack`) |
15 | | - - `description`, `authors`, `keywords`, `project.urls` |
16 | | - - `dependencies`: add your integration-specific dependencies |
17 | | - - `tool.hatch.version.raw-options`: if you renamed directories, the version path is still derived from git tags so no change is needed here |
| 18 | +```bash |
| 19 | +export CONTEXT_API_KEY="your-api-key" |
| 20 | +``` |
18 | 21 |
|
19 | | -4. **Add your component code** in the renamed directory and export your classes from `__init__.py`. |
| 22 | +## Components |
20 | 23 |
|
21 | | -5. **Add tests** in `tests/` — see the skeleton in `tests/test_example.py`. |
| 24 | +| Component | Purpose | Import | |
| 25 | +| --- | --- | --- | |
| 26 | +| `ContextWebSearch` | Search the live web and return ranked Haystack Documents and source links | `haystack_integrations.components.websearch.context` | |
| 27 | +| `ContextFetcher` | Fetch webpages or YouTube videos as clean Markdown Documents | `haystack_integrations.components.fetchers.context` | |
| 28 | +| `ContextCrawler` | Crawl websites into Documents with explicit page and depth limits | `haystack_integrations.components.fetchers.context` | |
22 | 29 |
|
23 | | -6. **Search for all `TODO` comments** across the project and address them. |
| 30 | +All components support both `run()` and `run_async()`, Haystack serialization, custom timeouts, and retry configuration. |
24 | 31 |
|
25 | | -Check out the [video walkthrough](https://www.youtube.com/watch?v=SWC0QecAMcI) for a step-by-step guide on how to use this template. |
| 32 | +## Search the live web |
26 | 33 |
|
27 | | -## Namespace convention |
| 34 | +```python |
| 35 | +from haystack_integrations.components.websearch.context import ContextWebSearch |
28 | 36 |
|
29 | | -Haystack integrations use the `haystack_integrations` namespace package. The directory structure under `src/` determines the import path for your component. |
| 37 | +search = ContextWebSearch(top_k=5, include_markdown=True) |
| 38 | +result = search.run(query="Recent advances in retrieval-augmented generation") |
30 | 39 |
|
31 | | -**Components** (converters, embedders, generators, rankers, etc.) use: |
| 40 | +documents = result["documents"] |
| 41 | +links = result["links"] |
32 | 42 | ``` |
33 | | -src/haystack_integrations/components/<type>/<name>/ |
34 | | -``` |
35 | | -Import path: `from haystack_integrations.components.<type>.<name> import MyComponent` |
36 | 43 |
|
37 | | -Common component types: `converters`, `embedders`, `generators`, `rankers`, `retrievers`, `connectors`, `tools`, `websearch` |
| 44 | +Use `include_domains`, `exclude_domains`, `freshness`, and `country` to constrain results. Extra Context.dev Search API fields can be supplied through `search_params`. |
38 | 45 |
|
39 | | -**Document stores** use a separate namespace: |
40 | | -``` |
41 | | -src/haystack_integrations/document_stores/<name>/ |
| 46 | +## Fetch webpages or YouTube transcripts |
| 47 | + |
| 48 | +```python |
| 49 | +from haystack_integrations.components.fetchers.context import ContextFetcher |
| 50 | + |
| 51 | +fetcher = ContextFetcher() |
| 52 | +result = fetcher.run( |
| 53 | + urls=[ |
| 54 | + "https://haystack.deepset.ai", |
| 55 | + "https://www.youtube.com/watch?v=UF8uR6Z6KLc", |
| 56 | + ] |
| 57 | +) |
| 58 | + |
| 59 | +documents = result["documents"] |
42 | 60 | ``` |
43 | | -Import path: `from haystack_integrations.document_stores.<name> import MyDocumentStore` |
44 | 61 |
|
45 | | -## Development |
| 62 | +Each URL becomes a Haystack `Document`. Webpages contain clean Markdown and page metadata; supported YouTube URLs return timestamped transcript Markdown. |
46 | 63 |
|
47 | | -This project uses [Hatch](https://hatch.pypa.io/) for build and environment management. |
| 64 | +## Crawl a website |
48 | 65 |
|
49 | | -```bash |
50 | | -# Install Hatch |
51 | | -pip install hatch |
52 | | - |
53 | | -# Format and lint |
54 | | -hatch run fmt # auto-fix |
55 | | -hatch run fmt-check # check only |
56 | | - |
57 | | -# Run tests |
58 | | -hatch run test:unit # unit tests only |
59 | | -hatch run test:integration # integration tests only |
60 | | -hatch run test:all # all tests |
61 | | -hatch run test:cov # with coverage |
| 66 | +```python |
| 67 | +from haystack_integrations.components.fetchers.context import ContextCrawler |
| 68 | + |
| 69 | +crawler = ContextCrawler(crawl_params={"maxPages": 25, "maxDepth": 2}) |
| 70 | +result = crawler.run(urls=["https://docs.haystack.deepset.ai"]) |
| 71 | + |
| 72 | +documents = result["documents"] |
62 | 73 | ``` |
63 | 74 |
|
64 | | -## Publishing to PyPI |
| 75 | +`ContextCrawler` defaults to one page to prevent accidental credit consumption. Set `maxPages` explicitly for larger crawls. |
| 76 | + |
| 77 | +## Async usage |
65 | 78 |
|
66 | | -This template includes a GitHub Actions workflow that publishes your package to PyPI when you push a version tag. |
| 79 | +```python |
| 80 | +result = await search.run_async(query="Haystack agents") |
| 81 | +documents = result["documents"] |
| 82 | +``` |
67 | 83 |
|
68 | | -1. **Add a `PYPI_API_TOKEN` secret** to your repository settings (Settings > Secrets and variables > Actions). |
| 84 | +The fetcher and crawler process multiple input URLs concurrently in their async methods. |
69 | 85 |
|
70 | | -2. **Create a version tag** and push it: |
71 | | - ```bash |
72 | | - git tag v0.1.0 |
73 | | - git push origin v0.1.0 |
74 | | - ``` |
| 86 | +## Development |
75 | 87 |
|
76 | | -The release workflow will build and publish the package automatically. |
| 88 | +See [CONTRIBUTING.md](CONTRIBUTING.md) for the Hatch-based development and release workflow. |
77 | 89 |
|
78 | 90 | ## License |
79 | 91 |
|
80 | | -`Apache-2.0` - See [LICENSE](LICENSE) for details. |
| 92 | +Apache-2.0. See [LICENSE](LICENSE). |
0 commit comments