purestrata 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 (39) hide show
  1. purestrata-0.1.0/.gitignore +12 -0
  2. purestrata-0.1.0/LICENSE +21 -0
  3. purestrata-0.1.0/PKG-INFO +227 -0
  4. purestrata-0.1.0/README.md +202 -0
  5. purestrata-0.1.0/examples/api_tool_use.py +85 -0
  6. purestrata-0.1.0/examples/data/cad/bracket_mk3.dxf +260 -0
  7. purestrata-0.1.0/examples/data/failures/plant_failures.csv +9 -0
  8. purestrata-0.1.0/examples/data/manuals/ja/cnc_press_maintenance.md +34 -0
  9. purestrata-0.1.0/examples/data/manuals/lathe_mk3_maintenance.md +44 -0
  10. purestrata-0.1.0/examples/quickstart.py +67 -0
  11. purestrata-0.1.0/pyproject.toml +71 -0
  12. purestrata-0.1.0/src/purestrata/__init__.py +67 -0
  13. purestrata-0.1.0/src/purestrata/cli.py +161 -0
  14. purestrata-0.1.0/src/purestrata/corpus.py +78 -0
  15. purestrata-0.1.0/src/purestrata/export/__init__.py +15 -0
  16. purestrata-0.1.0/src/purestrata/export/finetune.py +214 -0
  17. purestrata-0.1.0/src/purestrata/ingest/__init__.py +7 -0
  18. purestrata-0.1.0/src/purestrata/ingest/cad.py +253 -0
  19. purestrata-0.1.0/src/purestrata/ingest/failures.py +145 -0
  20. purestrata-0.1.0/src/purestrata/ingest/manual.py +404 -0
  21. purestrata-0.1.0/src/purestrata/mcp_server.py +96 -0
  22. purestrata-0.1.0/src/purestrata/pipeline/__init__.py +6 -0
  23. purestrata-0.1.0/src/purestrata/pipeline/chunk.py +66 -0
  24. purestrata-0.1.0/src/purestrata/pipeline/clean.py +31 -0
  25. purestrata-0.1.0/src/purestrata/search.py +110 -0
  26. purestrata-0.1.0/src/purestrata/tools/__init__.py +13 -0
  27. purestrata-0.1.0/src/purestrata/tools/executor.py +185 -0
  28. purestrata-0.1.0/src/purestrata/tools/schemas.py +209 -0
  29. purestrata-0.1.0/src/purestrata/types.py +122 -0
  30. purestrata-0.1.0/tests/conftest.py +47 -0
  31. purestrata-0.1.0/tests/test_cli.py +69 -0
  32. purestrata-0.1.0/tests/test_corpus.py +56 -0
  33. purestrata-0.1.0/tests/test_export.py +66 -0
  34. purestrata-0.1.0/tests/test_ingest_cad.py +47 -0
  35. purestrata-0.1.0/tests/test_ingest_failures.py +51 -0
  36. purestrata-0.1.0/tests/test_ingest_manual.py +106 -0
  37. purestrata-0.1.0/tests/test_mcp.py +60 -0
  38. purestrata-0.1.0/tests/test_search.py +69 -0
  39. purestrata-0.1.0/tests/test_tools.py +110 -0
