bigdata-smart-batching 1.2.1__tar.gz → 1.3.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.
Files changed (22) hide show
  1. {bigdata_smart_batching-1.2.1 → bigdata_smart_batching-1.3.1}/CHANGELOG.md +13 -0
  2. {bigdata_smart_batching-1.2.1 → bigdata_smart_batching-1.3.1}/PKG-INFO +45 -2
  3. {bigdata_smart_batching-1.2.1 → bigdata_smart_batching-1.3.1}/README.md +44 -1
  4. {bigdata_smart_batching-1.2.1 → bigdata_smart_batching-1.3.1}/examples/example.py +4 -3
  5. bigdata_smart_batching-1.3.1/plan.json +20473 -0
  6. {bigdata_smart_batching-1.2.1 → bigdata_smart_batching-1.3.1}/pyproject.toml +1 -1
  7. {bigdata_smart_batching-1.2.1 → bigdata_smart_batching-1.3.1}/src/bigdata_smart_batching/__init__.py +8 -0
  8. {bigdata_smart_batching-1.2.1 → bigdata_smart_batching-1.3.1}/src/bigdata_smart_batching/search_function.py +98 -2
  9. {bigdata_smart_batching-1.2.1 → bigdata_smart_batching-1.3.1}/src/bigdata_smart_batching/smart_batching.py +23 -0
  10. {bigdata_smart_batching-1.2.1 → bigdata_smart_batching-1.3.1}/tests/test_validation.py +63 -0
  11. {bigdata_smart_batching-1.2.1 → bigdata_smart_batching-1.3.1}/uv.lock +1 -1
  12. {bigdata_smart_batching-1.2.1 → bigdata_smart_batching-1.3.1}/.gitignore +0 -0
  13. {bigdata_smart_batching-1.2.1 → bigdata_smart_batching-1.3.1}/LICENSE +0 -0
  14. {bigdata_smart_batching-1.2.1 → bigdata_smart_batching-1.3.1}/Makefile +0 -0
  15. {bigdata_smart_batching-1.2.1 → bigdata_smart_batching-1.3.1}/docs/smart-batching-architecture.md +0 -0
  16. {bigdata_smart_batching-1.2.1 → bigdata_smart_batching-1.3.1}/examples/example_overlapping.py +0 -0
  17. {bigdata_smart_batching-1.2.1 → bigdata_smart_batching-1.3.1}/src/bigdata_smart_batching/output_converter.py +0 -0
  18. {bigdata_smart_batching-1.2.1 → bigdata_smart_batching-1.3.1}/src/bigdata_smart_batching/smart_batching_config.py +0 -0
  19. {bigdata_smart_batching-1.2.1 → bigdata_smart_batching-1.3.1}/tests/__init__.py +0 -0
  20. {bigdata_smart_batching-1.2.1 → bigdata_smart_batching-1.3.1}/tests/test_config.py +0 -0
  21. {bigdata_smart_batching-1.2.1 → bigdata_smart_batching-1.3.1}/tests/test_output_converter.py +0 -0
  22. {bigdata_smart_batching-1.2.1 → bigdata_smart_batching-1.3.1}/tests/test_rate_limiter.py +0 -0
@@ -5,6 +5,19 @@ All notable changes to this project are documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+
9
+ ## [1.3.1] - 2026-05-18
10
+
11
+ ### Added
12
+
13
+ - Document-level **source** filters: `INCLUDE` / `EXCLUDE` with a non-empty list of source ID strings, validated with `validate_source_filter`, modeled as `SourceFilter` / `SourceFilterInput` with `SourceMode` (type alias of `CategoryMode`). Serialized to `query.filters.source` on co-mention, volume, and search payloads. `plan_search(..., source=...)` and `source_filter` plumbed through `SmartBatchingPlanner` co-mention and volume flows. Payload builders `build_comention_payload`, `build_volume_payload`, and `build_search_query` accept optional `source_filter`. Types and validator re-exported from the package root.
14
+
15
+ ## [1.3.0] - 2026-05-12
16
+
17
+ ### Added
18
+
19
+ - Document-level **source** filters: `INCLUDE` / `EXCLUDE` with a non-empty list of source ID strings, validated with `validate_source_filter`, modeled as `SourceFilter` / `SourceFilterInput` with `SourceMode` (type alias of `CategoryMode`). Serialized to `query.filters.source` on co-mention, volume, and search payloads. `plan_search(..., source=...)` and `source_filter` plumbed through `SmartBatchingPlanner` co-mention and volume flows. Payload builders `build_comention_payload`, `build_volume_payload`, and `build_search_query` accept optional `source_filter`. Types and validator re-exported from the package root.
20
+
8
21
  ## [1.2.1] - 2026-05-12
