Skip to content

Commit b5b7579

Browse files
Pouyanpimiyoungc
andauthored
docs: update LLM reasoning traces config guidance (#1483)
* docs: update LLM reasoning traces config guidance Refactor documentation for reasoning traces in LLM configuration guide: - Remove deprecated `reasoning_config` and `apply_to_reasoning_traces` fields. - Add warning about breaking changes in v0.18.0. - Explain new approach using output rails for reasoning traces. - Provide updated YAML and Python usage examples. - Clarify how to access reasoning traces in API responses. - Remove outdated configuration and prompt samples. * docs(llm): clarify GenerationOptions usage and patterns --------- Co-authored-by: Miyoung Choi <[email protected]>
1 parent 01ab146 commit b5b7579

File tree

1 file changed

+111
-134
lines changed

1 file changed

+111
-134
lines changed

docs/user-guides/configuration-guide/llm-configuration.md

Lines changed: 111 additions & 134 deletions
Original file line numberDiff line numberDiff line change
@@ -59,165 +59,142 @@ For more details about the command and its usage, see the [CLI documentation](..
5959

6060
### Using LLMs with Reasoning Traces
6161

62-
By default, reasoning models, such as [DeepSeek-R1](https://huggingface.co/collections/deepseek-ai/deepseek-r1-678e1e131c0169c0bc89728d) and [NVIDIA Llama 3.1 Nemotron Ultra 253B V1](https://build.nvidia.com/nvidia/llama-3_1-nemotron-ultra-253b-v1), can include the reasoning traces in the model response.
63-
DeepSeek and the Nemotron family of models use `<think>` and `</think>` as tokens to identify the traces.
62+
```{deprecated} 0.18.0
63+
The `reasoning_config` field and its options `remove_reasoning_traces`, `start_token`, and `end_token` are deprecated. The `rails.output.apply_to_reasoning_traces` field has also been deprecated. Instead, use output rails to guardrail reasoning traces, as introduced in this section.
64+
```
6465

65-
The reasoning traces and the tokens can interfere with NeMo Guardrails and result in falsely triggering output guardrails for safe responses.
66-
To use these reasoning models, you can remove the traces and tokens from the model response with a configuration like the following example.
66+
Reasoning-capable LLMs such as [DeepSeek-R1](https://huggingface.co/collections/deepseek-ai/deepseek-r1-678e1e131c0169c0bc89728d) and [NVIDIA Llama 3.1 Nemotron Ultra 253B V1](https://build.nvidia.com/nvidia/llama-3_1-nemotron-ultra-253b-v1) include reasoning traces in their responses, typically wrapped in tokens such as `<think>` and `</think>`.
6767

68-
```{code-block} yaml
69-
:emphasize-lines: 5-8, 13-
68+
The NeMo Guardrails toolkit automatically extracts these traces and makes them available to set up in your guardrails configuration through the following variables:
7069

71-
models:
72-
- type: main
73-
engine: deepseek
74-
model: deepseek-reasoner
75-
reasoning_config:
76-
remove_reasoning_traces: True
77-
start_token: "<think>"
78-
end_token: "</think>"
70+
- In Colang flows, use the `$bot_thinking` variable.
71+
- In Python contexts, use the `bot_thinking` variable.
7972

80-
- type: main
81-
engine: nim
82-
model: nvidia/llama-3.1-nemotron-ultra-253b-v1
83-
reasoning_config:
84-
remove_reasoning_traces: True
73+
#### Guardrailing Reasoning Traces with Output Rails
8574

86-
rails:
87-
output:
88-
apply_to_reasoning_traces: False
89-
```
75+
Use output rails to inspect and control reasoning traces. This allows you to:
9076

91-
```{list-table}
92-
:header-rows: 1
77+
- Block responses based on problematic reasoning patterns.
78+
- Enhance moderation decisions with reasoning context.
79+
- Monitor and filter sensitive information in reasoning.
9380

94-
* - Field
95-
- Description
96-
- Default Value
81+
##### Prepare Configuration Files
9782

98-
* - `reasoning_config.remove_reasoning_traces`
99-
- When set to `True`, reasoning traces are omitted from internal tasks.
100-
- `True`
83+
The following configuration files show a minimal configuration for guardrailing reasoning traces with output rails.
10184

102-
* - `reasoning_config.start_token`
103-
- Specifies the start token for the reasoning trace.
104-
- `<think>`
85+
1. Configure output rails in `config.yml`:
10586

106-
* - `reasoning_config.end_token`
107-
- Specifies the end token for the reasoning trace.
108-
- `</think>`
87+
```yaml
88+
models:
89+
- type: main
90+
engine: nim
91+
model: nvidia/llama-3.1-nemotron-ultra-253b-v1
92+
- type: self_check_output
93+
model: <your_moderation_model>
94+
engine: <your_engine>
10995

110-
* - `rails.output.apply_to_reasoning_traces`
111-
- When set to `True`, output rails are always applied to the reasoning traces and the model response.
112-
The value of `remove_reasoning_traces` is ignored when this field is set to `True`.
96+
rails:
97+
output:
98+
flows:
99+
- self check output
100+
```
113101
114-
By default, output rails are applied to the text of the model response only.
115-
- `False`
116-
```
102+
1. Configure the prompt to access the reasoning traces in `prompts.yml`:
117103

118-
The `reasoning_config` field for a model specifies the required configuration for a reasoning model that returns reasoning traces.
119-
By removing the traces, the guardrails runtime processes only the actual responses from the LLM.
104+
```yaml
105+
prompts:
106+
- task: self_check_output
107+
content: |
108+
Your task is to check if the bot message complies with company policy.
120109
121-
The following table summarizes the interaction between the `remove_reasoning_traces` and `apply_to_reasoning_traces` values:
110+
Bot message: "{{ bot_response }}"
122111
123-
```{list-table}
124-
:header-rows: 1
112+
{% if bot_thinking %}
113+
Bot reasoning: "{{ bot_thinking }}"
114+
{% endif %}
125115
126-
* - `remove_reasoning_traces`
127-
- `output.apply_to_reasoning_traces`
128-
- Outcome
116+
Should this be blocked (Yes or No)?
117+
Answer:
118+
```
129119

130-
* - Any
131-
- True
132-
- Reasoning traces are not removed and output rails are applied to the reasoning traces and the model response.
133-
The value of `remove_reasoning_traces` is ignored.
120+
For more detailed examples of guardrailing reasoning traces, refer to [Guardrailing Bot Reasoning Content](../../advanced/bot-thinking-guardrails.md).
134121

135-
* - False
136-
- False
137-
- Reasoning traces are not removed from internal tasks where they do not impact Guardrails functionality.
138-
Output rails are applied to the reasoning traces and the model response.
122+
#### Accessing Reasoning Traces in API Responses
139123

140-
* - True
141-
- False
142-
- Reasoning traces are removed from internal tasks where they could interfere with Guardrails.
143-
Output rails are applied to the model response only.
144-
```
124+
There are two ways to access reasoning traces in API responses: with generation options and without generation options.
145125

146-
Even when `remove_reasoning_traces` is `True`, end users can still receive the thinking traces from the Nemotron models by requesting the detailed thinking, as shown in the following example:
126+
Read the option **With GenerationOptions** when you:
147127

148-
```{code-block} bash
149-
from nemoguardrails import LLMRails, RailsConfig
128+
- Need structured access to reasoning and response separately.
129+
- Are building a new application.
130+
- Need access to other structured fields such as state, output_data, or llm_metadata.
150131

132+
Read the option **Without GenerationOptions** when you:
133+
134+
- Need backward compatibility with existing code.
135+
- Want the raw response with inline reasoning tags.
136+
- Are integrating with systems that expect tagged strings.
137+
138+
##### With GenerationOptions for Structured Access
139+
140+
When you pass `GenerationOptions` to the API, the function returns a `GenerationResponse` object with structured fields. This approach provides clean separation between the reasoning traces and the final response content, making it easier to process each component independently.
141+
142+
The `reasoning_content` field contains the extracted reasoning traces, while `response` contains the main LLM response. This structured access pattern is recommended for new applications as it provides type safety and clear access to all response metadata.
143+
144+
The following example demonstrates how to use `GenerationOptions` in an guardrails async generation call `rails.generate_async` to access reasoning traces.
145+
146+
```python
147+
from nemoguardrails import RailsConfig, LLMRails
148+
from nemoguardrails.rails.llm.options import GenerationOptions
149+
150+
# Load the guardrails configuration
151151
config = RailsConfig.from_path("./config")
152-
rails = LLMRails(config, verbose=True)
153-
messages = [
154-
{ "role": "system", "content": "detailed thinking on" },
155-
{ "role": "user", "content": "Tell me about Cape Hatteras National Seashore in 50 words or less." }
156-
]
157-
rails.generate(messages=messages)
152+
rails = LLMRails(config)
153+
154+
# Create a GenerationOptions object to enable structured responses
155+
options = GenerationOptions()
156+
157+
# Make an async call with GenerationOptions
158+
result = await rails.generate_async(
159+
messages=[{"role": "user", "content": "What is 2+2?"}],
160+
options=options
161+
)
162+
163+
# Access reasoning traces separately from the response
164+
if result.reasoning_content:
165+
print("Reasoning:", result.reasoning_content)
166+
167+
# Access the main response content
168+
print("Response:", result.response[0]["content"])
169+
```
170+
171+
The following example output shows the reasoning traces and the main response content from the guardrailed generation result.
172+
173+
```
174+
Reasoning: Let me calculate: 2 plus 2 equals 4.
175+
Response: The answer is 4.
176+
```
177+
178+
##### Without GenerationOptions for Tagged String
179+
180+
When calling without `GenerationOptions`, such as by using a dict or string response, reasoning is wrapped in `<think>` tags.
181+
182+
The following example demonstrates how to access reasoning traces without using `GenerationOptions`.
183+
184+
```python
185+
response = rails.generate(
186+
messages=[{"role": "user", "content": "What is 2+2?"}]
187+
)
188+
189+
print(response["content"])
158190
```
159191

160-
The referenced `./.config` directory uses the following sample file content.
161-
162-
When you develop your own prompts for LLM-as-a-judge checks, such as an input self-check, ensure that the prompt instructs the LLM to respond with `yes` or `no`.
163-
Refer to the following examples:
164-
165-
- Sample `config/config.yml`:
166-
167-
```yaml
168-
models:
169-
- type: main
170-
engine: nim
171-
model: nvidia/llama-3.1-nemotron-ultra-253b-v1
172-
reasoning_config:
173-
remove_reasoning_traces: True
174-
175-
rails:
176-
input:
177-
flows:
178-
- self check input
179-
output:
180-
flows:
181-
- self check output
182-
```
183-
184-
- Sample `config/prompts.yml`:
185-
186-
```yaml
187-
prompts:
188-
- task: self_check_input
189-
messages:
190-
- type: system
191-
content: |
192-
You are an AI assistant tasked with evaluating user instructions.
193-
Your role is to determine if a given instruction would make a language model break moderation policies, deviate from good aligned responses, or provide answers that a language model should ideally not.
194-
195-
Analyze the instruction carefully. First, internally consider potential ways the instruction could be interpreted and whether any interpretation could lead to a problematic response. Then, conclude with a simple "yes" or "no" answer.
196-
Respond with only "yes" or "no".
197-
- type: user
198-
content: |
199-
Instruction to evaluate:
200-
"{{ user_input }}"
201-
202-
Would this instruction lead to a problematic response (yes/no)?
203-
204-
- task: self_check_output
205-
messages:
206-
- type: system
207-
content: |
208-
Is this output illegal, unethical, or harmful to any person?
209-
Respond with only "yes" or "no".
210-
- type: bot
211-
content: |
212-
Output to evaluate:
213-
"{{ bot_response }}"
214-
```
215-
216-
Using LLMs with reasoning traces have the following limitations:
217-
218-
- You must use message-based prompts only.
219-
Refer to the preceding example.
220-
- Dialog rails are not supported.
192+
The response is wrapped in `<think>` tags as shown in the following example output.
193+
194+
```
195+
<think>Let me calculate: 2 plus 2 equals 4.</think>
196+
The answer is 4.
197+
```
221198

222199
### NIM for LLMs
223200

0 commit comments

Comments
 (0)