Natural Language Update¶
NLQueryUpdaterExecutor updates existing records based on natural language instructions. It supports direct field updates, foreign key reassignment, related entity updates, and JSONB field patching.
Basic Usage¶
from amsdal_ml.ml_models.openai_model import OpenAIModel
from amsdal_ml.ml_retrievers.query_updater import NLQueryUpdaterExecutor
llm = OpenAIModel()
llm.setup()
updater = NLQueryUpdaterExecutor(llm=llm, queryset=Customer.objects.all())
analysis = await updater.analyze(
'Change the email of customer John Doe to john.doe@newdomain.com'
)
print(analysis) # update analysis with intent and changes
updated = await updater.execute(analysis)
How It Works¶
The update operation follows a 3-phase pipeline:
Phase 1: Split¶
The LLM splits the natural language instruction into:
- Find query — which records to update (e.g., "customer John Doe")
- Update instruction — what to change (e.g., "change email to john.doe@newdomain.com")
Phase 2: Resolution¶
The executor:
- Resolves nested entity references mentioned in the update instruction via LLM
- For FK field updates, resolves referenced entities
- Detects the update intent type
Phase 3: Patch¶
The executor:
- Generates the update payload
- Applies changes within a transaction
- Returns updated records
Update Intent Types¶
The executor detects the type of update and handles each differently:
| Intent | Description | Example |
|---|---|---|
UPDATE_DIRECT |
Change a field value directly | "Change email to ..." |
REASSIGN_FK |
Change a foreign key reference | "Move customer to Sales department" |
UPDATE_RELATED |
Update a related entity | "Change the department name to Marketing" |
MIXED |
Combination of the above | "Move to Sales and update email" |
AMBIGUOUS |
Intent cannot be determined | No changes detected or conflicting instructions |
Update Preview¶
The UpdateAnalysis includes a preview of changes before execution:
updater = NLQueryUpdaterExecutor(llm=llm, queryset=Customer.objects.all())
analysis = await updater.analyze(
'Change John Doe email to john@new.com'
)
for preview in analysis.target_updates:
print(f'Entity: {preview.entity_type}#{preview.entity_id}')
for change in preview.changes:
print(f' {change.field_path}: {change.current_value} → {change.updated_value}')
Each UpdateChange includes:
| Field | Description |
|---|---|
field_path |
Dot-separated field path |
current_value |
Current value |
updated_value |
New value |
field_type |
Field kind: direct, fk, or jsonb |
JSONB Updates¶
For models with JSONB fields, the executor tracks changes at the path level and applies diffs rather than replacing the entire field.
Authorization¶
updater = NLQueryUpdaterExecutor(
llm=llm,
queryset=Customer.objects.all(),
on_before_save=my_auth_callback,
)