Skip to content

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,
)