apify-haystack 0.1.7__tar.gz → 0.1.8b2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- apify_haystack-0.1.8b2/CHANGELOG.md +88 -0
- apify_haystack-0.1.8b2/CONTRIBUTING.md +70 -0
- apify_haystack-0.1.8b2/PKG-INFO +166 -0
- apify_haystack-0.1.8b2/README.md +138 -0
- apify_haystack-0.1.8b2/pyproject.toml +220 -0
- apify_haystack-0.1.8b2/pyproject.toml.orig +173 -0
- apify_haystack-0.1.8b2/src/apify_haystack/__init__.py +21 -0
- apify_haystack-0.1.8b2/src/apify_haystack/_actor_tool.py +208 -0
- apify_haystack-0.1.8b2/src/apify_haystack/_client.py +84 -0
- apify_haystack-0.1.8b2/src/apify_haystack/_constants.py +7 -0
- apify_haystack-0.1.8b2/src/apify_haystack/_dataset.py +398 -0
- apify_haystack-0.1.8b2/src/apify_haystack/_web_search.py +127 -0
- apify_haystack-0.1.8b2/src/apify_haystack/py.typed +0 -0
- apify_haystack-0.1.7/PKG-INFO +0 -118
- apify_haystack-0.1.7/README.md +0 -87
- apify_haystack-0.1.7/pyproject.toml +0 -168
- apify_haystack-0.1.7/src/apify_haystack/__init__.py +0 -7
- apify_haystack-0.1.7/src/apify_haystack/apify_dataset.py +0 -259
- apify_haystack-0.1.7/src/apify_haystack/constants.py +0 -2
- apify_haystack-0.1.7/src/apify_haystack/examples/apify_actor_call.py +0 -49
- apify_haystack-0.1.7/src/apify_haystack/examples/apify_dataset_load.py +0 -31
- apify_haystack-0.1.7/src/apify_haystack/examples/crawl_and_process_data.py +0 -84
- apify_haystack-0.1.7/src/apify_haystack/examples/instagram_comments_analysis.py +0 -85
- apify_haystack-0.1.7/src/apify_haystack/examples/rag_with_crawled_website.py +0 -113
- {apify_haystack-0.1.7 → apify_haystack-0.1.8b2}/LICENSE +0 -0
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
<!-- git-cliff-unreleased-start -->
|
|
6
|
+
## 0.1.8 - **not yet released**
|
|
7
|
+
|
|
8
|
+
### 🚀 Features
|
|
9
|
+
|
|
10
|
+
- Add support for Python 3.14 ([#36](https://github.com/apify/apify-haystack/pull/36)) ([fe4abac](https://github.com/apify/apify-haystack/commit/fe4abacc1511b1cbd40d98cd9b5d57ef3b9dcb5a)) by [@vdusek](https://github.com/vdusek)
|
|
11
|
+
- [**breaking**] Migrate to apify-client 3.x ([#47](https://github.com/apify/apify-haystack/pull/47)) ([8358f91](https://github.com/apify/apify-haystack/commit/8358f915c9b320206e7c11b08a4e64d28bac5aad)) by [@vdusek](https://github.com/vdusek), closes [#28](https://github.com/apify/apify-haystack/issues/28)
|
|
12
|
+
- [**breaking**] Migrate to Haystack 3.x ([#39](https://github.com/apify/apify-haystack/pull/39)) ([783706e](https://github.com/apify/apify-haystack/commit/783706eb07e0365efc7f9831de46115028add91f)) by [@vdusek](https://github.com/vdusek)
|
|
13
|
+
- [**breaking**] Create the Apify client in `warm_up` and release it in `close` ([#41](https://github.com/apify/apify-haystack/pull/41)) ([405455c](https://github.com/apify/apify-haystack/commit/405455cba9fcfea6c780c315d5634ee783780029)) by [@vdusek](https://github.com/vdusek)
|
|
14
|
+
- [**breaking**] Take the API token as a Haystack `Secret` and support component serialization ([#42](https://github.com/apify/apify-haystack/pull/42)) ([f52c359](https://github.com/apify/apify-haystack/commit/f52c35978a86dd69cd4d478d396b052ee76b0853)) by [@vdusek](https://github.com/vdusek)
|
|
15
|
+
- Add async support to the components ([#57](https://github.com/apify/apify-haystack/pull/57)) ([3d15741](https://github.com/apify/apify-haystack/commit/3d15741496cdca24441f93806a3bb2d3d61f0e6c)) by [@vdusek](https://github.com/vdusek)
|
|
16
|
+
- Add ApifyWebSearch component ([#58](https://github.com/apify/apify-haystack/pull/58)) ([974f861](https://github.com/apify/apify-haystack/commit/974f8616c1632ccf8bf444e2567534bb1371a936)) by [@vdusek](https://github.com/vdusek)
|
|
17
|
+
- Add ApifyActorTool for Haystack Agents ([#59](https://github.com/apify/apify-haystack/pull/59)) ([96cfedc](https://github.com/apify/apify-haystack/commit/96cfedcb798f59b17f1b97e116e697065020745c)) by [@vdusek](https://github.com/vdusek)
|
|
18
|
+
- [**breaking**] Rename the token parameter to apify_token and read APIFY_TOKEN ([#62](https://github.com/apify/apify-haystack/pull/62)) ([8db8ce3](https://github.com/apify/apify-haystack/commit/8db8ce3bb25dd24add347deec7d5d67b7b6369a8)) by [@vdusek](https://github.com/vdusek)
|
|
19
|
+
- Add a default dataset mapping function ([#64](https://github.com/apify/apify-haystack/pull/64)) ([c25c9a3](https://github.com/apify/apify-haystack/commit/c25c9a3160ca7425737abd52986d756d009df9d8)) by [@vdusek](https://github.com/vdusek)
|
|
20
|
+
- Mark ApifyActorTool output as untrusted external content ([#65](https://github.com/apify/apify-haystack/pull/65)) ([ee93080](https://github.com/apify/apify-haystack/commit/ee930801ccf7ac88ed77be9c27b9dea57a02c038)) by [@vdusek](https://github.com/vdusek)
|
|
21
|
+
- Add a max_total_charge_usd limit to the Actor runs ([#70](https://github.com/apify/apify-haystack/pull/70)) ([83a8184](https://github.com/apify/apify-haystack/commit/83a81847cc4050cabd44183979440ab944350d95)) by [@vdusek](https://github.com/vdusek)
|
|
22
|
+
|
|
23
|
+
### 🐛 Bug Fixes
|
|
24
|
+
|
|
25
|
+
- Respect input passed to `run` in Actor and task calls ([#33](https://github.com/apify/apify-haystack/pull/33)) ([78a3882](https://github.com/apify/apify-haystack/commit/78a388256a8230d397b135bca4c3d0cbce9c16da)) by [@vdusek](https://github.com/vdusek)
|
|
26
|
+
- [**breaking**] Raise when an Actor or task run does not succeed ([#63](https://github.com/apify/apify-haystack/pull/63)) ([46ef2f2](https://github.com/apify/apify-haystack/commit/46ef2f29aeecda69ab6155eaa76b423fb1b4d28c)) by [@vdusek](https://github.com/vdusek)
|
|
27
|
+
|
|
28
|
+
### 🚜 Refactor
|
|
29
|
+
|
|
30
|
+
- [**breaking**] Make the constants module private ([#68](https://github.com/apify/apify-haystack/pull/68)) ([8f5dbbd](https://github.com/apify/apify-haystack/commit/8f5dbbd7a4fa0e8c3c7c8036799d40744ee47624)) by [@vdusek](https://github.com/vdusek)
|
|
31
|
+
- [**breaking**] Make all modules private and export the public API from the package root ([#77](https://github.com/apify/apify-haystack/pull/77)) ([4e6ccca](https://github.com/apify/apify-haystack/commit/4e6cccae287999f9ceb72fe9b67c2305b1206113)) by [@vdusek](https://github.com/vdusek)
|
|
32
|
+
|
|
33
|
+
### ⚙️ Miscellaneous Tasks
|
|
34
|
+
|
|
35
|
+
- [**breaking**] Drop support for Python 3.9 ([#34](https://github.com/apify/apify-haystack/pull/34)) ([d86960d](https://github.com/apify/apify-haystack/commit/d86960dbe3ad794541833680cfd05c3331170c26)) by [@vdusek](https://github.com/vdusek)
|
|
36
|
+
- [**breaking**] Drop support for Python 3.10 ([#35](https://github.com/apify/apify-haystack/pull/35)) ([5b33fe5](https://github.com/apify/apify-haystack/commit/5b33fe53dd722d584461909edc2d7aacfdb686d9)) by [@vdusek](https://github.com/vdusek)
|
|
37
|
+
- [**breaking**] Drop the unused python-dotenv dependency and move examples out of the package ([#43](https://github.com/apify/apify-haystack/pull/43)) ([9b3de5e](https://github.com/apify/apify-haystack/commit/9b3de5e81babcede7d3287fcacf1189f72d02224)) by [@vdusek](https://github.com/vdusek)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
<!-- git-cliff-unreleased-end -->
|
|
41
|
+
# Changelog
|
|
42
|
+
|
|
43
|
+
## [0.1.7](https://github.com/apify/apify-haystack/releases/tag/0.1.7) (2024-12-09)
|
|
44
|
+
|
|
45
|
+
🐛 Bug Fixes
|
|
46
|
+
- Use CI from crawlee-python to publish to PyPI
|
|
47
|
+
|
|
48
|
+
## [0.1.6](https://github.com/apify/apify-haystack/releases/tag/0.1.6) (2024-12-09)
|
|
49
|
+
|
|
50
|
+
🐛 Bug Fixes
|
|
51
|
+
- Fix description in pyproject.toml
|
|
52
|
+
|
|
53
|
+
## [0.1.5](https://github.com/apify/apify-haystack/releases/tag/0.1.5) (2024-09-04)
|
|
54
|
+
|
|
55
|
+
🚀 Features
|
|
56
|
+
- Add link to google colab in the README
|
|
57
|
+
|
|
58
|
+
## [0.1.4](https://github.com/apify/apify-haystack/releases/tag/0.1.4) (2024-09-04)
|
|
59
|
+
|
|
60
|
+
🚀 Features
|
|
61
|
+
- Allow to add Actor inputs (`run_input`) in the ApifyDatasetFromActorCall.run() method
|
|
62
|
+
|
|
63
|
+
## [0.1.3](https://github.com/apify/apify-haystack/releases/tag/0.1.3) (2024-08-04)
|
|
64
|
+
|
|
65
|
+
🚀 Features
|
|
66
|
+
- Update code examples in the documentation
|
|
67
|
+
|
|
68
|
+
## [0.1.2](https://github.com/apify/apify-haystack/releases/tag/0.1.2) (2024-08-02)
|
|
69
|
+
|
|
70
|
+
🐛 Bug Fixes
|
|
71
|
+
- Correct examples in the documentation
|
|
72
|
+
|
|
73
|
+
## [0.1.1](https://github.com/apify/apify-haystack/releases/tag/0.1.1) (2024-07-31)
|
|
74
|
+
|
|
75
|
+
🐛 Bug Fixes
|
|
76
|
+
- Fixed publication to PyPI
|
|
77
|
+
|
|
78
|
+
## [0.1.0](https://github.com/apify/apify-haystack/releases/tag/0.1.0) (2024-07-30)
|
|
79
|
+
|
|
80
|
+
🚀 Features
|
|
81
|
+
- Added support for the Apify-Haystack integration
|
|
82
|
+
- Added code examples
|
|
83
|
+
|
|
84
|
+
## [0.0.1] (2024-07-25)
|
|
85
|
+
|
|
86
|
+
🚀 Features
|
|
87
|
+
- Dummy package `apify-haystack` was released on PyPI.
|
|
88
|
+
- Added CI
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# Development
|
|
2
|
+
|
|
3
|
+
Here you'll find a contributing guide to get started with development.
|
|
4
|
+
|
|
5
|
+
## Environment
|
|
6
|
+
|
|
7
|
+
For local development, you need a Python version that satisfies `requires-python` in `pyproject.toml`.
|
|
8
|
+
|
|
9
|
+
We use [uv](https://docs.astral.sh/uv/) for project management. Install it and set up your IDE accordingly.
|
|
10
|
+
|
|
11
|
+
We use [Poe the Poet](https://poethepoet.natn.io/) as a task runner, similar to npm scripts in `package.json`. All tasks are defined in `pyproject.toml` under `[tool.poe.tasks]`. Run `uv run poe` to list them with their descriptions, and `uv run poe <task>` to run one.
|
|
12
|
+
|
|
13
|
+
## Dependencies
|
|
14
|
+
|
|
15
|
+
To install this package with its development dependencies and the pre-commit hooks, run:
|
|
16
|
+
|
|
17
|
+
```sh
|
|
18
|
+
uv run poe install-dev
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Code checking
|
|
22
|
+
|
|
23
|
+
To run all code checks (lint, type check, and unit tests), run:
|
|
24
|
+
|
|
25
|
+
```sh
|
|
26
|
+
uv run poe check-code
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
We use [ruff](https://docs.astral.sh/ruff/) for linting and formatting, [ty](https://docs.astral.sh/ty/) for type checking, and [pytest](https://docs.pytest.org/) for tests. All of them are configured in `pyproject.toml`, and each has its own task (`lint`, `format`, `type-check`, `unit-tests`).
|
|
30
|
+
|
|
31
|
+
## Tests
|
|
32
|
+
|
|
33
|
+
Unit tests (`tests/unit`) are isolated from the Apify API. Run them with `uv run poe unit-tests`, or a single test with `uv run pytest tests/unit/<path>.py::<test_name>`.
|
|
34
|
+
|
|
35
|
+
Integration tests (`tests/integration`) run the components against the Apify platform, so they need an Apify API token in the `APIFY_TOKEN` environment variable and are skipped without one. Run them with `uv run poe integration-tests`. They run real Actors on that account, which costs a little. CI runs them on pull requests from this repository and on pushes to `main`, with the test user's token.
|
|
36
|
+
|
|
37
|
+
## Documentation
|
|
38
|
+
|
|
39
|
+
We adhere to the [Google docstring format](https://sphinxcontrib-napoleon.readthedocs.io/en/latest/example_google.html) for documenting our codebase. Every user-facing class or method is documented. Documentation standards are enforced using [Ruff](https://docs.astral.sh/ruff/).
|
|
40
|
+
|
|
41
|
+
## Release process
|
|
42
|
+
|
|
43
|
+
Publishing new versions to [PyPI](https://pypi.org/project/apify-haystack) is automated through GitHub Actions.
|
|
44
|
+
|
|
45
|
+
- **Beta releases**: On each commit to the main branch, a new beta release is automatically published. The version number is determined based on the latest release and conventional commits. The beta version suffix is incremented by 1 from the last beta release on PyPI.
|
|
46
|
+
- **Stable releases**: A stable version release may be created by triggering the `Stable release` GitHub Actions workflow. The version number is determined based on the latest release and conventional commits (`auto` release type), or it may be overridden using the `custom` release type.
|
|
47
|
+
|
|
48
|
+
### Publishing to PyPI manually
|
|
49
|
+
|
|
50
|
+
1. **Do not do this unless absolutely necessary.** In all conceivable scenarios, you should use the `Stable release` workflow instead.
|
|
51
|
+
2. **Make sure you know what you're doing.**
|
|
52
|
+
3. Update the version number by modifying the `version` field under `project` in `pyproject.toml`:
|
|
53
|
+
|
|
54
|
+
```toml
|
|
55
|
+
[project]
|
|
56
|
+
name = "apify_haystack"
|
|
57
|
+
version = "x.z.y"
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
4. Build the package:
|
|
61
|
+
|
|
62
|
+
```sh
|
|
63
|
+
uv run poe build
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
5. Upload to PyPI:
|
|
67
|
+
|
|
68
|
+
```sh
|
|
69
|
+
uv publish --token YOUR_API_TOKEN
|
|
70
|
+
```
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: apify_haystack
|
|
3
|
+
Version: 0.1.8b2
|
|
4
|
+
Summary: Apify-haystack integration
|
|
5
|
+
Keywords: apify,crawler,haystack,rag,scraper,scraping
|
|
6
|
+
Author: Apify Technologies s.r.o.
|
|
7
|
+
Author-email: Apify Technologies s.r.o. <support@apify.com>
|
|
8
|
+
License-Expression: Apache-2.0
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: Operating System :: OS Independent
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
17
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
18
|
+
Classifier: Typing :: Typed
|
|
19
|
+
Requires-Dist: apify-client>=3.3.0,<4.0.0
|
|
20
|
+
Requires-Dist: haystack-ai>=3.0.0,<4.0.0
|
|
21
|
+
Requires-Python: >=3.11
|
|
22
|
+
Project-URL: Homepage, https://apify.com
|
|
23
|
+
Project-URL: Changelog, https://github.com/apify/apify-haystack/blob/main/CHANGELOG.md
|
|
24
|
+
Project-URL: Documentation, https://docs.apify.com/platform/integrations/haystack
|
|
25
|
+
Project-URL: Issue Tracker, https://github.com/apify/apify-haystack/issues
|
|
26
|
+
Project-URL: Repository, https://github.com/apify/apify-haystack
|
|
27
|
+
Description-Content-Type: text/markdown
|
|
28
|
+
|
|
29
|
+
# Apify-Haystack integration
|
|
30
|
+
|
|
31
|
+
[](https://github.com/apify/apify-haystack/blob/main/LICENSE)
|
|
32
|
+
[](https://badge.fury.io/py/apify-haystack)
|
|
33
|
+
[](https://pypi.org/project/apify-haystack)
|
|
34
|
+
|
|
35
|
+
The Apify-Haystack integration allows easy interaction between the [Apify](https://apify.com/) platform and [Haystack](https://haystack.deepset.ai/).
|
|
36
|
+
|
|
37
|
+
Apify is a platform for web scraping, data extraction, and web automation tasks.
|
|
38
|
+
It provides serverless applications called Actors for tasks like crawling websites and scraping Facebook, Instagram, and Google results.
|
|
39
|
+
|
|
40
|
+
Haystack offers an ecosystem of tools for building, managing, and deploying search engines and LLM applications.
|
|
41
|
+
|
|
42
|
+
## Installation
|
|
43
|
+
|
|
44
|
+
Apify-haystack is available as the [`apify-haystack`](https://pypi.org/project/apify-haystack/) package on PyPI. It requires Python 3.11 or newer and Haystack 3.
|
|
45
|
+
|
|
46
|
+
```sh
|
|
47
|
+
pip install apify-haystack
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Components
|
|
51
|
+
|
|
52
|
+
- `ApifyDatasetFromActorCall` runs an Actor, waits for it to finish, and loads its default dataset.
|
|
53
|
+
- `ApifyDatasetFromTaskCall` does the same for a saved Actor task.
|
|
54
|
+
- `ApifyDatasetLoader` loads an existing dataset by its ID.
|
|
55
|
+
- `ApifyWebSearch` searches the web with the [RAG Web Browser](https://apify.com/apify/rag-web-browser) Actor and returns the content of the top result pages.
|
|
56
|
+
- `ApifyActorTool` is a tool for Haystack Agents that runs any Actor and returns its dataset items. It takes its parameters from the Actor's input schema, and it marks the items it hands to the LLM as untrusted external content to guard against prompt injection.
|
|
57
|
+
|
|
58
|
+
The dataset components turn dataset items into Haystack `Document` objects with a mapping function. Without one, they use `default_dataset_mapping_function`, which takes the `markdown` or `text` of website and search Actors with the page `url`, `title`, and `description` as `meta`, and the whole item as JSON for other Actors. Every component also has `run_async`, which `Pipeline.run_async` uses to run it without blocking the event loop. When an Actor or task run finishes with any status other than `SUCCEEDED`, the component raises a `RuntimeError` instead of loading a partial dataset.
|
|
59
|
+
|
|
60
|
+
The components read your Apify API token from the `APIFY_TOKEN` environment variable, or from `APIFY_API_TOKEN` if `APIFY_TOKEN` isn't set. To pass the token differently, use a Haystack `Secret`, for example `apify_token=Secret.from_env_var('MY_APIFY_TOKEN')`.
|
|
61
|
+
|
|
62
|
+
## Examples
|
|
63
|
+
|
|
64
|
+
### Crawl a website using Apify's Website Content Crawler and convert it to Haystack Documents
|
|
65
|
+
|
|
66
|
+
You need an Apify account and API token to run this example.
|
|
67
|
+
You can start with a free account at [Apify](https://apify.com/) and get your [API token](https://docs.apify.com/platform/integrations/api).
|
|
68
|
+
|
|
69
|
+
In the example below, set the `APIFY_TOKEN` environment variable and run the script:
|
|
70
|
+
|
|
71
|
+
```python
|
|
72
|
+
from haystack import Document
|
|
73
|
+
|
|
74
|
+
from apify_haystack import ApifyDatasetFromActorCall
|
|
75
|
+
|
|
76
|
+
actor_id = 'apify/website-content-crawler'
|
|
77
|
+
run_input = {
|
|
78
|
+
'maxCrawlPages': 3, # limit the number of pages to crawl
|
|
79
|
+
'startUrls': [{'url': 'https://haystack.deepset.ai/'}],
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def dataset_mapping_function(dataset_item: dict) -> Document:
|
|
84
|
+
return Document(content=dataset_item.get('text'), meta={'url': dataset_item.get('url')})
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
actor = ApifyDatasetFromActorCall(
|
|
88
|
+
actor_id=actor_id, run_input=run_input, dataset_mapping_function=dataset_mapping_function
|
|
89
|
+
)
|
|
90
|
+
print(f'Calling the Apify Actor {actor_id}. Crawling will take some time.')
|
|
91
|
+
print('You can monitor the progress at: https://console.apify.com/actors/runs')
|
|
92
|
+
|
|
93
|
+
dataset = actor.run()['documents']
|
|
94
|
+
|
|
95
|
+
print(f'Loaded {len(dataset)} documents from the Apify Actor {actor_id}:')
|
|
96
|
+
for d in dataset:
|
|
97
|
+
print(d)
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Search the web
|
|
101
|
+
|
|
102
|
+
`ApifyWebSearch` returns the top result pages as Markdown `Document` objects, with the page `url`, `title`, and `description` in `meta`, and their URLs in `links`:
|
|
103
|
+
|
|
104
|
+
```python
|
|
105
|
+
from apify_haystack import ApifyWebSearch
|
|
106
|
+
|
|
107
|
+
search = ApifyWebSearch(top_k=3)
|
|
108
|
+
result = search.run(query='What is Haystack?')
|
|
109
|
+
|
|
110
|
+
for document in result['documents']:
|
|
111
|
+
print(document.meta['url'], document.meta['title'])
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### Give an Agent access to an Actor
|
|
115
|
+
|
|
116
|
+
`ApifyActorTool` lets a Haystack `Agent` run an Actor. Limit `dataset_items_limit` to keep the tool output within the model's context window. For pay-per-event Actors, `max_total_charge_usd` caps what each run the Agent starts can cost:
|
|
117
|
+
|
|
118
|
+
```python
|
|
119
|
+
from haystack.components.agents import Agent
|
|
120
|
+
from haystack.components.generators.chat import OpenAIChatGenerator
|
|
121
|
+
from haystack.dataclasses import ChatMessage
|
|
122
|
+
|
|
123
|
+
from apify_haystack import ApifyActorTool
|
|
124
|
+
|
|
125
|
+
tool = ApifyActorTool('apify/rag-web-browser', dataset_items_limit=3, max_total_charge_usd=0.5)
|
|
126
|
+
agent = Agent(chat_generator=OpenAIChatGenerator(), tools=[tool])
|
|
127
|
+
|
|
128
|
+
result = agent.run([ChatMessage.from_user('What is new in Haystack 3?')])
|
|
129
|
+
print(result['last_message'].text)
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### Save and load a pipeline
|
|
133
|
+
|
|
134
|
+
The components and the tool support Haystack serialization. The token is saved as the name of its environment variable, never as its value. Haystack 3 only loads classes and functions from trusted modules, so allow `apify_haystack` and the module with your mapping function:
|
|
135
|
+
|
|
136
|
+
```python
|
|
137
|
+
from haystack import Pipeline
|
|
138
|
+
|
|
139
|
+
yaml = pipeline.dumps()
|
|
140
|
+
restored = Pipeline.loads(yaml, allowed_modules=['apify_haystack', 'my_project.mapping'])
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### More examples
|
|
144
|
+
|
|
145
|
+
The [examples directory](https://github.com/apify/apify-haystack/tree/main/examples) has more examples:
|
|
146
|
+
|
|
147
|
+
- Load a dataset from Apify and convert it to a Haystack Document
|
|
148
|
+
- Call [Website Content Crawler](https://apify.com/apify/website-content-crawler) and convert the data into the Haystack Documents
|
|
149
|
+
- Crawl websites, retrieve text content, and store it in the `InMemoryDocumentStore`
|
|
150
|
+
- Retrieval-Augmented Generation (RAG): Extracting text from a website & question answering <a href="https://colab.research.google.com/github/deepset-ai/haystack-cookbook/blob/main/notebooks/apify_haystack_rag.ipynb" target="_parent"><img src="https://colab.research.google.com/assets/colab-badge.svg" alt="Open In Colab"/></a>
|
|
151
|
+
- Analyze your Instagram comments' vibe with Apify and Haystack <a href="https://colab.research.google.com/github/deepset-ai/haystack-cookbook/blob/main/notebooks/apify_haystack_instagram_comments_analysis.ipynb" target="_parent"><img src="https://colab.research.google.com/assets/colab-badge.svg" alt="Open In Colab"/></a>
|
|
152
|
+
|
|
153
|
+
## Support
|
|
154
|
+
|
|
155
|
+
If you find any bug or issue, please [submit an issue on GitHub](https://github.com/apify/apify-haystack/issues).
|
|
156
|
+
For questions, you can ask on [Stack Overflow](https://stackoverflow.com/questions/tagged/apify), in GitHub Discussions or you can join our [Discord server](https://discord.com/invite/jyEM2PRvMU).
|
|
157
|
+
|
|
158
|
+
## Contributing
|
|
159
|
+
|
|
160
|
+
Code contributions are welcome.
|
|
161
|
+
If you have ideas for improvements, submit an issue or create a pull request.
|
|
162
|
+
For contribution guidelines, see [CONTRIBUTING.md](https://github.com/apify/apify-haystack/blob/main/CONTRIBUTING.md).
|
|
163
|
+
|
|
164
|
+
## License
|
|
165
|
+
|
|
166
|
+
This project is licensed under the Apache License 2.0 - see the [LICENSE](https://github.com/apify/apify-haystack/blob/main/LICENSE) file for details.
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
# Apify-Haystack integration
|
|
2
|
+
|
|
3
|
+
[](https://github.com/apify/apify-haystack/blob/main/LICENSE)
|
|
4
|
+
[](https://badge.fury.io/py/apify-haystack)
|
|
5
|
+
[](https://pypi.org/project/apify-haystack)
|
|
6
|
+
|
|
7
|
+
The Apify-Haystack integration allows easy interaction between the [Apify](https://apify.com/) platform and [Haystack](https://haystack.deepset.ai/).
|
|
8
|
+
|
|
9
|
+
Apify is a platform for web scraping, data extraction, and web automation tasks.
|
|
10
|
+
It provides serverless applications called Actors for tasks like crawling websites and scraping Facebook, Instagram, and Google results.
|
|
11
|
+
|
|
12
|
+
Haystack offers an ecosystem of tools for building, managing, and deploying search engines and LLM applications.
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
Apify-haystack is available as the [`apify-haystack`](https://pypi.org/project/apify-haystack/) package on PyPI. It requires Python 3.11 or newer and Haystack 3.
|
|
17
|
+
|
|
18
|
+
```sh
|
|
19
|
+
pip install apify-haystack
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Components
|
|
23
|
+
|
|
24
|
+
- `ApifyDatasetFromActorCall` runs an Actor, waits for it to finish, and loads its default dataset.
|
|
25
|
+
- `ApifyDatasetFromTaskCall` does the same for a saved Actor task.
|
|
26
|
+
- `ApifyDatasetLoader` loads an existing dataset by its ID.
|
|
27
|
+
- `ApifyWebSearch` searches the web with the [RAG Web Browser](https://apify.com/apify/rag-web-browser) Actor and returns the content of the top result pages.
|
|
28
|
+
- `ApifyActorTool` is a tool for Haystack Agents that runs any Actor and returns its dataset items. It takes its parameters from the Actor's input schema, and it marks the items it hands to the LLM as untrusted external content to guard against prompt injection.
|
|
29
|
+
|
|
30
|
+
The dataset components turn dataset items into Haystack `Document` objects with a mapping function. Without one, they use `default_dataset_mapping_function`, which takes the `markdown` or `text` of website and search Actors with the page `url`, `title`, and `description` as `meta`, and the whole item as JSON for other Actors. Every component also has `run_async`, which `Pipeline.run_async` uses to run it without blocking the event loop. When an Actor or task run finishes with any status other than `SUCCEEDED`, the component raises a `RuntimeError` instead of loading a partial dataset.
|
|
31
|
+
|
|
32
|
+
The components read your Apify API token from the `APIFY_TOKEN` environment variable, or from `APIFY_API_TOKEN` if `APIFY_TOKEN` isn't set. To pass the token differently, use a Haystack `Secret`, for example `apify_token=Secret.from_env_var('MY_APIFY_TOKEN')`.
|
|
33
|
+
|
|
34
|
+
## Examples
|
|
35
|
+
|
|
36
|
+
### Crawl a website using Apify's Website Content Crawler and convert it to Haystack Documents
|
|
37
|
+
|
|
38
|
+
You need an Apify account and API token to run this example.
|
|
39
|
+
You can start with a free account at [Apify](https://apify.com/) and get your [API token](https://docs.apify.com/platform/integrations/api).
|
|
40
|
+
|
|
41
|
+
In the example below, set the `APIFY_TOKEN` environment variable and run the script:
|
|
42
|
+
|
|
43
|
+
```python
|
|
44
|
+
from haystack import Document
|
|
45
|
+
|
|
46
|
+
from apify_haystack import ApifyDatasetFromActorCall
|
|
47
|
+
|
|
48
|
+
actor_id = 'apify/website-content-crawler'
|
|
49
|
+
run_input = {
|
|
50
|
+
'maxCrawlPages': 3, # limit the number of pages to crawl
|
|
51
|
+
'startUrls': [{'url': 'https://haystack.deepset.ai/'}],
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def dataset_mapping_function(dataset_item: dict) -> Document:
|
|
56
|
+
return Document(content=dataset_item.get('text'), meta={'url': dataset_item.get('url')})
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
actor = ApifyDatasetFromActorCall(
|
|
60
|
+
actor_id=actor_id, run_input=run_input, dataset_mapping_function=dataset_mapping_function
|
|
61
|
+
)
|
|
62
|
+
print(f'Calling the Apify Actor {actor_id}. Crawling will take some time.')
|
|
63
|
+
print('You can monitor the progress at: https://console.apify.com/actors/runs')
|
|
64
|
+
|
|
65
|
+
dataset = actor.run()['documents']
|
|
66
|
+
|
|
67
|
+
print(f'Loaded {len(dataset)} documents from the Apify Actor {actor_id}:')
|
|
68
|
+
for d in dataset:
|
|
69
|
+
print(d)
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### Search the web
|
|
73
|
+
|
|
74
|
+
`ApifyWebSearch` returns the top result pages as Markdown `Document` objects, with the page `url`, `title`, and `description` in `meta`, and their URLs in `links`:
|
|
75
|
+
|
|
76
|
+
```python
|
|
77
|
+
from apify_haystack import ApifyWebSearch
|
|
78
|
+
|
|
79
|
+
search = ApifyWebSearch(top_k=3)
|
|
80
|
+
result = search.run(query='What is Haystack?')
|
|
81
|
+
|
|
82
|
+
for document in result['documents']:
|
|
83
|
+
print(document.meta['url'], document.meta['title'])
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### Give an Agent access to an Actor
|
|
87
|
+
|
|
88
|
+
`ApifyActorTool` lets a Haystack `Agent` run an Actor. Limit `dataset_items_limit` to keep the tool output within the model's context window. For pay-per-event Actors, `max_total_charge_usd` caps what each run the Agent starts can cost:
|
|
89
|
+
|
|
90
|
+
```python
|
|
91
|
+
from haystack.components.agents import Agent
|
|
92
|
+
from haystack.components.generators.chat import OpenAIChatGenerator
|
|
93
|
+
from haystack.dataclasses import ChatMessage
|
|
94
|
+
|
|
95
|
+
from apify_haystack import ApifyActorTool
|
|
96
|
+
|
|
97
|
+
tool = ApifyActorTool('apify/rag-web-browser', dataset_items_limit=3, max_total_charge_usd=0.5)
|
|
98
|
+
agent = Agent(chat_generator=OpenAIChatGenerator(), tools=[tool])
|
|
99
|
+
|
|
100
|
+
result = agent.run([ChatMessage.from_user('What is new in Haystack 3?')])
|
|
101
|
+
print(result['last_message'].text)
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Save and load a pipeline
|
|
105
|
+
|
|
106
|
+
The components and the tool support Haystack serialization. The token is saved as the name of its environment variable, never as its value. Haystack 3 only loads classes and functions from trusted modules, so allow `apify_haystack` and the module with your mapping function:
|
|
107
|
+
|
|
108
|
+
```python
|
|
109
|
+
from haystack import Pipeline
|
|
110
|
+
|
|
111
|
+
yaml = pipeline.dumps()
|
|
112
|
+
restored = Pipeline.loads(yaml, allowed_modules=['apify_haystack', 'my_project.mapping'])
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### More examples
|
|
116
|
+
|
|
117
|
+
The [examples directory](https://github.com/apify/apify-haystack/tree/main/examples) has more examples:
|
|
118
|
+
|
|
119
|
+
- Load a dataset from Apify and convert it to a Haystack Document
|
|
120
|
+
- Call [Website Content Crawler](https://apify.com/apify/website-content-crawler) and convert the data into the Haystack Documents
|
|
121
|
+
- Crawl websites, retrieve text content, and store it in the `InMemoryDocumentStore`
|
|
122
|
+
- Retrieval-Augmented Generation (RAG): Extracting text from a website & question answering <a href="https://colab.research.google.com/github/deepset-ai/haystack-cookbook/blob/main/notebooks/apify_haystack_rag.ipynb" target="_parent"><img src="https://colab.research.google.com/assets/colab-badge.svg" alt="Open In Colab"/></a>
|
|
123
|
+
- Analyze your Instagram comments' vibe with Apify and Haystack <a href="https://colab.research.google.com/github/deepset-ai/haystack-cookbook/blob/main/notebooks/apify_haystack_instagram_comments_analysis.ipynb" target="_parent"><img src="https://colab.research.google.com/assets/colab-badge.svg" alt="Open In Colab"/></a>
|
|
124
|
+
|
|
125
|
+
## Support
|
|
126
|
+
|
|
127
|
+
If you find any bug or issue, please [submit an issue on GitHub](https://github.com/apify/apify-haystack/issues).
|
|
128
|
+
For questions, you can ask on [Stack Overflow](https://stackoverflow.com/questions/tagged/apify), in GitHub Discussions or you can join our [Discord server](https://discord.com/invite/jyEM2PRvMU).
|
|
129
|
+
|
|
130
|
+
## Contributing
|
|
131
|
+
|
|
132
|
+
Code contributions are welcome.
|
|
133
|
+
If you have ideas for improvements, submit an issue or create a pull request.
|
|
134
|
+
For contribution guidelines, see [CONTRIBUTING.md](https://github.com/apify/apify-haystack/blob/main/CONTRIBUTING.md).
|
|
135
|
+
|
|
136
|
+
## License
|
|
137
|
+
|
|
138
|
+
This project is licensed under the Apache License 2.0 - see the [LICENSE](https://github.com/apify/apify-haystack/blob/main/LICENSE) file for details.
|