moca-reader-llamaindex 0.6.0__py3-none-any.whl

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.
@@ -0,0 +1,77 @@
1
+ """A LlamaIndex retriever over MOCA packages (Reader interface §7).
2
+
3
+ ``MocaRetriever`` wraps a host-built ``moca_reader.Search``: its backend, audiences and hooks. Every call goes
4
+ through the Reader's gate, so the retrieval policy and the host's audience filter always apply, and nothing a
5
+ caller passes can widen them. Each citation record becomes a ``NodeWithScore``: a ``TextNode`` with the text, the
6
+ whole record under ``metadata["moca_citation"]`` and the consuming guide's flat ``moca_*`` fields beside it, and
7
+ the record's score. The MOCA keys are excluded from the text LlamaIndex sends to a model or an embedder.
8
+
9
+ Package text is untrusted input to a model: pass it to a model as quoted reference material to cite, never as
10
+ instructions (Reader contract §12).
11
+ """
12
+
13
+ from __future__ import annotations
14
+
15
+ from typing import Any
16
+
17
+ from llama_index.core.callbacks import CallbackManager
18
+ from llama_index.core.retrievers import BaseRetriever
19
+ from llama_index.core.schema import NodeWithScore, QueryBundle, TextNode
20
+
21
+ from moca_reader import CitationRecord, Search, flat_metadata
22
+
23
+ __all__ = ["MocaRetriever", "node_id", "to_node"]
24
+ __version__ = "0.6.0"
25
+
26
+
27
+ def node_id(record: CitationRecord) -> str:
28
+ """A unique id: the node's versioned reference, then the byte span, since one node can return several chunks."""
29
+ span = record.get("span")
30
+ ref = str(record["node"]["ref"])
31
+ return f"{ref}:{span['start']}-{span['end']}" if isinstance(span, dict) else ref
32
+
33
+
34
+ def to_node(record: CitationRecord) -> NodeWithScore:
35
+ """A citation record as a LlamaIndex ``NodeWithScore``."""
36
+ metadata: dict[str, Any] = {"moca_citation": record, **flat_metadata(record)}
37
+ keys = list(metadata)
38
+ node = TextNode(
39
+ id_=node_id(record),
40
+ text=record.get("text") or "",
41
+ metadata=metadata,
42
+ excluded_llm_metadata_keys=keys,
43
+ excluded_embed_metadata_keys=keys,
44
+ )
45
+ score = record.get("score")
46
+ return NodeWithScore(node=node, score=float(score) if isinstance(score, (int, float)) else None)
47
+
48
+
49
+ class MocaRetriever(BaseRetriever):
50
+ """Retrieves citation records from MOCA packages as LlamaIndex ``NodeWithScore``s.
51
+
52
+ ``search`` is the host's ``moca_reader.Search``; the other arguments are the search options for every call.
53
+ """
54
+
55
+ def __init__(
56
+ self,
57
+ search: Search,
58
+ *,
59
+ limit: int = 5,
60
+ locale: str | None = None,
61
+ concepts: list[str] | None = None,
62
+ scope: str | None = None,
63
+ include_all: bool = False,
64
+ callback_manager: CallbackManager | None = None,
65
+ ) -> None:
66
+ super().__init__(callback_manager=callback_manager)
67
+ self._search = search
68
+ self._options: dict[str, Any] = {
69
+ "limit": limit,
70
+ "include_all": include_all,
71
+ "locale": locale,
72
+ "concepts": concepts,
73
+ "scope": scope,
74
+ }
75
+
76
+ def _retrieve(self, query_bundle: QueryBundle) -> list[NodeWithScore]:
77
+ return [to_node(r) for r in self._search.search(query_bundle.query_str, **self._options)]
File without changes
@@ -0,0 +1,68 @@
1
+ Metadata-Version: 2.5
2
+ Name: moca-reader-llamaindex
3
+ Version: 0.6.0
4
+ Summary: A LlamaIndex retriever over MOCA packages: citation records as scored nodes, through the MOCA Reader's gate.
5
+ Project-URL: Homepage, https://openmoca.org
6
+ Project-URL: Source, https://github.com/openmoca/moca-reader-python
7
+ Author: MOCA Standard Contributors
8
+ License-Expression: Apache-2.0
9
+ Keywords: citations,llama-index,llamaindex,moca,rag,retriever
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Typing :: Typed
13
+ Requires-Python: >=3.11
14
+ Requires-Dist: llama-index-core>=0.14
15
+ Requires-Dist: moca-reader==0.6.0
16
+ Description-Content-Type: text/markdown
17
+
18
+ # moca-reader-llamaindex
19
+
20
+ A [LlamaIndex](https://www.llamaindex.ai) retriever over MOCA packages, built
21
+ on the [MOCA Reader for Python](https://github.com/openmoca/moca-reader-python).
22
+
23
+ ```sh
24
+ pip install moca-reader-llamaindex
25
+ ```
26
+
27
+ ```python
28
+ from moca_reader import LexicalBackend, Library, Search, read_package
29
+ from moca_reader_llamaindex import MocaRetriever
30
+
31
+ pkg = read_package("support-kb.moca", trust_root="trust-root.json")
32
+ library = Library().add(pkg)
33
+ search = Search(library, LexicalBackend(library), audiences=["public"])
34
+
35
+ retriever = MocaRetriever(search, limit=3)
36
+ for result in retriever.retrieve("How long is the refund window?"):
37
+ print(result.node.metadata["moca_node_ref"], result.score)
38
+ print(result.node.get_content()[:80])
39
+ ```
40
+
41
+ `MocaRetriever` wraps the `Search` you build: its backend (lexical, dense,
42
+ hybrid or your own store), its audiences and its hooks. Every call goes through
43
+ the Reader's gate, so content that is out of force, superseded, deprecated or
44
+ outside your audiences never comes back, and nothing a caller passes can widen
45
+ that. Use it anywhere LlamaIndex takes a retriever, such as a
46
+ `RetrieverQueryEngine`.
47
+
48
+ Each result is a `NodeWithScore` holding a `TextNode`:
49
+
50
+ | Field | Holds |
51
+ | --- | --- |
52
+ | `text` | The text of the node, or of a sidecar chunk |
53
+ | `node_id` | The node's versioned reference and byte span |
54
+ | `metadata["moca_citation"]` | The whole citation record: package, version and digest, trust signals, evidence |
55
+ | `metadata["moca_*"]` | The flat fields of the consuming guide (`moca_node_ref`, `moca_package_digest`, `moca_status`, `moca_signed`, ...) |
56
+ | `score` | The search score |
57
+
58
+ The MOCA metadata keys are excluded from the text LlamaIndex sends to a model
59
+ or an embedder, so they travel with the node without filling the prompt.
60
+
61
+ **Package text is untrusted input.** Present it to a model as quoted reference
62
+ material to cite, never as instructions
63
+ ([Reader contract §12](https://github.com/openmoca/moca-spec/blob/main/spec/moca-reader-contract.md#12-handing-content-to-a-model)).
64
+ Show users the source (`moca_node_ref`, the package version) with each answer.
65
+
66
+ ## Licence
67
+
68
+ Apache-2.0.
@@ -0,0 +1,5 @@
1
+ moca_reader_llamaindex/__init__.py,sha256=eDjRlNdRQEBlFIMh5AP_No5wuQl6XDkUU9PNm5mtF58,3068
2
+ moca_reader_llamaindex/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
+ moca_reader_llamaindex-0.6.0.dist-info/METADATA,sha256=J2jJkfB7Gt8i7lSJWCHu1gss0ZtudCvuV96hLfKRy7I,2835
4
+ moca_reader_llamaindex-0.6.0.dist-info/WHEEL,sha256=2iZrJkDIkeDh0k9SikKMqFuRP-ua6mb4Ir1AsER4BEw,87
5
+ moca_reader_llamaindex-0.6.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.33.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any