lit-acquisition 0.1.0__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 (30) hide show
  1. lit_acquisition-0.1.0/.gitignore +24 -0
  2. lit_acquisition-0.1.0/PKG-INFO +219 -0
  3. lit_acquisition-0.1.0/README.md +187 -0
  4. lit_acquisition-0.1.0/pyproject.toml +60 -0
  5. lit_acquisition-0.1.0/src/lit_acquisition/__init__.py +150 -0
  6. lit_acquisition-0.1.0/src/lit_acquisition/_parse_service.py +29 -0
  7. lit_acquisition-0.1.0/src/lit_acquisition/_rust_io.py +26 -0
  8. lit_acquisition-0.1.0/src/lit_acquisition/config.py +301 -0
  9. lit_acquisition-0.1.0/src/lit_acquisition/contracts.py +200 -0
  10. lit_acquisition-0.1.0/src/lit_acquisition/gateway.py +465 -0
  11. lit_acquisition-0.1.0/src/lit_acquisition/literature_type_classifier.py +291 -0
  12. lit_acquisition-0.1.0/src/lit_acquisition/normalizers.py +692 -0
  13. lit_acquisition-0.1.0/src/lit_acquisition/provider_health.py +83 -0
  14. lit_acquisition-0.1.0/src/lit_acquisition/pubmed_service.py +186 -0
  15. lit_acquisition-0.1.0/src/lit_acquisition/query_translator.py +189 -0
  16. lit_acquisition-0.1.0/src/lit_acquisition/relevance_gate.py +364 -0
  17. lit_acquisition-0.1.0/src/lit_acquisition/search_service.py +308 -0
  18. lit_acquisition-0.1.0/src/lit_acquisition/utils/__init__.py +12 -0
  19. lit_acquisition-0.1.0/src/lit_acquisition/utils/llm_params.py +25 -0
  20. lit_acquisition-0.1.0/src/lit_acquisition/utils/ssrf.py +36 -0
  21. lit_acquisition-0.1.0/src/lit_acquisition/utils/text.py +33 -0
  22. lit_acquisition-0.1.0/src/lit_acquisition/web_search/__init__.py +7 -0
  23. lit_acquisition-0.1.0/src/lit_acquisition/web_search/adapter.py +65 -0
  24. lit_acquisition-0.1.0/src/lit_acquisition/web_search/firecrawl_adapter.py +242 -0
  25. lit_acquisition-0.1.0/src/lit_acquisition/web_search/serpapi_adapter.py +137 -0
  26. lit_acquisition-0.1.0/src/lit_acquisition/web_search/tavily_adapter.py +132 -0
  27. lit_acquisition-0.1.0/src/lit_acquisition/workflow.py +1066 -0
  28. lit_acquisition-0.1.0/tests/test_config.py +105 -0
  29. lit_acquisition-0.1.0/tests/test_contracts.py +133 -0
  30. lit_acquisition-0.1.0/uv.lock +1507 -0
