llmrivotril 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 (102) hide show
  1. llmrivotril-0.1.0/.github/constraints-ci.txt +10 -0
  2. llmrivotril-0.1.0/.github/constraints-runtime.txt +25 -0
  3. llmrivotril-0.1.0/.github/workflows/ci.yml +88 -0
  4. llmrivotril-0.1.0/.github/workflows/release.yml +44 -0
  5. llmrivotril-0.1.0/.gitignore +57 -0
  6. llmrivotril-0.1.0/.pre-commit-config.yaml +14 -0
  7. llmrivotril-0.1.0/CHANGELOG.md +327 -0
  8. llmrivotril-0.1.0/CONTRIBUTING.md +65 -0
  9. llmrivotril-0.1.0/LICENSE +21 -0
  10. llmrivotril-0.1.0/PKG-INFO +283 -0
  11. llmrivotril-0.1.0/README.md +170 -0
  12. llmrivotril-0.1.0/README.pt-BR.md +160 -0
  13. llmrivotril-0.1.0/docs/configuration.md +112 -0
  14. llmrivotril-0.1.0/docs/configuration.pt-BR.md +112 -0
  15. llmrivotril-0.1.0/docs/guardrails-and-safety.md +94 -0
  16. llmrivotril-0.1.0/docs/guardrails-and-safety.pt-BR.md +101 -0
  17. llmrivotril-0.1.0/docs/integrations.md +169 -0
  18. llmrivotril-0.1.0/docs/integrations.pt-BR.md +172 -0
  19. llmrivotril-0.1.0/docs/observability.md +96 -0
  20. llmrivotril-0.1.0/docs/observability.pt-BR.md +101 -0
  21. llmrivotril-0.1.0/docs/providers.md +124 -0
  22. llmrivotril-0.1.0/docs/providers.pt-BR.md +125 -0
  23. llmrivotril-0.1.0/docs/rag.md +122 -0
  24. llmrivotril-0.1.0/docs/rag.pt-BR.md +131 -0
  25. llmrivotril-0.1.0/docs/releasing.md +60 -0
  26. llmrivotril-0.1.0/docs/releasing.pt-BR.md +55 -0
  27. llmrivotril-0.1.0/docs/reliability.md +141 -0
  28. llmrivotril-0.1.0/docs/reliability.pt-BR.md +144 -0
  29. llmrivotril-0.1.0/docs/streaming-and-tools.md +72 -0
  30. llmrivotril-0.1.0/docs/streaming-and-tools.pt-BR.md +72 -0
  31. llmrivotril-0.1.0/docs/technical-review.md +353 -0
  32. llmrivotril-0.1.0/examples/basic_usage.py +37 -0
  33. llmrivotril-0.1.0/examples/comparison.py +199 -0
  34. llmrivotril-0.1.0/examples/demo.py +218 -0
  35. llmrivotril-0.1.0/examples/tools_example.py +51 -0
  36. llmrivotril-0.1.0/pyproject.toml +244 -0
  37. llmrivotril-0.1.0/scripts/benchmark.py +287 -0
  38. llmrivotril-0.1.0/src/llmrivotril/__init__.py +97 -0
  39. llmrivotril-0.1.0/src/llmrivotril/_async.py +28 -0
  40. llmrivotril-0.1.0/src/llmrivotril/agent.py +1348 -0
  41. llmrivotril-0.1.0/src/llmrivotril/cache.py +311 -0
  42. llmrivotril-0.1.0/src/llmrivotril/cli.py +115 -0
  43. llmrivotril-0.1.0/src/llmrivotril/config.py +245 -0
  44. llmrivotril-0.1.0/src/llmrivotril/content.py +43 -0
  45. llmrivotril-0.1.0/src/llmrivotril/exceptions.py +14 -0
  46. llmrivotril-0.1.0/src/llmrivotril/guardrails.py +126 -0
  47. llmrivotril-0.1.0/src/llmrivotril/integrations/__init__.py +21 -0
  48. llmrivotril-0.1.0/src/llmrivotril/integrations/_common.py +38 -0
  49. llmrivotril-0.1.0/src/llmrivotril/integrations/adk.py +94 -0
  50. llmrivotril-0.1.0/src/llmrivotril/integrations/autogen.py +72 -0
  51. llmrivotril-0.1.0/src/llmrivotril/integrations/crewai.py +92 -0
  52. llmrivotril-0.1.0/src/llmrivotril/integrations/langchain.py +132 -0
  53. llmrivotril-0.1.0/src/llmrivotril/memory.py +200 -0
  54. llmrivotril-0.1.0/src/llmrivotril/metrics.py +169 -0
  55. llmrivotril-0.1.0/src/llmrivotril/moderation.py +80 -0
  56. llmrivotril-0.1.0/src/llmrivotril/pii.py +108 -0
  57. llmrivotril-0.1.0/src/llmrivotril/plugins.py +139 -0
  58. llmrivotril-0.1.0/src/llmrivotril/pricing.py +129 -0
  59. llmrivotril-0.1.0/src/llmrivotril/providers.py +1313 -0
  60. llmrivotril-0.1.0/src/llmrivotril/py.typed +0 -0
  61. llmrivotril-0.1.0/src/llmrivotril/rag/__init__.py +16 -0
  62. llmrivotril-0.1.0/src/llmrivotril/rag/chunkers.py +80 -0
  63. llmrivotril-0.1.0/src/llmrivotril/rag/document.py +21 -0
  64. llmrivotril-0.1.0/src/llmrivotril/rag/loaders.py +211 -0
  65. llmrivotril-0.1.0/src/llmrivotril/rag/pipeline.py +141 -0
  66. llmrivotril-0.1.0/src/llmrivotril/rag/retrievers.py +252 -0
  67. llmrivotril-0.1.0/src/llmrivotril/rag/vector_stores.py +543 -0
  68. llmrivotril-0.1.0/src/llmrivotril/resilience.py +335 -0
  69. llmrivotril-0.1.0/src/llmrivotril/scaffold.py +261 -0
  70. llmrivotril-0.1.0/src/llmrivotril/semantic.py +175 -0
  71. llmrivotril-0.1.0/src/llmrivotril/semantic_cache.py +128 -0
  72. llmrivotril-0.1.0/src/llmrivotril/server.py +233 -0
  73. llmrivotril-0.1.0/src/llmrivotril/static/tailwind.min.js +83 -0
  74. llmrivotril-0.1.0/src/llmrivotril/templates/dashboard.html +115 -0
  75. llmrivotril-0.1.0/src/llmrivotril/tools.py +221 -0
  76. llmrivotril-0.1.0/src/llmrivotril/verifier.py +533 -0
  77. llmrivotril-0.1.0/tests/__init__.py +0 -0
  78. llmrivotril-0.1.0/tests/conftest.py +22 -0
  79. llmrivotril-0.1.0/tests/test_agent.py +702 -0
  80. llmrivotril-0.1.0/tests/test_cache.py +237 -0
  81. llmrivotril-0.1.0/tests/test_cli.py +58 -0
  82. llmrivotril-0.1.0/tests/test_config.py +230 -0
  83. llmrivotril-0.1.0/tests/test_guardrails.py +104 -0
  84. llmrivotril-0.1.0/tests/test_integrations.py +234 -0
  85. llmrivotril-0.1.0/tests/test_memory.py +213 -0
  86. llmrivotril-0.1.0/tests/test_metrics.py +107 -0
  87. llmrivotril-0.1.0/tests/test_metrics_auto_save.py +62 -0
  88. llmrivotril-0.1.0/tests/test_moderation.py +87 -0
  89. llmrivotril-0.1.0/tests/test_pii.py +67 -0
  90. llmrivotril-0.1.0/tests/test_plugins.py +132 -0
  91. llmrivotril-0.1.0/tests/test_pricing.py +59 -0
  92. llmrivotril-0.1.0/tests/test_providers.py +790 -0
  93. llmrivotril-0.1.0/tests/test_public_api.py +15 -0
  94. llmrivotril-0.1.0/tests/test_rag.py +379 -0
  95. llmrivotril-0.1.0/tests/test_resilience.py +180 -0
  96. llmrivotril-0.1.0/tests/test_semantic.py +98 -0
  97. llmrivotril-0.1.0/tests/test_semantic_cache.py +85 -0
  98. llmrivotril-0.1.0/tests/test_semantic_integration.py +56 -0
  99. llmrivotril-0.1.0/tests/test_server.py +204 -0
  100. llmrivotril-0.1.0/tests/test_tools.py +277 -0
  101. llmrivotril-0.1.0/tests/test_vector_stores.py +469 -0
  102. llmrivotril-0.1.0/tests/test_verifier.py +161 -0
