yamcps-docs 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.
- yamcps_docs-0.1.0/.github/workflows/verify_release.py +69 -0
- yamcps_docs-0.1.0/.github/workflows/workflow.yaml +65 -0
- yamcps_docs-0.1.0/.gitignore +220 -0
- yamcps_docs-0.1.0/LICENSE +21 -0
- yamcps_docs-0.1.0/PKG-INFO +207 -0
- yamcps_docs-0.1.0/README.md +181 -0
- yamcps_docs-0.1.0/contributing.md +66 -0
- yamcps_docs-0.1.0/examples/devis-travaux.md +37 -0
- yamcps_docs-0.1.0/examples/manifest.json +15 -0
- yamcps_docs-0.1.0/pyproject.toml +54 -0
- yamcps_docs-0.1.0/src/yamcps_docs/__init__.py +158 -0
- yamcps_docs-0.1.0/src/yamcps_docs/cli.py +31 -0
- yamcps_docs-0.1.0/src/yamcps_docs/ingest.py +96 -0
- yamcps_docs-0.1.0/src/yamcps_docs/py.typed +0 -0
- yamcps_docs-0.1.0/src/yamcps_docs/skills/docs-research/SKILL.md +17 -0
- yamcps_docs-0.1.0/tests/test_build_version.py +79 -0
- yamcps_docs-0.1.0/tests/test_core_integration.py +97 -0
- yamcps_docs-0.1.0/tests/test_docs.py +258 -0
- yamcps_docs-0.1.0/tests/test_release.py +71 -0
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"""Validate the exact plugin artifacts before uploading them to PyPI."""
|
|
2
|
+
|
|
3
|
+
import argparse
|
|
4
|
+
import tarfile
|
|
5
|
+
import zipfile
|
|
6
|
+
from email.parser import BytesParser
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def _wheel_metadata(path: Path) -> bytes:
|
|
11
|
+
with zipfile.ZipFile(path) as wheel:
|
|
12
|
+
names = wheel.namelist()
|
|
13
|
+
metadata_paths = [name for name in names if name.endswith(".dist-info/METADATA")]
|
|
14
|
+
if len(metadata_paths) != 1 or "yamcps_docs/__init__.py" not in names:
|
|
15
|
+
raise ValueError("Wheel must contain docs and exactly one metadata file")
|
|
16
|
+
return wheel.read(metadata_paths[0])
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def _source_metadata(path: Path) -> bytes:
|
|
20
|
+
with tarfile.open(path, "r:gz") as archive:
|
|
21
|
+
members = [
|
|
22
|
+
m
|
|
23
|
+
for m in archive.getmembers()
|
|
24
|
+
if m.name.count("/") == 1 and m.name.endswith("/PKG-INFO")
|
|
25
|
+
]
|
|
26
|
+
if len(members) != 1:
|
|
27
|
+
raise ValueError("Expected one root source metadata file")
|
|
28
|
+
stream = archive.extractfile(members[0])
|
|
29
|
+
if stream is None:
|
|
30
|
+
raise ValueError("Missing source metadata")
|
|
31
|
+
with stream:
|
|
32
|
+
return stream.read()
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def verify(directory: Path, tag: str) -> None:
|
|
36
|
+
"""Require exactly one yamcps-docs wheel and sdist matching a v-prefixed tag.
|
|
37
|
+
|
|
38
|
+
Args:
|
|
39
|
+
directory: Dedicated output directory for the plugin build.
|
|
40
|
+
tag: GitHub release tag, such as v0.1.0.
|
|
41
|
+
|
|
42
|
+
Raises:
|
|
43
|
+
ValueError: Unexpected artifacts, distribution name or version.
|
|
44
|
+
"""
|
|
45
|
+
files = sorted(directory.iterdir())
|
|
46
|
+
wheels = [p for p in files if p.name.endswith(".whl")]
|
|
47
|
+
sources = [p for p in files if p.name.endswith(".tar.gz")]
|
|
48
|
+
if len(files) != 2 or len(wheels) != 1 or len(sources) != 1:
|
|
49
|
+
raise ValueError("Expected exactly one plugin wheel and one source archive")
|
|
50
|
+
if not tag.startswith("v") or not tag[1:]:
|
|
51
|
+
raise ValueError("Release tag must have the form v<package-version>")
|
|
52
|
+
metadata = [_wheel_metadata(wheels[0]), _source_metadata(sources[0])]
|
|
53
|
+
for raw in metadata:
|
|
54
|
+
message = BytesParser().parsebytes(raw)
|
|
55
|
+
if message["Name"] != "yamcps-docs" or message["Version"] != tag[1:]:
|
|
56
|
+
raise ValueError("Only yamcps-docs matching the release tag may be published")
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def main() -> None:
|
|
60
|
+
"""Validate a build directory against its release tag."""
|
|
61
|
+
parser = argparse.ArgumentParser(description=__doc__)
|
|
62
|
+
parser.add_argument("directory", type=Path)
|
|
63
|
+
parser.add_argument("--tag", required=True)
|
|
64
|
+
args = parser.parse_args()
|
|
65
|
+
verify(args.directory, args.tag)
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
if __name__ == "__main__":
|
|
69
|
+
main()
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
name: Publish yamcps-docs to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
|
|
7
|
+
permissions:
|
|
8
|
+
contents: read
|
|
9
|
+
|
|
10
|
+
concurrency:
|
|
11
|
+
group: pypi-${{ github.event.release.tag_name }}
|
|
12
|
+
cancel-in-progress: false
|
|
13
|
+
|
|
14
|
+
jobs:
|
|
15
|
+
build:
|
|
16
|
+
name: Build plugin distribution
|
|
17
|
+
runs-on: ubuntu-latest
|
|
18
|
+
steps:
|
|
19
|
+
- uses: actions/checkout@v4
|
|
20
|
+
with:
|
|
21
|
+
ref: ${{ github.event.release.tag_name }}
|
|
22
|
+
fetch-depth: 0
|
|
23
|
+
persist-credentials: false
|
|
24
|
+
- uses: actions/setup-python@v6
|
|
25
|
+
with:
|
|
26
|
+
python-version: '3.12'
|
|
27
|
+
- name: Verify release is based on main
|
|
28
|
+
run: git merge-base --is-ancestor HEAD origin/main
|
|
29
|
+
- name: Install build tools
|
|
30
|
+
run: python -m pip install build twine
|
|
31
|
+
# hatch-vcs reads the release tag from the complete Git history above.
|
|
32
|
+
# Keep the metadata check below: an inferred development version must not be published.
|
|
33
|
+
- name: Build only the plugin package
|
|
34
|
+
run: python -m build --outdir dist/package .
|
|
35
|
+
- name: Validate distribution identity and release version
|
|
36
|
+
env:
|
|
37
|
+
RELEASE_TAG: ${{ github.event.release.tag_name }}
|
|
38
|
+
run: python .github/workflows/verify_release.py dist/package --tag "$RELEASE_TAG"
|
|
39
|
+
- name: Check PyPI metadata
|
|
40
|
+
run: python -m twine check --strict dist/package/*
|
|
41
|
+
- uses: actions/upload-artifact@v4
|
|
42
|
+
with:
|
|
43
|
+
name: yamcps-docs-distributions
|
|
44
|
+
path: dist/package/*
|
|
45
|
+
if-no-files-found: error
|
|
46
|
+
retention-days: 7
|
|
47
|
+
|
|
48
|
+
publish:
|
|
49
|
+
name: Publish plugin distribution
|
|
50
|
+
needs: build
|
|
51
|
+
runs-on: ubuntu-latest
|
|
52
|
+
environment:
|
|
53
|
+
name: pypi
|
|
54
|
+
url: https://pypi.org/p/yamcps-docs
|
|
55
|
+
permissions:
|
|
56
|
+
id-token: write
|
|
57
|
+
steps:
|
|
58
|
+
- uses: actions/download-artifact@v4
|
|
59
|
+
with:
|
|
60
|
+
name: yamcps-docs-distributions
|
|
61
|
+
path: dist/package
|
|
62
|
+
- name: Publish yamcps-docs only
|
|
63
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
64
|
+
with:
|
|
65
|
+
packages-dir: dist/package/
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
# Byte-compiled / optimized / DLL files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[codz]
|
|
4
|
+
*$py.class
|
|
5
|
+
|
|
6
|
+
# C extensions
|
|
7
|
+
*.so
|
|
8
|
+
|
|
9
|
+
# Distribution / packaging
|
|
10
|
+
.Python
|
|
11
|
+
build/
|
|
12
|
+
develop-eggs/
|
|
13
|
+
dist/
|
|
14
|
+
downloads/
|
|
15
|
+
eggs/
|
|
16
|
+
.eggs/
|
|
17
|
+
lib/
|
|
18
|
+
lib64/
|
|
19
|
+
parts/
|
|
20
|
+
sdist/
|
|
21
|
+
var/
|
|
22
|
+
wheels/
|
|
23
|
+
share/python-wheels/
|
|
24
|
+
*.egg-info/
|
|
25
|
+
.installed.cfg
|
|
26
|
+
*.egg
|
|
27
|
+
MANIFEST
|
|
28
|
+
|
|
29
|
+
# PyInstaller
|
|
30
|
+
# Usually these files are written by a python script from a template
|
|
31
|
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
32
|
+
*.manifest
|
|
33
|
+
*.spec
|
|
34
|
+
|
|
35
|
+
# Installer logs
|
|
36
|
+
pip-log.txt
|
|
37
|
+
pip-delete-this-directory.txt
|
|
38
|
+
|
|
39
|
+
# Unit test / coverage reports
|
|
40
|
+
htmlcov/
|
|
41
|
+
.tox/
|
|
42
|
+
.nox/
|
|
43
|
+
.coverage
|
|
44
|
+
.coverage.*
|
|
45
|
+
.cache
|
|
46
|
+
nosetests.xml
|
|
47
|
+
coverage.xml
|
|
48
|
+
*.cover
|
|
49
|
+
*.py.cover
|
|
50
|
+
*.lcov
|
|
51
|
+
.hypothesis/
|
|
52
|
+
.pytest_cache/
|
|
53
|
+
cover/
|
|
54
|
+
|
|
55
|
+
# Translations
|
|
56
|
+
*.mo
|
|
57
|
+
*.pot
|
|
58
|
+
|
|
59
|
+
# Django stuff:
|
|
60
|
+
*.log
|
|
61
|
+
local_settings.py
|
|
62
|
+
db.sqlite3
|
|
63
|
+
db.sqlite3-journal
|
|
64
|
+
|
|
65
|
+
# Flask stuff:
|
|
66
|
+
instance/
|
|
67
|
+
.webassets-cache
|
|
68
|
+
|
|
69
|
+
# Scrapy stuff:
|
|
70
|
+
.scrapy
|
|
71
|
+
|
|
72
|
+
# Sphinx documentation
|
|
73
|
+
docs/_build/
|
|
74
|
+
|
|
75
|
+
# PyBuilder
|
|
76
|
+
.pybuilder/
|
|
77
|
+
target/
|
|
78
|
+
|
|
79
|
+
# Jupyter Notebook
|
|
80
|
+
.ipynb_checkpoints
|
|
81
|
+
|
|
82
|
+
# IPython
|
|
83
|
+
profile_default/
|
|
84
|
+
ipython_config.py
|
|
85
|
+
|
|
86
|
+
# pyenv
|
|
87
|
+
# For a library or package, you might want to ignore these files since the code is
|
|
88
|
+
# intended to run in multiple environments; otherwise, check them in:
|
|
89
|
+
# .python-version
|
|
90
|
+
|
|
91
|
+
# pipenv
|
|
92
|
+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
|
93
|
+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
|
94
|
+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
|
95
|
+
# install all needed dependencies.
|
|
96
|
+
# Pipfile.lock
|
|
97
|
+
|
|
98
|
+
# uv
|
|
99
|
+
# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
|
|
100
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
101
|
+
# commonly ignored for libraries.
|
|
102
|
+
# uv.lock
|
|
103
|
+
|
|
104
|
+
# poetry
|
|
105
|
+
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
|
106
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
107
|
+
# commonly ignored for libraries.
|
|
108
|
+
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
|
109
|
+
# poetry.lock
|
|
110
|
+
# poetry.toml
|
|
111
|
+
|
|
112
|
+
# pdm
|
|
113
|
+
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
|
114
|
+
# pdm recommends including project-wide configuration in pdm.toml, but excluding .pdm-python.
|
|
115
|
+
# https://pdm-project.org/en/latest/usage/project/#working-with-version-control
|
|
116
|
+
# pdm.lock
|
|
117
|
+
# pdm.toml
|
|
118
|
+
.pdm-python
|
|
119
|
+
.pdm-build/
|
|
120
|
+
|
|
121
|
+
# pixi
|
|
122
|
+
# Similar to Pipfile.lock, it is generally recommended to include pixi.lock in version control.
|
|
123
|
+
# pixi.lock
|
|
124
|
+
# Pixi creates a virtual environment in the .pixi directory, just like venv module creates one
|
|
125
|
+
# in the .venv directory. It is recommended not to include this directory in version control.
|
|
126
|
+
.pixi/*
|
|
127
|
+
!.pixi/config.toml
|
|
128
|
+
|
|
129
|
+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
|
130
|
+
__pypackages__/
|
|
131
|
+
|
|
132
|
+
# Celery stuff
|
|
133
|
+
celerybeat-schedule*
|
|
134
|
+
celerybeat.pid
|
|
135
|
+
|
|
136
|
+
# Redis
|
|
137
|
+
*.rdb
|
|
138
|
+
*.aof
|
|
139
|
+
*.pid
|
|
140
|
+
|
|
141
|
+
# RabbitMQ
|
|
142
|
+
mnesia/
|
|
143
|
+
rabbitmq/
|
|
144
|
+
rabbitmq-data/
|
|
145
|
+
|
|
146
|
+
# ActiveMQ
|
|
147
|
+
activemq-data/
|
|
148
|
+
|
|
149
|
+
# SageMath parsed files
|
|
150
|
+
*.sage.py
|
|
151
|
+
|
|
152
|
+
# Environments
|
|
153
|
+
.env
|
|
154
|
+
.envrc
|
|
155
|
+
.venv
|
|
156
|
+
env/
|
|
157
|
+
venv/
|
|
158
|
+
ENV/
|
|
159
|
+
env.bak/
|
|
160
|
+
venv.bak/
|
|
161
|
+
|
|
162
|
+
# Spyder project settings
|
|
163
|
+
.spyderproject
|
|
164
|
+
.spyproject
|
|
165
|
+
|
|
166
|
+
# Rope project settings
|
|
167
|
+
.ropeproject
|
|
168
|
+
|
|
169
|
+
# mkdocs/Zensical documentation
|
|
170
|
+
/site
|
|
171
|
+
|
|
172
|
+
# mypy
|
|
173
|
+
.mypy_cache/
|
|
174
|
+
.dmypy.json
|
|
175
|
+
dmypy.json
|
|
176
|
+
|
|
177
|
+
# Pyre type checker
|
|
178
|
+
.pyre/
|
|
179
|
+
|
|
180
|
+
# pytype static type analyzer
|
|
181
|
+
.pytype/
|
|
182
|
+
|
|
183
|
+
# Cython debug symbols
|
|
184
|
+
cython_debug/
|
|
185
|
+
|
|
186
|
+
# PyCharm
|
|
187
|
+
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
|
188
|
+
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
|
189
|
+
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
|
190
|
+
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
|
191
|
+
# .idea/
|
|
192
|
+
|
|
193
|
+
# Abstra
|
|
194
|
+
# Abstra is an AI-powered process automation framework.
|
|
195
|
+
# Ignore directories containing user credentials, local state, and settings.
|
|
196
|
+
# Learn more at https://abstra.io/docs
|
|
197
|
+
.abstra/
|
|
198
|
+
|
|
199
|
+
# Visual Studio Code
|
|
200
|
+
# Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore that
|
|
201
|
+
# can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
|
|
202
|
+
# and can be added to the global gitignore or merged into this file. However, if you prefer, you
|
|
203
|
+
# could uncomment the following to ignore the entire vscode folder
|
|
204
|
+
# .vscode/
|
|
205
|
+
# Temporary file for partial code execution
|
|
206
|
+
tempCodeRunnerFile.py
|
|
207
|
+
|
|
208
|
+
# Ruff stuff:
|
|
209
|
+
.ruff_cache/
|
|
210
|
+
|
|
211
|
+
# PyPI configuration file
|
|
212
|
+
.pypirc
|
|
213
|
+
|
|
214
|
+
# Marimo
|
|
215
|
+
marimo/_static/
|
|
216
|
+
marimo/_lsp/
|
|
217
|
+
__marimo__/
|
|
218
|
+
|
|
219
|
+
# Streamlit
|
|
220
|
+
.streamlit/secrets.toml
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 JoReci
|
|
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,207 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: yamcps-docs
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Local document retrieval connector for yamcps
|
|
5
|
+
Project-URL: Repository, https://github.com/JoReci2/yamcps-docs
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
Requires-Python: >=3.12
|
|
9
|
+
Requires-Dist: yamcps>=0.1
|
|
10
|
+
Provides-Extra: dev
|
|
11
|
+
Requires-Dist: bandit; extra == 'dev'
|
|
12
|
+
Requires-Dist: build; extra == 'dev'
|
|
13
|
+
Requires-Dist: coverage; extra == 'dev'
|
|
14
|
+
Requires-Dist: editables; extra == 'dev'
|
|
15
|
+
Requires-Dist: hatch-vcs<1,>=0.4; extra == 'dev'
|
|
16
|
+
Requires-Dist: hatchling; extra == 'dev'
|
|
17
|
+
Requires-Dist: mypy; extra == 'dev'
|
|
18
|
+
Requires-Dist: pytest-asyncio>=1; extra == 'dev'
|
|
19
|
+
Requires-Dist: pytest>=8; extra == 'dev'
|
|
20
|
+
Requires-Dist: radon; extra == 'dev'
|
|
21
|
+
Requires-Dist: ruff; extra == 'dev'
|
|
22
|
+
Provides-Extra: formats
|
|
23
|
+
Requires-Dist: pypdf<7,>=5; extra == 'formats'
|
|
24
|
+
Requires-Dist: python-docx<2,>=1; extra == 'formats'
|
|
25
|
+
Description-Content-Type: text/markdown
|
|
26
|
+
|
|
27
|
+
# yamcps-docs
|
|
28
|
+
|
|
29
|
+
Recherche documentaire locale via le RAG natif du moteur
|
|
30
|
+
[yamcps](https://github.com/JoReci2/yamcps). Le plugin expose les documents indexés
|
|
31
|
+
en lecture seule dans MCP ; l'ingestion se fait séparément en ligne de commande.
|
|
32
|
+
Aucun secret n'est requis.
|
|
33
|
+
|
|
34
|
+
TXT et Markdown UTF-8 sont pris en charge de base ; PDF texte et DOCX nécessitent
|
|
35
|
+
l'extra `formats`. L'extraction ne fait ni OCR, ni extraction de figures, ni
|
|
36
|
+
reconstruction de la mise en page.
|
|
37
|
+
|
|
38
|
+
## Démarrage rapide
|
|
39
|
+
|
|
40
|
+
Python ≥ 3.12 et un moteur yamcps compatible avec les configurations et le RAG
|
|
41
|
+
natifs sont requis. Installer le plugin dans le même environnement que le moteur :
|
|
42
|
+
|
|
43
|
+
```sh
|
|
44
|
+
python -m pip install 'yamcps-docs[formats]'
|
|
45
|
+
yamcps configs set --connector docs
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Laisser les champs `index` et `model` vides pour utiliser l'index par défaut du
|
|
49
|
+
moteur et la recherche lexicale. Depuis la racine de ce dépôt, essayer le devis de travaux
|
|
50
|
+
fictif fourni :
|
|
51
|
+
|
|
52
|
+
```sh
|
|
53
|
+
yamcps-docs ingest examples/manifest.json
|
|
54
|
+
yamcps serve --connector docs
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Les fichiers d'exemple sont disponibles dans [examples](examples) ; hors du dépôt,
|
|
58
|
+
les copier ensemble dans un dossier local. Depuis le client MCP, demander de
|
|
59
|
+
rechercher `DEV-2026-0042` dans le corpus `demo/travaux`.
|
|
60
|
+
|
|
61
|
+
Le serveur n'ingère rien au démarrage. Utiliser le même compte et la même
|
|
62
|
+
configuration pour l'ingestion et le serveur. Le manifeste remplace le contenu du
|
|
63
|
+
corpus désigné : ne pas utiliser l'exemple pour remplacer un corpus existant.
|
|
64
|
+
|
|
65
|
+
Par exemple, demander ensuite : « Quel est le montant TTC du devis et quel acompte
|
|
66
|
+
est prévu ? » ou « La peinture est-elle comprise dans le poste TRV-003 ? », avec
|
|
67
|
+
les passages sources à l'appui.
|
|
68
|
+
|
|
69
|
+
## Configuration
|
|
70
|
+
|
|
71
|
+
Configurer les chemins avec `yamcps configs set --connector docs` ; aucun export
|
|
72
|
+
de variable d'environnement n'est nécessaire. Les valeurs sont enregistrées dans
|
|
73
|
+
un fichier JSON local. Préférer des chemins absolus pour éviter les différences
|
|
74
|
+
de répertoire courant.
|
|
75
|
+
|
|
76
|
+
| Champ | Description | Valeur par défaut | Ancienne variable de repli |
|
|
77
|
+
| --- | --- | --- | --- |
|
|
78
|
+
| `index` | Chemin de l'index SQLite | Vide : index du moteur pour `docs` | `YAMCPS_DOCS_INDEX` |
|
|
79
|
+
| `model` | Dossier d'un modèle sémantique local | Vide : recherche lexicale | `YAMCPS_DOCS_MODEL` |
|
|
80
|
+
|
|
81
|
+
Les deux champs sont facultatifs. Voir le
|
|
82
|
+
[guide de configuration du moteur](https://github.com/JoReci2/yamcps/blob/main/docs/configuration.md)
|
|
83
|
+
pour leur priorité, `--config-file` et le mode non interactif. Pour un fichier de
|
|
84
|
+
configuration personnalisé, le transmettre aux deux commandes :
|
|
85
|
+
|
|
86
|
+
```sh
|
|
87
|
+
yamcps-docs ingest /chemin/vers/manifest.json --config-file /chemin/vers/config.json
|
|
88
|
+
yamcps serve --connector docs --config-file /chemin/vers/config.json
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### Recherche sémantique locale optionnelle
|
|
92
|
+
|
|
93
|
+
Sans modèle, la recherche est lexicale et ne comprend pas les synonymes. Installer
|
|
94
|
+
l'extra `rag`, puis télécharger explicitement un modèle Sentence Transformers
|
|
95
|
+
avec yamcps depuis Hugging Face. Par exemple, pour un modèle multilingue :
|
|
96
|
+
|
|
97
|
+
```sh
|
|
98
|
+
python -m pip install 'yamcps[rag]'
|
|
99
|
+
yamcps models download sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
La commande affiche le chemin absolu du dossier téléchargé. Par défaut, il se
|
|
103
|
+
trouve sous `~/.local/share/yamcps/models/<organisation>--<modele>/<commit>`.
|
|
104
|
+
L'option `--revision` permet de choisir une branche, un tag ou un commit ;
|
|
105
|
+
`--destination /chemin/absolu/vers/un-nouveau-dossier` fixe le dossier local.
|
|
106
|
+
Le téléchargement nécessite une connexion réseau et n'active pas le modèle.
|
|
107
|
+
|
|
108
|
+
Pour activer la recherche hybride, renseigner le chemin affiché dans le champ
|
|
109
|
+
`model`, puis ingérer le corpus dans un nouvel index. Un modèle compatible déjà
|
|
110
|
+
présent sur la machine peut aussi être utilisé directement :
|
|
111
|
+
|
|
112
|
+
```sh
|
|
113
|
+
yamcps configs set --connector docs --name model --value /chemin/absolu/vers/modele-local
|
|
114
|
+
yamcps configs set --connector docs --name index --value /chemin/absolu/docs-hybrid.sqlite3
|
|
115
|
+
yamcps-docs ingest /chemin/vers/manifest.json
|
|
116
|
+
yamcps serve --connector docs
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Utiliser le même modèle pour l'ingestion et la recherche. Un changement de modèle
|
|
120
|
+
exige un nouvel index et une réingestion. Aucun modèle n'est fourni ni téléchargé
|
|
121
|
+
automatiquement, et aucun code distant n'est autorisé. Côté serveur, le modèle est
|
|
122
|
+
chargé au premier appel MCP, dans un thread, jamais à l'import ou à l'enregistrement
|
|
123
|
+
du plugin.
|
|
124
|
+
|
|
125
|
+
Pour un serveur hors ligne, télécharger le modèle sur une machine connectée,
|
|
126
|
+
puis copier son dossier sur le serveur, y installer aussi l'extra `rag` et
|
|
127
|
+
configurer `model` avec le chemin local de cette copie.
|
|
128
|
+
Évaluer sa qualité sur vos questions métier ; aucune qualification IVVQ n'est
|
|
129
|
+
revendiquée.
|
|
130
|
+
|
|
131
|
+
## Ingestion d'un corpus
|
|
132
|
+
|
|
133
|
+
Créer un manifeste JSON à côté des fichiers à indexer. Par exemple, avec `devis-travaux.md`
|
|
134
|
+
dans le même dossier que `manifest.json` :
|
|
135
|
+
|
|
136
|
+
```json
|
|
137
|
+
{
|
|
138
|
+
"corpus": "demo/travaux",
|
|
139
|
+
"sources": [
|
|
140
|
+
{
|
|
141
|
+
"path": "devis-travaux.md",
|
|
142
|
+
"document_id": "DEV-2026-0042",
|
|
143
|
+
"revision": "1.0",
|
|
144
|
+
"metadata": {"project": "renovation-salon", "status": "example", "type": "devis"}
|
|
145
|
+
}
|
|
146
|
+
]
|
|
147
|
+
}
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
Puis lancer :
|
|
151
|
+
|
|
152
|
+
```sh
|
|
153
|
+
yamcps-docs ingest /chemin/vers/manifest.json
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
Le manifeste est un **snapshot complet d'un seul corpus** : retirer une source
|
|
157
|
+
supprime cette révision de l'index. Garder explicitement les anciennes révisions
|
|
158
|
+
souhaitées. Les métadonnées sont facultatives et associent des clés à des valeurs
|
|
159
|
+
textuelles ; elles servent aux filtres de recherche. L'extraction de toutes les
|
|
160
|
+
sources se termine avant la synchronisation atomique du corpus. Une ingestion
|
|
161
|
+
identique réutilise les passages existants.
|
|
162
|
+
|
|
163
|
+
Les chemins des sources sont relatifs au dossier du manifeste. Les chemins
|
|
164
|
+
absolus, les traversées `..` et les liens symboliques sont refusés. Chaque source
|
|
165
|
+
est limitée à 20 MiB et à 4 millions de caractères extraits ; un texte vide est
|
|
166
|
+
refusé. N'ingérer que des fichiers de confiance.
|
|
167
|
+
|
|
168
|
+
Le découpage utilise au plus 1200 caractères par passage, sans chevauchement.
|
|
169
|
+
L'option `--chunk-size` permet une valeur de 64 à 16000. Un passage peut couper une
|
|
170
|
+
phrase ou un tableau. Les contenus sont stockés en clair dans SQLite : protéger
|
|
171
|
+
le dossier avec les droits du système et sauvegarder l'index si nécessaire.
|
|
172
|
+
|
|
173
|
+
## Recherche et citations dans MCP
|
|
174
|
+
|
|
175
|
+
| Outil | Paramètres | Description |
|
|
176
|
+
| --- | --- | --- |
|
|
177
|
+
| `docs_search` | `query`, `corpus`, `filters=None`, `limit=5` | Recherche de passages sourcés ; limite de 1 à 20 |
|
|
178
|
+
| `docs_get_document` | `corpus`, `document_id`, `revision` | Texte extrait d'une révision précise |
|
|
179
|
+
| `docs_get_passage` | `passage_id` | Passage cité et provenance exacte |
|
|
180
|
+
| `docs_index_status` | `corpus` | Mode, compteurs et date du dernier passage modifié |
|
|
181
|
+
|
|
182
|
+
Toujours préciser le corpus lors d'une recherche. Les filtres correspondent
|
|
183
|
+
exactement aux métadonnées du manifeste, par exemple
|
|
184
|
+
`{"project": "renovation-salon", "type": "devis"}` ; ils ne constituent pas des droits
|
|
185
|
+
d'accès.
|
|
186
|
+
|
|
187
|
+
Les ressources `docs://source/{corpus}/{document_id}/{revision}` (segments encodés)
|
|
188
|
+
et `docs://passage/{passage_id}` exposent aussi les références citées. Pour une
|
|
189
|
+
citation vérifiable, conserver `document_id`, `revision`, `source_uri`,
|
|
190
|
+
`passage_id` et les offsets `start`/`end` renvoyés. Ces offsets désignent des
|
|
191
|
+
caractères dans le texte extrait, début inclus et fin exclue ; ils ne garantissent
|
|
192
|
+
pas une pagination dans le document original.
|
|
193
|
+
|
|
194
|
+
L'index est une copie des sources au moment de l'ingestion. La date indiquée par
|
|
195
|
+
`docs_index_status` concerne les passages modifiés et ne prouve pas la fraîcheur
|
|
196
|
+
des fichiers sources. Un index absent produit une erreur explicative au premier
|
|
197
|
+
appel, sans empêcher les autres plugins de démarrer. Aucune mutation de l'index
|
|
198
|
+
n'est exposée au modèle via MCP.
|
|
199
|
+
|
|
200
|
+
Le skill embarqué
|
|
201
|
+
[docs-research](src/yamcps_docs/skills/docs-research/SKILL.md) guide la recherche de
|
|
202
|
+
preuves et la citation des révisions exactes.
|
|
203
|
+
|
|
204
|
+
## Contribution
|
|
205
|
+
|
|
206
|
+
Voir [contributing.md](contributing.md) pour l'installation de développement,
|
|
207
|
+
l'intégration au moteur et les validations.
|