@@ -0,0 +1,24 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ *.so
6
+ .Python
7
+ build/
8
+ dist/
9
+ *.egg-info/
10
+ *.egg
11
+
12
+ # Virtual environments
13
+ .venv/
14
+ venv/
15
+
16
+ # Testing
17
+ .pytest_cache/
18
+ .coverage
19
+ htmlcov/
20
+
21
+ # IDE
22
+ .idea/
23
+ .vscode/
24
+ *.swp
@@ -0,0 +1,219 @@
1
+ Metadata-Version: 2.4
2
+ Name: lit-acquisition
3
+ Version: 0.1.0
4
+ Summary: Multilingual biomedical literature acquisition toolkit - search, download, and classify academic papers from 15+ providers
5
+ Author: Lingua Seeker Maintainers
6
+ License-Expression: MIT
7
+ Keywords: acquisition,biomedical,crossref,literature,multilingual,openalex,pubmed
8
+ Classifier: Development Status :: 4 - Beta
9
+ Classifier: Intended Audience :: Science/Research
10
+ Classifier: License :: OSI Approved :: MIT License
11
+ Classifier: Programming Language :: Python :: 3.12
12
+ Classifier: Programming Language :: Python :: 3.13
13
+ Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
14
+ Requires-Python: >=3.12
15
+ Requires-Dist: httpx[socks]>=0.27.0
16
+ Requires-Dist: loguru>=0.7.0
17
+ Requires-Dist: openai>=1.0.0
18
+ Requires-Dist: pydantic>=2.7.0
19
+ Requires-Dist: pyjstage2>=0.1.2
20
+ Requires-Dist: pymupdf>=1.27.2
21
+ Provides-Extra: dev
22
+ Requires-Dist: pytest-asyncio>=0.23.0; extra == 'dev'
23
+ Requires-Dist: pytest>=8.2.0; extra == 'dev'
24
+ Requires-Dist: ruff>=0.5.0; extra == 'dev'
25
+ Provides-Extra: rust-io
26
+ Requires-Dist: rust-io; extra == 'rust-io'
27
+ Provides-Extra: web-search
28
+ Requires-Dist: firecrawl-py>=4.28.2; extra == 'web-search'
29
+ Requires-Dist: google-search-results>=2.4.2; extra == 'web-search'
30
+ Requires-Dist: tavily-python>=0.5.0; extra == 'web-search'
31
+ Description-Content-Type: text/markdown
32
+
33
+ # lit-acquisition
34
+
35
+ Multilingual biomedical literature acquisition toolkit — search, download, and classify academic papers from 15+ providers.
36
+
37
+ ## Features
38
+
39
+ - **15+ provider integrations**: Crossref, PubMed, OpenAlex, EuropePMC, DOAJ, J-STAGE, arXiv, bioRxiv, medRxiv, SciELO, BASE, CORE, OpenAIRE, CiNii, Unpaywall
40
+ - **Multilingual search**: Query translation into 6 languages (en, zh, ja, de, fr, ru) with language-aware provider routing
41
+ - **PDF download**: DOI → Unpaywall OA resolution, PMCID → EuropePMC render, direct URL with HTML→PDF redirect handling
42
+ - **Relevance gate**: LLM-based classification to filter irrelevant downloads
43
+ - **Literature type classification**: Keyword-based classification (case report, sequencing, functional study) across 10+ languages
44
+ - **Web search fallback**: Firecrawl, Tavily, and SerpApi adapters for discovering papers beyond academic APIs
45
+ - **Provider health tracking**: Automatic health monitoring with sliding-window stats and unhealthy provider deprioritization
46
+
47
+ ## Installation
48
+
49
+ ```bash
50
+ pip install lit-acquisition
51
+ ```
52
+
53
+ With web search support:
54
+
55
+ ```bash
56
+ pip install "lit-acquisition[web-search]"
57
+ ```
58
+
59
+ With Rust native extensions (faster HTTP I/O):
60
+
61
+ ```bash
62
+ pip install "lit-acquisition[rust-io]"
63
+ ```
64
+
65
+ ## Quick Start
66
+
67
+ ### Configure
68
+
69
+ ```python
70
+ from lit_acquisition import configure
71
+
72
+ configure(
73
+ # LLM for relevance gate and query translation
74
+ llm_base_url="https://api.openai.com/v1",
75
+ llm_api_key="sk-...",
76
+ llm_model="gpt-4o",
77
+
78
+ # Optional: dedicated translation model
79
+ translation_base_url="https://api.openai.com/v1",
80
+ translation_api_key="sk-...",
81
+ translation_model="gpt-4o-mini",
82
+
83
+ # Optional: web search providers
84
+ firecrawl_api_key="fc-...",
85
+ tavily_api_key="tvly-...",
86
+
87
+ # Optional: network proxy
88
+ proxy="http://127.0.0.1:7890",
89
+
90
+ # Optional: PubMed API key (higher rate limits)
91
+ pubmed_api_key="...",
92
+ )
93
+ ```
94
+
95
+ Or via environment variables:
96
+
97
+ ```bash
98
+ export LIT_LLM_BASE_URL=https://api.openai.com/v1
99
+ export LIT_LLM_API_KEY=sk-...
100
+ export LIT_LLM_MODEL=gpt-4o
101
+ ```
102
+
103
+ ### Search a Single Provider
104
+
105
+ ```python
106
+ import asyncio
107
+ from lit_acquisition import search_provider
108
+
109
+ async def main():
110
+ result = await search_provider(
111
+ provider="crossref",
112
+ query="MECP2 Rett syndrome case report",
113
+ limit=20,
114
+ )
115
+ print(f"Found {len(result.items)} items")
116
+ for item in result.items:
117
+ print(f" - {item.get('title', 'untitled')}")
118
+
119
+ asyncio.run(main())
120
+ ```
121
+
122
+ ### Run the Full Multilingual Pipeline
123
+
124
+ ```python
125
+ import asyncio
126
+ from lit_acquisition import multilingual_acquisition_workflow
127
+
128
+ async def main():
129
+ result = await multilingual_acquisition_workflow({
130
+ "query": "MECP2 Rett syndrome case report",
131
+ "action": "search", # or "download" to also fetch PDFs
132
+ "limit": 30,
133
+ "language": "auto",
134
+ "relevance_gate": True, # LLM-based relevance filtering
135
+ "literature_types": ["case_report"],
136
+ })
137
+ print(f"Success: {result['success']}")
138
+ print(f"Items: {len(result['items'])}")
139
+ print(f"Downloads: {len(result['downloads'])}")
140
+
141
+ asyncio.run(main())
142
+ ```
143
+
144
+ ### Download PDFs
145
+
146
+ ```python
147
+ import asyncio
148
+ from lit_acquisition import download_file_from_url
149
+
150
+ async def main():
151
+ file_path, final_url, warnings = await download_file_from_url(
152
+ url="https://example.com/paper.pdf",
153
+ download_path="./downloads",
154
+ filename_stem="my_paper",
155
+ )
156
+ print(f"Downloaded to: {file_path}")
157
+
158
+ asyncio.run(main())
159
+ ```
160
+
161
+ ### Use the PubMed Service
162
+
163
+ ```python
164
+ import asyncio
165
+ from lit_acquisition import get_pubmed_service
166
+
167
+ async def main():
168
+ svc = get_pubmed_service()
169
+ candidates = await svc.search_candidates("BRCA1 breast cancer", candidate_limit=10)
170
+ for c in candidates:
171
+ print(f" PMID: {c.pmid}, Title: {c.title}")
172
+
173
+ asyncio.run(main())
174
+ ```
175
+
176
+ ## Supported Providers
177
+
178
+ | Provider | Search | Download | Notes |
179
+ |----------|--------|----------|-------|
180
+ | Crossref | ✓ | — | Metadata only |
181
+ | Unpaywall | ✓ | ✓ | OA PDF resolution via DOI |
182
+ | OpenAlex | ✓ | — | Metadata only |
183
+ | EuropePMC | ✓ | ✓ | Full text via PMCID render |
184
+ | PMC | ✓ | ✓ | esearch + esummary |
185
+ | DOAJ | ✓ | — | Metadata only |
186
+ | J-STAGE | ✓ | — | Japanese literature |
187
+ | CiNii | ✓ | — | Japanese research |
188
+ | arXiv | ✓ | ✓ | Preprint server |
189
+ | bioRxiv | ✓ | ✓ | Preprint server |
190
+ | medRxiv | ✓ | ✓ | Preprint server |
191
+ | SciELO | ✓ | — | Latin American literature |
192
+ | BASE | ✓ | — | Multidisciplinary |
193
+ | CORE | ✓ | — | Open access |
194
+ | OpenAIRE | ✓ | — | European research |
195
+
196
+ ## Configuration Reference
197
+
198
+ ### Environment Variables
199
+
200
+ | Variable | Description | Default |
201
+ |----------|-------------|---------|
202
+ | `LIT_LLM_BASE_URL` | LLM API base URL | — |
203
+ | `LIT_LLM_API_KEY` | LLM API key | — |
204
+ | `LIT_LLM_MODEL` | LLM model name | — |
205
+ | `LIT_LLM_API_KEYS` | Comma-separated API key pool | — |
206
+ | `LIT_LLM_MAX_TOKENS` | Max tokens for LLM | `8192` |
207
+ | `LIT_TRANSLATION_BASE_URL` | Translation LLM base URL | Falls back to LLM config |
208
+ | `LIT_TRANSLATION_API_KEY` | Translation LLM API key | Falls back to LLM config |
209
+ | `LIT_TRANSLATION_MODEL` | Translation LLM model | Falls back to LLM config |
210
+ | `LIT_FIRECRAWL_API_KEY` | Firecrawl API key | — |
211
+ | `LIT_TAVILY_API_KEY` | Tavily API key | — |
212
+ | `LIT_SERPAPI_API_KEY` | SerpApi API key | — |
213
+ | `LIT_PROXY` | HTTP/HTTPS/SOCKS proxy URL | — |
214
+ | `LIT_NO_PROXY` | Comma-separated proxy bypass domains | `cn,ncbi.nlm.nih.gov,...` |
215
+ | `LIT_PUBMED_API_KEY` | PubMed eutils API key | — |
216
+
217
+ ## License
218
+
219
+ MIT
@@ -0,0 +1,187 @@
1
+ # lit-acquisition
2
+
3
+ Multilingual biomedical literature acquisition toolkit — search, download, and classify academic papers from 15+ providers.
4
+
5
+ ## Features
6
+
7
+ - **15+ provider integrations**: Crossref, PubMed, OpenAlex, EuropePMC, DOAJ, J-STAGE, arXiv, bioRxiv, medRxiv, SciELO, BASE, CORE, OpenAIRE, CiNii, Unpaywall
8
+ - **Multilingual search**: Query translation into 6 languages (en, zh, ja, de, fr, ru) with language-aware provider routing
9
+ - **PDF download**: DOI → Unpaywall OA resolution, PMCID → EuropePMC render, direct URL with HTML→PDF redirect handling
10
+ - **Relevance gate**: LLM-based classification to filter irrelevant downloads
11
+ - **Literature type classification**: Keyword-based classification (case report, sequencing, functional study) across 10+ languages
12
+ - **Web search fallback**: Firecrawl, Tavily, and SerpApi adapters for discovering papers beyond academic APIs
13
+ - **Provider health tracking**: Automatic health monitoring with sliding-window stats and unhealthy provider deprioritization
14
+
15
+ ## Installation
16
+
17
+ ```bash
18
+ pip install lit-acquisition
19
+ ```
20
+
21
+ With web search support:
22
+
23
+ ```bash
24
+ pip install "lit-acquisition[web-search]"
25
+ ```
26
+
27
+ With Rust native extensions (faster HTTP I/O):
28
+
29
+ ```bash
30
+ pip install "lit-acquisition[rust-io]"
31
+ ```
32
+
33
+ ## Quick Start
34
+
35
+ ### Configure
36
+
37
+ ```python
38
+ from lit_acquisition import configure
39
+
40
+ configure(
41
+ # LLM for relevance gate and query translation
42
+ llm_base_url="https://api.openai.com/v1",
43
+ llm_api_key="sk-...",
44
+ llm_model="gpt-4o",
45
+
46
+ # Optional: dedicated translation model
47
+ translation_base_url="https://api.openai.com/v1",
48
+ translation_api_key="sk-...",
49
+ translation_model="gpt-4o-mini",
50
+
51
+ # Optional: web search providers
52
+ firecrawl_api_key="fc-...",
53
+ tavily_api_key="tvly-...",
54
+
55
+ # Optional: network proxy
56
+ proxy="http://127.0.0.1:7890",
57
+
58
+ # Optional: PubMed API key (higher rate limits)
59
+ pubmed_api_key="...",
60
+ )
61
+ ```
62
+
63
+ Or via environment variables:
64
+
65
+ ```bash
66
+ export LIT_LLM_BASE_URL=https://api.openai.com/v1
67
+ export LIT_LLM_API_KEY=sk-...
68
+ export LIT_LLM_MODEL=gpt-4o
69
+ ```
70
+
71
+ ### Search a Single Provider
72
+
73
+ ```python
74
+ import asyncio
75
+ from lit_acquisition import search_provider
76
+
77
+ async def main():
78
+ result = await search_provider(
79
+ provider="crossref",
80
+ query="MECP2 Rett syndrome case report",
81
+ limit=20,
82
+ )
83
+ print(f"Found {len(result.items)} items")
84
+ for item in result.items:
85
+ print(f" - {item.get('title', 'untitled')}")
86
+
87
+ asyncio.run(main())
88
+ ```
89
+
90
+ ### Run the Full Multilingual Pipeline
91
+
92
+ ```python
93
+ import asyncio
94
+ from lit_acquisition import multilingual_acquisition_workflow
95
+
96
+ async def main():
97
+ result = await multilingual_acquisition_workflow({
98
+ "query": "MECP2 Rett syndrome case report",
99
+ "action": "search", # or "download" to also fetch PDFs
100
+ "limit": 30,
101
+ "language": "auto",
102
+ "relevance_gate": True, # LLM-based relevance filtering
103
+ "literature_types": ["case_report"],
104
+ })
105
+ print(f"Success: {result['success']}")
106
+ print(f"Items: {len(result['items'])}")
107
+ print(f"Downloads: {len(result['downloads'])}")
108
+
109
+ asyncio.run(main())
110
+ ```
111
+
112
+ ### Download PDFs
113
+
114
+ ```python
115
+ import asyncio
116
+ from lit_acquisition import download_file_from_url
117
+
118
+ async def main():
119
+ file_path, final_url, warnings = await download_file_from_url(
120
+ url="https://example.com/paper.pdf",
121
+ download_path="./downloads",
122
+ filename_stem="my_paper",
123
+ )
124
+ print(f"Downloaded to: {file_path}")
125
+
126
+ asyncio.run(main())
127
+ ```
128
+
129
+ ### Use the PubMed Service
130
+
131
+ ```python
132
+ import asyncio
133
+ from lit_acquisition import get_pubmed_service
134
+
135
+ async def main():
136
+ svc = get_pubmed_service()
137
+ candidates = await svc.search_candidates("BRCA1 breast cancer", candidate_limit=10)
138
+ for c in candidates:
139
+ print(f" PMID: {c.pmid}, Title: {c.title}")
140
+
141
+ asyncio.run(main())
142
+ ```
143
+
144
+ ## Supported Providers
145
+
146
+ | Provider | Search | Download | Notes |
147
+ |----------|--------|----------|-------|
148
+ | Crossref | ✓ | — | Metadata only |
149
+ | Unpaywall | ✓ | ✓ | OA PDF resolution via DOI |
150
+ | OpenAlex | ✓ | — | Metadata only |
151
+ | EuropePMC | ✓ | ✓ | Full text via PMCID render |
152
+ | PMC | ✓ | ✓ | esearch + esummary |
153
+ | DOAJ | ✓ | — | Metadata only |
154
+ | J-STAGE | ✓ | — | Japanese literature |
155
+ | CiNii | ✓ | — | Japanese research |
156
+ | arXiv | ✓ | ✓ | Preprint server |
157
+ | bioRxiv | ✓ | ✓ | Preprint server |
158
+ | medRxiv | ✓ | ✓ | Preprint server |
159
+ | SciELO | ✓ | — | Latin American literature |
160
+ | BASE | ✓ | — | Multidisciplinary |
161
+ | CORE | ✓ | — | Open access |
162
+ | OpenAIRE | ✓ | — | European research |
163
+
164
+ ## Configuration Reference
165
+
166
+ ### Environment Variables
167
+
168
+ | Variable | Description | Default |
169
+ |----------|-------------|---------|
170
+ | `LIT_LLM_BASE_URL` | LLM API base URL | — |
171
+ | `LIT_LLM_API_KEY` | LLM API key | — |
172
+ | `LIT_LLM_MODEL` | LLM model name | — |
173
+ | `LIT_LLM_API_KEYS` | Comma-separated API key pool | — |
174
+ | `LIT_LLM_MAX_TOKENS` | Max tokens for LLM | `8192` |
175
+ | `LIT_TRANSLATION_BASE_URL` | Translation LLM base URL | Falls back to LLM config |
176
+ | `LIT_TRANSLATION_API_KEY` | Translation LLM API key | Falls back to LLM config |
177
+ | `LIT_TRANSLATION_MODEL` | Translation LLM model | Falls back to LLM config |
178
+ | `LIT_FIRECRAWL_API_KEY` | Firecrawl API key | — |
179
+ | `LIT_TAVILY_API_KEY` | Tavily API key | — |
180
+ | `LIT_SERPAPI_API_KEY` | SerpApi API key | — |
181
+ | `LIT_PROXY` | HTTP/HTTPS/SOCKS proxy URL | — |
182
+ | `LIT_NO_PROXY` | Comma-separated proxy bypass domains | `cn,ncbi.nlm.nih.gov,...` |
183
+ | `LIT_PUBMED_API_KEY` | PubMed eutils API key | — |
184
+
185
+ ## License
186
+
187
+ MIT
@@ -0,0 +1,60 @@
1
+ [project]
2
+ name = "lit-acquisition"
3
+ version = "0.1.0"
4
+ description = "Multilingual biomedical literature acquisition toolkit - search, download, and classify academic papers from 15+ providers"
5
+ readme = "README.md"
6
+ requires-python = ">=3.12"
7
+ license = "MIT"
8
+ authors = [
9
+ { name = "Lingua Seeker Maintainers" },
10
+ ]
11
+ keywords = ["literature", "biomedical", "acquisition", "pubmed", "crossref", "openalex", "multilingual"]
12
+ classifiers = [
13
+ "Development Status :: 4 - Beta",
14
+ "Intended Audience :: Science/Research",
15
+ "License :: OSI Approved :: MIT License",
16
+ "Programming Language :: Python :: 3.12",
17
+ "Programming Language :: Python :: 3.13",
18
+ "Topic :: Scientific/Engineering :: Bio-Informatics",
19
+ ]
20
+ dependencies = [
21
+ "httpx[socks]>=0.27.0",
22
+ "pydantic>=2.7.0",
23
+ "loguru>=0.7.0",
24
+ "pymupdf>=1.27.2",
25
+ "openai>=1.0.0",
26
+ "pyjstage2>=0.1.2",
27
+ ]
28
+
29
+ [project.optional-dependencies]
30
+ web-search = [
31
+ "firecrawl-py>=4.28.2",
32
+ "tavily-python>=0.5.0",
33
+ "google-search-results>=2.4.2",
34
+ ]
35
+ rust-io = [
36
+ "rust-io",
37
+ ]
38
+ dev = [
39
+ "pytest>=8.2.0",
40
+ "pytest-asyncio>=0.23.0",
41
+ "ruff>=0.5.0",
42
+ ]
43
+
44
+ [build-system]
45
+ requires = ["hatchling"]
46
+ build-backend = "hatchling.build"
47
+
48
+ [tool.hatch.build.targets.wheel]
49
+ packages = ["src/lit_acquisition"]
50
+
51
+ [tool.ruff]
52
+ line-length = 120
53
+ target-version = "py312"
54
+
55
+ [tool.pytest.ini_options]
56
+ testpaths = ["tests"]
57
+ asyncio_mode = "auto"
58
+
59
+ [tool.ruff.lint]
60
+ ignore = ["BLE001", "S110", "PLC0206"]
@@ -0,0 +1,150 @@
1
+ """lit-acquisition: Multilingual biomedical literature acquisition toolkit.
2
+
3
+ Search, download, and classify academic papers from 15+ providers including
4
+ Crossref, PubMed, OpenAlex, EuropePMC, DOAJ, J-STAGE, arXiv, and more.
5
+
6
+ Quick start::
7
+
8
+ from lit_acquisition import configure, search_provider, download_file_from_url
9
+
10
+ # Configure your LLM provider (for query translation and relevance gate)
11
+ configure(
12
+ llm_base_url="https://api.openai.com/v1",
13
+ llm_api_key="sk-...",
14
+ llm_model="gpt-4o",
15
+ )
16
+
17
+ # Search a single provider
18
+ result = await search_provider(provider="crossref", query="MECP2 Rett syndrome")
19
+
20
+ # Or run the full multilingual pipeline
21
+ from lit_acquisition import multilingual_acquisition_workflow
22
+ result = await multilingual_acquisition_workflow({"query": "MECP2 Rett syndrome", "action": "search"})
23
+ """
24
+
25
+ from .config import (
26
+ LitAcquisitionConfig,
27
+ LLMConfig,
28
+ NetworkConfig,
29
+ PubMedConfig,
30
+ TranslationLLMConfig,
31
+ WebSearchConfig,
32
+ configure,
33
+ get_config,
34
+ reload_config,
35
+ )
36
+ from .contracts import (
37
+ DownloadResult,
38
+ OnlineAcquisitionGatewayRequest,
39
+ OnlineAcquisitionGatewayResult,
40
+ OnlineAcquisitionItem,
41
+ OnlineAcquisitionRequest,
42
+ OnlineAcquisitionResponse,
43
+ OnlineAcquisitionRouteInfo,
44
+ OnlineAcquisitionSourceTraceEntry,
45
+ )
46
+ from .gateway import (
47
+ call_provider,
48
+ call_provider_with_retry,
49
+ download_file_from_url,
50
+ resolve_oa_url,
51
+ search_provider,
52
+ )
53
+ from .literature_type_classifier import (
54
+ LiteratureType,
55
+ classify_item,
56
+ classify_items,
57
+ filter_by_type,
58
+ )
59
+ from .normalizers import normalize_items
60
+ from .provider_health import ProviderHealthTracker, ProviderStats, get_health_tracker
61
+ from .pubmed_service import (
62
+ OnlineAcquisitionPubMedArticle,
63
+ OnlineAcquisitionPubMedCandidate,
64
+ OnlineAcquisitionPubMedService,
65
+ get_pubmed_service,
66
+ )
67
+ from .query_translator import (
68
+ TARGET_LANGUAGES,
69
+ TranslatedQueries,
70
+ translate_query,
71
+ )
72
+ from .relevance_gate import (
73
+ RelevanceGateResult,
74
+ RelevanceJudgment,
75
+ run_relevance_gate,
76
+ )
77
+ from .search_service import (
78
+ build_provider_plan,
79
+ dedupe_candidates,
80
+ rank_candidates,
81
+ search_multilingual,
82
+ search_parallel,
83
+ )
84
+ from .workflow import (
85
+ multilingual_acquisition_workflow,
86
+ online_acquisition_workflow,
87
+ )
88
+
89
+ __all__ = [
90
+ "TARGET_LANGUAGES",
91
+ "DownloadResult",
92
+ "LLMConfig",
93
+ # Config
94
+ "LitAcquisitionConfig",
95
+ # Literature type classifier
96
+ "LiteratureType",
97
+ "NetworkConfig",
98
+ "OnlineAcquisitionGatewayRequest",
99
+ "OnlineAcquisitionGatewayResult",
100
+ # Contracts
101
+ "OnlineAcquisitionItem",
102
+ "OnlineAcquisitionPubMedArticle",
103
+ "OnlineAcquisitionPubMedCandidate",
104
+ # PubMed
105
+ "OnlineAcquisitionPubMedService",
106
+ "OnlineAcquisitionRequest",
107
+ "OnlineAcquisitionResponse",
108
+ "OnlineAcquisitionRouteInfo",
109
+ "OnlineAcquisitionSourceTraceEntry",
110
+ "ProviderHealthTracker",
111
+ "ProviderStats",
112
+ "PubMedConfig",
113
+ # Relevance gate
114
+ "RelevanceGateResult",
115
+ "RelevanceJudgment",
116
+ # Query translator
117
+ "TranslatedQueries",
118
+ "TranslationLLMConfig",
119
+ "WebSearchConfig",
120
+ # Search
121
+ "build_provider_plan",
122
+ # Gateway
123
+ "call_provider",
124
+ "call_provider_with_retry",
125
+ "classify_item",
126
+ "classify_items",
127
+ "configure",
128
+ "dedupe_candidates",
129
+ "download_file_from_url",
130
+ "filter_by_type",
131
+ "get_config",
132
+ # Provider health
133
+ "get_health_tracker",
134
+ "get_pubmed_service",
135
+ "multilingual_acquisition_workflow",
136
+ # Normalizers
137
+ "normalize_items",
138
+ # Workflow
139
+ "online_acquisition_workflow",
140
+ "rank_candidates",
141
+ "reload_config",
142
+ "resolve_oa_url",
143
+ "run_relevance_gate",
144
+ "search_multilingual",
145
+ "search_parallel",
146
+ "search_provider",
147
+ "translate_query",
148
+ ]
149
+
150
+ __version__ = "0.1.0"
@@ -0,0 +1,29 @@
1
+ """Optional MinerU parse service integration.
2
+
3
+ The multilingual workflow uses MinerU for early PDF parsing before the
4
+ relevance gate. When the ``parse_document`` module is not available
5
+ (e.g. when lit-acquisition is used standalone), batch parsing is skipped
6
+ and the relevance gate falls back to PyMuPDF text extraction.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+
12
+ def create_parse_service():
13
+ """Create a parse service instance.
14
+
15
+ Returns:
16
+ A parse service object with ``parse_local_files`` method.
17
+
18
+ Raises:
19
+ ImportError: When the parse_document module is not available.
20
+ """
21
+ try:
22
+ from lit_acquisition_parse_document import create_parse_service as _create
23
+ except ImportError as exc:
24
+ raise ImportError(
25
+ "MinerU parse service is not available. "
26
+ "Install the 'lit-acquisition-parse' extra or use the workflow "
27
+ "without early batch parsing."
28
+ ) from exc
29
+ return _create()
@@ -0,0 +1,26 @@
1
+ """Optional Rust native extension loader.
2
+
3
+ When the ``rust-io`` package is installed, HTTP I/O is handled by the
4
+ fast Rust extension. When it is not available, the module falls back
5
+ to ``None``, and the gateway uses ``httpx`` as a pure-Python fallback.
6
+
7
+ Install the Rust extension for better performance::
8
+
9
+ pip install rust-io
10
+ """
11
+
12
+ from __future__ import annotations
13
+
14
+ from loguru import logger
15
+
16
+ NET_AVAILABLE: bool = False
17
+ net_io = None
18
+
19
+ _NATIVE_IMPORT_ERRORS = (ImportError, RuntimeError, SystemError, OSError)
20
+
21
+ try:
22
+ import rust_io.net as net_io # noqa: F401
23
+
24
+ NET_AVAILABLE = True
25
+ except _NATIVE_IMPORT_ERRORS:
26
+ logger.debug("rust_io.net not available - using httpx fallback for HTTP I/O")