9
22
 
10
23
  ### Fixed
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: bigdata-smart-batching
3
- Version: 1.2.1
3
+ Version: 1.3.1
4
4
  Summary: High-performance semantic search with intelligent company grouping and parallel execution
5
5
  Project-URL: homepage, https://bigdata.com/api
6
6
  Author-email: "Bigdata.com" <support@ravenpack.com>
@@ -29,6 +29,7 @@ This module provides a two-step pipeline for efficient semantic search:
29
29
  - **Parallel execution** -- rate-limited concurrent requests with semaphore-controlled concurrency.
30
30
  - **Proportional sampling** -- retrieve a percentage of results while preserving the distribution across baskets.
31
31
  - **Category filtering** -- restrict searches to specific document categories (news, transcripts, filings, ...).
32
+ - **Source filtering** -- include or exclude documents by source identifiers (`INCLUDE` / `EXCLUDE` plus a list of source IDs).
32
33
  - **Sentiment filtering** -- restrict searches to one or more inclusive document-level sentiment ranges.
33
34
  - **Throughput controls** -- shared sliding-window rate limiter and concurrency semaphore across all planning HTTP work, with shared exponential backoff on `429` / `403` / timeout retries.
34
35
  - **Deterministic plans** -- every request stays within service limits; plans can be saved and replayed.
@@ -164,6 +165,43 @@ Valid category values are exposed via `VALID_CATEGORY_VALUES` and include:
164
165
  `news_public`, `podcasts`, `research`, `research_academic_journals`,
165
166
  `research_investment_research`, `transcripts`.
166
167
 
168
+ ### Source Filtering
169
+
170
+ Restrict searches by **source** (document source IDs) using the `source` argument.
171
+ It accepts either a `SourceFilter` dataclass or a plain dict with `mode`
172
+ (`INCLUDE` or `EXCLUDE`) and `values` (a non-empty list of source ID strings).
173
+ The filter is serialized to `query.filters.source` on co-mention, volume, and
174
+ search payloads during planning.
175
+
176
+ ```python
177
+ from bigdata_smart_batching import SourceFilter, SourceMode, plan_search
178
+
179
+ plan = plan_search(
180
+ universe="id_name_mapping_us_top_3000.csv",
181
+ start_date="2023-01-01",
182
+ end_date="2023-12-31",
183
+ text="merger acquisition",
184
+ source=SourceFilter(
185
+ mode=SourceMode.INCLUDE,
186
+ values=("source-id-1", "source-id-2"),
187
+ ),
188
+ )
189
+
190
+ # Equivalent dict form:
191
+ plan = plan_search(
192
+ universe="id_name_mapping_us_top_3000.csv",
193
+ start_date="2023-01-01",
194
+ end_date="2023-12-31",
195
+ text="merger acquisition",
196
+ source={"mode": "EXCLUDE", "values": ["source-id-to-drop"]},
197
+ )
198
+ ```
199
+
200
+ `SourceMode` is the same `INCLUDE` / `EXCLUDE` enum as `CategoryMode`. String
201
+ values are trimmed; empty strings are rejected. Use
202
+ `validate_source_filter(source)` to validate and normalize input into the API
203
+ dict shape.
204
+
167
205
  ### Sentiment Filtering
168
206
 
169
207
  Restrict searches to documents whose sentiment falls inside one or more
@@ -263,6 +301,7 @@ Step 2: EXECUTION
263
301
  | `min_period_days` | `int` | `30` | Minimum days per sub-period |
264
302
  | `min_entities_per_basket` | `int` | `1` | Lower bound on entities per basket |
265
303
  | `category` | `CategoryFilter \| dict \| None` | `None` | Optional category filter (`mode` + `values`) |
304
+ | `source` | `SourceFilter \| dict \| None` | `None` | Optional source filter by source IDs (`mode` + `values`) |
266
305
  | `sentiment` | `SentimentRange \| dict \| list \| None` | `None` | Optional sentiment filter: one inclusive `{min, max}` range or a list of disjoint ranges |
267
306
  | `content_diversification` | `bool` | `True` | Enable/disable content diversification in ranking |
268
307
  | `requests_per_minute` | `int` | `100` | Global rate limit shared across all planning HTTP work (co-mention + volume) |
@@ -289,14 +328,18 @@ Step 2: EXECUTION
289
328
  - `load_universe_from_csv(csv_path)` -- load entity IDs from a CSV only.
290
329
  - `save_plan(plan, path)` / `load_plan(path)` -- persist plans as JSON.
