rail-engine 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 (31) hide show
  1. rail_engine-0.1.0/LICENSE +21 -0
  2. rail_engine-0.1.0/MANIFEST.in +7 -0
  3. rail_engine-0.1.0/PKG-INFO +152 -0
  4. rail_engine-0.1.0/README-INGEST.md +91 -0
  5. rail_engine-0.1.0/README-RETRIEVAL.md +128 -0
  6. rail_engine-0.1.0/README.md +233 -0
  7. rail_engine-0.1.0/pyproject.toml +41 -0
  8. rail_engine-0.1.0/rail_engine.egg-info/PKG-INFO +152 -0
  9. rail_engine-0.1.0/rail_engine.egg-info/SOURCES.txt +29 -0
  10. rail_engine-0.1.0/rail_engine.egg-info/dependency_links.txt +1 -0
  11. rail_engine-0.1.0/rail_engine.egg-info/requires.txt +2 -0
  12. rail_engine-0.1.0/rail_engine.egg-info/top_level.txt +1 -0
  13. rail_engine-0.1.0/railtown/engine/__init__.py +25 -0
  14. rail_engine-0.1.0/railtown/engine/auth.py +68 -0
  15. rail_engine-0.1.0/railtown/engine/client.py +431 -0
  16. rail_engine-0.1.0/railtown/engine/embeddings.py +90 -0
  17. rail_engine-0.1.0/railtown/engine/exceptions.py +53 -0
  18. rail_engine-0.1.0/railtown/engine/indexing.py +88 -0
  19. rail_engine-0.1.0/railtown/engine/models.py +92 -0
  20. rail_engine-0.1.0/railtown/engine/storage.py +334 -0
  21. rail_engine-0.1.0/railtown/engine/utils.py +85 -0
  22. rail_engine-0.1.0/setup.cfg +4 -0
  23. rail_engine-0.1.0/tests/test_embeddings.py +125 -0
  24. rail_engine-0.1.0/tests/test_indexing.py +127 -0
  25. rail_engine-0.1.0/tests/test_ingest_auth.py +93 -0
  26. rail_engine-0.1.0/tests/test_ingest_client.py +256 -0
  27. rail_engine-0.1.0/tests/test_retrieval_auth.py +107 -0
  28. rail_engine-0.1.0/tests/test_retrieval_client.py +132 -0
  29. rail_engine-0.1.0/tests/test_storage.py +556 -0
  30. rail_engine-0.1.0/tests/test_utils.py +227 -0
  31. rail_engine-0.1.0/tests/test_webhook_handler.py +270 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Railtown AI
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,7 @@
1
+ # Include custom README files for both packages
2
+ include README-INGEST.md
3
+ include README-RETRIEVAL.md
4
+ # Include standard README.md (for backward compatibility)
5
+ include README.md
6
+ # Include LICENSE
7
+ include LICENSE
@@ -0,0 +1,152 @@
1
+ Metadata-Version: 2.4
2
+ Name: rail-engine
3
+ Version: 0.1.0
4
+ Summary: Python SDK for Railtown AI Rail Engine - Retrieval
5
+ Author-email: Railtown AI <support@railtown.ai>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/railtownai/railengine-sdk
8
+ Project-URL: Documentation, https://github.com/railtownai/railengine-sdk
9
+ Project-URL: Repository, https://github.com/railtownai/railengine-sdk
10
+ Keywords: railtown,rail-engine,retrieval,sdk
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Requires-Python: >=3.10
19
+ Description-Content-Type: text/markdown
20
+ License-File: LICENSE
21
+ Requires-Dist: httpx>=0.24.0
22
+ Requires-Dist: pydantic>=1.10.0
23
+ Dynamic: license-file
24
+
25
+ # Rail Engine Retrieval SDK
26
+
27
+ Python SDK for retrieving and searching data from Railtown AI Rail Engine - handles embeddings, storage documents, and indexed content.
28
+
29
+ ## Overview
30
+
31
+ The `rail-engine` package provides a Pythonic interface for retrieving and searching data from Rail Engine. It supports async/await patterns, client-side filtering, automatic pagination, and Pydantic model deserialization.
32
+
33
+ ## Installation
34
+
35
+ ```bash
36
+ pip install rail-engine
37
+ ```
38
+
39
+ Or using `uv`:
40
+
41
+ ```bash
42
+ uv pip install rail-engine
43
+ ```
44
+
45
+ ## Quick Start
46
+
47
+ ```python
48
+ import asyncio
49
+ from railtown.engine import RailEngine
50
+
51
+ async def main():
52
+ # Initialize client (reads from ENGINE_PAT and ENGINE_ID env vars)
53
+ async with RailEngine() as client:
54
+ # Search vector store
55
+ results = client.search_vector_store(
56
+ engine_id=client.engine_id,
57
+ vector_store="VectorStore1",
58
+ query="apple"
59
+ )
60
+ async for item in results:
61
+ print(item)
62
+
63
+ asyncio.run(main())
64
+ ```
65
+
66
+ ## Configuration
67
+
68
+ ### Environment Variables
69
+
70
+ - `ENGINE_PAT` (required) - Personal Access Token
71
+ - `ENGINE_ID` (required) - Engine ID (can also be passed to constructor)
72
+ - `RAILTOWN_API_URL` (optional) - Base API URL (defaults to `https://cndr.railtown.ai/api`)
73
+
74
+ ### Constructor Parameters
75
+
76
+ - `pat` (optional) - PAT token (if not provided, reads from `ENGINE_PAT` env)
77
+ - `engine_id` (optional) - Engine ID (if not provided, reads from `ENGINE_ID` env, required if not in env)
78
+ - `api_url` (optional) - Base API URL (if not provided, reads from `RAILTOWN_API_URL` env or defaults to production)
79
+ - `model` (optional) - Pydantic model type for deserializing retrieved data
80
+
81
+ ## Features
82
+
83
+ - **Multiple retrieval methods**:
84
+ - `search_vector_store()` - Semantic search in vector stores
85
+ - `get_storage_document_by_id()` - Get document by ID
86
+ - `get_storage_document_by_customer_key()` - Get documents by customer key
87
+ - `query_storage_by_jsonpath()` - Query using JSONPath
88
+ - `list_storage_documents()` - List all documents with pagination
89
+ - `search_index()` - Full-text search using Azure Search
90
+ - **Client-side filtering** - Filter results using `filter_fn` parameter
91
+ - **Automatic pagination** - Handles pagination automatically
92
+ - **Model deserialization** - Optional Pydantic model support with per-call override
93
+ - **Graceful error handling** - Returns None or empty iterables on errors
94
+ - **Async/await support** - Built for modern async Python applications
95
+
96
+ ## API Reference
97
+
98
+ ### RailEngine Client
99
+
100
+ #### Methods
101
+
102
+ - `search_vector_store(engine_id, vector_store, query, filter_fn=None, model=None)` - Search vector store
103
+ - `get_storage_document_by_id(engine_id, engine_document_id, filter_fn=None, model=None)` - Get document by ID
104
+ - `get_storage_document_by_customer_key(engine_id, customer_key, page_number=1, page_size=25, filter_fn=None, model=None)` - Get documents by customer key
105
+ - `query_storage_by_jsonpath(engine_id, json_path_query, filter_fn=None, model=None)` - Query by JSONPath
106
+ - `list_storage_documents(engine_id, customer_key=None, page_number=1, page_size=100, filter_fn=None, model=None)` - List documents
107
+ - `search_index(project_id, engine_id, query, filter_fn=None, model=None)` - Search index
108
+
109
+ #### Properties
110
+
111
+ - `pat` - PAT token
112
+ - `engine_id` - Engine ID
113
+ - `api_url` - Base API URL
114
+ - `model` - Default model type
115
+
116
+ ## Examples
117
+
118
+ See the [`samples/`](https://github.com/railtownai/railengine-sdk/tree/main/samples) directory for comprehensive examples:
119
+
120
+ - [`samples/retrieval_example.py`](https://github.com/railtownai/railengine-sdk/blob/main/samples/retrieval_example.py) - Retrieval examples
121
+ - [`samples/README.md`](https://github.com/railtownai/railengine-sdk/blob/main/samples/README.md) - Samples documentation
122
+
123
+ ## Error Handling
124
+
125
+ The SDK provides custom exception classes:
126
+
127
+ - `RailtownError` - Base exception
128
+ - `RailtownBadRequestError` - 400 Bad Request
129
+ - `RailtownUnauthorizedError` - 401 Unauthorized
130
+ - `RailtownNotFoundError` - 404 Not Found
131
+ - `RailtownConflictError` - 409 Conflict
132
+ - `RailtownServerError` - 5xx Server errors
133
+
134
+ Returns `None` or empty iterables on errors (graceful degradation).
135
+
136
+ ## Requirements
137
+
138
+ - Python 3.10+
139
+ - httpx >= 0.24.0
140
+ - pydantic >= 1.10.0
141
+
142
+ ## Related Package
143
+
144
+ For ingesting data into Rail Engine, see [`rail-engine-ingest`](https://pypi.org/project/rail-engine-ingest/).
145
+
146
+ ## License
147
+
148
+ MIT
149
+
150
+ ## Support
151
+
152
+ For issues, questions, or contributions, please visit the [GitHub repository](https://github.com/railtownai/railengine-sdk).
@@ -0,0 +1,91 @@
1
+ # Rail Engine Ingestion SDK
2
+
3
+ Python SDK for ingesting data into Railtown AI Rail Engine - handles embeddings, storage, indexing, and webhook publishing.
4
+
5
+ ## Overview
6
+
7
+ The `rail-engine-ingest` package provides a Pythonic interface for publishing data to Rail Engine. It supports async/await patterns, Pydantic model validation, and familiar configuration patterns.
8
+
9
+ ## Installation
10
+
11
+ ```bash
12
+ uv pip install rail-engine-ingest
13
+ ```
14
+
15
+ ## Quick Start
16
+
17
+ ```python
18
+
19
+ # Copy your ENGINE_TOKEN from https://cndr.railtown.ai Project Settings
20
+
21
+ import asyncio
22
+ from railtown.engine.ingest import RailEngineIngest
23
+ import base64
24
+ import json
25
+
26
+ engine_token = os.getenv("ENGINE_TOKEN")
27
+
28
+ async def main():
29
+ # Initialize client
30
+ async with RailEngineIngest(engine_token=engine_token) as client:
31
+ # Ingest data
32
+ data = {
33
+ "name": "Chicken Shawarma",
34
+ "meal": "lunch",
35
+ "calories": 95
36
+ }
37
+ response = await client.upsert(data)
38
+ print(f"Status: {response.status_code}")
39
+
40
+ asyncio.run(main())
41
+ ```
42
+
43
+ ## Configuration
44
+
45
+ ### Environment Variable
46
+
47
+ - `ENGINE_TOKEN` - Base64-encoded JSON string containing ingestion credentials
48
+
49
+ ### Constructor Parameters
50
+
51
+ - `engine_token` (optional) - ENGINE_TOKEN string (if not provided, reads from env)
52
+ - `model` (optional) - Pydantic model type for validating ingested data
53
+
54
+ ## Features
55
+
56
+ - **Single `upsert()` method** - Unified interface for ingesting data
57
+ - **Multiple data formats** - Accepts Pydantic models, dictionaries, or JSON strings
58
+ - **Model validation** - Optional Pydantic model validation
59
+ - **Direct JSON payload** - Sends data directly as JSON to the ingestion endpoint
60
+ - **Async/await support** - Built for modern async Python applications
61
+
62
+ ## Error Handling
63
+
64
+ The SDK provides custom exception classes:
65
+
66
+ - `RailtownError` - Base exception
67
+ - `RailtownBadRequestError` - 400 Bad Request
68
+ - `RailtownUnauthorizedError` - 401 Unauthorized
69
+ - `RailtownNotFoundError` - 404 Not Found
70
+ - `RailtownConflictError` - 409 Conflict
71
+ - `RailtownServerError` - 5xx Server errors
72
+
73
+ Exceptions are raised on errors.
74
+
75
+ ## Requirements
76
+
77
+ - Python 3.10+
78
+ - httpx >= 0.24.0
79
+ - pydantic >= 1.10.0
80
+
81
+ ## Related Package
82
+
83
+ For retrieving and searching data from Rail Engine, see [`rail-engine`](https://pypi.org/project/rail-engine/).
84
+
85
+ ## License
86
+
87
+ MIT
88
+
89
+ ## Support
90
+
91
+ For issues, questions, or contributions, please visit the [GitHub repository](https://github.com/railtownai/railengine-sdk).
@@ -0,0 +1,128 @@
1
+ # Rail Engine Retrieval SDK
2
+
3
+ Python SDK for retrieving and searching data from Railtown AI Rail Engine - handles embeddings, storage documents, and indexed content.
4
+
5
+ ## Overview
6
+
7
+ The `rail-engine` package provides a Pythonic interface for retrieving and searching data from Rail Engine. It supports async/await patterns, client-side filtering, automatic pagination, and Pydantic model deserialization.
8
+
9
+ ## Installation
10
+
11
+ ```bash
12
+ pip install rail-engine
13
+ ```
14
+
15
+ Or using `uv`:
16
+
17
+ ```bash
18
+ uv pip install rail-engine
19
+ ```
20
+
21
+ ## Quick Start
22
+
23
+ ```python
24
+ import asyncio
25
+ from railtown.engine import RailEngine
26
+
27
+ async def main():
28
+ # Initialize client (reads from ENGINE_PAT and ENGINE_ID env vars)
29
+ async with RailEngine() as client:
30
+ # Search vector store
31
+ results = client.search_vector_store(
32
+ engine_id=client.engine_id,
33
+ vector_store="VectorStore1",
34
+ query="apple"
35
+ )
36
+ async for item in results:
37
+ print(item)
38
+
39
+ asyncio.run(main())
40
+ ```
41
+
42
+ ## Configuration
43
+
44
+ ### Environment Variables
45
+
46
+ - `ENGINE_PAT` (required) - Personal Access Token
47
+ - `ENGINE_ID` (required) - Engine ID (can also be passed to constructor)
48
+ - `RAILTOWN_API_URL` (optional) - Base API URL (defaults to `https://cndr.railtown.ai/api`)
49
+
50
+ ### Constructor Parameters
51
+
52
+ - `pat` (optional) - PAT token (if not provided, reads from `ENGINE_PAT` env)
53
+ - `engine_id` (optional) - Engine ID (if not provided, reads from `ENGINE_ID` env, required if not in env)
54
+ - `api_url` (optional) - Base API URL (if not provided, reads from `RAILTOWN_API_URL` env or defaults to production)
55
+ - `model` (optional) - Pydantic model type for deserializing retrieved data
56
+
57
+ ## Features
58
+
59
+ - **Multiple retrieval methods**:
60
+ - `search_vector_store()` - Semantic search in vector stores
61
+ - `get_storage_document_by_id()` - Get document by ID
62
+ - `get_storage_document_by_customer_key()` - Get documents by customer key
63
+ - `query_storage_by_jsonpath()` - Query using JSONPath
64
+ - `list_storage_documents()` - List all documents with pagination
65
+ - `search_index()` - Full-text search using Azure Search
66
+ - **Client-side filtering** - Filter results using `filter_fn` parameter
67
+ - **Automatic pagination** - Handles pagination automatically
68
+ - **Model deserialization** - Optional Pydantic model support with per-call override
69
+ - **Graceful error handling** - Returns None or empty iterables on errors
70
+ - **Async/await support** - Built for modern async Python applications
71
+
72
+ ## API Reference
73
+
74
+ ### RailEngine Client
75
+
76
+ #### Methods
77
+
78
+ - `search_vector_store(engine_id, vector_store, query, filter_fn=None, model=None)` - Search vector store
79
+ - `get_storage_document_by_id(engine_id, engine_document_id, filter_fn=None, model=None)` - Get document by ID
80
+ - `get_storage_document_by_customer_key(engine_id, customer_key, page_number=1, page_size=25, filter_fn=None, model=None)` - Get documents by customer key
81
+ - `query_storage_by_jsonpath(engine_id, json_path_query, filter_fn=None, model=None)` - Query by JSONPath
82
+ - `list_storage_documents(engine_id, customer_key=None, page_number=1, page_size=100, filter_fn=None, model=None)` - List documents
83
+ - `search_index(project_id, engine_id, query, filter_fn=None, model=None)` - Search index
84
+
85
+ #### Properties
86
+
87
+ - `pat` - PAT token
88
+ - `engine_id` - Engine ID
89
+ - `api_url` - Base API URL
90
+ - `model` - Default model type
91
+
92
+ ## Examples
93
+
94
+ See the [`samples/`](https://github.com/railtownai/railengine-sdk/tree/main/samples) directory for comprehensive examples:
95
+
96
+ - [`samples/retrieval_example.py`](https://github.com/railtownai/railengine-sdk/blob/main/samples/retrieval_example.py) - Retrieval examples
97
+ - [`samples/README.md`](https://github.com/railtownai/railengine-sdk/blob/main/samples/README.md) - Samples documentation
98
+
99
+ ## Error Handling
100
+
101
+ The SDK provides custom exception classes:
102
+
103
+ - `RailtownError` - Base exception
104
+ - `RailtownBadRequestError` - 400 Bad Request
105
+ - `RailtownUnauthorizedError` - 401 Unauthorized
106
+ - `RailtownNotFoundError` - 404 Not Found
107
+ - `RailtownConflictError` - 409 Conflict
108
+ - `RailtownServerError` - 5xx Server errors
109
+
110
+ Returns `None` or empty iterables on errors (graceful degradation).
111
+
112
+ ## Requirements
113
+
114
+ - Python 3.10+
115
+ - httpx >= 0.24.0
116
+ - pydantic >= 1.10.0
117
+
118
+ ## Related Package
119
+
120
+ For ingesting data into Rail Engine, see [`rail-engine-ingest`](https://pypi.org/project/rail-engine-ingest/).
121
+
122
+ ## License
123
+
124
+ MIT
125
+
126
+ ## Support
127
+
128
+ For issues, questions, or contributions, please visit the [GitHub repository](https://github.com/railtownai/railengine-sdk).
@@ -0,0 +1,233 @@
1
+ # Rail Engine Python SDK
2
+
3
+ Python SDK for Railtown AI Rail Engine - providing a Pythonic interface for ingesting and retrieving data from Rail Engine.
4
+
5
+ ## Overview
6
+
7
+ The Rail Engine Python SDK is split into two separate packages:
8
+
9
+ - **`rail-engine-ingest`** - For publishing data to Rail Engine (handles embeddings, storage, indexing, and webhook publishing)
10
+ - **`rail-engine`** - For retrieving and searching data (embeddings, storage documents, and indexed content)
11
+
12
+ Both packages support:
13
+
14
+ - Async/await patterns
15
+ - Client-side filtering
16
+ - Automatic pagination
17
+ - Pydantic model support for type safety
18
+ - Familiar configuration patterns (like OpenAI SDK)
19
+
20
+ ## Installation
21
+
22
+ ### Ingestion Package
23
+
24
+ ```bash
25
+ uv pip install rail-engine-ingest
26
+ ```
27
+
28
+ ### Retrieval Package
29
+
30
+ ```bash
31
+ uv pip install rail-engine
32
+ ```
33
+
34
+ ### Both Packages
35
+
36
+ ```bash
37
+ uv pip install rail-engine-ingest rail-engine
38
+ ```
39
+
40
+ ## Quick Start
41
+
42
+ ### Ingestion
43
+
44
+ ```python
45
+ import asyncio
46
+ from railtown.engine.ingest import RailEngineIngest
47
+ import base64
48
+ import json
49
+
50
+ # Create ENGINE_TOKEN (base64-encoded JSON)
51
+ token_data = {
52
+ "IngestionUrl": "https://eng123.railtownlogs.com",
53
+ "IngestionApiToken": "your-auth-token",
54
+ "EngineId": "your-engine-guid"
55
+ }
56
+ engine_token = base64.b64encode(json.dumps(token_data).encode()).decode()
57
+
58
+ async def main():
59
+ # Initialize client
60
+ async with RailEngineIngest(engine_token=engine_token) as client:
61
+ # Ingest data
62
+ data = {
63
+ "EventId": "event-123",
64
+ "ProjectId": "project-456",
65
+ "food_name": "Apple",
66
+ "calories": 95
67
+ }
68
+ response = await client.upsert(data)
69
+ print(f"Status: {response.status_code}")
70
+
71
+ asyncio.run(main())
72
+ ```
73
+
74
+ ### Retrieval
75
+
76
+ ```python
77
+ import asyncio
78
+ from railtown.engine import RailEngine
79
+
80
+ async def main():
81
+ # Initialize client (reads from ENGINE_PAT and ENGINE_ID env vars)
82
+ async with RailEngine() as client:
83
+ # Search vector store
84
+ results = client.search_vector_store(
85
+ engine_id=client.engine_id,
86
+ vector_store="VectorStore1",
87
+ query="apple"
88
+ )
89
+ async for item in results:
90
+ print(item)
91
+
92
+ asyncio.run(main())
93
+ ```
94
+
95
+ ## Configuration
96
+
97
+ ### Ingestion (`rail-engine-ingest`)
98
+
99
+ **Environment Variable:**
100
+
101
+ - `ENGINE_TOKEN` - Base64-encoded JSON string containing ingestion credentials
102
+
103
+ **Constructor Parameters:**
104
+
105
+ - `engine_token` (optional) - ENGINE_TOKEN string (if not provided, reads from env)
106
+ - `model` (optional) - Pydantic model type for validating ingested data
107
+
108
+ ### Retrieval (`rail-engine`)
109
+
110
+ **Environment Variables:**
111
+
112
+ - `ENGINE_PAT` (required) - Personal Access Token
113
+ - `ENGINE_ID` (required) - Engine ID (can also be passed to constructor)
114
+ - `RAILTOWN_API_URL` (optional) - Base API URL (defaults to `https://cndr.railtown.ai/api`)
115
+
116
+ **Constructor Parameters:**
117
+
118
+ - `pat` (optional) - PAT token (if not provided, reads from `ENGINE_PAT` env)
119
+ - `engine_id` (optional) - Engine ID (if not provided, reads from `ENGINE_ID` env, required if not in env)
120
+ - `api_url` (optional) - Base API URL (if not provided, reads from `RAILTOWN_API_URL` env or defaults to production)
121
+ - `model` (optional) - Pydantic model type for deserializing retrieved data
122
+
123
+ ## Features
124
+
125
+ ### Ingestion Features
126
+
127
+ - **Single `upsert()` method** - Unified interface for ingesting data
128
+ - **Multiple data formats** - Accepts Pydantic models, dictionaries, or JSON strings
129
+ - **Model validation** - Optional Pydantic model validation
130
+ - **Direct JSON payload** - Sends data directly as JSON to the ingestion endpoint
131
+ - **UTF-8 encoding** - All text operations use UTF-8
132
+
133
+ ### Retrieval Features
134
+
135
+ - **Multiple retrieval methods**:
136
+ - `search_vector_store()` - Semantic search in vector stores
137
+ - `get_storage_document_by_id()` - Get document by ID
138
+ - `get_storage_document_by_customer_key()` - Get documents by customer key
139
+ - `query_storage_by_jsonpath()` - Query using JSONPath
140
+ - `list_storage_documents()` - List all documents with pagination
141
+ - `search_index()` - Full-text search using Azure Search
142
+ - **Client-side filtering** - Filter results using `filter_fn` parameter
143
+ - **Automatic pagination** - Handles pagination automatically
144
+ - **Model deserialization** - Optional Pydantic model support with per-call override
145
+ - **Graceful error handling** - Returns None or empty iterables on errors
146
+
147
+ ## Examples
148
+
149
+ See the [`samples/`](samples/) directory for comprehensive examples:
150
+
151
+ - [`samples/ingestion_example.py`](samples/ingestion_example.py) - Ingestion examples
152
+ - [`samples/retrieval_example.py`](samples/retrieval_example.py) - Retrieval examples
153
+ - [`samples/README.md`](samples/README.md) - Samples documentation
154
+
155
+ ## API Reference
156
+
157
+ ### Ingestion Client (`RailEngineIngest`)
158
+
159
+ #### Methods
160
+
161
+ - `upsert(data)` - Upsert data to Rail Engine
162
+ - Accepts: Pydantic model instance, dict, or JSON string
163
+ - Returns: HTTP response
164
+
165
+ #### Properties
166
+
167
+ - `ingestion_url` - Ingestion URL from decoded ENGINE_TOKEN
168
+ - `ingestion_api_token` - API token from decoded ENGINE_TOKEN
169
+ - `engine_id` - Engine ID from decoded ENGINE_TOKEN
170
+
171
+ ### Retrieval Client (`RailEngine`)
172
+
173
+ #### Methods
174
+
175
+ - `search_vector_store(engine_id, vector_store, query, filter_fn=None, model=None)` - Search vector store
176
+ - `get_storage_document_by_id(engine_id, engine_document_id, filter_fn=None, model=None)` - Get document by ID
177
+ - `get_storage_document_by_customer_key(engine_id, customer_key, page_number=1, page_size=25, filter_fn=None, model=None)` - Get documents by customer key
178
+ - `query_storage_by_jsonpath(engine_id, json_path_query, filter_fn=None, model=None)` - Query by JSONPath
179
+ - `list_storage_documents(engine_id, customer_key=None, page_number=1, page_size=100, filter_fn=None, model=None)` - List documents
180
+ - `search_index(project_id, engine_id, query, filter_fn=None, model=None)` - Search index
181
+
182
+ #### Properties
183
+
184
+ - `pat` - PAT token
185
+ - `engine_id` - Engine ID
186
+ - `api_url` - Base API URL
187
+ - `model` - Default model type
188
+
189
+ ## Error Handling
190
+
191
+ The SDK provides custom exception classes:
192
+
193
+ - `RailtownError` - Base exception
194
+ - `RailtownBadRequestError` - 400 Bad Request
195
+ - `RailtownUnauthorizedError` - 401 Unauthorized
196
+ - `RailtownNotFoundError` - 404 Not Found
197
+ - `RailtownConflictError` - 409 Conflict
198
+ - `RailtownServerError` - 5xx Server errors
199
+
200
+ **Ingestion**: Raises exceptions on errors
201
+ **Retrieval**: Returns `None` or empty iterables on errors (graceful degradation)
202
+
203
+ ## Requirements
204
+
205
+ - Python 3.10+
206
+ - httpx >= 0.24.0
207
+ - pydantic >= 1.10.0
208
+
209
+ ## Testing
210
+
211
+ Run the test suite:
212
+
213
+ ```bash
214
+ # Install development dependencies
215
+ uv pip install -r requirements-dev.txt
216
+
217
+ # Run all tests
218
+ pytest
219
+
220
+ # Run with coverage
221
+ pytest --cov=railtown --cov-report=html
222
+
223
+ # Run specific test file
224
+ pytest tests/test_ingest_client.py
225
+ ```
226
+
227
+ ## License
228
+
229
+ MIT
230
+
231
+ ## Support
232
+
233
+ For issues, questions, or contributions, please visit the [GitHub repository](https://github.com/railtownai/railengine-sdk).
@@ -0,0 +1,41 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.0", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "rail-engine"
7
+ version = "0.1.0"
8
+ description = "Python SDK for Railtown AI Rail Engine - Retrieval"
9
+ readme = "README-RETRIEVAL.md"
10
+ requires-python = ">=3.10"
11
+ authors = [
12
+ {name = "Railtown AI", email = "support@railtown.ai"}
13
+ ]
14
+ license = {text = "MIT"}
15
+ keywords = ["railtown", "rail-engine", "retrieval", "sdk"]
16
+ classifiers = [
17
+ "Development Status :: 4 - Beta",
18
+ "Intended Audience :: Developers",
19
+ "License :: OSI Approved :: MIT License",
20
+ "Programming Language :: Python :: 3",
21
+ "Programming Language :: Python :: 3.10",
22
+ "Programming Language :: Python :: 3.11",
23
+ "Programming Language :: Python :: 3.12",
24
+ ]
25
+ dependencies = [
26
+ "httpx>=0.24.0",
27
+ "pydantic>=1.10.0",
28
+ ]
29
+
30
+ [project.urls]
31
+ Homepage = "https://github.com/railtownai/railengine-sdk"
32
+ Documentation = "https://github.com/railtownai/railengine-sdk"
33
+ Repository = "https://github.com/railtownai/railengine-sdk"
34
+
35
+ [tool.setuptools.packages.find]
36
+ include = ["railtown.engine*"]
37
+ exclude = ["railtown.engine.ingest*"]
38
+ namespaces = false
39
+
40
+ [tool.setuptools.package-data]
41
+ "*" = ["py.typed"]