@@ -0,0 +1,12 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ .venv/
4
+ dist/
5
+ build/
6
+ *.egg-info/
7
+ .pytest_cache/
8
+ .ruff_cache/
9
+ examples/corpus/
10
+ examples/output/
11
+ .env
12
+ .DS_Store
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Daiki Ito
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,227 @@
1
+ Metadata-Version: 2.5
2
+ Name: purestrata
3
+ Version: 0.1.0
4
+ Summary: Open data layer for manufacturing AI: structure drawings, spec sheets, and failure knowledge into LLM tools and fine-tuning datasets.
5
+ Project-URL: Homepage, https://github.com/daikiito-dk/PureStrata
6
+ Project-URL: Repository, https://github.com/daikiito-dk/PureStrata
7
+ Author: Daiki Ito
8
+ License-Expression: MIT
9
+ License-File: LICENSE
10
+ Keywords: cad,dxf,failure-analysis,fine-tuning,llm,manuals,manufacturing,mcp,rag,tool-calling
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.10
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Topic :: Scientific/Engineering
18
+ Classifier: Topic :: Text Processing
19
+ Requires-Python: >=3.10
20
+ Provides-Extra: mcp
21
+ Requires-Dist: mcp>=1.2; extra == 'mcp'
22
+ Provides-Extra: pdf
23
+ Requires-Dist: pypdf>=4.0; extra == 'pdf'
24
+ Description-Content-Type: text/markdown
25
+
26
+ # PureStrata
27
+
28
+ **English** | [日本語](#日本語)
29
+
30
+ The open data layer for manufacturing AI. Ingest **drawings, spec sheets, and failure knowledge** into one portable, provenance-tagged corpus — query it from any LLM through MCP or tool calling, then export the same corpus as **fine-tuning datasets**.
31
+
32
+ Manufacturing is where LLMs struggle most: CAD drawings, dense maintenance manuals, and failure knowledge locked in spreadsheets. Japanese factories in particular hold decades of primary data — drawings, 保全記録, and skilled-worker know-how — that never reaches the open web. PureStrata turns those documents into a structured, auditable layer that model developers and AI teams can actually use.
33
+
34
+ ```
35
+ [ manuals (MD/PDF) ] [ drawings (DXF) ] [ failure logs (CSV/JSONL) ]
36
+ │ │ │
37
+ └─────────────────────┴──────────────────────┘
38
+ ▼
39
+ [ ingest ] clean → structure → provenance
40
+ ▼
41
+ [ corpus ] portable *.strata.jsonl files
42
+ ▼
43
+ ┌─────────────────────┴─────────────────────┐
44
+ ▼ ▼ ▼
45
+ [ MCP server ] [ tool calling (Grok, [ fine-tuning datasets ]
46
+ any MCP client OpenAI, local LLMs) ] chat / tool-trace / CoT
47
+ ```
48
+
49
+ ## Why this exists
50
+
51
+ - **LLMs are weak on manufacturing data.** PDF drawings, CAD files, and complex spec sheets are exactly the data that never made it into pretraining corpora.
52
+ - **Failure knowledge is the missing stratum.** Most RAG stacks retrieve manual text. Factory troubleshooting runs on *symptom → cause → countermeasure* records. PureStrata treats failure cases as first-class structured data.
53
+ - **Provenance is non-negotiable.** Every record carries its source file and locator, so any answer an LLM gives can be audited back to the drawing, section, or spreadsheet row it came from.
54
+ - **No lock-in.** The corpus is plain JSONL you own. Zero required dependencies for the core. Runs on your machine, air-gap friendly.
55
+
56
+ ## Install
57
+
58
+ ```bash
59
+ uv add purestrata # or: pip install purestrata
60
+ pip install "purestrata[pdf]" # optional: PDF manual support (pypdf)
61
+ pip install "purestrata[mcp]" # optional: MCP server support
62
+ ```
63
+
64
+ Python 3.10+ required.
65
+
66
+ ## Quickstart
67
+
68
+ ```bash
69
+ git clone https://github.com/daikiito-dk/PureStrata
70
+ cd PureStrata
71
+ make setup
72
+ make demo # ingest the bundled sample data, then search it
73
+ ```
74
+
75
+ Or step by step:
76
+
77
+ ```bash
78
+ # 1. Ingest manuals, a drawing, and a failure log into a corpus
79
+ purestrata ingest-manual examples/data/manuals/lathe_mk3_maintenance.md --out corpus/
80
+ purestrata ingest-manual examples/data/manuals/ja/cnc_press_maintenance.md --out corpus/
81
+ purestrata ingest-dxf examples/data/cad/bracket_mk3.dxf --out corpus/
82
+ purestrata ingest-failures examples/data/failures/plant_failures.csv --out corpus/
83
+
84
+ # 2. Inspect and search (English and Japanese)
85
+ purestrata inspect --corpus corpus/
86
+ purestrata search "spindle vibration" --corpus corpus/
87
+ purestrata search "ブレーキ 停止時間" --corpus corpus/
88
+
89
+ # 3. Export fine-tuning datasets from the same corpus
90
+ purestrata export chat --corpus corpus/ --out dataset_chat.jsonl
91
+ purestrata export tool_trace --corpus corpus/ --out dataset_tools.jsonl
92
+ purestrata export cot --corpus corpus/ --out dataset_cot.jsonl
93
+ ```
94
+
95
+ ## The three record families
96
+
97
+ | Kind | Source | What the LLM gets |
98
+ | --- | --- | --- |
99
+ | `manual_section` | Markdown / PDF manuals | Clean, chunked spec-sheet passages with section paths |
100
+ | `procedure` | Numbered lists in manuals | Ordered maintenance steps as structured arrays |
101
+ | `safety_notice` | WARNING / CAUTION lines (EN + JA) | Severity-tagged precautions |
102
+ | `part_record` | Parts tables | Part number, name, quantity, spec |
103
+ | `drawing` | ASCII DXF files | Title block, layers, entity counts, annotations, bounds |
104
+ | `failure_case` | CSV / JSONL failure logs | Symptom, root cause, countermeasure, severity, tags |
105
+
106
+ ## Tools (identical over MCP, OpenAI-style calls, and Python)
107
+
108
+ | Tool | Purpose |
109
+ | --- | --- |
110
+ | `list_corpus` | Inventory: record counts by kind, loaded documents |
111
+ | `search_documents` | Ranked passage search (English and Japanese) |
112
+ | `get_safety_notices` | Warnings and cautions, optionally ranked |
113
+ | `get_procedure` | Full ordered steps of one procedure |
114
+ | `search_parts` | Parts lookup from parts lists |
115
+ | `list_drawings` / `get_drawing` | CAD inventory and full drawing metadata |
116
+ | `search_failure_cases` | **Troubleshooting first:** match symptoms against past failures |
117
+ | `get_failure_case` | One full case by ID |
118
+
119
+ ```bash
120
+ purestrata tools openai # JSON schemas ready for Grok / OpenAI / compatible APIs
121
+ purestrata tools anthropic
122
+ ```
123
+
124
+ ## Integrations
125
+
126
+ **Grok / OpenAI / any OpenAI-compatible API** — pass the tool schemas to the chat completions endpoint and execute returned tool calls locally. See `examples/api_tool_use.py`:
127
+
128
+ ```bash
129
+ export PURESTRATA_BASE_URL=https://api.x.ai/v1
130
+ export PURESTRATA_API_KEY=your-key
131
+ uv run python examples/api_tool_use.py "The lathe is vibrating during cutting. What should we check?"
132
+ ```
133
+
134
+ Your corpus is queried locally; results go back to the model with provenance.
135
+
136
+ **MCP (Model Context Protocol)** — run the bundled server and register it with any MCP client:
137
+
138
+ ```json
139
+ { "mcpServers": { "purestrata": { "command": "purestrata", "args": ["serve", "--corpus", "/path/to/corpus"] } } }
140
+ ```
141
+
142
+ **Python API** — the same tools as a library:
143
+
144
+ ```python
145
+ import purestrata as ps
146
+
147
+ chunks = ps.ingest_manual("manual.md") + ps.ingest_failures("failures.csv")
148
+ ps.write_chunks(chunks, "corpus/", "my_doc")
149
+ executor = ps.ToolExecutor(ps.Corpus.load("corpus/"))
150
+ hits = executor.execute("search_failure_cases", {"query": "spindle vibration", "top_k": 3})
151
+ ```
152
+
153
+ ## Fine-tuning exports
154
+
155
+ The same corpus that serves live queries becomes training data:
156
+
157
+ - **chat** — system/user/assistant JSONL accepted by OpenAI's and xAI's fine-tuning APIs
158
+ - **tool_trace** — model-issued tool call → provenance-tagged tool result → grounded answer
159
+ - **cot** — instruction / reasoning / output records for chain-of-thought training
160
+
161
+ CoT records are a deliberate scaffold: they are transparent, grounded in structured fields, and built to be **reviewed and sharpened by maintenance engineers** before training. That expert-in-the-loop pass is where dataset quality comes from — PureStrata keeps the work auditable so it can be done rigorously.
162
+
163
+ ## Status and roadmap
164
+
165
+ Current: local ingestion (Markdown, PDF, ASCII DXF, CSV/JSONL), BM25 search with Japanese support, MCP server, tool schemas, fine-tune exports.
166
+
167
+ Planned: HTML/DXF-R2018 support, STEP files, per-layer geometry search, embedding search, evaluation harness for fine-tune sets, and a hosted SaaS for teams that need managed ingestion, access control, and expert review workflows.
168
+
169
+ ## Development
170
+
171
+ ```bash
172
+ make setup # uv sync (installs dev tools and all extras)
173
+ make lint # ruff check + format check
174
+ make test # pytest
175
+ ```
176
+
177
+ ## License
178
+
179
+ [MIT](LICENSE)
180
+
181
+ ---
182
+
183
+ ## 日本語
184
+
185
+ PureStrata は製造業AIのためのオープンなデータレイヤーです。**図面・仕様書・不具合ナレッジ**を1つのポータブルで出所証明(プロビナンス)付きのコーパスに取り込み、MCPやツール呼び出しでどのLLMからでも検索でき、同じコーパスから**微調整用データセット**を書き出せます。
186
+
187
+ 製造業はLLMが最も苦手とする領域です。CAD図面、高密度な保全マニュアル、そしてスプレッドシートに閉じ込められた不具合ナレッジ。特に日本の工場には、図面・保全記録・熟練工のノウハウという、Web上に存在しない一次データが蓄積されています。PureStrataはそれらの文書を、構造化され監査可能なデータ層に変換します。
188
+
189
+ ### 特徴
190
+
191
+ - **3つのレコード族を第一級データとして扱う**: 仕様書(`manual_section` / `procedure` / `safety_notice` / `part_record`)、図面(DXFタイトルブロック・レイヤー・注記)、不具合ナレッジ(現象→原因→対策)。特に「不具合ナレッジ」は通常のRAGには欠けている層で、工場のトラブルシューティングの中核です。
192
+ - **完全な出所証明**: すべてのレコードが元ファイルと位置情報を保持し、LLMの回答がどの図面・セクション・行に遡れるか監査できます。
193
+ - **ロックインなし**: コーパスはプレーンなJSONL。コアは依存ゼロ。ローカル実行でエアギップ環境にも対応します。
194
+ - **日本語対応検索**: 依存ゼロのBM25実装がCJKバイグラム解析に対応し、日本語の不具合記録もそのまま検索できます。
195
+ - **Grok / OpenAI / ローカルLLM対応**: OpenAI互換のツール呼び出し用スキーマと、MCPサーバーの両方を同梱。特定モデルへの依存はありません。
196
+
197
+ ### クイックスタート
198
+
199
+ ```bash
200
+ git clone https://github.com/daikiito-dk/PureStrata
201
+ cd PureStrata
202
+ make setup
203
+ make demo # サンプルデータを取り込んで検索
204
+
205
+ # 手順で実行する場合
206
+ purestrata ingest-manual examples/data/manuals/ja/cnc_press_maintenance.md --out corpus/
207
+ purestrata ingest-dxf examples/data/cad/bracket_mk3.dxf --out corpus/
208
+ purestrata ingest-failures examples/data/failures/plant_failures.csv --out corpus/
209
+ purestrata search "ブレーキ 停止時間" --corpus corpus/
210
+ purestrata export cot --corpus corpus/ --out dataset_cot.jsonl
211
+ ```
212
+
213
+ ### 微調整用データセット
214
+
215
+ `chat`(OpenAI / xAIファインチューニングAPI対応のメッセージ形式)、`tool_trace`(ツール呼び出し→出所付き結果→根拠ある回答)、`cot`(推論過程付き問答)の3形式で書き出せます。CoTレコードは構造化フィールドから生成される透明な雛形であり、保全エンジニアによるレビュー・推敲(ヒューマン・イン・ザ・ループ)を前提に設計されています。データ品質はその専門家レビューで決まるため、PureStrataはその作業を監査可能な形で支えます。
216
+
217
+ ### 開発
218
+
219
+ ```bash
220
+ make setup # uv sync
221
+ make lint # ruff
222
+ make test # pytest
223
+ ```
224
+
225
+ ### ライセンス
226
+
227
+ [MIT](LICENSE)
@@ -0,0 +1,202 @@
1
+ # PureStrata
2
+
3
+ **English** | [日本語](#日本語)
4
+
5
+ The open data layer for manufacturing AI. Ingest **drawings, spec sheets, and failure knowledge** into one portable, provenance-tagged corpus — query it from any LLM through MCP or tool calling, then export the same corpus as **fine-tuning datasets**.
6
+
7
+ Manufacturing is where LLMs struggle most: CAD drawings, dense maintenance manuals, and failure knowledge locked in spreadsheets. Japanese factories in particular hold decades of primary data — drawings, 保全記録, and skilled-worker know-how — that never reaches the open web. PureStrata turns those documents into a structured, auditable layer that model developers and AI teams can actually use.
8
+
9
+ ```
10
+ [ manuals (MD/PDF) ] [ drawings (DXF) ] [ failure logs (CSV/JSONL) ]
11
+ │ │ │
12
+ └─────────────────────┴──────────────────────┘
13
+ ▼
14
+ [ ingest ] clean → structure → provenance
15
+ ▼
16
+ [ corpus ] portable *.strata.jsonl files
17
+ ▼
18
+ ┌─────────────────────┴─────────────────────┐
19
+ ▼ ▼ ▼
20
+ [ MCP server ] [ tool calling (Grok, [ fine-tuning datasets ]
21
+ any MCP client OpenAI, local LLMs) ] chat / tool-trace / CoT
22
+ ```
23
+
24
+ ## Why this exists
25
+
26
+ - **LLMs are weak on manufacturing data.** PDF drawings, CAD files, and complex spec sheets are exactly the data that never made it into pretraining corpora.
27
+ - **Failure knowledge is the missing stratum.** Most RAG stacks retrieve manual text. Factory troubleshooting runs on *symptom → cause → countermeasure* records. PureStrata treats failure cases as first-class structured data.
28
+ - **Provenance is non-negotiable.** Every record carries its source file and locator, so any answer an LLM gives can be audited back to the drawing, section, or spreadsheet row it came from.
29
+ - **No lock-in.** The corpus is plain JSONL you own. Zero required dependencies for the core. Runs on your machine, air-gap friendly.
30
+
31
+ ## Install
32
+
33
+ ```bash
34
+ uv add purestrata # or: pip install purestrata
35
+ pip install "purestrata[pdf]" # optional: PDF manual support (pypdf)
36
+ pip install "purestrata[mcp]" # optional: MCP server support
37
+ ```
38
+
39
+ Python 3.10+ required.
40
+
41
+ ## Quickstart
42
+
43
+ ```bash
44
+ git clone https://github.com/daikiito-dk/PureStrata
45
+ cd PureStrata
46
+ make setup
47
+ make demo # ingest the bundled sample data, then search it
48
+ ```
49
+
50
+ Or step by step:
51
+
52
+ ```bash
53
+ # 1. Ingest manuals, a drawing, and a failure log into a corpus
54
+ purestrata ingest-manual examples/data/manuals/lathe_mk3_maintenance.md --out corpus/
55
+ purestrata ingest-manual examples/data/manuals/ja/cnc_press_maintenance.md --out corpus/
56
+ purestrata ingest-dxf examples/data/cad/bracket_mk3.dxf --out corpus/
57
+ purestrata ingest-failures examples/data/failures/plant_failures.csv --out corpus/
58
+
59
+ # 2. Inspect and search (English and Japanese)
60
+ purestrata inspect --corpus corpus/
61
+ purestrata search "spindle vibration" --corpus corpus/
62
+ purestrata search "ブレーキ 停止時間" --corpus corpus/
63
+
64
+ # 3. Export fine-tuning datasets from the same corpus
65
+ purestrata export chat --corpus corpus/ --out dataset_chat.jsonl
66
+ purestrata export tool_trace --corpus corpus/ --out dataset_tools.jsonl
67
+ purestrata export cot --corpus corpus/ --out dataset_cot.jsonl
68
+ ```
69
+
70
+ ## The three record families
71
+
72
+ | Kind | Source | What the LLM gets |
73
+ | --- | --- | --- |
74
+ | `manual_section` | Markdown / PDF manuals | Clean, chunked spec-sheet passages with section paths |
75
+ | `procedure` | Numbered lists in manuals | Ordered maintenance steps as structured arrays |
76
+ | `safety_notice` | WARNING / CAUTION lines (EN + JA) | Severity-tagged precautions |
77
+ | `part_record` | Parts tables | Part number, name, quantity, spec |
78
+ | `drawing` | ASCII DXF files | Title block, layers, entity counts, annotations, bounds |
79
+ | `failure_case` | CSV / JSONL failure logs | Symptom, root cause, countermeasure, severity, tags |
80
+
81
+ ## Tools (identical over MCP, OpenAI-style calls, and Python)
82
+
83
+ | Tool | Purpose |
84
+ | --- | --- |
85
+ | `list_corpus` | Inventory: record counts by kind, loaded documents |
86
+ | `search_documents` | Ranked passage search (English and Japanese) |
87
+ | `get_safety_notices` | Warnings and cautions, optionally ranked |
88
+ | `get_procedure` | Full ordered steps of one procedure |
89
+ | `search_parts` | Parts lookup from parts lists |
90
+ | `list_drawings` / `get_drawing` | CAD inventory and full drawing metadata |
91
+ | `search_failure_cases` | **Troubleshooting first:** match symptoms against past failures |
92
+ | `get_failure_case` | One full case by ID |
93
+
94
+ ```bash
95
+ purestrata tools openai # JSON schemas ready for Grok / OpenAI / compatible APIs
96
+ purestrata tools anthropic
97
+ ```
98
+
99
+ ## Integrations
100
+
101
+ **Grok / OpenAI / any OpenAI-compatible API** — pass the tool schemas to the chat completions endpoint and execute returned tool calls locally. See `examples/api_tool_use.py`:
102
+
103
+ ```bash
104
+ export PURESTRATA_BASE_URL=https://api.x.ai/v1
105
+ export PURESTRATA_API_KEY=your-key
106
+ uv run python examples/api_tool_use.py "The lathe is vibrating during cutting. What should we check?"
107
+ ```
108
+
109
+ Your corpus is queried locally; results go back to the model with provenance.
110
+
111
+ **MCP (Model Context Protocol)** — run the bundled server and register it with any MCP client:
112
+
113
+ ```json
114
+ { "mcpServers": { "purestrata": { "command": "purestrata", "args": ["serve", "--corpus", "/path/to/corpus"] } } }
115
+ ```
116
+
117
+ **Python API** — the same tools as a library:
118
+
119
+ ```python
120
+ import purestrata as ps
121
+
122
+ chunks = ps.ingest_manual("manual.md") + ps.ingest_failures("failures.csv")
123
+ ps.write_chunks(chunks, "corpus/", "my_doc")
124
+ executor = ps.ToolExecutor(ps.Corpus.load("corpus/"))
125
+ hits = executor.execute("search_failure_cases", {"query": "spindle vibration", "top_k": 3})
126
+ ```
127
+
128
+ ## Fine-tuning exports
129
+
130
+ The same corpus that serves live queries becomes training data:
131
+
132
+ - **chat** — system/user/assistant JSONL accepted by OpenAI's and xAI's fine-tuning APIs
133
+ - **tool_trace** — model-issued tool call → provenance-tagged tool result → grounded answer
134
+ - **cot** — instruction / reasoning / output records for chain-of-thought training
135
+
136
+ CoT records are a deliberate scaffold: they are transparent, grounded in structured fields, and built to be **reviewed and sharpened by maintenance engineers** before training. That expert-in-the-loop pass is where dataset quality comes from — PureStrata keeps the work auditable so it can be done rigorously.
137
+
138
+ ## Status and roadmap
139
+
140
+ Current: local ingestion (Markdown, PDF, ASCII DXF, CSV/JSONL), BM25 search with Japanese support, MCP server, tool schemas, fine-tune exports.
141
+
142
+ Planned: HTML/DXF-R2018 support, STEP files, per-layer geometry search, embedding search, evaluation harness for fine-tune sets, and a hosted SaaS for teams that need managed ingestion, access control, and expert review workflows.
143
+
144
+ ## Development
145
+
146
+ ```bash
147
+ make setup # uv sync (installs dev tools and all extras)
148
+ make lint # ruff check + format check
149
+ make test # pytest
150
+ ```
151
+
152
+ ## License
153
+
154
+ [MIT](LICENSE)
155
+
156
+ ---
157
+
158
+ ## 日本語
159
+
160
+ PureStrata は製造業AIのためのオープンなデータレイヤーです。**図面・仕様書・不具合ナレッジ**を1つのポータブルで出所証明(プロビナンス)付きのコーパスに取り込み、MCPやツール呼び出しでどのLLMからでも検索でき、同じコーパスから**微調整用データセット**を書き出せます。
161
+
162
+ 製造業はLLMが最も苦手とする領域です。CAD図面、高密度な保全マニュアル、そしてスプレッドシートに閉じ込められた不具合ナレッジ。特に日本の工場には、図面・保全記録・熟練工のノウハウという、Web上に存在しない一次データが蓄積されています。PureStrataはそれらの文書を、構造化され監査可能なデータ層に変換します。
163
+
164
+ ### 特徴
165
+
166
+ - **3つのレコード族を第一級データとして扱う**: 仕様書(`manual_section` / `procedure` / `safety_notice` / `part_record`)、図面(DXFタイトルブロック・レイヤー・注記)、不具合ナレッジ(現象→原因→対策)。特に「不具合ナレッジ」は通常のRAGには欠けている層で、工場のトラブルシューティングの中核です。
167
+ - **完全な出所証明**: すべてのレコードが元ファイルと位置情報を保持し、LLMの回答がどの図面・セクション・行に遡れるか監査できます。
168
+ - **ロックインなし**: コーパスはプレーンなJSONL。コアは依存ゼロ。ローカル実行でエアギップ環境にも対応します。
169
+ - **日本語対応検索**: 依存ゼロのBM25実装がCJKバイグラム解析に対応し、日本語の不具合記録もそのまま検索できます。
170
+ - **Grok / OpenAI / ローカルLLM対応**: OpenAI互換のツール呼び出し用スキーマと、MCPサーバーの両方を同梱。特定モデルへの依存はありません。
171
+
172
+ ### クイックスタート
173
+
174
+ ```bash
175
+ git clone https://github.com/daikiito-dk/PureStrata
176
+ cd PureStrata
177
+ make setup
178
+ make demo # サンプルデータを取り込んで検索
179
+
180
+ # 手順で実行する場合
181
+ purestrata ingest-manual examples/data/manuals/ja/cnc_press_maintenance.md --out corpus/
182
+ purestrata ingest-dxf examples/data/cad/bracket_mk3.dxf --out corpus/
183
+ purestrata ingest-failures examples/data/failures/plant_failures.csv --out corpus/
184
+ purestrata search "ブレーキ 停止時間" --corpus corpus/
185
+ purestrata export cot --corpus corpus/ --out dataset_cot.jsonl
186
+ ```
187
+
188
+ ### 微調整用データセット
189
+
190
+ `chat`(OpenAI / xAIファインチューニングAPI対応のメッセージ形式)、`tool_trace`(ツール呼び出し→出所付き結果→根拠ある回答)、`cot`(推論過程付き問答)の3形式で書き出せます。CoTレコードは構造化フィールドから生成される透明な雛形であり、保全エンジニアによるレビュー・推敲(ヒューマン・イン・ザ・ループ)を前提に設計されています。データ品質はその専門家レビューで決まるため、PureStrataはその作業を監査可能な形で支えます。
191
+
192
+ ### 開発
193
+
194
+ ```bash
195
+ make setup # uv sync
196
+ make lint # ruff
197
+ make test # pytest
198
+ ```
199
+
200
+ ### ライセンス
201
+
202
+ [MIT](LICENSE)
@@ -0,0 +1,85 @@
1
+ """Query a PureStrata corpus from Grok (or any OpenAI-compatible API) with tool calling.
2
+
3
+ The PureStrata tool schemas are passed to the chat completions endpoint;
4
+ tool calls are executed locally against your corpus, and results are sent
5
+ back with provenance. Your data never leaves your machine except through
6
+ the API you configure.
7
+
8
+ export PURESTRATA_BASE_URL=https://api.x.ai/v1 # or https://api.openai.com/v1
9
+ export PURESTRATA_API_KEY=your-key
10
+ export PURESTRATA_MODEL=grok-4 # model id of your provider
11
+ uv run python examples/api_tool_use.py "The lathe is vibrating during cutting. What should we check?"
12
+ """
13
+
14
+ from __future__ import annotations
15
+
16
+ import json
17
+ import os
18
+ import sys
19
+ import urllib.request
20
+ from pathlib import Path
21
+
22
+ from purestrata import Corpus, ToolError, ToolExecutor, openai_tools
23
+
24
+ HERE = Path(__file__).resolve().parent
25
+
26
+
27
+ def call_llm(base_url: str, api_key: str, model: str, messages: list[dict], tools: list[dict]) -> dict:
28
+ payload = {"model": model, "messages": messages, "tools": tools}
29
+ request = urllib.request.Request(
30
+ f"{base_url.rstrip('/')}/chat/completions",
31
+ data=json.dumps(payload).encode("utf-8"),
32
+ headers={"Content-Type": "application/json", "Authorization": f"Bearer {api_key}"},
33
+ )
34
+ with urllib.request.urlopen(request, timeout=120) as response:
35
+ return json.loads(response.read())
36
+
37
+
38
+ def main() -> None:
39
+ base_url = os.environ.get("PURESTRATA_BASE_URL", "https://api.x.ai/v1")
40
+ api_key = os.environ.get("PURESTRATA_API_KEY", "")
41
+ model = os.environ.get("PURESTRATA_MODEL", "grok-4")
42
+ question = (
43
+ sys.argv[1]
44
+ if len(sys.argv) > 1
45
+ else "The lathe is vibrating during cutting. What should we check?"
46
+ )
47
+ corpus_dir = os.environ.get("PURESTRATA_CORPUS", str(HERE / "corpus"))
48
+ if not api_key:
49
+ print("Set PURESTRATA_API_KEY to run this example.", file=sys.stderr)
50
+ sys.exit(1)
51
+
52
+ executor = ToolExecutor(Corpus.load(corpus_dir))
53
+ tools = openai_tools()
54
+ messages: list[dict] = [{"role": "user", "content": question}]
55
+
56
+ for _round in range(5):
57
+ data = call_llm(base_url, api_key, model, messages, tools)
58
+ message = data["choices"][0]["message"]
59
+ messages.append(message)
60
+ tool_calls = message.get("tool_calls") or []
61
+ if not tool_calls:
62
+ print(message.get("content") or "(no content returned)")
63
+ return
64
+ for call in tool_calls:
65
+ name = call["function"]["name"]
66
+ try:
67
+ args = json.loads(call["function"]["arguments"] or "{}")
68
+ except json.JSONDecodeError:
69
+ args = {}
70
+ print(f"-> {name}({args})")
71
+ try:
72
+ result = executor.execute(name, args)
73
+ except ToolError as exc:
74
+ result = {"error": str(exc)}
75
+ messages.append(
76
+ {
77
+ "role": "tool",
78
+ "tool_call_id": call["id"],
79
+ "content": json.dumps(result, ensure_ascii=False, default=str),
80
+ }
81
+ )
82
+
83
+
84
+ if __name__ == "__main__":
85
+ main()