Skip to content

Latest commit

 

History

History
1464 lines (1325 loc) · 52 KB

7. prompt with all the files above in it.md

File metadata and controls

1464 lines (1325 loc) · 52 KB

What is this file?

This is a prompt I used to generate the initial code. This file combines all the other files in this directory I submitted to GPT4 as input to get the initial draft.

This is documentation for the assistants api you should use:

The Assistants API allows you to build AI assistants within your own applications. An Assistant has instructions and can leverage models, tools, and knowledge to respond to user queries. The Assistants API currently supports three types of tools: Code Interpreter, Retrieval, and Function calling. In the future, we plan to release more OpenAI-built tools, and allow you to provide your own tools on our platform.

At a high level, a typical integration of the Assistants API has the following flow:

Create an Assistant in the API by defining it custom instructions and picking a model. If helpful, enable tools like Code Interpreter, Retrieval, and Function calling. Create a Thread when a user starts a conversation. Add Messages to the Thread as the user ask questions. Run the Assistant on the Thread to trigger responses. This automatically calls the relevant tools. The Assistants API is in beta and we are actively working on adding more functionality. Share your feedback in our Developer Forum! This starter guide walks through the key steps to create and run an Assistant that uses Code Interpreter.

Step 1: Create an Assistant An Assistant represents an entity that can be configured to respond to users’ Messages using several parameters like:

Instructions: how the Assistant and model should behave or respond Model: you can specify any GPT-3.5 or GPT-4 models, including fine-tuned models. The Retrieval tool requires gpt-3.5-turbo-1106 and gpt-4-1106-preview models. Tools: the API supports Code Interpreter and REtrieval that are built and hosted by OpenAI. Functions: the API allows you to define custom function signatures, with similar behavior as our function calling feature. In this example, we're creating an Assistant that is a personal math tutor, with the Code Interpreter tool enabled:

Calls to the Assistants API require that you pass a Beta header. This is handled automatically if you’re using OpenAI’s official Python and Node.js SDKs. OpenAI-Beta: assistants=v1 node.js

node.js const assistant = await openai.beta.assistants.create({ name: "Math Tutor", instructions: "You are a personal math tutor. Write and run code to answer math questions.", tools: [{ type: "code_interpreter" }], model: "gpt-4-1106-preview" }); Step 2: Create a Thread A Thread represents a conversation. We recommend creating one Thread per user as soon as the user initiates the conversation. Pass any user-specific context and files in this thread by creating Messages.

node.js

node.js const thread = await openai.beta.threads.create(); Threads don’t have a size limit. You can pass as many Messages as you want to a Thread. The API will ensure that requests to the model fit within the maximum context window, using relevant optimization techniques such as truncation.

Step 3: Add a Message to a Thread A Message contains the user's text, and optionally, any files that the user uploads. Image files aren't supported today, but we plan to add support for them in the coming months.

node.js

node.js const message = await openai.beta.threads.messages.create( thread.id, { role: "user", content: "I need to solve the equation 3x + 11 = 14. Can you help me?" } ); Now if you list Messages in Thread, you will see that this message is added to the thread on creation:

