Handling Multi-Message Input for Custom Functions in OpenAI Assistant API

I am working with the OpenAI Assistant API and facing a challenge with custom functions in a conversational context. Specifically, I’ve created a custom function named AddPerson, which requires several pieces of information (like firstName, lastName, contactTypes, and emailAddress) to function correctly.

The issue arises in a conversational flow where the user provides this information over multiple messages, rather than in a single input. For instance, the user might start by expressing a desire to add a new person, then provide their name, email, and contact type in separate follow-up messages.

In scenarios where all details are provided in one message, the function triggers a required_action status as expected. However, when the details are provided across multiple messages, the function’s final status is completed - even if not all required information has been gathered.

Here’s the sequence of user inputs in the latter scenario:

  1. “I would like to create a new person.”
  2. “Sure, let’s add Emily Arun with email as emilyarun@gmail.com.”
  3. “Emily is a buyer.”

After the last input, I would expect the run.status to be required_action, prompting for any missing information. Instead, it directly goes to completed.

I am looking for advice on how to effectively aggregate information provided across multiple messages in a conversational flow and ensure that the AddPerson function only triggers once all required information is gathered. How can I implement a mechanism to track and manage this data collection process within the conversation?

Any insights or suggestions on how to approach this issue would be greatly appreciated. Thank you in advance for your help!

-arun

Can you show me how you defines the function when creating the assistant ? You could try to describe more precisely what the function does when you add it to the assistant and that might be able to make GPT perform better.

Here we go…

function_json = {
“name”: “AddPerson”,
“description”: “Add a new person to CT and return the response”,
“parameters”: {
“type”: “object”,
“properties”: {
“firstName”: {
“type”: “string”,
“description”: “The first name of the person”
},
“lastName”: {
“type”: “string”,
“description”: “The last name of the person”
},
“contactTypes”: {
“type”: “string”,
“enum”: [“Buyer”, “Seller”],
“description”: “The type of contact, either Buyer or Seller”
},
“emailAddress”: {
“type”: “string”,
“description”: “The email address of the person”
}
},
“required”: [“firstName”, “lastName”, “contactTypes”, “emailAddress”]
}
}

Please note, as a test case, I made all of them required and the assistant api is intelligent enough in asking for all required details even if I fail to pass some. However after passing in all the details, it doesn’t mark the run.status as required_action instead it marks as completed after collecting all the required information. Its kind of puzzling to me. Like I mentioned in my original post if I try to give all at once it just mark run.status are required_action for the same assistant

Yeah, seems alright. You can try being super detailed, for example say in description: “Add a new person to Clientown once all the details about the person are known: first name, last name, contact type and email”

Also, it might not know what’s the deal with “Clientown”. Does the user say that word in their prompt ? If not, I think you could probably delete it to not confuse the assistant.

There’s no guarantee it will work but you could try.

That didnt work either. Look at the instructions below (again not the actual company name)

You’re an assistant, an assistant for “AstraTech Solutions,” a SaaS product specializing in various business operations like “Add People, Send Email”. Your key role is to interpret and handle user requests related to AstraTech Solutions’ functions. Most importantly, you are programmed not to proceed with any function execution until all required parameters are fully satisfied. All calls are directed to an external API, so it’s crucial to first confirm that all necessary parameters have been collected. Once you’re confident about the completeness of the data, obtain a final confirmation from the user (YES to proceed, NO to not proceed) before invoking the external API. After receiving this final confirmation, you’ll initiate the required action.

I believe your issue stems from the fact that the API cannot retain memory. It doesn’t remember what you have previously communicated when you send a new response. To rectify this, you need to include your entire conversation in each prompt you send. For instance, if you need to send a prompt that says “Yes”, you should have a script that takes your entire previous conversation and incorporates it into that prompt. So, it would look something like this:

“User: Add user ‘A’” # Previous Prompt
“Response: Do you want me to add user ‘A’ into the system?” # Previous Prompt
“User: Yes” # Current Prompt

All the other data would be incorporated into your “Yes” prompt through a script. There are many tutorials on how to do this on this forum. You can search for them in the upper right corner.

1 Like

Thank you for your input on maintaining conversation context within the OpenAI Assistant API. I understand your point about incorporating the entire conversation in each prompt to retain memory and context. However, my understanding is that the Assistant API is designed to handle the state and manage the context of an entire conversation thread automatically.

In my current setup, I am using custom functions like AddPerson within a single conversation thread. My expectation is that the Assistant API should keep track of the conversation history and understand the flow of the dialogue within this thread. This would mean it can reference previous interactions and maintain continuity without needing to manually include the entire conversation history in each new prompt.

However, I am facing an issue where the Assistant does not seem to retain this context when details are provided across multiple messages. This is leading to a situation where the run.status is not behaving as expected.

If you encounter the issue that not all the information gathered previously is used to create the new DB entry then it could be a solution to add each new piece of information into a temporary data object.
For example if the user asked to create a new client and provides the name require to call the function for the temporary object. The goal is to collect and store all data during the conversation as the data is being entered by the user.
Then when the information in the temporary object suffices to create a new customer then proceed with the final step.

Yes, I would try that in a regular chat.completion API where there is no internal state management or memory but my simple question, the idea of the new Assistant is to manage both state and memory as part of thread and let it figure our calling the function once all the required parameters information are collected from the user.

To me, this is exactly what Assistant API is meant for and I’m surprised there is no solution to this simple problem of handling the user inputs in a multi-message strategy which is strange to me and it definitely looks like a bug in the API!

If via multi-message required inputs are not collected, I dont understand what the use of having the thread, messages etc and especially the ability to handle state and memory management because the API doesn’t only charge for the tokens it also charges for the memory and the entire conversation history everytime.

Try to rewrite the prompt in a more structured manner.

  1. You are … and your task is to …
  2. After identifying the user request gather information according to the requirements: if A then B, if C then D
  3. When all information has been gathered, confirm once more with the user
  4. Add the information to the DB by calling the respective function

I suggest to work with the prompt.
Another idea is to update the prompt during the conversation depending on the state of the conversation.

1 Like

Yep, I did tried that too and mentioned that in my previous reply. Just for your quick reference, review the below prompt

“”"
You’re an assistant, an assistant for “AstraTech Solutions,” a SaaS product specializing in various business operations like “Add People, Send Email”. Your key role is to interpret and handle user requests related to AstraTech Solutions’ functions. Most importantly, you are programmed not to proceed with any function execution until all required parameters are fully satisfied. All calls are directed to an external API, so it’s crucial to first confirm that all necessary parameters have been collected. Once you’re confident about the completeness of the data, obtain a final confirmation from the user (YES to proceed, NO to not proceed) before invoking the external API. After receiving this final confirmation, you’ll initiate the required action.
“”"

I dont think we can go clear than this. The problem is it follows the prompt requests quite well and it does engages in a neat conversation however the problem is, even after the user confirms with “Yes”, it doesn’t mark the run.status as required_Action instead it marks as “Completed” which is super strange and I’m clueless why that the case.

You can try the same at your end as well. Im trying really hard not to consider this as a bug but unfortunately that’s where this is driving to. I’m surprised to see very limited talk about this in this forum or elsewhere.

Yes, I did read your prompt and suggested to work on it a bit more with a template structure.

IDK, hope this will help.