Skip to content

Commit 2646995

Browse files
Pouyanpimiyoungcgreptile-apps[bot]
authored
docs: fix inaccuracies in init-function, knowledge base, and cache docs (#1709)
Signed-off-by: Miyoung Choi <miyoungc@nvidia.com> Co-authored-by: Miyoung Choi <miyoungc@nvidia.com> Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
1 parent 73e7791 commit 2646995

File tree

3 files changed

+56
-36
lines changed

3 files changed

+56
-36
lines changed

docs/configure-rails/caching/model-memory-cache.md

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ The NVIDIA NeMo Guardrails library supports an in-memory cache that avoids makin
2020

2121
In-memory caches are supported for all NemoGuard models: [Content-Safety](https://build.nvidia.com/nvidia/llama-3_1-nemoguard-8b-content-safety), [Topic-Control](https://build.nvidia.com/nvidia/llama-3_1-nemoguard-8b-topic-control), and [Jailbreak Detection](https://build.nvidia.com/nvidia/nemoguard-jailbreak-detect). You can configure each model independently.
2222

23-
The cache uses exact matching (after removing whitespace) on LLM prompts with a Least-Frequently-Used (LFU) algorithm for cache evictions.
23+
The cache uses exact matching (after normalizing whitespace) on LLM prompts with a Least-Frequently-Used (LFU) algorithm for cache evictions. Whitespace normalization collapses consecutive whitespace characters into a single space and trims leading/trailing whitespace.
2424

2525
For observability, cache hits and misses are visible in OpenTelemetry (OTEL) telemetry and stored in logs at a configurable interval.
2626

@@ -166,14 +166,7 @@ The most important metric is the *Hit Rate*, which represents the proportion of
166166
These statistics accumulate while the library is running.
167167

168168
```text
169-
"LFU Cache Statistics - "
170-
"Size: 23/10000 | "
171-
"Hits: 20 | "
172-
"Misses: 3 | "
173-
"Hit Rate: 87% | "
174-
"Evictions: 0 | "
175-
"Puts: 21 | "
176-
"Updates: 4"
169+
Cache Stats :: Size: 23/10000 | Hits: 20 | Misses: 3 | Hit Rate: 87.00% | Evictions: 0 | Puts: 21 | Updates: 4
177170
```
178171

179172
The following list describes the metrics included in the cache statistics:

docs/configure-rails/custom-initialization/init-function.md

Lines changed: 35 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,12 @@ content:
2424

2525
If `config.py` contains an `init` function, it is called during `LLMRails` initialization. Use it to set up shared resources and register action parameters.
2626

27+
```{important}
28+
The `init` function **must be synchronous** (`def init`, not `async def init`). The framework calls it without `await`, so an async function would silently do nothing.
29+
```
30+
31+
Any top-level code in `config.py` runs at import time, before `init()` is called. This can be used for provider registration that does not require the `LLMRails` instance.
32+
2733
## Basic Usage
2834

2935
```python
@@ -39,17 +45,19 @@ def init(app: LLMRails):
3945

4046
## Registering Action Parameters
4147

42-
Action parameters registered in `config.py` are automatically injected into actions that declare them:
48+
Action parameters registered in `config.py` are automatically injected into actions that declare them. The runtime matches parameters by name, i.e., the parameter name in the action must match the name used during registration.
4349

4450
**config.py:**
4551

4652
```python
53+
import os
54+
4755
from nemoguardrails import LLMRails
4856

4957
def init(app: LLMRails):
5058
# Initialize shared resources
5159
db = DatabaseConnection(host="localhost", port=5432)
52-
api_client = ExternalAPIClient(api_key="...")
60+
api_client = ExternalAPIClient(api_key=os.environ.get("API_KEY"))
5361

5462
# Register as action parameters
5563
app.register_action_param("db", db)
@@ -72,6 +80,20 @@ async def call_external_service(query: str, api_client=None):
7280
return await api_client.search(query)
7381
```
7482

83+
## Built-in Action Parameters
84+
85+
In addition to parameters you register, the runtime automatically injects these built-in parameters into any action that declares them:
86+
87+
| Parameter | Type | Description |
88+
|-----------|------|-------------|
89+
| `config` | `RailsConfig` | The full rails configuration object |
90+
| `context` | `dict` | The current conversation context |
91+
| `events` | `list` | The event history |
92+
| `llm` | LLM instance | The main LLM (auto-registered during initialization) |
93+
| `llm_task_manager` | `LLMTaskManager` | Manages LLM task execution |
94+
95+
See [Custom Data](custom-data.md) for details on accessing `config.custom_data` inside actions.
96+
7597
## Accessing the Configuration
7698

7799
The `app` parameter provides access to the full configuration:
@@ -91,37 +113,32 @@ def init(app: LLMRails):
91113
## Example: Database Connection
92114

93115
```python
94-
import asyncpg
116+
import os
117+
import psycopg2
95118
from nemoguardrails import LLMRails
96119

97-
async def create_db_pool():
98-
return await asyncpg.create_pool(
99-
host="localhost",
100-
database="mydb",
101-
user="user",
102-
password="password"
103-
)
104-
105120
def init(app: LLMRails):
106-
import asyncio
107-
108121
# Create connection pool
109-
loop = asyncio.get_event_loop()
110-
db_pool = loop.run_until_complete(create_db_pool())
122+
conn = psycopg2.connect(
123+
host=os.environ.get("DB_HOST", "localhost"),
124+
database=os.environ.get("DB_NAME", "mydb"),
125+
user=os.environ.get("DB_USER", "user"),
126+
password=os.environ.get("DB_PASSWORD"),
127+
)
111128

112-
# Register for use in actions
113-
app.register_action_param("db_pool", db_pool)
129+
app.register_action_param("db_conn", conn)
114130
```
115131

116132
## Example: API Client Initialization
117133

118134
```python
135+
import os
119136
import httpx
120137
from nemoguardrails import LLMRails
121138

122139
def init(app: LLMRails):
123140
# Get API key from custom_data in config.yml
124-
api_key = app.config.custom_data.get("api_key")
141+
api_key = os.environ.get("API_KEY") or app.config.custom_data.get("api_key")
125142

126143
# Create HTTP client with authentication
127144
client = httpx.AsyncClient(

docs/configure-rails/other-configurations/knowledge-base.md

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ Currently, only the Markdown format is supported.
4040

4141
Documents in the knowledge base `kb` folder are automatically processed and indexed for retrieval. The system:
4242

43-
1. Splits documents into topic chunks based on markdown headers.
43+
1. Splits documents into topic chunks based on markdown headers. Large chunks are further split at blank lines to stay within a maximum chunk size.
4444
2. Uses the configured embedding model to create vector representations of each chunk.
4545
3. Stores the embeddings for efficient similarity search.
4646

@@ -126,26 +126,37 @@ Place markdown files in the `kb` folder as described above. This is the simplest
126126
Implement a custom action to retrieve chunks from external sources:
127127

128128
```python
129+
from typing import Optional
130+
129131
from nemoguardrails.actions import action
132+
from nemoguardrails.actions.actions import ActionResult
133+
from nemoguardrails.kb.kb import KnowledgeBase
130134
131-
@action()
132-
async def retrieve_relevant_chunks(context: dict, llm: BaseLLM):
133-
"""Custom retrieval from external knowledge base."""
134-
user_message = context.get("last_user_message")
135+
@action(is_system_action=True)
136+
async def retrieve_relevant_chunks(
137+
context: Optional[dict] = None,
138+
kb: Optional[KnowledgeBase] = None,
139+
):
140+
user_message = context.get("last_user_message") if context else None
135141
136142
# Implement custom retrieval logic
137143
# For example, query an external vector database
138144
chunks = await query_external_kb(user_message)
145+
relevant_chunks = "\n".join(chunks)
139146
140-
return chunks
147+
return ActionResult(
148+
return_value=relevant_chunks,
149+
context_updates={"relevant_chunks": relevant_chunks},
150+
)
141151
```
142152

143153
### 3. Using Custom EmbeddingSearchProvider
144154

145155
For advanced use cases, implement a custom embedding search provider:
146156

147157
```python
148-
from nemoguardrails.embeddings.index import EmbeddingsIndex
158+
from typing import List, Optional
159+
from nemoguardrails.embeddings.index import EmbeddingsIndex, IndexItem
149160
150161
class CustomEmbeddingSearchProvider(EmbeddingsIndex):
151162
"""Custom embedding search provider."""
@@ -154,8 +165,7 @@ class CustomEmbeddingSearchProvider(EmbeddingsIndex):
154165
# Custom indexing logic
155166
pass
156167
157-
async def search(self, text: str, max_results: int) -> List[IndexItem]:
158-
# Custom search logic
168+
async def search(self, text: str, max_results: int, threshold: Optional[float] = None) -> List[IndexItem]:
159169
pass
160170
```
161171

0 commit comments

Comments
 (0)