291
330
  - `validate_category_filter(category)` -- validate and normalize a category filter to the API dict shape.
331
+ - `validate_source_filter(source)` -- validate and normalize a source filter to the API dict shape (`filters.source`).
292
332
  - `validate_sentiment_range(sentiment)` -- validate and normalize sentiment range(s) into the list-of-`{min, max}` dicts emitted as `filters.sentiment.ranges`.
293
- - `build_comention_payload(...)`, `build_volume_payload(...)`, `build_search_query(...)` -- low-level payload builders used by the planner; useful if you need to construct custom requests.
333
+ - `build_comention_payload(...)`, `build_volume_payload(...)`, `build_search_query(...)` -- low-level payload builders used by the planner; each accepts optional `category_filter`, `source_filter`, and `sentiment_filter` alongside entities and dates. Useful if you need to construct custom requests.
294
334
 
295
335
  ### Public Types
296
336
 
297
337
  - `CategoryFilter` -- frozen dataclass with `mode: CategoryMode` and `values: tuple[str, ...]`.
298
338
  - `CategoryMode` -- `StrEnum` with `INCLUDE` and `EXCLUDE` values.
299
339
  - `CategoryFilterInput` -- type alias: `CategoryFilter | dict[str, str | list[str]]`.
340
+ - `SourceFilter` -- frozen dataclass with `mode: SourceMode` and `values: tuple[str, ...]` (source IDs).
341
+ - `SourceMode` -- type alias of `CategoryMode` (`INCLUDE`, `EXCLUDE`).
342
+ - `SourceFilterInput` -- type alias: `SourceFilter | dict[str, str | list[str]]`.
300
343
  - `SentimentRange` -- frozen dataclass with inclusive `min: float` and `max: float`.
301
344
  - `SentimentRangeInput` -- type alias for one `SentimentRange` / `{min, max}` dict, or a non-empty list of either.
302
345
  - `UniverseInput` -- type alias: `str | list[str]`.
@@ -13,6 +13,7 @@ This module provides a two-step pipeline for efficient semantic search:
13
13
  - **Parallel execution** -- rate-limited concurrent requests with semaphore-controlled concurrency.
14
14
  - **Proportional sampling** -- retrieve a percentage of results while preserving the distribution across baskets.
15
15
  - **Category filtering** -- restrict searches to specific document categories (news, transcripts, filings, ...).
16
+ - **Source filtering** -- include or exclude documents by source identifiers (`INCLUDE` / `EXCLUDE` plus a list of source IDs).
16
17
  - **Sentiment filtering** -- restrict searches to one or more inclusive document-level sentiment ranges.
17
18
  - **Throughput controls** -- shared sliding-window rate limiter and concurrency semaphore across all planning HTTP work, with shared exponential backoff on `429` / `403` / timeout retries.
18
19
  - **Deterministic plans** -- every request stays within service limits; plans can be saved and replayed.
@@ -148,6 +149,43 @@ Valid category values are exposed via `VALID_CATEGORY_VALUES` and include:
148
149
  `news_public`, `podcasts`, `research`, `research_academic_journals`,
149
150
  `research_investment_research`, `transcripts`.
150
151
 
152
+ ### Source Filtering
153
+
154
+ Restrict searches by **source** (document source IDs) using the `source` argument.
155
+ It accepts either a `SourceFilter` dataclass or a plain dict with `mode`
156
+ (`INCLUDE` or `EXCLUDE`) and `values` (a non-empty list of source ID strings).
157
+ The filter is serialized to `query.filters.source` on co-mention, volume, and
158
+ search payloads during planning.
159
+
160
+ ```python
161
+ from bigdata_smart_batching import SourceFilter, SourceMode, plan_search
162
+
163
+ plan = plan_search(
164
+ universe="id_name_mapping_us_top_3000.csv",
165
+ start_date="2023-01-01",
166
+ end_date="2023-12-31",
167
+ text="merger acquisition",
168
+ source=SourceFilter(
169
+ mode=SourceMode.INCLUDE,
170
+ values=("source-id-1", "source-id-2"),
171
+ ),
172
+ )
173
+
174
+ # Equivalent dict form:
175
+ plan = plan_search(
176
+ universe="id_name_mapping_us_top_3000.csv",
177
+ start_date="2023-01-01",
178
+ end_date="2023-12-31",
179
+ text="merger acquisition",
180
+ source={"mode": "EXCLUDE", "values": ["source-id-to-drop"]},
181
+ )
182
+ ```
183
+
184
+ `SourceMode` is the same `INCLUDE` / `EXCLUDE` enum as `CategoryMode`. String
185
+ values are trimmed; empty strings are rejected. Use
186
+ `validate_source_filter(source)` to validate and normalize input into the API
187
+ dict shape.
188
+
151
189
  ### Sentiment Filtering
