Creating Files with the Code Interpreter

Creating Files with the Code Interpreter

Amazon Bedrock Agents can also create and return files to users. They can generate files using the native intelligence of the model to create file types like .CSV files, or by writing code using the code interpreter to create binary files, such as data charts. Agents return files in the response stream.


Bedrock Agent Response Stream

The response stream consists of events, formatted as JSON. It conveys detailed data about the Agent’s thought process and actions as it follows the ReAct model (Reasoning and Acting). Below are some key fields:

  • ‘files’: Contains files generated naturally by the Agent’s LLM model.
  • ’trace’: Contains information about the Agent’s thought process and workflow steps. There are several types of trace events:
    • ‘modelInvocationInput’: Contains:
    • ‘rationale’: Contains the Agent’s reasoning.
    • ‘invocationInput’: Contains details about action group invocation parameters.
      • ‘codeInterpreterInvocationInput’: Contains the code generated by the model and passed to the code interpreter.
    • ‘observation’: Contains critical observations, including:
      • ‘codeInterpreterInvocationOutput’: Contains specific output from code interpretation:
        • ’executionOutput’: Contains the result of code execution.
        • ’executionError’: Contains errors if any occurred during code execution.
        • ‘files’: Contains files generated from code interpretation.
      • ‘finalResponse’: Contains the Agent’s final response.

We will redefine our helper function to capture file results from the response stream. Then, we will use it to save files generated by the Agent, whether through its intelligence or using the code interpreter, and return them to the user.


Redefining the Helper Function

We will redefine the process_response helper function to capture and display richer details from the response stream. Here, we import IPython.display to enable richer output display in notebooks, such as embedding returned files for visualization. We also need additional libraries for notebook and /images/4-invoking-agent/4.3-generating-files-with-code-interpreter/image handling.

from IPython.display import display, Markdown
import matplotlib.pyplot as plt
import matplotlib./images/4-invoking-agent/4.3-generating-files-with-code-interpreter/image as mpimg
def process_response(resp, enable_trace:bool=True, show_code_use:bool=False):
    if resp['ResponseMetadata']['HTTPStatusCode'] != 200:
        print(f"API Response was not 200: {resp}")

    event_stream = resp['completion']
    for event in event_stream:
        if 'files' in event.keys():
            files_event = event['files']
            display(Markdown("### Files"))
            files_list = files_event['files']
            for this_file in files_list:
                print(f"{this_file['name']} ({this_file['type']})")
                file_bytes = this_file['bytes']

                # Save bytes to a file, with the file name and bytes 
                file_name = os.path.join('output', this_file['name'])
                with open(file_name, 'wb') as f:
                    f.write(file_bytes)
                if this_file['type'] == '/images/4-invoking-agent/4.3-generating-files-with-code-interpreter/image/png' or this_file['type'] == '/images/4-invoking-agent/4.3-generating-files-with-code-interpreter/image/jpeg':
                    img = mpimg.imread(file_name)
                    plt.imshow(img)
                    plt.show()

        if 'trace' in event.keys() and enable_trace:
            trace_event = event.get('trace')['trace']['orchestrationTrace']

            if 'modelInvocationInput' in trace_event.keys():
                pass

            if 'rationale' in trace_event.keys():
                rationale = trace_event['rationale']['text']
                display(Markdown(f"### Rationale\n{rationale}"))

            if 'invocationInput' in trace_event.keys() and show_code_use:
                inv_input = trace_event['invocationInput']
                if 'codeInterpreterInvocationInput' in inv_input:
                    gen_code = inv_input['codeInterpreterInvocationInput']['code']
                    code = f"```python\n{gen_code}\n```"
                    display(Markdown(f"### Generated code\n{code}"))

            if 'observation' in trace_event.keys():
                obs = trace_event['observation']
                if 'codeInterpreterInvocationOutput' in obs:
                    if 'executionOutput' in obs['codeInterpreterInvocationOutput'].keys() and show_code_use:
                        raw_output = obs['codeInterpreterInvocationOutput']['executionOutput']
                        output = f"```\n{raw_output}\n```"
                        display(Markdown(f"### Output from code execution\n{output}"))

                    if 'executionError' in obs['codeInterpreterInvocationOutput'].keys():
                        display(Markdown(f"### Error from code execution\n{obs['codeInterpreterInvocationOutput']['executionError']}"))

                    if 'files' in obs['codeInterpreterInvocationOutput'].keys():
                        display(Markdown("### Files generated\n"))
                        display(Markdown(f"{obs['codeInterpreterInvocationOutput']['files']}"))

                if 'finalResponse' in obs:                    
                    final_resp = obs['finalResponse']['text']
                    display(Markdown(f"### Final response\n{final_resp}"))
                    return final_resp

Creating Files by Generating Code

We will ask the Agent to generate a file, which it will return via the response stream.

query = """
Please generate a list of the 10 greatest books of all time. Return it as a CSV file. Always return the file, even if you have provided it before.
"""

invoke_agent_helper(query, session_id, agent_id, agent_alias_id, enable_trace=False, session_state=sessionState,
                    memory_id=memory_id, show_code_use=True)

generates-files


Creating Charts by Interpreting Code

We will send the same stock price data file as before, but this time request a chart. Our Agent will need to write Python code to generate the chart. The enhanced response stream parser with markdown will display the chart in the notebook.

# Invoke Agent and process the response stream
query = "Given the attached price data file, please make me a chart with moving average in red and actual data in blue"

sessionState=add_file_to_session_state(stock_file, 'CODE_INTERPRETER')

invoke_agent_helper(query, session_id, agent_id, agent_alias_id, enable_trace=True, session_state=sessionState,
                    memory_id=memory_id, show_code_use=True)

gen-charts


Generating Synthetic Data and Analyzing It

# Invoke Agent and process the response stream
query = """
generate two csv files for me. 
one called SALES, with 3 columns: COMPANY_ID, COMPANY_NAME, and SALES_2024. 
the other called DETAILS, with 3 columns: COMPANY_ID, COMPANY_STATE_CODE. 
follow these rules:
1) each file should contain 200 companies, and share the same company ID’s. 
2) use human readable english words in the names (not random strings of letters and digits), 
3) use ID’s of the form: C00001. 
4) Only use states that are generally considered to be near the east coast or near the west coast. 
5) Make the revenue from each eastern company range from 0 to $700,000, 
6) Make revenue from each western company range from $500,000 up to $2,000,000. 
When done, test to be sure you have followed each of the above rules, 
and produce a chart comparing sales per company in the two regions using box plots.
"""

invoke_agent_helper(query, session_id, agent_id, agent_alias_id, enable_trace=True, session_state=sessionState,
                    memory_id=memory_id, show_code_use=True)

analytics