@@ -0,0 +1,10 @@
1
+ # Reproducible versions for the CI toolchain.
2
+ # Runtime/provider dependencies remain version ranges in pyproject.toml so
3
+ # downstream applications can resolve them with their own dependency set.
4
+ build==1.6.1
5
+ httpx==0.28.1
6
+ mypy==2.3.1
7
+ pytest==9.1.1
8
+ pytest-asyncio==1.4.0
9
+ ruff==0.16.8
10
+ twine==7.0.0
@@ -0,0 +1,25 @@
1
+ # Runtime/provider versions validated together in the Python 3.13 integration
2
+ # venv. Use this file as a reproducible baseline; downstream applications may
3
+ # maintain a narrower set for the providers they actually enable.
4
+ anthropic==1.9.0
5
+ boto3==1.43.105
6
+ botocore==1.43.105
7
+ cohere==7.2.0
8
+ crewai==1.15.23
9
+ fastapi==0.141.1
10
+ google-adk==2.10.0
11
+ google-genai==2.25.0
12
+ httpx==0.28.1
13
+ instructor==1.15.4
14
+ langchain-core==1.6.6
15
+ openai==2.54.0
16
+ pydantic==2.12.5
17
+ qdrant-client==1.19.1
18
+ scikit-learn==1.9.1
19
+ scipy==1.18.1
20
+ s3transfer==0.19.2
21
+ sentence-transformers==6.1.0
22
+ tiktoken==0.14.0
23
+ torch==2.14.0
24
+ transformers==5.17.0
25
+ uvicorn==0.54.0
@@ -0,0 +1,88 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main, develop]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ jobs:
10
+ lint-and-test:
11
+ runs-on: ubuntu-latest
12
+ strategy:
13
+ fail-fast: false
14
+ matrix:
15
+ python-version: ["3.10", "3.11", "3.12", "3.13"]
16
+
17
+ steps:
18
+ - name: Checkout repository
19
+ uses: actions/checkout@v4
20
+
21
+ - name: Set up Python ${{ matrix.python-version }}
22
+ uses: actions/setup-python@v5
23
+ with:
24
+ python-version: ${{ matrix.python-version }}
25
+ cache: pip
26
+ cache-dependency-path: pyproject.toml
27
+
28
+ - name: Install dependencies
29
+ run: |
30
+ python -m pip install --upgrade pip
31
+ pip install -c .github/constraints-ci.txt -e ".[ci]"
32
+
33
+ - name: Lint with ruff
34
+ run: ruff check src tests examples scripts
35
+
36
+ - name: Check formatting with ruff
37
+ run: ruff format --check src tests examples scripts
38
+
39
+ - name: Type check with mypy
40
+ run: mypy src
41
+
42
+ - name: Test with pytest
43
+ run: pytest -v
44
+
45
+ build:
46
+ runs-on: ubuntu-latest
47
+ steps:
48
+ - name: Checkout repository
49
+ uses: actions/checkout@v4
50
+
51
+ - name: Set up Python
52
+ uses: actions/setup-python@v5
53
+ with:
54
+ python-version: "3.12"
55
+ cache: pip
56
+ cache-dependency-path: pyproject.toml
57
+
58
+ - name: Install build dependencies
59
+ run: |
60
+ python -m pip install --upgrade pip
61
+ pip install -c .github/constraints-ci.txt -e ".[ci]"
62
+
63
+ - name: Build package
64
+ run: python -m build
65
+
66
+ - name: Check package metadata
67
+ run: twine check dist/*
68
+
69
+ extras:
70
+ runs-on: ubuntu-latest
71
+ steps:
72
+ - name: Checkout repository
73
+ uses: actions/checkout@v4
74
+
75
+ - name: Set up Python
76
+ uses: actions/setup-python@v5
77
+ with:
78
+ python-version: "3.12"
79
+ cache: pip
80
+ cache-dependency-path: pyproject.toml
81
+
82
+ - name: Install with all extras
83
+ run: |
84
+ python -m pip install --upgrade pip
85
+ pip install -c .github/constraints-ci.txt -e ".[dev]"
86
+
87
+ - name: Run tests with extras installed
88
+ run: pytest -v
@@ -0,0 +1,44 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ release:
5
+ types: [published]
6
+
7
+ permissions: {}
8
+
9
+ jobs:
10
+ publish:
11
+ name: Build and publish distributions
12
+ runs-on: ubuntu-latest
13
+ # Configure this environment's protection rules (required reviewers,
14
+ # wait timer) in Settings -> Environments to gate the actual upload step
15
+ # behind manual approval -- switching from Trusted Publishing to a
16
+ # static API token removed OIDC's per-run, unexfiltratable credential;
17
+ # an approval gate is the mitigation for that trade-off.
18
+ environment:
19
+ name: pypi
20
+ url: https://pypi.org/p/llmrivotril
21
+ permissions:
22
+ contents: read
23
+
24
+ steps:
25
+ - name: Check out the release tag
26
+ uses: actions/checkout@v4
27
+
28
+ - name: Set up Python
29
+ uses: actions/setup-python@v5
30
+ with:
31
+ python-version: "3.12"
32
+
33
+ - name: Build distributions
34
+ run: |
35
+ python -m pip install --upgrade pip
36
+ python -m pip install -c .github/constraints-ci.txt build twine
37
+ python -m build
38
+ twine check dist/*
39
+
40
+ - name: Publish to PyPI
41
+ env:
42
+ TWINE_USERNAME: __token__
43
+ TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
44
+ run: twine upload --skip-existing dist/*
@@ -0,0 +1,57 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
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
+ # Virtual environments
30
+ .venv
31
+ venv/
32
+ ENV/
33
+ env/
34
+
35
+ # IDEs
36
+ .vscode/
37
+ .idea/
38
+ *.swp
39
+ *.swo
40
+ *~
41
+
42
+ # Testing
43
+ .pytest_cache/
44
+ .coverage
45
+ htmlcov/
46
+ .tox/
47
+
48
+ # Environment variables
49
+ .env
50
+ .env.local
51
+
52
+ # OS files
53
+ .DS_Store
54
+ Thumbs.db
55
+
56
+ # Logs
57
+ *.log
@@ -0,0 +1,14 @@
1
+ repos:
2
+ - repo: https://github.com/astral-sh/ruff-pre-commit
3
+ rev: v0.6.9
4
+ hooks:
5
+ - id: ruff
6
+ args: [--fix]
7
+ - id: ruff-format
8
+
9
+ - repo: https://github.com/pre-commit/mirrors-mypy
10
+ rev: v1.11.2
11
+ hooks:
12
+ - id: mypy
13
+ additional_dependencies: [types-python-dateutil]
14
+ args: [src]
@@ -0,0 +1,327 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ## [0.1.0] - 2026-09-29
11
+
12
+ ### Added
13
+
14
+ - First release candidate for PyPI distribution.
15
+ - Framework-integration adapters for CrewAI (`BaseLLM`), AG2/pyautogen
16
+ (`ModelClient` protocol, no extra dependency), LangChain/LangGraph
17
+ (`BaseChatModel`), and Google ADK (`BaseLlm`) under
18
+ `llmrivotril.integrations`. Each is optional (`llmrivotril[crewai]`,
19
+ `llmrivotril[langchain]`, `llmrivotril[adk]`, or `llmrivotril[integrations]`
20
+ for all three) and documented in `docs/integrations.md`, including
21
+ multi-agent/crew setup notes.
22
+ - Three independent, opt-in token-saving controls, all off by default and
23
+ documented in `docs/reliability.md`:
24
+ - `SemanticCache` (`llmrivotril.semantic_cache`) -- wraps any `BaseCache`
25
+ backend with an embedding-similarity lookup, so paraphrased repeat
26
+ prompts hit the cache too, not just byte-identical ones. Requires
27
+ `llmrivotril[semantic]`.
28
+ - `MemoryStore(max_tokens=..., count_tokens=...)` -- trims the oldest
29
+ memory turns by actual token count, layered on top of the existing
30
+ turn-count `retention_window` cap. `RivotrilAgent(memory_max_tokens=...)`
31
+ wires this in automatically for its default memory store.
32
+ - `MemoryStore(summarize=..., summarize_trigger_turns=...)` -- compacts
33
+ turns that would otherwise be dropped into a short summary instead.
34
+ `RivotrilAgent(memory_summarize=True, memory_summarize_trigger_turns=...)`
35
+ wires in a summarizer backed by the agent's own provider.
36
+ - `BaseCache.get`/`set` gained an optional `prompt=` parameter (ignored by
37
+ the existing exact-match backends) so a fuzzy-matching cache can see the
38
+ raw prompt text; this is a backward-compatible addition, not a breaking
39
+ change to the interface.
40
+ - Brazilian Portuguese translations (`*.pt-BR.md`) of the README and every
41
+ public doc, each cross-linked with its English original.
42
+ - RAG context injection, deterministic vector-store identifiers, protected
43
+ memory persistence, cache namespacing, and expanded telemetry.
44
+ - Explicit grounding failure policies and provider-specific retry handling.
45
+ - Gemini adapter migration to the `google-genai` SDK.
46
+ - `RAGPipeline.retrieve()`/`aretrieve()` for accessing ranked documents with
47
+ IDs and metadata before formatting context for an LLM.
48
+ - Public top-level exports for `BaseLoader`, `BaseChunker` and `BaseRetriever`
49
+ so custom RAG components do not depend on internal module paths.
50
+ - Async RAG methods now execute synchronous loading, chunking and retrieval in
51
+ a short-lived worker without blocking the event loop.
52
+ - RAG queries support exact metadata filters, source labels and maximum context
53
+ size limits.
54
+ - PostgreSQL, Qdrant and Pinecone use native metadata filters when available;
55
+ Weaviate now supports native filters for explicitly configured flattened
56
+ metadata fields and keeps a client-side fallback for other fields.
57
+
58
+ ### Changed
59
+
60
+ - CI and release workflows now use `.github/constraints-ci.txt` to keep lint,
61
+ type-check, test, and packaging tool versions reproducible without pinning
62
+ runtime/provider dependencies for downstream applications.
63
+ - LangChain, CrewAI and Google ADK integrations now support streaming through
64
+ their native adapter protocols; LangChain also supports `bind_tools()`.
65
+ - Prompt content can contain text, image, audio and document parts. OpenAI,
66
+ Azure, Anthropic, Gemini and Bedrock preserve supported rich content while
67
+ guardrails, PII redaction, token accounting and memory use a safe text view.
68
+ - Bedrock Converse streaming now accumulates `toolUse` deltas and executes the
69
+ generic agent tool loop.
70
+
71
+ ### Fixed
72
+
73
+ - RAG retrievers now reject negative `top_k` values instead of relying on
74
+ Python slicing semantics.
75
+ - Three `WeaviateRetriever` tests only passed when `weaviate-client` happened
76
+ to be installed locally, because `_collection_properties()`/
77
+ `_native_metadata_filter()` do a real (unmocked) `from weaviate.classes...
78
+ import ...` that a mocked `client=` object can't stand in for. This wasn't
79
+ caught by the "326 tests passed" gate recorded earlier in
80
+ `docs/technical-review.md`, because that run had `weaviate-client`
81
+ installed -- CI's `lint-and-test` job (`pip install -e ".[ci]"`, no
82
+ optional extras) would have failed on these 3. Fixed by mocking
83
+ `weaviate.classes.config`/`.query` the same way the other optional
84
+ vector-store dependencies already are; verified clean with zero optional
85
+ packages installed, matching real CI exactly.
86
+
87
+ ### Security
88
+
89
+ - Dashboard log rendering no longer interpolates untrusted content as HTML.
90
+ - SQL table identifiers are validated before being used by the pgvector
91
+ adapter.
92
+
93
+ ## [0.0.9] - 2026-09-28
94
+
95
+ ### Added
96
+
97
+ - `AnthropicProvider`/`CohereProvider`/`GeminiProvider` now implement
98
+ `stream()`/`astream()` (previously unimplemented, raised
99
+ `NotImplementedError`), each using that provider's native streaming API
100
+ and yielding plain text chunks. Not verified against a live account --
101
+ same caveat as the Azure/Bedrock adapters.
102
+ - `run_stream()`/`run_stream_async()` now accept `response_model=`. Returns
103
+ a `StreamedStructuredResult`/`AsyncStreamedStructuredResult` instead of a
104
+ plain iterator: iterate it for the raw JSON text as it streams, and read
105
+ `.result` after the loop ends for the validated `response_model`
106
+ instance (partial JSON isn't a valid model, so there's nothing to
107
+ validate until the stream is done). Can't be combined with `tools=`
108
+ (raises `ValueError`).
109
+
110
+ ## [0.0.8] - 2026-09-28
111
+
112
+ ### Added
113
+
114
+ - `ModerationGuardrail`: flags input/output via OpenAI's moderation
115
+ endpoint, for adversarial/unsafe content the local keyword/regex/topic
116
+ guardrails aren't meant to catch. Fails closed by default (`fail_open=`
117
+ to opt out).
118
+ - `RIVOTRIL_DASHBOARD_TOKENS`: multiple named bearer tokens for the
119
+ dashboard (`"label1:token1,label2:token2"`) instead of one shared secret;
120
+ each valid token's label is logged on access. `RIVOTRIL_DASHBOARD_TOKEN`
121
+ (singular) still works as a single unlabeled token.
122
+ - `AzureOpenAIProvider` and `BedrockProvider`: new provider adapters.
123
+ Azure OpenAI uses the `openai` SDK's dedicated `AzureOpenAI`/
124
+ `AsyncAzureOpenAI` clients (no extra install). Bedrock uses the Bedrock
125
+ Runtime Converse API for one request shape across model families
126
+ (requires `llmrivotril[bedrock]`); `tools=` isn't translated to Converse's
127
+ tool-call format yet, and `acomplete`/`astream` run the synchronous boto3
128
+ call in a worker thread since boto3 has no official async client. Neither
129
+ adapter has been verified against a live Azure/AWS account -- built from
130
+ documented API shapes and covered by mocked unit tests only.
131
+ - `PgVectorRetriever`, `QdrantRetriever`, `WeaviateRetriever`,
132
+ `PineconeRetriever`: external vector-store retrievers for RAG beyond
133
+ in-memory scale, behind `llmrivotril[pgvector|qdrant|weaviate|pinecone]`
134
+ (or `llmrivotril[vector-stores]` for all four). Also not verified against
135
+ a live service -- same caveat as the two new providers.
136
+
137
+ ### Fixed
138
+
139
+ - The non-streaming multi-round tool-calling loop
140
+ (`_handle_tool_calls`/`_handle_tool_calls_async`) passed `tools=None` on
141
+ every follow-up call after the first, so a conversation needing a second
142
+ tool call in the same turn could never request one -- the model was never
143
+ offered any tool schemas past round one.
144
+
145
+ ## [0.0.7] - 2026-09-28
146
+
147
+ ### Added
148
+
149
+ - `InMemoryEmbeddingRetriever(cache_path=...)`: content-hash-keyed embedding
150
+ cache persisted to JSON, so re-ingesting unchanged document content across
151
+ process restarts skips recomputing its embedding.
152
+ - `run_stream()`/`run_stream_async()` accept `tools=`; a turn where the model
153
+ answers directly still streams token by token, and a turn where it calls a
154
+ tool falls back to a single blocking round-trip for that turn.
155
+ - `MemoryStore(auto_save_path=...)` / `RIVOTRIL_MEMORY_PATH`: persist
156
+ conversation history to a JSON file automatically, mirroring
157
+ `RIVOTRIL_METRICS_PATH`/`RIVOTRIL_CACHE_PATH`.
158
+ - `RAGPipeline.aingest()`/`RAGPipeline.aquery()`: async wrappers (via a
159
+ worker thread) so ingestion/retrieval don't block the event loop inside
160
+ `run_async()`.
161
+ - `py.typed` marker (PEP 561) so downstream type checkers pick up this
162
+ package's types.
163
+ - Dashboard endpoints are now rate-limited per client IP
164
+ (`RIVOTRIL_DASHBOARD_RATE_LIMIT_MAX_CALLS`/`_PER_SECONDS`).
165
+
166
+ ### Fixed
167
+
168
+ - `InMemoryEmbeddingRetriever.retrieve()` scored documents with a pure-Python
169
+ cosine-similarity loop; switched to a cached numpy matrix (~5x faster at a
170
+ few thousand documents), with the pure-Python path kept as a fallback when
171
+ numpy isn't installed.
172
+ - `InMemoryEmbeddingRetriever._load_model()` had the same unlocked
173
+ lazy-model-load race already fixed in `semantic.py`; added the same
174
+ double-checked lock.
175
+ - Deleted `InMemoryKeywordRetriever`'s duplicated `[a-z0-9]+` tokenizer/
176
+ stopword list (same accent-splitting bug as `verifier.py`); it now reuses
177
+ the shared, fixed `_tokenize`.
178
+ - Test isolation: `tests/test_config.py` set `os.environ[...]` directly and
179
+ only had a before-test cleanup fixture, so a var left set by its last test
180
+ leaked into whatever test module pytest ran next. Also fixed a subtler
181
+ variant of the same bug in the fix itself: calling `monkeypatch.delenv()`
182
+ from *inside* another fixture's post-`yield` teardown gets undone by
183
+ monkeypatch's own finalizer (which runs afterwards, in reverse dependency
184
+ order) -- switched to plain `os.environ.pop()` for this cleanup.
185
+
186
+ ### Documentation
187
+
188
+ - Documented that `plugins="auto"` executes code from any installed
189
+ package's entry points, with no sandboxing.
190
+ - Documented that Azure OpenAI and AWS Bedrock are not supported via
191
+ `base_url` (they need a different client/auth/request shape, not just a
192
+ different endpoint).
193
+ - Documented the local dashboard's trust model (single shared token, no
194
+ per-user accounts -- not for multi-tenant or public exposure).
195
+
196
+ ## [0.0.6] - 2026-09-27
197
+
198
+ ### Added
199
+
200
+ - Response caching:
201
+ - `cache=` argument on `RivotrilAgent` (`InMemoryCache`, `DiskCache`, `RedisCache`, or custom `BaseCache`).
202
+ - `RIVOTRIL_CACHE_PATH` environment variable to activate disk-based caching.
203
+ - Deterministic cache keys based on model, messages, tools, and response model.
204
+ - `RedisCache` for multi-process/distributed deployments (optional `llmrivotril[redis]` dependency).
205
+ - Schema-repair fallback for structured outputs:
206
+ - `schema_repair_attempts=` argument on `RivotrilAgent`.
207
+ - `RIVOTRIL_SCHEMA_REPAIR_ATTEMPTS` environment variable.
208
+ - Re-prompts the model with validation errors when Pydantic schema validation fails.
209
+ - Cost tracking:
210
+ - `track_costs=` argument on `RivotrilAgent`.
211
+ - `RIVOTRIL_TRACK_COSTS` environment variable.
212
+ - Built-in pricing table for OpenAI, Anthropic, Cohere, and Gemini models.
213
+ - `estimate_cost()`, `register_pricing()`, and `list_supported_models()` helpers.
214
+ - PII detection and redaction:
215
+ - `redact_pii=` argument on `RivotrilAgent`.
216
+ - `RIVOTRIL_REDACT_PII` environment variable.
217
+ - `PIIRedactor` with regex scanners for email, CPF, CNPJ, phone, and credit card.
218
+ - Token budget controls on `RivotrilAgent`:
219
+ - `max_prompt_tokens` and `max_session_tokens` constructor arguments.
220
+ - `RIVOTRIL_MAX_PROMPT_TOKENS` and `RIVOTRIL_MAX_SESSION_TOKENS` environment variables.
221
+ - `TokenBudgetExceededError` raised when a run would exceed the configured budget.
222
+ - Plugin system via Python entry points:
223
+ - Groups `llmrivotril.guardrails` and `llmrivotril.verifiers`.
224
+ - `plugins="auto"` or `plugins=[...]` on `RivotrilAgent`.
225
+ - `discover_plugins()` and `load_plugins()` helpers exported from the top-level package.
226
+ - Automatic metrics persistence:
227
+ - `RIVOTRIL_METRICS_PATH` environment variable and `metrics_path=` argument on `RivotrilAgent`.
228
+ - `MetricsCollector.load_metrics()` alias for `load_from_json()`.
229
+ - Function calling / tools support:
230
+ - `tools=` argument on `agent.run()` and `agent.run_async()`.
231
+ - `ToolRegistry` and `ToolCall` exported from the top-level package.
232
+ - Accepts OpenAI-style tool dicts or plain Python callables (auto-introspected into schemas).
233
+ - Built-in tool-call loop with follow-up completion.
234
+ - Offline dashboard: Tailwind CSS is now bundled and served locally instead of loaded from CDN.
235
+ - File-based configuration via `llmrivotril.toml`, `llmrivotril.yaml`, or `[tool.llmrivotril]` in `pyproject.toml`.
236
+ - Precedence: file defaults < environment variables < constructor arguments.
237
+ - `RIVOTRIL_PROVIDER` environment variable and `provider=` argument on `RivotrilAgent`.
238
+ - Multi-provider support with adapters for OpenAI, Anthropic, Cohere, and Gemini in `llmrivotril.providers`.
239
+ - `ModelBasedFaithfulnessVerifier` for LLM-as-a-judge grounding checks.
240
+
241
+ ### Fixed
242
+
243
+ - PII redaction now applies to structured (`response_model=`) results and runs
244
+ before a response is written to `cache=`; previously `redact_pii=True` left
245
+ structured outputs unredacted and could persist raw PII at rest in the cache.
246
+ - `DiskCache` no longer uses `pickle` (arbitrary code execution risk if the
247
+ cache file is ever tampered with); it now stores JSON in a local SQLite
248
+ file, with indexed per-key reads/writes instead of rewriting the whole
249
+ store on every `get`/`set`.
250
+ - `PIIRedactor.redact()` no longer corrupts text when two pattern matches
251
+ overlap; overlapping spans are merged before replacement.
252
+ - The local dashboard's token check now uses a constant-time comparison
253
+ (`secrets.compare_digest`) instead of `!=`, closing a timing side-channel.
254
+ - `_load_dotenv()` no longer silently swallows a missing `python-dotenv`
255
+ install; it's a core dependency and is now imported unconditionally.
256
+ - Fixed a duplicated `_ENV_INTS` definition in `config.py` that silently
257
+ discarded the first set of keys.
258
+ - Corrected the configuration-precedence docstring in `config.py` to match
259
+ the actual lookup order.
260
+ - `CircuitBreaker` no longer lets multiple threads dispatch a HALF_OPEN probe
261
+ concurrently; checking and transitioning state is now a single atomic
262
+ operation instead of two separately-locked steps.
263
+ - `KeywordOverlapVerifier`'s tokenizer used `[a-z0-9]+`, which split accented
264
+ words (e.g. "informação" -> "informa" + "o"), corrupting grounding checks
265
+ for Portuguese and other accented-language text. Switched to a
266
+ Unicode-aware pattern and added Portuguese stopwords alongside the
267
+ existing English list.
268
+
269
+ ## [0.0.5] - 2026-09-25
270
+
271
+ ### Added
272
+
273
+ - Local RAG module (`llmrivotril.rag`) with:
274
+ - `Document` model
275
+ - `TextLoader` and `MarkdownLoader`
276
+ - `SimpleChunker` with configurable size and overlap
277
+ - `InMemoryKeywordRetriever` (no external dependencies)
278
+ - `InMemoryEmbeddingRetriever` (optional `sentence-transformers`)
279
+ - `RAGPipeline` to ingest sources and feed context into `RivotrilAgent`
280
+ - Re-exported RAG primitives from the top-level `llmrivotril` package.
281
+
282
+ ## [0.0.4] - 2026-09-25
283
+
284
+ ### Added
285
+
286
+ - `llmrivotril init [PATH]` CLI command to scaffold a new project with:
287
+ - `pyproject.toml`, `.gitignore`, `.env.example`, `README.md`
288
+ - package directory with `agent.py` and `guardrails.py`
289
+ - starter `tests/test_agent.py`
290
+
291
+ ## [0.0.3] - 2026-09-25
292
+
293
+ ### Added
294
+
295
+ - Environment-variable configuration via `llmrivotril.config.load_env_config()`.
296
+ - `RIVOTRIL_MODEL`, `RIVOTRIL_API_KEY`, `RIVOTRIL_BASE_URL`, `RIVOTRIL_SYSTEM_PROMPT`
297
+ - `RIVOTRIL_REQUEST_TIMEOUT`
298
+ - `RIVOTRIL_RATE_LIMIT_MAX_CALLS`, `RIVOTRIL_RATE_LIMIT_PER_SECONDS`
299
+ - `RIVOTRIL_RETRY_MAX_ATTEMPTS`, `RIVOTRIL_RETRY_MIN_WAIT`, `RIVOTRIL_RETRY_MAX_WAIT`
300
+ - `RIVOTRIL_CIRCUIT_FAILURE_THRESHOLD`, `RIVOTRIL_CIRCUIT_RECOVERY_TIMEOUT`
301
+ - Explicit constructor arguments always override environment values.
302
+ - `/api/health` endpoint on the dashboard returning status, version, and UTC timestamp.
303
+ - Async-safe `AsyncRateLimiter` used by `RivotrilAgent.run_async()`.
304
+ - `system_prompt` support injected as a `system` message.
305
+ - `context_sources` accepts `str | list[str] | None` and joins multiple sources.
306
+ - Structured logging through the `llmrivotril` logger.
307
+ - CLI commands: `benchmark`, `doctor`, `version`.
308
+ - `request_timeout` forwarded to OpenAI/instructor calls.
309
+ - Per-agent `metrics` injection and `MetricsCollector.reset()`.
310
+ - `disallowed_patterns` regex guardrails on input and output.
311
+
312
+ ### Changed
313
+
314
+ - `tiktoken` encoding now falls back to `cl100k_base` for unknown model names, improving compatibility with local/Ollama models.
315
+ - `Guardrail` output validation also checks `disallowed_keywords`.
316
+
317
+ ## [0.0.2] - 2026-09-24
318
+
319
+ ### Added
320
+
321
+ - First packaged release of LLM-Rivotril.
322
+
323
+ ## [0.0.1] - 2026-09-20
324
+
325
+ ### Added
326
+
327
+ - Proof-of-concept agent with basic guardrails.
@@ -0,0 +1,65 @@
1
+ # Contributing to LLM-Rivotril
2
+
3
+ Thank you for your interest in improving LLM-Rivotril!
4
+
5
+ ## Getting Started
6
+
7
+ 1. Fork the repository.
8
+ 2. Clone your fork:
9
+ ```bash
10
+ git clone https://github.com/your-username/llmrivotril.git
11
+ cd llmrivotril
12
+ ```
13
+ 3. Create a virtual environment and install in editable mode:
14
+ ```bash
15
+ python -m venv .venv
16
+ source .venv/bin/activate
17
+ pip install -e ".[dev]"
18
+ ```
19
+ For a lighter install that skips optional provider SDKs and semantic dependencies,
20
+ use `pip install -e ".[ci]"`.
21
+
22
+ ## Development Workflow
23
+
24
+ 1. Create a feature branch:
25
+ ```bash
26
+ git checkout -b feature/your-feature-name
27
+ ```
28
+ 2. Make your changes, adding tests for new behavior.
29
+ 3. Run the test suite:
30
+ ```bash
31
+ pytest
32
+ ```
33
+ 4. Run linting and type checks:
34
+ ```bash
35
+ ruff check src tests examples scripts
36
+ ruff format --check src tests examples scripts
37
+ mypy src
38
+ ```
39
+ 5. Commit your changes and open a pull request.
40
+
41
+ ## Code Style
42
+
43
+ - Follow PEP 8.
44
+ - Use type hints for public functions and classes.
45
+ - Keep functions focused and small.
46
+ - Write docstrings for modules, classes, and public methods.
47
+
48
+ ## Testing
49
+
50
+ - Place unit tests in `tests/`.
51
+ - Use `pytest` fixtures to isolate stateful components such as `MemoryStore` and `MetricsCollector`.
52
+ - Mock external API calls (OpenAI / Instructor) in agent tests.
53
+
54
+ ## Reporting Issues
55
+
56
+ When reporting bugs, include:
57
+
58
+ - Python version
59
+ - Package version (`pip show llmrivotril`)
60
+ - Minimal reproducible example
61
+ - Expected vs actual behavior
62
+
63
+ ## License
64
+
65
+ By contributing, you agree that your contributions will be licensed under the MIT License.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 LLM-Rivotril Contributors
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.