152
190
 
153
191
  Restrict searches to documents whose sentiment falls inside one or more
@@ -247,6 +285,7 @@ Step 2: EXECUTION
247
285
  | `min_period_days` | `int` | `30` | Minimum days per sub-period |
248
286
  | `min_entities_per_basket` | `int` | `1` | Lower bound on entities per basket |
249
287
  | `category` | `CategoryFilter \| dict \| None` | `None` | Optional category filter (`mode` + `values`) |
288
+ | `source` | `SourceFilter \| dict \| None` | `None` | Optional source filter by source IDs (`mode` + `values`) |
250
289
  | `sentiment` | `SentimentRange \| dict \| list \| None` | `None` | Optional sentiment filter: one inclusive `{min, max}` range or a list of disjoint ranges |
251
290
  | `content_diversification` | `bool` | `True` | Enable/disable content diversification in ranking |
252
291
  | `requests_per_minute` | `int` | `100` | Global rate limit shared across all planning HTTP work (co-mention + volume) |
@@ -273,14 +312,18 @@ Step 2: EXECUTION
273
312
  - `load_universe_from_csv(csv_path)` -- load entity IDs from a CSV only.
274
313
  - `save_plan(plan, path)` / `load_plan(path)` -- persist plans as JSON.
275
314
  - `validate_category_filter(category)` -- validate and normalize a category filter to the API dict shape.
315
+ - `validate_source_filter(source)` -- validate and normalize a source filter to the API dict shape (`filters.source`).
276
316
  - `validate_sentiment_range(sentiment)` -- validate and normalize sentiment range(s) into the list-of-`{min, max}` dicts emitted as `filters.sentiment.ranges`.
277
- - `build_comention_payload(...)`, `build_volume_payload(...)`, `build_search_query(...)` -- low-level payload builders used by the planner; useful if you need to construct custom requests.
317
+ - `build_comention_payload(...)`, `build_volume_payload(...)`, `build_search_query(...)` -- low-level payload builders used by the planner; each accepts optional `category_filter`, `source_filter`, and `sentiment_filter` alongside entities and dates. Useful if you need to construct custom requests.
278
318
 
279
319
  ### Public Types
280
320
 
281
321
  - `CategoryFilter` -- frozen dataclass with `mode: CategoryMode` and `values: tuple[str, ...]`.
282
322
  - `CategoryMode` -- `StrEnum` with `INCLUDE` and `EXCLUDE` values.
283
323
  - `CategoryFilterInput` -- type alias: `CategoryFilter | dict[str, str | list[str]]`.
324
+ - `SourceFilter` -- frozen dataclass with `mode: SourceMode` and `values: tuple[str, ...]` (source IDs).
325
+ - `SourceMode` -- type alias of `CategoryMode` (`INCLUDE`, `EXCLUDE`).
326
+ - `SourceFilterInput` -- type alias: `SourceFilter | dict[str, str | list[str]]`.
284
327
  - `SentimentRange` -- frozen dataclass with inclusive `min: float` and `max: float`.
285
328
  - `SentimentRangeInput` -- type alias for one `SentimentRange` / `{min, max}` dict, or a non-empty list of either.
286
329
  - `UniverseInput` -- type alias: `str | list[str]`.
@@ -67,6 +67,7 @@ def main() -> None:
67
67
  # Optional: filter by category to restrict document sources.
68
68
  # Accepts a CategoryFilter instance or a plain dict:
69
69
  category={"mode": "INCLUDE", "values": ["news_premium"]},
70
+ source={"mode": "INCLUDE", "values": ["5A5702"]},
70
71
  content_diversification=False,
71
72
  sentiment=[{"min": -1, "max": -0.5},{"min": 0.5, "max": 1}],
72
73
  )
@@ -80,12 +81,12 @@ def main() -> None:
80
81
  print(f"Plan execution time: {plan_elapsed_s:.3f}s")
81
82
 
82
83
  # Step 2: Execute search with 10% of total chunks (preserves distribution)
83
- if False:
84
+ if True:
84
85
  search_t0 = time.perf_counter()
85
86
  results_raw = execute_search(
86
87
  search_plan=plan,
87
- chunk_percentage=1,
88
- requests_per_minute=300,
88
+ chunk_percentage=0.1,
89
+ requests_per_minute=450,
89
90
  )
90
91
  search_elapsed_s = time.perf_counter() - search_t0
91
92
  print(f"Search execution time: {search_elapsed_s:.3f}s")