{ "object": "list", "data": [ { "created_at": 1696995451, "id": "msg_4rb1Skx3XgQZEe4PHVRFQhr0", "object": "thread.message", "thread_id": "thread_34p0sfdas0823smfv", "role": "user", "content": [{ "type": "text", "text": { "value": "I need to solve the equation 3x + 11 = 14. Can you help me?", "annotations": [] } }], ... Step 4: Run the Assistant For the Assistant to respond to the user message, you need to create a Run. This makes the Assistant read the Thread and decide whether to call tools or simply use the model to best answer the user query. As the run progresses, the assistant appends Messages to the thread with the role="assistant" .

You can optionally pass additional instructions to the Assistant while creating the Run:

node.js

node.js const run = await openai.beta.threads.runs.create( thread.id, { assistant_id: assistant.id, instructions: "Please address the user as Jane Doe. The user has a premium account." } ); Step 5: Display the Assistant's Response This creates a Run in a queued status. You can periodically retrieve the Run to check on its status to see if it has moved to completed.

node.js

node.js const run = await openai.beta.threads.runs.retrieve( thread.id, run.id ); Once the Run completes, you can retrieve the Messages added by the Assistant to the Thread.

node.js

node.js const messages = await openai.beta.threads.messages.list( thread.id ); And finally, display them to the user! During this Run, the Assistant added two new Messages to the Thread.

ROLE CONTENT user I need to solve the equation 3x + 11 = 14. Can you help me? assistant Certainly, Jane Doe. To solve the equation (3x + 11 = 14) for (x), you'll want to isolate (x) on one side of the equation. Here's how you can do that: Subtract 11 from both sides of the equation to get (3x = 3). Then, divide both sides by 3 to solve for (x). Let me calculate the value of (x) for you. assistant The solution to the equation (3x + 11 = 14) is (x = 1). You can also retrieve the Run Steps of this Run if you'd like to explore or display the inner workings of the Assistant and its tools.

Next Dive deeper into How Assistants work Learn more about Tools Was this page useful?

How Assistants work Beta The Assistants API is designed to help developers build powerful AI assistants capable of performing a variety of tasks.

The Assistants API is in beta and we are actively working on adding more functionality. Share your feedback in our Developer Forum! Assistants can call OpenAI’s models with specific instructions to tune their personality and capabilities. Assistants can access multiple tools in parallel. These can be both OpenAI-hosted tools — like Code interpreter and Knowledge retrieval — or tools you build / host (via Function calling). Assistants can access persistent Threads. Threads simplify AI application development by storing message history and truncating it when the conversation gets too long for the model’s context length. You create a Thread once, and simply append Messages to it as your users reply. Assistants can access Files in several formats — either as part of their creation or as part of Threads between Assistants and users. When using tools, Assistants can also create files (e.g., images, spreadsheets, etc) and cite files they reference in the Messages they create. Objects Assistants object architecture diagram

OBJECT WHAT IT REPRESENTS Assistant Purpose-built AI that uses OpenAI’s models and calls tools Thread A conversation session between an Assistant and a user. Threads store Messages and automatically handle truncation to fit content into a model’s context. Message A message created by an Assistant or a user. Messages can include text, images, and other files. Messages stored as a list on the Thread. Run An invocation of an Assistant on a Thread. The Assistant uses it’s configuration and the Thread’s Messages to perform tasks by calling models and tools. As part of a Run, the Assistant appends Messages to the Thread. Run Step A detailed list of steps the Assistant took as part of a Run. An Assistant can call tools or create Messages during it’s run. Examining Run Steps allows you to introspect how the Assistant is getting to it’s final results. Creating Assistants We recommend using OpenAI’s latest models with the Assistants API for best results and maximum compatibility with tools. To get started, creating an Assistant only requires specifying the model to use. But you can further customize the behavior of the Assistant:

Use the instructions parameter to guide the personality of the Assistant and define it’s goals. Instructions are similar to system messages in the Chat Completions API. Use the tools parameter to give the Assistant access to up to 128 tools. You can give it access to OpenAI-hosted tools like code_interpreter and retrieval, or call a third-party tools via a function calling. Use the file_ids parameter to give the tools like code_interpreter and retrieval access to files. Files are uploaded using the File upload endpoint and must have the purpose set to assistants to be used with this API. For example, to create an Assistant that can create data visualization based on a .csv file, first upload a file.

node.js

node.js const file = await openai.files.create({ file: fs.createReadStream("mydata.csv"), purpose: "assistants", }); And then create the Assistant with the uploaded file.

node.js

node.js const assistant = await openai.beta.assistants.create({ name: "Data visualizer", description: "You are great at creating beautiful data visualizations. You analyze data present in .csv files, understand trends, and come up with data visualizations relevant to those trends. You also share a brief text summary of the trends observed.", model: "gpt-4-1106-preview", tools: [{"type": "code_interpreter"}], file_ids: [file.id] }); You can attach a maximum of 20 files per Assistant, and they can be at most 512 MB each. In addition, the size of all the files uploaded by your organization should not exceed 100GB. You can request an increase in this storage limit using our help center.

You can also use the AssistantFile object to create, delete, or view associations between Assistant and File objects. Note that deleting an AssistantFile doesn’t delete the original File object, it simply deletes the association between that File and the Assistant. To delete a File, use the File delete endpoint instead.

Managing Threads and Messages Threads and Messages represent a conversation session between an Assistant and a user. There is no limit to the number of Messages you can store in a Thread. Once the size of the Messages exceeds the context window of the model, the Thread smartly truncates them to fit. You can create a Thread with an initial list of Messages like this:

node.js

node.js const thread = await openai.beta.threads.create({ messages: [ { "role": "user", "content": "Create 3 data visualizations based on the trends in this file.", "file_ids": [file.id] } ] }); Messages can contain text, images, or files. At the moment, user-created Messages cannot contain image files but we plan to add support for this in the future.

Message annotations

Messages created by Assistants may contain annotations within the content array of the object. Annotations provide information around how you should annotate the text in the Message.

There are two types of Annotations:

file_citation: File citations are created by the retrieval tool and define references to a specific quote in a specific file that was uploaded and used by the Assistant to generate the response. file_path: File path annotations are created by the code_interpreter tool and contain references to the files generated by the tool. When annotations are present in the Message object, you'll see illegible model-generated substrings in the text that you should replace with the annotations. These strings may look something like 【13†source】 or sandbox:/mnt/data/file.csv. Here’s an example python code snippet that replaces these strings with information present in the annotations.

Retrieve the message object

message = client.beta.threads.messages.retrieve( thread_id="...", message_id="..." )

Extract the message content

message_content = message.content[0].text annotations = message_content.annotations citations = []

Iterate over the annotations and add footnotes

for index, annotation in enumerate(annotations): # Replace the text with a footnote message_content.value = message_content.value.replace(annotation.text, f' [{index}]')

# Gather citations based on annotation attributes
if (file_citation := getattr(annotation, 'file_citation', None)):
    cited_file = client.files.retrieve(file_citation.file_id)
    citations.append(f'[{index}] {file_citation.quote} from {cited_file.filename}')
elif (file_path := getattr(annotation, 'file_path', None)):
    cited_file = client.files.retrieve(file_path.file_id)
    citations.append(f'[{index}] Click <here> to download {cited_file.filename}')
    # Note: File download functionality not implemented above for brevity

Add footnotes to the end of the message before displaying to user

message_content.value += '\n' + '\n'.join(citations) Runs and Run Steps When you have all the context you need from your user in the Thread, you can run the Thread with an Assistant of your choice.

node.js

node.js const run = await openai.beta.threads.runs.create( thread.id, { assistant_id: assistant.id } ); By default, a Run will use the model and tools configuration specified in Assistant object, but you can override most of these when creating the Run for added flexibility:

node.js

node.js const run = await openai.beta.threads.runs.create( thread.id, { assistant_id: assistant.id, model: "gpt-4-1106-preview", instructions: "additional instructions", tools: [{"type": "code_interpreter"}, {"type": "retrieval"}] } ); Note: file_ids associated with the Assistant cannot be overridden during Run creation. You must use the modify Assistant endpoint to do this.

Run lifecycle

Run objects can have multiple statuses.

Run lifecycle - diagram showing possible status transitions

STATUS DEFINITION queued When Runs are first created or when you complete the required_action, they are moved to a queued status. They should almost immediately move to in_progress. in_progress While in_progress, the Assistant uses the model and tools to perform steps. You can view progress being made by the Run by examining the Run Steps. completed The Run successfully completed! You can now view all Messages the Assistant added to the Thread, and all the steps the Run took. You can also continue the conversation by adding more user Messages to the Thread and creating another Run. requires_action When using the Function calling tool, the Run will move to a required_action state once the model determines the names and arguments of the functions to be called. You must then run those functions and submit the outputs before the run proceeds. If the outputs are not provided before the expires_at timestamp passes (roughly 10 mins past creation), the run will move to an expired status. expired This happens when the function calling outputs were not submitted before expires_at and the run expires. Additionally, if the runs take too long to execute and go beyond the time stated in expires_at, our systems will expire the run. cancelling You can attempt to cancel an in_progress run using the Cancel Run endpoint. Once the attempt to cancel succeeds, status of the Run moves to cancelled. Cancellation is attempted but not guaranteed. cancelled Run was successfully cancelled. failed You can view the reason for the failure by looking at the last_error object in the Run. The timestamp for the failure will be recorded under failed_at. Polling for updates

In order to keep the status of your run up to date, you will have to periodically retrieve the Run object. You can check the status of the run each time you retrieve the object to determine what your application should do next. We plan to add support for streaming to make this simpler in the near future.

Thread locks

When a Run is in_progress and not in a terminal state, the Thread is locked. This means that:

New Messages cannot be added to the Thread. New Runs cannot be created on the Thread. Run steps

Run steps lifecycle - diagram showing possible status transitions

Run step statuses have the same meaning as Run statuses.

Most of the interesting detail in the Run Step object lives in the step_details field. There can be two types of step details:

message_creation: This Run Step is created when the Assistant creates a Message on the Thread. tool_calls: This Run Step is created when the Assistant calls a tool. Details around this are covered in the relevant sections of the Tools guide. Limitations During this beta, there are several known limitations we are looking to address in the coming weeks and months. We will publish a changelog on this page when we add support for additional functionality.

Tools Beta Give Assistants access to OpenAI-hosted tools like Code Interpreter and Knowledge Retrieval, or build your own tools using Function calling.

The Assistants API is in beta and we are actively working on adding more functionality. Share your feedback in our Developer Forum! Code Interpreter Code Interpreter allows the Assistants API to write and run Python code in a sandboxed execution environment. This tool can process files with diverse data and formatting, and generate files with data and images of graphs. Code Interpreter allows your Assistant to run code iteratively to solve challenging code and math problems. When your Assistant writes code that fails to run, it can iterate on this code by attempting to run different code until the code execution succeeds.

Enabling Code Interpreter Pass the code_interpreterin the tools parameter of the Assistant object to enable Code Interpreter:

node.js

node.js const assistant = await openai.beta.assistants.create({ instructions: "You are a personal math tutor. When asked a math question, write and run code to answer the question.", model: "gpt-4-1106-preview", tools: [{"type": "code_interpreter"}] }); The model then decides when to invoke Code Interpreter in a Run based on the nature of the user request. This behavior can be promoted by prompting in the Assistant's instructions (e.g., “write code to solve this problem”).

Passing files to Code Interpreter Code Interpreter can parse data from files. This is useful when you want to provide a large volume of data to the Assistant or allow your users to upload their own files for analysis.

Files that are passed at the Assistant level are accessible by all Runs with this Assistant:

node.js

node.js // Upload a file with an "assistants" purpose const file = await openai.files.create({ file: fs.createReadStream("mydata.csv"), purpose: "assistants", });

// Create an assistant using the file ID const assistant = await openai.beta.assistants.create({ instructions: "You are a personal math tutor. When asked a math question, write and run code to answer the question.", model: "gpt-4-1106-preview", tools: [{"type": "code_interpreter"}], file_ids: [file.id] }); Files can also be passed at the Thread level. These files are only accessible in the specific Thread. Upload the File using the File upload endpoint and then pass the File ID as part of the Message creation request:

node.js

node.js const thread = await openai.beta.threads.create({ messages: [ { "role": "user", "content": "I need to solve the equation 3x + 11 = 14. Can you help me?", "file_ids": [file.id] } ] }); Files have a maximum size of 512 MB. Code Interpreter supports a variety of file formats including .csv, .pdf, .json and many more. More details on the file extensions (and their corresponding MIME-types) supported can be found in the Supported files section below.

Reading images and files generated by Code Interpreter Code Interpreter in the API also outputs files, such as generating image diagrams, CSVs, and PDFs. There are two types of files that are generated:

Images Data files (e.g. a csv file with data generated by the Assistant) When Code Interpreter generates an image, you can look up and download this file in the file_id field of the Assistant Message response:

{ "id": "msg_OHGpsFRGFYmz69MM1u8KYCwf", "object": "thread.message", "created_at": 1698964262, "thread_id": "thread_uqorHcTs46BZhYMyPn6Mg5gW", "role": "assistant", "content": [ { "type": "image_file", "image_file": { "file_id": "file-WsgZPYWAauPuW4uvcgNUGcb" } } ]

...

} The file content can then be downloaded by passing the file ID to the Files API:

node.js

node.js const file = await openai.files.retrieveContent(file.id); When Code Interpreter references a file path (e.g., ”Download this csv file”), file paths are listed as annotations. You can convert these annotations into links to download the file:

{ "id": "msg_3jyIh3DgunZSNMCOORflDyih", "object": "thread.message", "created_at": 1699073585, "thread_id": "thread_ZRvNTPOoYVGssUZr3G8cRRzE", "role": "assistant", "content": [ { "type": "text", "text": { "value": "The rows of the CSV file have been shuffled and saved to a new CSV file. You can download the shuffled CSV file from the following link:\n\nDownload Shuffled CSV File", "annotations": [ { "type": "file_path", "text": "sandbox:/mnt/data/shuffled_file.csv", "start_index": 167, "end_index": 202, "file_path": { "file_id": "file-oSgJAzAnnQkVB3u7yCoE9CBe" } } ... Input and output logs of Code Interpreter By listing the steps of a Run that called Code Interpreter, you can inspect the code input and outputs logs of Code Interpreter:

node.js

node.js const runSteps = await openai.beta.threads.runs.steps.list( thread.id, run.id ); { "object": "list", "data": [ { "id": "step_DQfPq3JPu8hRKW0ctAraWC9s", "object": "assistant.run.step", "type": "tool_calls", "run_id": "run_kme4a442kme4a442", "thread_id": "thread_34p0sfdas0823smfv", "status": "completed", "step_details": { "type": "tool_calls", "tool_calls": [ { "type": "code", "code": { "input": "# Calculating 2 + 2\nresult = 2 + 2\nresult", "outputs": [ { "type": "logs", "logs": "4" } ... } Knowledge Retrieval Retrieval augments the Assistant with knowledge from outside its model, such as proprietary product information or documents provided by your users. Once a file is uploaded and passed to the Assistant, OpenAI will automatically chunk your documents, index and store the embeddings, and implement vector search to retrieve relevant content to answer user queries.

Enabling Retrieval Pass the retrieval in the tools parameter of the Assistant to enable Retrieval:

node.js

node.js const assistant = await openai.beta.assistants.create({ instructions: "You are a customer support chatbot. Use your knowledge base to best respond to customer queries.", model: "gpt-4-1106-preview", tools: [{"type": "retrieval"}] }); How it works The model then decides when to retrieve content based on the user Messages. The Assistants API automatically chooses between two retrieval techniques:

it either passes the file content in the prompt for short documents, or performs a vector search for longer documents Retrieval currently optimizes for quality by adding all relevant content to the context of model calls. We plan to introduce other retrieval strategies to enable developers to choose a different tradeoff between retrieval quality and model usage cost.

Uploading files for retrieval Similar to Code Interpreter, files can be passed at the Assistant-level or at the Thread-level

node.js

node.js // Upload a file with an "assistants" purpose const file = await openai.files.create({ file: fs.createReadStream("knowledge.pdf"), purpose: "assistants", });

// Add the file to the assistant const assistant = await openai.beta.assistants.create({ instructions: "You are a customer support chatbot. Use your knowledge base to best respond to customer queries.", model: "gpt-4-1106-preview", tools: [{"type": "retrieval"}], file_ids: [file.id] }); Files can also be added to a Message in a Thread. These files are only accessible within this specific thread. After having uploaded a file, you can pass the ID of this File when creating the Message:

node.js

node.js const message = await openai.beta.threads.messages.create( thread.id, { role: "user", content: "I can't find in the PDF manual how to turn off this device.", file_ids: [file.id] } ); Maximum file size is 512MB. Retrieval supports a variety of file formats including .pdf, .md, .docx and many more. More details on the file extensions (and their corresponding MIME-types) supported can be found in the Supported files section below.

Deleting files To remove a file from the assistant, you can detach the file from the assistant:

node.js

node.js const fileDeletionStatus = await openai.beta.assistants.files.del( assistant.id, file.id ); Detaching the file from the assistant removes the file from the retrieval index as well.

File citations When Code Interpreter outputs file paths in a Message, you can convert them to corresponding file downloads using the annotations field. See the Annotations section for an example of how to do this.

{ "id": "msg_3jyIh3DgunZSNMCOORflDyih", "object": "thread.message", "created_at": 1699073585, "thread_id": "thread_ZRvNTPOoYVGssUZr3G8cRRzE", "role": "assistant", "content": [ { "type": "text", "text": { "value": "The rows of the CSV file have been shuffled and saved to a new CSV file. You can download the shuffled CSV file from the following link:\n\nDownload Shuffled CSV File", "annotations": [ { "type": "file_path", "text": "sandbox:/mnt/data/shuffled_file.csv", "start_index": 167, "end_index": 202, "file_path": { "file_id": "file-oSgJAzAnnQkVB3u7yCoE9CBe" } } ] } } ], "file_ids": [ "file-oSgJAzAnnQkVB3u7yCoE9CBe" ], ... }, Function calling Similar to the Chat Completions API, the Assistants API supports function calling. Function calling allows you to describe functions to the Assistants and have it intelligently return the functions that need to be called along with their arguments. The Assistants API will pause execution during a Run when it invokes functions, and you can supply the results of the function call back to continue the Run execution.

Defining functions First, define your functions when creating an Assistant:

node.js

node.js const assistant = await openai.beta.assistants.create({ instructions: "You are a weather bot. Use the provided functions to answer questions.", model: "gpt-4-1106-preview", tools: [{ "type": "function", "function": { "name": "getCurrentWeather", "description": "Get the weather in location", "parameters": { "type": "object", "properties": { "location": {"type": "string", "description": "The city and state e.g. San Francisco, CA"}, "unit": {"type": "string", "enum": ["c", "f"]} }, "required": ["location"] } } }, { "type": "function", "function": { "name": "getNickname", "description": "Get the nickname of a city", "parameters": { "type": "object", "properties": { "location": {"type": "string", "description": "The city and state e.g. San Francisco, CA"}, }, "required": ["location"] } } }] }); Reading the functions called by the Assistant When you initiate a Run with a user Message that triggers the function, the Run will enter a requires_action status. The model can provide multiple functions to call at once via the parallel function calling feature:

{ "id": "run_3HV7rrQsagiqZmYynKwEdcxS", "object": "thread.run", "assistant_id": "asst_rEEOF3OGMan2ChvEALwTQakP", "thread_id": "thread_dXgWKGf8Cb7md8p0wKiMDGKc", "status": "requires_action", "required_action": { "type": "submit_tool_outputs", "submit_tool_outputs": { "tool_calls": [ { "tool_call_id": "call_Vt5AqcWr8QsRTNGv4cDIpsmA", "type": "function", "function": { "name": "getCurrentWeather", "arguments": "{"location":"San Francisco"}" } }, { "tool_call_id": "call_45y0df8230430n34f8saa", "type": "function", "function": { "name": "getNickname", "arguments": "{"location":"Los Angeles"}" } } ] } }, ... Submitting functions outputs You can then complete the Run by submitting the output from the function(s) you call. Pass the tool_call_id referenced in the required_action object above to match output to each function call.

node.js

node.js const run = await openai.beta.threads.runs.submitToolOutputs( thread.id, run.id, { tool_outputs: [ { tool_call_id: callIds[0], output: "22C", }, { tool_call_id: callIds[1], output: "LA", }, ], } ); After submitting outputs, the run will enter the queued state before it continues it’s execution.

Supported files For text/ MIME types, the encoding must be one of utf-8, utf-16, or ascii.

FILE FORMAT MIME TYPE CODE INTERPRETER RETRIEVAL .c text/x-c .cpp text/x-c++ .csv application/csv .docx application/vnd.openxmlformats-officedocument.wordprocessingml.document .html text/html .java text/x-java .json application/json .md text/markdown .pdf application/pdf .php text/x-php .pptx application/vnd.openxmlformats-officedocument.presentationml.presentation .py text/x-python .py text/x-script.python .rb text/x-ruby .tex text/x-tex .txt text/plain .css text/css .jpeg image/jpeg .jpg image/jpeg .js text/javascript .gif image/gif .png image/png .tar application/x-tar .ts application/typescript .xlsx application/vnd.openxmlformats-officedocument.spreadsheetml.sheet .xml application/xml or "text/xml" .zip application/zip

THis is a log from the playground showing an execution flow:

POST v1/threads

{ "id": "thread_xdLXH1xiMnP0gtrFm4N8TDJ2", "object": "thread", "created_at": 1699322305, "metadata": {} }

POST v1/threads/thread_xdLXH1xiMnP0gtrFm4N8TDJ2/messages

{ "role": "user", "content": "What is the stock of apple and facebook rn?" }

{ "id": "msg_A4xMXXNn246503BgMGjzQtD2", "object": "thread.message", "created_at": 1699322305, "thread_id": "thread_xdLXH1xiMnP0gtrFm4N8TDJ2", "role": "user", "content": [ { "type": "text", "text": { "value": "What is the stock of apple and facebook rn?", "annotations": [] } } ], "file_ids": [], "assistant_id": null, "run_id": null, "metadata": {} }

GET /v1/threads/thread_xdLXH1xiMnP0gtrFm4N8TDJ2/runs

Response { "object": "list", "data": [], "first_id": null, "last_id": null, "has_more": false }

GET /v1/threads/thread_xdLXH1xiMnP0gtrFm4N8TDJ2/messages

Response { "object": "list", "data": [ { "id": "msg_A4xMXXNn246503BgMGjzQtD2", "object": "thread.message", "created_at": 1699322305, "thread_id": "thread_xdLXH1xiMnP0gtrFm4N8TDJ2", "role": "user", "content": [ { "type": "text", "text": { "value": "What is the stock of apple and facebook rn?", "annotations": [] } } ], "file_ids": [], "assistant_id": null, "run_id": null, "metadata": {} } ], "first_id": "msg_A4xMXXNn246503BgMGjzQtD2", "last_id": "msg_A4xMXXNn246503BgMGjzQtD2", "has_more": false }

[Create a run given an assistant, thread identifier is in the post path, run is queued] POST /v1/threads/thread_xdLXH1xiMnP0gtrFm4N8TDJ2/runs

Request { "assistant_id": "asst_Tosm5sWKNHb4iGfgQVCT9ZDl" }

Response { "id": "run_vV6i4asmD9mNoBfHsE8Hu9RI", "object": "thread.run", "created_at": 1699322306, "assistant_id": "asst_Tosm5sWKNHb4iGfgQVCT9ZDl", "thread_id": "thread_xdLXH1xiMnP0gtrFm4N8TDJ2", "status": "queued", "started_at": null, "expires_at": 1699322906, "cancelled_at": null, "failed_at": null, "completed_at": null, "last_error": null, "model": "gpt-4-1106-preview", "instructions": "Be a friendly finance bro who will help me with trading", "tools": [ { "type": "code_interpreter" }, { "type": "retrieval" }, { "type": "function", "function": { "name": "get_stock_price", "description": "Get the current stock price", "parameters": { "type": "object", "properties": { "symbol": { "type": "string", "description": "The stock symbol" } }, "required": [ "symbol" ] } } } ], "file_ids": [], "metadata": {} }

[The run is now in progress] GET /v1/threads/thread_xdLXH1xiMnP0gtrFm4N8TDJ2/runs/run_vV6i4asmD9mNoBfHsE8Hu9RI

{ "id": "run_vV6i4asmD9mNoBfHsE8Hu9RI", "object": "thread.run", "created_at": 1699322306, "assistant_id": "asst_Tosm5sWKNHb4iGfgQVCT9ZDl", "thread_id": "thread_xdLXH1xiMnP0gtrFm4N8TDJ2", "status": "in_progress", "started_at": 1699322306, "expires_at": 1699322906, "cancelled_at": null, "failed_at": null, "completed_at": null, "last_error": null, "model": "gpt-4-1106-preview", "instructions": "Be a friendly finance bro who will help me with trading", "tools": [ { "type": "code_interpreter" }, { "type": "retrieval" }, { "type": "function", "function": { "name": "get_stock_price", "description": "Get the current stock price", "parameters": { "type": "object", "properties": { "symbol": { "type": "string", "description": "The stock symbol" } }, "required": [ "symbol" ] } } } ], "file_ids": [], "metadata": {} }

[We can now get the steps, although this seems more explanatory rather than essential, we can already see it has decided to call tools, no arguments yet] GET /v1/threads/thread_xdLXH1xiMnP0gtrFm4N8TDJ2/runs/run_vV6i4asmD9mNoBfHsE8Hu9RI/steps

Response { "object": "list", "data": [ { "id": "step_q08M3EKauFiQGWQ54bitUC5Q", "object": "thread.run.step", "created_at": 1699322307, "run_id": "run_vV6i4asmD9mNoBfHsE8Hu9RI", "assistant_id": "asst_Tosm5sWKNHb4iGfgQVCT9ZDl", "thread_id": "thread_xdLXH1xiMnP0gtrFm4N8TDJ2", "type": "tool_calls", "status": "in_progress", "cancelled_at": null, "completed_at": null, "expires_at": 1699322906, "failed_at": null, "last_error": null, "step_details": { "type": "tool_calls", "tool_calls": [] } } ], "first_id": "step_q08M3EKauFiQGWQ54bitUC5Q", "last_id": "step_q08M3EKauFiQGWQ54bitUC5Q", "has_more": false }

[Now it has filled in the arguments in the tool step, still marking the step as in progress] GET /v1/threads/thread_xdLXH1xiMnP0gtrFm4N8TDJ2/runs/run_vV6i4asmD9mNoBfHsE8Hu9RI/steps

Response { "object": "list", "data": [ { "id": "step_q08M3EKauFiQGWQ54bitUC5Q", "object": "thread.run.step", "created_at": 1699322307, "run_id": "run_vV6i4asmD9mNoBfHsE8Hu9RI", "assistant_id": "asst_Tosm5sWKNHb4iGfgQVCT9ZDl", "thread_id": "thread_xdLXH1xiMnP0gtrFm4N8TDJ2", "type": "tool_calls", "status": "in_progress", "cancelled_at": null, "completed_at": null, "expires_at": 1699322906, "failed_at": null, "last_error": null, "step_details": { "type": "tool_calls", "tool_calls": [ { "id": "call_E5aMr3eMMhoHmhPpjVWxhxDN", "type": "function", "function": { "name": "get_stock_price", "arguments": "{"symbol": "AAPL"}" } }, { "id": "call_k3di6catEDyJI62WJz4ryGLW", "type": "function", "function": { "name": "get_stock_price", "arguments": "{"symbol": "META"}" } } ] } } ], "first_id": "step_q08M3EKauFiQGWQ54bitUC5Q", "last_id": "step_q08M3EKauFiQGWQ54bitUC5Q", "has_more": false }

[Check the run, observe that it requires an action to continue. Seems like we did not need to call steps at all, we can just use the run status to ] GET /v1/threads/thread_xdLXH1xiMnP0gtrFm4N8TDJ2/runs/run_vV6i4asmD9mNoBfHsE8Hu9RI44

Response { "object": "list", "data": [ { "id": "run_vV6i4asmD9mNoBfHsE8Hu9RI", "object": "thread.run", "created_at": 1699322306, "assistant_id": "asst_Tosm5sWKNHb4iGfgQVCT9ZDl", "thread_id": "thread_xdLXH1xiMnP0gtrFm4N8TDJ2", "status": "requires_action", "started_at": 1699322306, "expires_at": 1699322906, "cancelled_at": null, "failed_at": null, "completed_at": null, "required_action": { "type": "submit_tool_outputs", "submit_tool_outputs": { "tool_calls": [ { "id": "call_E5aMr3eMMhoHmhPpjVWxhxDN", "type": "function", "function": { "name": "get_stock_price", "arguments": "{"symbol": "AAPL"}" } }, { "id": "call_k3di6catEDyJI62WJz4ryGLW", "type": "function", "function": { "name": "get_stock_price", "arguments": "{"symbol": "META"}" } } ] } }, "last_error": null, "model": "gpt-4-1106-preview", "instructions": "Be a friendly finance bro who will help me with trading", "tools": [ { "type": "code_interpreter" }, { "type": "retrieval" }, { "type": "function", "function": { "name": "get_stock_price", "description": "Get the current stock price", "parameters": { "type": "object", "properties": { "symbol": { "type": "string", "description": "The stock symbol" } }, "required": [ "symbol" ] } } } ], "file_ids": [], "metadata": {} } ], "first_id": "run_vV6i4asmD9mNoBfHsE8Hu9RI", "last_id": "run_vV6i4asmD9mNoBfHsE8Hu9RI", "has_more": false }

[(explanatory only), this simply returns all the runs for a given thread, effectively returns an array with a single element which is the same as in the previous request] GET /v1/threads/thread_xdLXH1xiMnP0gtrFm4N8TDJ2/runs

{ "object": "list", "data": [ { "id": "run_vV6i4asmD9mNoBfHsE8Hu9RI", "object": "thread.run", "created_at": 1699322306, "assistant_id": "asst_Tosm5sWKNHb4iGfgQVCT9ZDl", "thread_id": "thread_xdLXH1xiMnP0gtrFm4N8TDJ2", "status": "requires_action", "started_at": 1699322306, "expires_at": 1699322906, "cancelled_at": null, "failed_at": null, "completed_at": null, "required_action": { "type": "submit_tool_outputs", "submit_tool_outputs": { "tool_calls": [ { "id": "call_E5aMr3eMMhoHmhPpjVWxhxDN", "type": "function", "function": { "name": "get_stock_price", "arguments": "{"symbol": "AAPL"}" } }, { "id": "call_k3di6catEDyJI62WJz4ryGLW", "type": "function", "function": { "name": "get_stock_price", "arguments": "{"symbol": "META"}" } } ] } }, "last_error": null, "model": "gpt-4-1106-preview", "instructions": "Be a friendly finance bro who will help me with trading", "tools": [ { "type": "code_interpreter" }, { "type": "retrieval" }, { "type": "function", "function": { "name": "get_stock_price", "description": "Get the current stock price", "parameters": { "type": "object", "properties": { "symbol": { "type": "string", "description": "The stock symbol" } }, "required": [ "symbol" ] } } } ], "file_ids": [], "metadata": {} } ], "first_id": "run_vV6i4asmD9mNoBfHsE8Hu9RI", "last_id": "run_vV6i4asmD9mNoBfHsE8Hu9RI", "has_more": false }

[Submitting the output of tools we have computed on our side ] POST /v1/threads/thread_xdLXH1xiMnP0gtrFm4N8TDJ2/runs/run_vV6i4asmD9mNoBfHsE8Hu9RI/submit_tool_outputs

Request { "threadId": "thread_xdLXH1xiMnP0gtrFm4N8TDJ2", "runId": "run_vV6i4asmD9mNoBfHsE8Hu9RI", "functionResponses": { "tool_outputs": [ { "tool_call_id": "call_E5aMr3eMMhoHmhPpjVWxhxDN", "output": "100" }, { "tool_call_id": "call_k3di6catEDyJI62WJz4ryGLW", "output": "233" } ] } }

Response { "id": "run_vV6i4asmD9mNoBfHsE8Hu9RI", "object": "thread.run", "created_at": 1699322306, "assistant_id": "asst_Tosm5sWKNHb4iGfgQVCT9ZDl", "thread_id": "thread_xdLXH1xiMnP0gtrFm4N8TDJ2", "status": "queued", "started_at": 1699322306, "expires_at": 1699322906, "cancelled_at": null, "failed_at": null, "completed_at": null, "last_error": null, "model": "gpt-4-1106-preview", "instructions": "Be a friendly finance bro who will help me with trading", "tools": [ { "type": "code_interpreter" }, { "type": "retrieval" }, { "type": "function", "function": { "name": "get_stock_price", "description": "Get the current stock price", "parameters": { "type": "object", "properties": { "symbol": { "type": "string", "description": "The stock symbol" } }, "required": [ "symbol" ] } } } ], "file_ids": [], "metadata": {} }

[Our run is in progress again after we have submitted tool outputs] GET /v1/threads/thread_xdLXH1xiMnP0gtrFm4N8TDJ2/runs/run_vV6i4asmD9mNoBfHsE8Hu9RI

{ "id": "run_vV6i4asmD9mNoBfHsE8Hu9RI", "object": "thread.run", "created_at": 1699322306, "assistant_id": "asst_Tosm5sWKNHb4iGfgQVCT9ZDl", "thread_id": "thread_xdLXH1xiMnP0gtrFm4N8TDJ2", "status": "in_progress", "started_at": 1699322559, "expires_at": 1699322906, "cancelled_at": null, "failed_at": null, "completed_at": null, "last_error": null, "model": "gpt-4-1106-preview", "instructions": "Be a friendly finance bro who will help me with trading", "tools": [ { "type": "code_interpreter" }, { "type": "retrieval" }, { "type": "function", "function": { "name": "get_stock_price", "description": "Get the current stock price", "parameters": { "type": "object", "properties": { "symbol": { "type": "string", "description": "The stock symbol" } }, "required": [ "symbol" ] } } } ], "file_ids": [], "metadata": {} }

GET [Get the steps and observe there is one incomplete step - message generation which depends on tool call, which was completed by our previous step] /v1/threads/thread_xdLXH1xiMnP0gtrFm4N8TDJ2/runs/run_vV6i4asmD9mNoBfHsE8Hu9RI/steps

{ "object": "list", "data": [ { "id": "step_BLAEv36wryuk2pKM5Lhbsa4H", "object": "thread.run.step", "created_at": 1699322560, "run_id": "run_vV6i4asmD9mNoBfHsE8Hu9RI", "assistant_id": "asst_Tosm5sWKNHb4iGfgQVCT9ZDl", "thread_id": "thread_xdLXH1xiMnP0gtrFm4N8TDJ2", "type": "message_creation", "status": "in_progress", "cancelled_at": null, "completed_at": null, "expires_at": 1699322906, "failed_at": null, "last_error": null, "step_details": { "type": "message_creation", "message_creation": { "message_id": "msg_IPUyyUWhGN81DGqRxhHolCRN" } } }, { "id": "step_q08M3EKauFiQGWQ54bitUC5Q", "object": "thread.run.step", "created_at": 1699322307, "run_id": "run_vV6i4asmD9mNoBfHsE8Hu9RI", "assistant_id": "asst_Tosm5sWKNHb4iGfgQVCT9ZDl", "thread_id": "thread_xdLXH1xiMnP0gtrFm4N8TDJ2", "type": "tool_calls", "status": "completed", "cancelled_at": null, "completed_at": 1699322559, "expires_at": 1699322906, "failed_at": null, "last_error": null, "step_details": { "type": "tool_calls", "tool_calls": [ { "id": "call_E5aMr3eMMhoHmhPpjVWxhxDN", "type": "function", "function": { "name": "get_stock_price", "arguments": "{"symbol": "AAPL"}", "output": "100" } }, { "id": "call_k3di6catEDyJI62WJz4ryGLW", "type": "function", "function": { "name": "get_stock_price", "arguments": "{"symbol": "META"}", "output": "233" } } ] } } ], "first_id": "step_BLAEv36wryuk2pKM5Lhbsa4H", "last_id": "step_q08M3EKauFiQGWQ54bitUC5Q", "has_more": false }

GET [(explanatory only) Observe the latest step (message generation based on our tool call step) is complete] /v1/threads/thread_xdLXH1xiMnP0gtrFm4N8TDJ2/runs/run_vV6i4asmD9mNoBfHsE8Hu9RI/steps

{ "object": "list", "data": [ { "id": "step_BLAEv36wryuk2pKM5Lhbsa4H", "object": "thread.run.step", "created_at": 1699322560, "run_id": "run_vV6i4asmD9mNoBfHsE8Hu9RI", "assistant_id": "asst_Tosm5sWKNHb4iGfgQVCT9ZDl", "thread_id": "thread_xdLXH1xiMnP0gtrFm4N8TDJ2", "type": "message_creation", "status": "completed", "cancelled_at": null, "completed_at": 1699322561, "expires_at": null, "failed_at": null, "last_error": null, "step_details": { "type": "message_creation", "message_creation": { "message_id": "msg_IPUyyUWhGN81DGqRxhHolCRN" } } }, { "id": "step_q08M3EKauFiQGWQ54bitUC5Q", "object": "thread.run.step", "created_at": 1699322307, "run_id": "run_vV6i4asmD9mNoBfHsE8Hu9RI", "assistant_id": "asst_Tosm5sWKNHb4iGfgQVCT9ZDl", "thread_id": "thread_xdLXH1xiMnP0gtrFm4N8TDJ2", "type": "tool_calls", "status": "completed", "cancelled_at": null, "completed_at": 1699322559, "expires_at": null, "failed_at": null, "last_error": null, "step_details": { "type": "tool_calls", "tool_calls": [ { "id": "call_E5aMr3eMMhoHmhPpjVWxhxDN", "type": "function", "function": { "name": "get_stock_price", "arguments": "{"symbol": "AAPL"}", "output": "100" } }, { "id": "call_k3di6catEDyJI62WJz4ryGLW", "type": "function", "function": { "name": "get_stock_price", "arguments": "{"symbol": "META"}", "output": "233" } } ] } } ], "first_id": "step_BLAEv36wryuk2pKM5Lhbsa4H", "last_id": "step_q08M3EKauFiQGWQ54bitUC5Q", "has_more": false }

GET [Observe the last run is complete] /v1/threads/thread_xdLXH1xiMnP0gtrFm4N8TDJ2/runs/run_vV6i4asmD9mNoBfHsE8Hu9RI

{ "id": "run_vV6i4asmD9mNoBfHsE8Hu9RI", "object": "thread.run", "created_at": 1699322306, "assistant_id": "asst_Tosm5sWKNHb4iGfgQVCT9ZDl", "thread_id": "thread_xdLXH1xiMnP0gtrFm4N8TDJ2", "status": "completed", "started_at": 1699322559, "expires_at": null, "cancelled_at": null, "failed_at": null, "completed_at": 1699322561, "last_error": null, "model": "gpt-4-1106-preview", "instructions": "Be a friendly finance bro who will help me with trading", "tools": [ { "type": "code_interpreter" }, { "type": "retrieval" }, { "type": "function", "function": { "name": "get_stock_price", "description": "Get the current stock price", "parameters": { "type": "object", "properties": { "symbol": { "type": "string", "description": "The stock symbol" } }, "required": [ "symbol" ] } } } ], "file_ids": [], "metadata": {} }

GET [See the latest assistant response on the top of the list] /v1/threads/thread_xdLXH1xiMnP0gtrFm4N8TDJ2/messages

{ "object": "list", "data": [ { "id": "msg_IPUyyUWhGN81DGqRxhHolCRN", "object": "thread.message", "created_at": 1699322560, "thread_id": "thread_xdLXH1xiMnP0gtrFm4N8TDJ2", "role": "assistant", "content": [ { "type": "text", "text": { "value": "The current stock price for Apple (AAPL) is $155.31 and for Meta Platforms (Facebook) (META) is $195.13. Keep in mind that stock prices are subject to quick fluctuations throughout the trading day. If you're considering trading, it's important to watch the market carefully or set your trading parameters appropriately. Need help with analyzing these stocks or any trading strategies? I'm here for you!", "annotations": [] } } ], "file_ids": [], "assistant_id": "asst_Tosm5sWKNHb4iGfgQVCT9ZDl", "run_id": "run_vV6i4asmD9mNoBfHsE8Hu9RI", "metadata": {} }, { "id": "msg_A4xMXXNn246503BgMGjzQtD2", "object": "thread.message", "created_at": 1699322305, "thread_id": "thread_xdLXH1xiMnP0gtrFm4N8TDJ2", "role": "user", "content": [ { "type": "text", "text": { "value": "What is the stock of apple and facebook rn?", "annotations": [] } } ], "file_ids": [], "assistant_id": null, "run_id": null, "metadata": {} } ], "first_id": "msg_IPUyyUWhGN81DGqRxhHolCRN", "last_id": "msg_A4xMXXNn246503BgMGjzQtD2", "has_more": false }

Now based on this documentation and example flow from one assistant run follow this spec to create a typescirpt file.

Write me a typescript cloudfare worker that will use openai.beta assistant, threads and runs to create an example assistant and run it.

The worker well expose a single hardcoded assistant, to which you can submit messages.

Libraries to use

  • Use a popular router library used with cloudfare workers.
  • Use the openai node library to interact with the openai APIs - don't submit http requests directly, use the library.

Two endpoints the worker will expose:

POST /threads It will simply return an idea of the thread created

POST /threads/:threadId/messages Will accept plain text in the body and return the response from the assistant as plain text as well

Thread creation

A thread will be created on a post, threads are not associated with a given assistant, they are just a way to group messages.

Message submission

Assistant retrieval and creation (will happen for sumbission of any message)

Internally the worker will list all the available assistants, check if the assistant with the hardcoded name is already created, use its identifier. If the assistant is not created, it will create it with hardcoded parameters and use its identifier.

Message submission

This is the tricky one, let's start coding up a assistant without custom tools to start with For each message we will block the response until we get a response from the assistant. That will require calling the APIs multiple times, PAY ATTENTION TO PLAYGROUND ASSISTANT LOGS (provided earlier), they will tell you what to do. Annotate your code with comments