apify-haystack 0.1.8b3__tar.gz → 1.0.1__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.8b3 → apify_haystack-1.0.1}/CHANGELOG.md +9 -3
- apify_haystack-1.0.1/PKG-INFO +172 -0
- apify_haystack-1.0.1/README.md +143 -0
- {apify_haystack-0.1.8b3 → apify_haystack-1.0.1}/pyproject.toml +6 -2
- {apify_haystack-0.1.8b3 → apify_haystack-1.0.1}/pyproject.toml.orig +4 -3
- {apify_haystack-0.1.8b3 → apify_haystack-1.0.1}/src/apify_haystack/_dataset.py +18 -17
- apify_haystack-0.1.8b3/PKG-INFO +0 -166
- apify_haystack-0.1.8b3/README.md +0 -138
- {apify_haystack-0.1.8b3 → apify_haystack-1.0.1}/CONTRIBUTING.md +0 -0
- {apify_haystack-0.1.8b3 → apify_haystack-1.0.1}/LICENSE +0 -0
- {apify_haystack-0.1.8b3 → apify_haystack-1.0.1}/src/apify_haystack/__init__.py +0 -0
- {apify_haystack-0.1.8b3 → apify_haystack-1.0.1}/src/apify_haystack/_actor_tool.py +0 -0
- {apify_haystack-0.1.8b3 → apify_haystack-1.0.1}/src/apify_haystack/_client.py +0 -0
- {apify_haystack-0.1.8b3 → apify_haystack-1.0.1}/src/apify_haystack/_constants.py +0 -0
- {apify_haystack-0.1.8b3 → apify_haystack-1.0.1}/src/apify_haystack/_web_search.py +0 -0
- {apify_haystack-0.1.8b3 → apify_haystack-1.0.1}/src/apify_haystack/py.typed +0 -0
|
@@ -2,8 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
## [1.0.1](https://github.com/apify/apify-haystack/releases/tag/v1.0.1) (2026-10-29)
|
|
6
|
+
|
|
7
|
+
### 🐛 Bug Fixes
|
|
8
|
+
|
|
9
|
+
- Allow running Actors and tasks without input ([#84](https://github.com/apify/apify-haystack/pull/84)) ([3036312](https://github.com/apify/apify-haystack/commit/3036312e567dc513529e1d822db009b44ca97041)) by [@vdusek](https://github.com/vdusek)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
## [1.0.0](https://github.com/apify/apify-haystack/releases/tag/v1.0.0) (2026-10-27)
|
|
7
13
|
|
|
8
14
|
### 🚀 Features
|
|
9
15
|
|
|
@@ -19,6 +25,7 @@ All notable changes to this project will be documented in this file.
|
|
|
19
25
|
- 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
26
|
- 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
27
|
- 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)
|
|
28
|
+
- Add support for Python 3.15 ([#37](https://github.com/apify/apify-haystack/pull/37)) ([9a1856e](https://github.com/apify/apify-haystack/commit/9a1856e3a57dd36fc1e528392dc64f089a1d4e33)) by [@vdusek](https://github.com/vdusek)
|
|
22
29
|
|
|
23
30
|
### 🐛 Bug Fixes
|
|
24
31
|
|
|
@@ -37,7 +44,6 @@ All notable changes to this project will be documented in this file.
|
|
|
37
44
|
- [**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
45
|
|
|
39
46
|
|
|
40
|
-
<!-- git-cliff-unreleased-end -->
|
|
41
47
|
# Changelog
|
|
42
48
|
|
|
43
49
|
## [0.1.7](https://github.com/apify/apify-haystack/releases/tag/0.1.7) (2024-12-09)
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: apify_haystack
|
|
3
|
+
Version: 1.0.1
|
|
4
|
+
Summary: Apify integration for Haystack: load Actor results as Documents, search the web, and give Agents access to Apify Actors.
|
|
5
|
+
Keywords: agents,apify,crawler,haystack,llm,rag,scraper,scraping,web-search
|
|
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: Programming Language :: Python :: 3.15
|
|
18
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
19
|
+
Classifier: Typing :: Typed
|
|
20
|
+
Requires-Dist: apify-client>=3.4.0,<4.0.0
|
|
21
|
+
Requires-Dist: haystack-ai>=3.0.0,<4.0.0
|
|
22
|
+
Requires-Python: >=3.11
|
|
23
|
+
Project-URL: Homepage, https://apify.com
|
|
24
|
+
Project-URL: Changelog, https://github.com/apify/apify-haystack/blob/main/CHANGELOG.md
|
|
25
|
+
Project-URL: Documentation, https://docs.apify.com/platform/integrations/haystack
|
|
26
|
+
Project-URL: Issue Tracker, https://github.com/apify/apify-haystack/issues
|
|
27
|
+
Project-URL: Repository, https://github.com/apify/apify-haystack
|
|
28
|
+
Description-Content-Type: text/markdown
|
|
29
|
+
|
|
30
|
+
<h1 align="center">Apify-Haystack integration</h1>
|
|
31
|
+
|
|
32
|
+
<p align="center">
|
|
33
|
+
<strong>The official integration of the <a href="https://apify.com/">Apify</a> platform with <a href="https://haystack.deepset.ai/">Haystack</a>.</strong>
|
|
34
|
+
</p>
|
|
35
|
+
|
|
36
|
+
<p align="center">
|
|
37
|
+
<a href="https://pypi.org/project/apify-haystack/"><img src="https://badge.fury.io/py/apify-haystack.svg" alt="PyPI version"></a>
|
|
38
|
+
<a href="https://pypi.org/project/apify-haystack/"><img src="https://img.shields.io/pypi/dm/apify-haystack" alt="PyPI downloads"></a>
|
|
39
|
+
<a href="https://pypi.org/project/apify-haystack/"><img src="https://img.shields.io/badge/python-3.11%2B-blue" alt="Python versions"></a>
|
|
40
|
+
<a href="https://github.com/apify/apify-haystack/actions/workflows/on_main.yaml"><img src="https://github.com/apify/apify-haystack/actions/workflows/on_main.yaml/badge.svg?branch=main" alt="Build status"></a>
|
|
41
|
+
<a href="https://github.com/apify/apify-haystack/blob/main/LICENSE"><img src="https://img.shields.io/pypi/l/apify-haystack" alt="License"></a>
|
|
42
|
+
<a href="https://discord.gg/jyEM2PRvMU"><img src="https://img.shields.io/discord/801163717915574323?label=discord" alt="Chat on Discord"></a>
|
|
43
|
+
</p>
|
|
44
|
+
|
|
45
|
+
Apify is a platform for web scraping, data extraction, and web automation tasks.
|
|
46
|
+
It provides serverless applications called Actors for tasks like crawling websites and scraping Facebook, Instagram, and Google results.
|
|
47
|
+
|
|
48
|
+
Haystack is an open-source framework for building LLM applications, RAG pipelines, and agents.
|
|
49
|
+
|
|
50
|
+
For a step-by-step guide, see the [Haystack integration](https://docs.apify.com/platform/integrations/haystack) page in the Apify documentation.
|
|
51
|
+
|
|
52
|
+
## Installation
|
|
53
|
+
|
|
54
|
+
The integration 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.
|
|
55
|
+
|
|
56
|
+
```sh
|
|
57
|
+
pip install apify-haystack
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Upgrading from 0.1.x? See [UPGRADING.md](https://github.com/apify/apify-haystack/blob/main/UPGRADING.md).
|
|
61
|
+
|
|
62
|
+
## Components
|
|
63
|
+
|
|
64
|
+
- `ApifyDatasetFromActorCall` runs an Actor, waits for it to finish, and loads its default dataset.
|
|
65
|
+
- `ApifyDatasetFromTaskCall` does the same for a saved Actor task.
|
|
66
|
+
- `ApifyDatasetLoader` loads an existing dataset by its ID.
|
|
67
|
+
- `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.
|
|
68
|
+
- `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.
|
|
69
|
+
|
|
70
|
+
The dataset components turn dataset items into Haystack `Document` objects with a mapping function. Without one, they use `default_dataset_mapping_function`. For website and search Actors, it takes the item's `markdown` or `text` as the content and the page `url`, `title`, and `description` as `meta`. For other Actors, the content is the whole item as JSON.
|
|
71
|
+
|
|
72
|
+
Every component also has `run_async`, which `Pipeline.run_async` uses to run it without blocking the event loop.
|
|
73
|
+
|
|
74
|
+
When an Actor or task run finishes with any status other than `SUCCEEDED`, the component raises a `RuntimeError`.
|
|
75
|
+
|
|
76
|
+
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')`.
|
|
77
|
+
|
|
78
|
+
## Examples
|
|
79
|
+
|
|
80
|
+
The examples need an Apify account and API token. You can start with a free account at [Apify](https://apify.com/) and get your [API token](https://docs.apify.com/platform/integrations/api), then set it as the `APIFY_TOKEN` environment variable.
|
|
81
|
+
|
|
82
|
+
### Crawl a website and load it as Documents
|
|
83
|
+
|
|
84
|
+
`ApifyDatasetFromActorCall` runs [Website Content Crawler](https://apify.com/apify/website-content-crawler) and loads the crawled pages as `Document` objects with the default mapping function:
|
|
85
|
+
|
|
86
|
+
```python
|
|
87
|
+
from apify_haystack import ApifyDatasetFromActorCall
|
|
88
|
+
|
|
89
|
+
crawler = ApifyDatasetFromActorCall(
|
|
90
|
+
actor_id='apify/website-content-crawler',
|
|
91
|
+
run_input={
|
|
92
|
+
'maxCrawlPages': 3,
|
|
93
|
+
'startUrls': [{'url': 'https://haystack.deepset.ai/'}],
|
|
94
|
+
},
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
for document in crawler.run()['documents']:
|
|
98
|
+
print(document.meta['url'], document.content[:100])
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### Search the web
|
|
102
|
+
|
|
103
|
+
`ApifyWebSearch` returns the top result pages as Markdown `Document` objects, with the page `url`, `title`, and `description` in `meta`, and their URLs in `links`:
|
|
104
|
+
|
|
105
|
+
```python
|
|
106
|
+
from apify_haystack import ApifyWebSearch
|
|
107
|
+
|
|
108
|
+
search = ApifyWebSearch(top_k=3)
|
|
109
|
+
result = search.run(query='What is Haystack?')
|
|
110
|
+
|
|
111
|
+
for document in result['documents']:
|
|
112
|
+
print(document.meta['url'], document.meta['title'])
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### Give an Agent access to an Actor
|
|
116
|
+
|
|
117
|
+
`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:
|
|
118
|
+
|
|
119
|
+
```python
|
|
120
|
+
from haystack.components.agents import Agent
|
|
121
|
+
from haystack.components.generators.chat import OpenAIChatGenerator
|
|
122
|
+
from haystack.dataclasses import ChatMessage
|
|
123
|
+
|
|
124
|
+
from apify_haystack import ApifyActorTool
|
|
125
|
+
|
|
126
|
+
tool = ApifyActorTool('apify/rag-web-browser', dataset_items_limit=3, max_total_charge_usd=0.5)
|
|
127
|
+
agent = Agent(chat_generator=OpenAIChatGenerator(), tools=[tool])
|
|
128
|
+
|
|
129
|
+
result = agent.run([ChatMessage.from_user('What is new in Haystack 3?')])
|
|
130
|
+
print(result['last_message'].text)
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### Save and load a pipeline
|
|
134
|
+
|
|
135
|
+
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 pass `apify_haystack` in `allowed_modules`, along with the module of your mapping function if you use a custom one:
|
|
136
|
+
|
|
137
|
+
```python
|
|
138
|
+
from haystack import Pipeline
|
|
139
|
+
|
|
140
|
+
from apify_haystack import ApifyDatasetLoader
|
|
141
|
+
|
|
142
|
+
pipeline = Pipeline()
|
|
143
|
+
pipeline.add_component('loader', ApifyDatasetLoader('YOUR-DATASET-ID'))
|
|
144
|
+
|
|
145
|
+
yaml = pipeline.dumps()
|
|
146
|
+
restored = Pipeline.loads(yaml, allowed_modules=['apify_haystack'])
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### More examples
|
|
150
|
+
|
|
151
|
+
The [examples directory](https://github.com/apify/apify-haystack/tree/main/examples) has complete scripts:
|
|
152
|
+
|
|
153
|
+
- [Load an existing dataset](https://github.com/apify/apify-haystack/blob/main/examples/apify_dataset_load.py) and convert its items to Documents.
|
|
154
|
+
- [Call Website Content Crawler](https://github.com/apify/apify-haystack/blob/main/examples/apify_actor_call.py) with a custom mapping function.
|
|
155
|
+
- [Crawl a website, store the pages in `InMemoryDocumentStore`, and retrieve them](https://github.com/apify/apify-haystack/blob/main/examples/crawl_and_process_data.py).
|
|
156
|
+
- [Answer questions about a crawled website with RAG](https://github.com/apify/apify-haystack/blob/main/examples/rag_with_crawled_website.py). <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>
|
|
157
|
+
- [Analyze the sentiment of Instagram comments](https://github.com/apify/apify-haystack/blob/main/examples/instagram_comments_analysis.py). <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>
|
|
158
|
+
|
|
159
|
+
## Support
|
|
160
|
+
|
|
161
|
+
If you find a bug, please [submit an issue on GitHub](https://github.com/apify/apify-haystack/issues).
|
|
162
|
+
For questions, ask on [Stack Overflow](https://stackoverflow.com/questions/tagged/apify) or join our [Discord server](https://discord.com/invite/jyEM2PRvMU).
|
|
163
|
+
|
|
164
|
+
## Contributing
|
|
165
|
+
|
|
166
|
+
Code contributions are welcome.
|
|
167
|
+
If you have ideas for improvements, submit an issue or create a pull request.
|
|
168
|
+
For contribution guidelines, see [CONTRIBUTING.md](https://github.com/apify/apify-haystack/blob/main/CONTRIBUTING.md).
|
|
169
|
+
|
|
170
|
+
## License
|
|
171
|
+
|
|
172
|
+
This project is licensed under the [Apache License 2.0](https://github.com/apify/apify-haystack/blob/main/LICENSE).
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
<h1 align="center">Apify-Haystack integration</h1>
|
|
2
|
+
|
|
3
|
+
<p align="center">
|
|
4
|
+
<strong>The official integration of the <a href="https://apify.com/">Apify</a> platform with <a href="https://haystack.deepset.ai/">Haystack</a>.</strong>
|
|
5
|
+
</p>
|
|
6
|
+
|
|
7
|
+
<p align="center">
|
|
8
|
+
<a href="https://pypi.org/project/apify-haystack/"><img src="https://badge.fury.io/py/apify-haystack.svg" alt="PyPI version"></a>
|
|
9
|
+
<a href="https://pypi.org/project/apify-haystack/"><img src="https://img.shields.io/pypi/dm/apify-haystack" alt="PyPI downloads"></a>
|
|
10
|
+
<a href="https://pypi.org/project/apify-haystack/"><img src="https://img.shields.io/badge/python-3.11%2B-blue" alt="Python versions"></a>
|
|
11
|
+
<a href="https://github.com/apify/apify-haystack/actions/workflows/on_main.yaml"><img src="https://github.com/apify/apify-haystack/actions/workflows/on_main.yaml/badge.svg?branch=main" alt="Build status"></a>
|
|
12
|
+
<a href="https://github.com/apify/apify-haystack/blob/main/LICENSE"><img src="https://img.shields.io/pypi/l/apify-haystack" alt="License"></a>
|
|
13
|
+
<a href="https://discord.gg/jyEM2PRvMU"><img src="https://img.shields.io/discord/801163717915574323?label=discord" alt="Chat on Discord"></a>
|
|
14
|
+
</p>
|
|
15
|
+
|
|
16
|
+
Apify is a platform for web scraping, data extraction, and web automation tasks.
|
|
17
|
+
It provides serverless applications called Actors for tasks like crawling websites and scraping Facebook, Instagram, and Google results.
|
|
18
|
+
|
|
19
|
+
Haystack is an open-source framework for building LLM applications, RAG pipelines, and agents.
|
|
20
|
+
|
|
21
|
+
For a step-by-step guide, see the [Haystack integration](https://docs.apify.com/platform/integrations/haystack) page in the Apify documentation.
|
|
22
|
+
|
|
23
|
+
## Installation
|
|
24
|
+
|
|
25
|
+
The integration 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.
|
|
26
|
+
|
|
27
|
+
```sh
|
|
28
|
+
pip install apify-haystack
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Upgrading from 0.1.x? See [UPGRADING.md](https://github.com/apify/apify-haystack/blob/main/UPGRADING.md).
|
|
32
|
+
|
|
33
|
+
## Components
|
|
34
|
+
|
|
35
|
+
- `ApifyDatasetFromActorCall` runs an Actor, waits for it to finish, and loads its default dataset.
|
|
36
|
+
- `ApifyDatasetFromTaskCall` does the same for a saved Actor task.
|
|
37
|
+
- `ApifyDatasetLoader` loads an existing dataset by its ID.
|
|
38
|
+
- `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.
|
|
39
|
+
- `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.
|
|
40
|
+
|
|
41
|
+
The dataset components turn dataset items into Haystack `Document` objects with a mapping function. Without one, they use `default_dataset_mapping_function`. For website and search Actors, it takes the item's `markdown` or `text` as the content and the page `url`, `title`, and `description` as `meta`. For other Actors, the content is the whole item as JSON.
|
|
42
|
+
|
|
43
|
+
Every component also has `run_async`, which `Pipeline.run_async` uses to run it without blocking the event loop.
|
|
44
|
+
|
|
45
|
+
When an Actor or task run finishes with any status other than `SUCCEEDED`, the component raises a `RuntimeError`.
|
|
46
|
+
|
|
47
|
+
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')`.
|
|
48
|
+
|
|
49
|
+
## Examples
|
|
50
|
+
|
|
51
|
+
The examples need an Apify account and API token. You can start with a free account at [Apify](https://apify.com/) and get your [API token](https://docs.apify.com/platform/integrations/api), then set it as the `APIFY_TOKEN` environment variable.
|
|
52
|
+
|
|
53
|
+
### Crawl a website and load it as Documents
|
|
54
|
+
|
|
55
|
+
`ApifyDatasetFromActorCall` runs [Website Content Crawler](https://apify.com/apify/website-content-crawler) and loads the crawled pages as `Document` objects with the default mapping function:
|
|
56
|
+
|
|
57
|
+
```python
|
|
58
|
+
from apify_haystack import ApifyDatasetFromActorCall
|
|
59
|
+
|
|
60
|
+
crawler = ApifyDatasetFromActorCall(
|
|
61
|
+
actor_id='apify/website-content-crawler',
|
|
62
|
+
run_input={
|
|
63
|
+
'maxCrawlPages': 3,
|
|
64
|
+
'startUrls': [{'url': 'https://haystack.deepset.ai/'}],
|
|
65
|
+
},
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
for document in crawler.run()['documents']:
|
|
69
|
+
print(document.meta['url'], document.content[:100])
|
|
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 pass `apify_haystack` in `allowed_modules`, along with the module of your mapping function if you use a custom one:
|
|
107
|
+
|
|
108
|
+
```python
|
|
109
|
+
from haystack import Pipeline
|
|
110
|
+
|
|
111
|
+
from apify_haystack import ApifyDatasetLoader
|
|
112
|
+
|
|
113
|
+
pipeline = Pipeline()
|
|
114
|
+
pipeline.add_component('loader', ApifyDatasetLoader('YOUR-DATASET-ID'))
|
|
115
|
+
|
|
116
|
+
yaml = pipeline.dumps()
|
|
117
|
+
restored = Pipeline.loads(yaml, allowed_modules=['apify_haystack'])
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### More examples
|
|
121
|
+
|
|
122
|
+
The [examples directory](https://github.com/apify/apify-haystack/tree/main/examples) has complete scripts:
|
|
123
|
+
|
|
124
|
+
- [Load an existing dataset](https://github.com/apify/apify-haystack/blob/main/examples/apify_dataset_load.py) and convert its items to Documents.
|
|
125
|
+
- [Call Website Content Crawler](https://github.com/apify/apify-haystack/blob/main/examples/apify_actor_call.py) with a custom mapping function.
|
|
126
|
+
- [Crawl a website, store the pages in `InMemoryDocumentStore`, and retrieve them](https://github.com/apify/apify-haystack/blob/main/examples/crawl_and_process_data.py).
|
|
127
|
+
- [Answer questions about a crawled website with RAG](https://github.com/apify/apify-haystack/blob/main/examples/rag_with_crawled_website.py). <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>
|
|
128
|
+
- [Analyze the sentiment of Instagram comments](https://github.com/apify/apify-haystack/blob/main/examples/instagram_comments_analysis.py). <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>
|
|
129
|
+
|
|
130
|
+
## Support
|
|
131
|
+
|
|
132
|
+
If you find a bug, please [submit an issue on GitHub](https://github.com/apify/apify-haystack/issues).
|
|
133
|
+
For questions, ask on [Stack Overflow](https://stackoverflow.com/questions/tagged/apify) or join our [Discord server](https://discord.com/invite/jyEM2PRvMU).
|
|
134
|
+
|
|
135
|
+
## Contributing
|
|
136
|
+
|
|
137
|
+
Code contributions are welcome.
|
|
138
|
+
If you have ideas for improvements, submit an issue or create a pull request.
|
|
139
|
+
For contribution guidelines, see [CONTRIBUTING.md](https://github.com/apify/apify-haystack/blob/main/CONTRIBUTING.md).
|
|
140
|
+
|
|
141
|
+
## License
|
|
142
|
+
|
|
143
|
+
This project is licensed under the [Apache License 2.0](https://github.com/apify/apify-haystack/blob/main/LICENSE).
|
|
@@ -4,8 +4,8 @@ build-backend = "uv_build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "apify_haystack"
|
|
7
|
-
version = "0.1
|
|
8
|
-
description = "Apify
|
|
7
|
+
version = "1.0.1"
|
|
8
|
+
description = "Apify integration for Haystack: load Actor results as Documents, search the web, and give Agents access to Apify Actors."
|
|
9
9
|
license = "Apache-2.0"
|
|
10
10
|
license-files = ["LICENSE"]
|
|
11
11
|
readme = "README.md"
|
|
@@ -18,16 +18,20 @@ classifiers = [
|
|
|
18
18
|
"Programming Language :: Python :: 3.12",
|
|
19
19
|
"Programming Language :: Python :: 3.13",
|
|
20
20
|
"Programming Language :: Python :: 3.14",
|
|
21
|
+
"Programming Language :: Python :: 3.15",
|
|
21
22
|
"Topic :: Software Development :: Libraries",
|
|
22
23
|
"Typing :: Typed",
|
|
23
24
|
]
|
|
24
25
|
keywords = [
|
|
26
|
+
"agents",
|
|
25
27
|
"apify",
|
|
26
28
|
"crawler",
|
|
27
29
|
"haystack",
|
|
30
|
+
"llm",
|
|
28
31
|
"rag",
|
|
29
32
|
"scraper",
|
|
30
33
|
"scraping",
|
|
34
|
+
"web-search",
|
|
31
35
|
]
|
|
32
36
|
dependencies = [
|
|
33
37
|
"apify-client>=3.4.0,<4.0.0",
|
|
@@ -4,8 +4,8 @@ build-backend = "uv_build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "apify_haystack"
|
|
7
|
-
version = "0.1
|
|
8
|
-
description = "Apify
|
|
7
|
+
version = "1.0.1"
|
|
8
|
+
description = "Apify integration for Haystack: load Actor results as Documents, search the web, and give Agents access to Apify Actors."
|
|
9
9
|
authors = [{ name = "Apify Technologies s.r.o.", email = "support@apify.com" }]
|
|
10
10
|
license = "Apache-2.0"
|
|
11
11
|
license-files = ["LICENSE"]
|
|
@@ -19,10 +19,11 @@ classifiers = [
|
|
|
19
19
|
"Programming Language :: Python :: 3.12",
|
|
20
20
|
"Programming Language :: Python :: 3.13",
|
|
21
21
|
"Programming Language :: Python :: 3.14",
|
|
22
|
+
"Programming Language :: Python :: 3.15",
|
|
22
23
|
"Topic :: Software Development :: Libraries",
|
|
23
24
|
"Typing :: Typed",
|
|
24
25
|
]
|
|
25
|
-
keywords = ["apify", "crawler", "haystack", "rag", "scraper", "scraping"]
|
|
26
|
+
keywords = ["agents", "apify", "crawler", "haystack", "llm", "rag", "scraper", "scraping", "web-search"]
|
|
26
27
|
dependencies = [
|
|
27
28
|
"apify-client>=3.4.0,<4.0.0",
|
|
28
29
|
"haystack-ai>=3.0.0,<4.0.0",
|
|
@@ -132,7 +132,8 @@ class ApifyDatasetFromActorCall(ApifyDatasetComponent):
|
|
|
132
132
|
`default_dataset_mapping_function`.
|
|
133
133
|
run_input (dict, optional): The input parameters for the Actor you want to run. This can be provided
|
|
134
134
|
either in the `run` method or during the class instantiation. If specified in both places,
|
|
135
|
-
the inputs are merged and the values from `run` take precedence.
|
|
135
|
+
the inputs are merged and the values from `run` take precedence. Without any input, the
|
|
136
|
+
Actor runs with its default input.
|
|
136
137
|
build (str, optional): Optionally specifies the Actor build to run.
|
|
137
138
|
It can be either a build tag or build number.
|
|
138
139
|
memory_mbytes (int, optional): Optional memory limit for the run, in megabytes.
|
|
@@ -160,7 +161,8 @@ class ApifyDatasetFromActorCall(ApifyDatasetComponent):
|
|
|
160
161
|
Args:
|
|
161
162
|
run_input (dict, optional): The input parameters for the Actor you want to run. This can be provided
|
|
162
163
|
either in the `run` method or during the class instantiation. If specified in both places,
|
|
163
|
-
the inputs are merged and the values from `run` take precedence.
|
|
164
|
+
the inputs are merged and the values from `run` take precedence. Without any input, the
|
|
165
|
+
Actor runs with its default input.
|
|
164
166
|
|
|
165
167
|
Example:
|
|
166
168
|
.. code-block:: python
|
|
@@ -172,8 +174,7 @@ class ApifyDatasetFromActorCall(ApifyDatasetComponent):
|
|
|
172
174
|
)
|
|
173
175
|
dataset = actor.run(run_input={"startUrls": [{"url": "https://haystack.deepset.ai/"}]})
|
|
174
176
|
"""
|
|
175
|
-
|
|
176
|
-
raise ValueError('Please provide the run_input either in the constructor or in the run method.')
|
|
177
|
+
run_input = _merge_inputs(self.run_input, run_input)
|
|
177
178
|
|
|
178
179
|
client = self._get_client()
|
|
179
180
|
run = client.actor(self.actor_id).call(
|
|
@@ -193,10 +194,10 @@ class ApifyDatasetFromActorCall(ApifyDatasetComponent):
|
|
|
193
194
|
Args:
|
|
194
195
|
run_input (dict, optional): The input parameters for the Actor you want to run. This can be provided
|
|
195
196
|
either in the `run_async` method or during the class instantiation. If specified in both places,
|
|
196
|
-
the inputs are merged and the values from `run_async` take precedence.
|
|
197
|
+
the inputs are merged and the values from `run_async` take precedence. Without any input, the
|
|
198
|
+
Actor runs with its default input.
|
|
197
199
|
"""
|
|
198
|
-
|
|
199
|
-
raise ValueError('Please provide the run_input either in the constructor or in the run method.')
|
|
200
|
+
run_input = _merge_inputs(self.run_input, run_input)
|
|
200
201
|
|
|
201
202
|
client = self._get_async_client()
|
|
202
203
|
run = await client.actor(self.actor_id).call(
|
|
@@ -260,7 +261,8 @@ class ApifyDatasetFromTaskCall(ApifyDatasetComponent):
|
|
|
260
261
|
`default_dataset_mapping_function`.
|
|
261
262
|
task_input (dict, optional): The input parameters for the task you want to run. This can be provided
|
|
262
263
|
either in the `run` method or during the class instantiation. If specified in both places,
|
|
263
|
-
the inputs are merged and the values from `run` take precedence.
|
|
264
|
+
the inputs are merged and the values from `run` take precedence. Without any input, the
|
|
265
|
+
task runs with its saved input.
|
|
264
266
|
build (str, optional): Optionally specifies the Actor build to run.
|
|
265
267
|
It can be either a build tag or build number.
|
|
266
268
|
memory_mbytes (int, optional): Optional memory limit for the run, in megabytes.
|
|
@@ -288,10 +290,10 @@ class ApifyDatasetFromTaskCall(ApifyDatasetComponent):
|
|
|
288
290
|
Args:
|
|
289
291
|
task_input (dict, optional): The input parameters for the task you want to run. This can be provided
|
|
290
292
|
either in the `run` method or during the class instantiation. If specified in both places,
|
|
291
|
-
the inputs are merged and the values from `run` take precedence.
|
|
293
|
+
the inputs are merged and the values from `run` take precedence. Without any input, the
|
|
294
|
+
task runs with its saved input.
|
|
292
295
|
"""
|
|
293
|
-
|
|
294
|
-
raise ValueError('Please provide the task_input either in the constructor or in the run method.')
|
|
296
|
+
task_input = _merge_inputs(self.task_input, task_input)
|
|
295
297
|
|
|
296
298
|
client = self._get_client()
|
|
297
299
|
run = client.task(self.task_id).call(
|
|
@@ -311,10 +313,10 @@ class ApifyDatasetFromTaskCall(ApifyDatasetComponent):
|
|
|
311
313
|
Args:
|
|
312
314
|
task_input (dict, optional): The input parameters for the task you want to run. This can be provided
|
|
313
315
|
either in the `run_async` method or during the class instantiation. If specified in both places,
|
|
314
|
-
the inputs are merged and the values from `run_async` take precedence.
|
|
316
|
+
the inputs are merged and the values from `run_async` take precedence. Without any input, the
|
|
317
|
+
task runs with its saved input.
|
|
315
318
|
"""
|
|
316
|
-
|
|
317
|
-
raise ValueError('Please provide the task_input either in the constructor or in the run method.')
|
|
319
|
+
task_input = _merge_inputs(self.task_input, task_input)
|
|
318
320
|
|
|
319
321
|
client = self._get_async_client()
|
|
320
322
|
run = await client.task(self.task_id).call(
|
|
@@ -375,9 +377,8 @@ def _serialize_mapping_function(dataset_mapping_function: Callable[[dict], Docum
|
|
|
375
377
|
|
|
376
378
|
|
|
377
379
|
def _merge_inputs(input1: dict | None, input2: dict | None) -> dict | None:
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
return input1 or input2
|
|
380
|
+
merged = (input1 or {}) | (input2 or {})
|
|
381
|
+
return merged or None
|
|
381
382
|
|
|
382
383
|
|
|
383
384
|
def _load_documents(
|
apify_haystack-0.1.8b3/PKG-INFO
DELETED
|
@@ -1,166 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: apify_haystack
|
|
3
|
-
Version: 0.1.8b3
|
|
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.4.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.
|
apify_haystack-0.1.8b3/README.md
DELETED
|
@@ -1,138 +0,0 @@
|
|
|
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.
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|