Advanced working with Chat Sessions#

Chat sessions in DecisionAI maintain state between the client and server. Understanding how to work with this state is key to effectively using the system.

The state is represented by the ChatSessionState class, which provides a comprehensive interface for managing the session. For complete API details, see Chat Session State.

Session State Management#

The chat session maintains state including:

  • Variables and their properties

  • Constraints and their status

  • Objective function

  • Model configuration

All of these components are accessible through properties and methods of the ChatSessionState class.

Accessing State#

Use the remote_state context manager to safely access and modify session state. When using the remote_state context manager, the following happens:

  1. Fetching the current state from the server

  2. Providing a safe environment for modifications

  3. Syncing changes back to the server when exiting the context

This ensures your local changes are properly propagated and maintains consistency between client and server.

with chat_session.remote_state() as state:  # state is a ChatSessionState instance
    # Access state properties
    py_class_name = state.py_class_name
    constraints = state.constraints
    variables = state.variables

The state context manager ensures thread-safe access and proper synchronization with the server.

Variables and Constraints#

The session provides methods to manage variables and constraints programmatically:

Variables#

with chat_session.remote_state() as state:
    # Get variable information
    base_vars = state.base_variable_ids
    user_vars = state.user_variable_ids
    var_descriptions = state.variable_descriptions

    # Check variable status
    is_enabled = state.is_variable_enabled("var_id")

    # Modify variables
    state.disable_variable("var_id")
    state.enable_variable("var_id")

Constraints#

with chat_session.remote_state() as state:
    # Get constraint information
    base_constraints = state.base_constraint_ids
    user_constraints = state.user_constraint_ids
    constraint_descriptions = state.constraint_descriptions

    # Access constraint details
    code = state.get_constraint_code("constraint_id")
    formulation = state.get_constraint_formulation("constraint_id")

    # Check constraint status
    is_enabled = state.is_constraint_enabled("constraint_id")

    # Modify constraints
    state.disable_constraint("constraint_id")
    state.enable_constraint("constraint_id")

Changing input data for a chat session#

You can replace the input data associated with a chat session at any time using the set_opt_input_data method. This is useful when you need to re-run the model with different parameters or updated datasets.

Calling set_opt_input_data performs the following actions:

  1. Uploads the new InputData object to the server.

  2. Updates the chat session to reference the new input data ID.

  3. Automatically triggers a validation process to check compatibility with existing constraints (see next section).

# Assume 'chat_session' is an existing ChatSession instance
# and 'new_input_data' is an InputData object
chat_session.set_opt_input_data(new_input_data)

Validating compatibility of constraints with new input data#

When you change the input data using set_opt_input_data, the system automatically validates whether the existing constraints are compatible with the new data. This is done by attempting to formulate the optimization model using the new data and the current set of constraints.

If a constraint causes an error during formulation (e.g., referencing data that no longer exists or has changed structure), it is marked as “incompatible”.

Important: Incompatible constraints are not automatically disabled. You need to manually review and disable them if necessary using the remote_state context manager.

# After calling chat_session.set_opt_input_data(new_input_data)

with chat_session.remote_state() as state:
    incompatible_ids = state.incompatible_constraint_ids
    if incompatible_ids:
        print(f"Found incompatible constraints: {incompatible_ids}")
        # Decide how to handle them, e.g., disable them
        for constraint_id in incompatible_ids:
            print(f"Disabling incompatible constraint: {constraint_id}")
            state.disable_constraint(constraint_id)
    else:
        print("All constraints are compatible with the new input data.")

This ensures that you are aware of potential issues arising from data changes and can decide how to proceed, whether by modifying the constraint, disabling it, or adjusting the input data further.

Advanced Features#

Soft Constraints and Priorities

Set constraint priorities to control soft constraint behavior:

with chat_session.remote_state() as state:
    # Set constraint priority
    state.set_constraint_priority("constraint_id", "A")  # Priority A
    state.set_constraint_priority("constraint_id", "B")  # Priority B
    state.set_constraint_priority("constraint_id", "C")  # Priority C
    state.set_constraint_priority("constraint_id", "hard")  # Hard constraint

    # Get constraint priority
    priority = state.get_constraint_priority("constraint_id")

# Solve with current constraint priorities
solution = chat_session.solve()

Mathematical Formulation

Access the complete mathematical representation:

with chat_session.remote_state() as state:
    # Get complete mathematical formulation
    math_form = state.get_mathematical_formulation()

    summary = state.executive_summary

Model Notations

Access and modify model notations:

with chat_session.remote_state() as state:
    # Access variable notations
    var_notations = state.variable_notations

    # Access input notations
    input_notations = state.input_notations

Monitoring Solve Operations#

You can monitor solve operations in real-time by providing a callback function to the connect() method. This is useful for tracking solve results, handling errors, or implementing custom logging.

Callback Signature

The callback function receives two parameters:

  • solution: Solution | None - The solution object when solve succeeds, None when it fails

  • error: Exception | None - The exception when solve fails, None when it succeeds

Basic Usage

Use the callback to monitor solve operations during chat interactions:

def my_solve_monitor(solution, error):
    if error:
        print(f"Solve failed: {error}")
    else:
        print(f"Solution status: {solution.status}")

async with chat_session.connect(post_solve_callback=my_solve_monitor) as chat:
    async for message in chat.stream_messages("Solve the model and present the solution"):
        print(message)

When to Use Callbacks

Use solve callbacks when you need to:

  • Monitor solve success/failure/infeasibility rates during development

  • Implement custom logging or alerting for solve operations

  • Collect solve statistics for performance analysis

  • Handle solve errors in automated workflows

  • Store solution history for comparison or rollback scenarios