Call function with suggested replies

I’m working on an assistant that is supposed interactively answer a few questions with the user to fill a complex form; essentially, the model gets 12 steps to ask the user about, one after the other, with every step getting more specific, for example:

Industry: Suggest up to 5 industries in the user might be engaged in.

This reliably results in good suggestions, for example:

Could you tell me which industries you are currently engaged in? Some common industries might be:

  1. Oil and Gas
  2. Manufacturing
  3. Water Treatment
  4. Power plants
  5. Food and Beverage

. We parse these responses, and extract the items to display buttons. This works… mostly, until it doesn’t.
Instead, I would love to define a function – say, showButtons – that takes a list of keywords, and renders those buttons along the response.

But I cannot get the model to do this, and have a nagging suspicion this isn’t really how function calling is supposed to be used - After all, the user doesn’t directly instruct it to call the showButtons function.
Does anybody have a suggestion for me?

Edit: I think I expressed myself badly. What I’m after is that the model invokes a function with the list of suggestions; so for the industries it recommended above, instead of returning a list, I’d like it to call a function with those industries instead, like this:

showButtons({keywords: [ "Oil and Gas", "Manufacturing", "Water Treatment",  "Power Plants", "Food and Beverage" ]})

…such that I can display those buttons below the model’s message, and enrich the context for the next run with data related to that keyword.

Sequences are particularly hard for the model to reliably follow. Long sequences like 12 steps especially… if you a specific order of questions you wish to ask it’s better to track where you’re at externally in your code. Then in your prompt give the model the current question to work with. You can definitely use functions in this case but what you want to do is focus the model via your prompt.

There are two separate capabilities of the model that you’re trying to leverage. The creativity of the model when prompting the user, you’ve seen that you don’t need a function for that. And the transformational mapping ability of the model when processing the user’s response, that’s where a function will help.

You just need to keep track of where you’re at in your flow inside your code and customize the prompt for the current step. You can make the model rock solid reliably for linear sequences of any length using this approach.

Branching sequences are a little trickier but even that’s just a variation of the above.

Hope that helps

Someone asked a similar thing the previous day. Here is a sample implementation based on that.

First, add a function that will check the task required.

{
  "name": "check_intent",
  "description": "Checks user intent based on user prompt",
  "parameters": {
    "type": "object",
    "properties": {
      "task": {
        "type": "string",
        "description": "Task that the user wants to invoke.",
        "enum": [
          "add_student_to_class",
          "delete_student_from_class",
          "call_debug_function"
        ]
      }
    },
    "required": [
      "task"
    ]
  }
}

We want this function to be invoked before any task is required.
It does not do anything internally but it tells us when to show the UI (in your case show some buttons)

You might need something in the instruction that tells it how to call this function.

You are a helpful assistant.
# tools
You have the following tools you can invoke depending on user prompt.
- check_intent, checks user intention.

Here is how it supposed to work

While that’s a great solution, it kind of solves the inverse problem of mine, which is calling a function that extracts keywords from the user input – while I’d like to extract keywords from the model output. I’ve added an example to the original post, that should illustrate what I mean better!

So what exactly is it that you can get the assistant to do? It seems you are able to have it procude a list of industries - but you can’t get it to call a function with those industries?
Or ?

The latter - calling the showButtons function with the industries it generated. It prints the list, it can call a function based on user input, but I cannot bring it to call a function with its own output.

It seems you would not want functions. As you suspect, the calling of functions is user input driven.

If this path must be very procedural and the answers closed, and you just want the AI to generate five choices at each step (instead of pregenerating the 5**12 possible endpoints if all are dependent), then it seems the best way would be to instruct every information-gathering step with its own instruction, while providing the chat history to let the AI sculpt the question and choices to the current round’s goals.

for goal in [“which product”, “for what purpose”, “how large a production volume”, “your budget”, …]:

  • system “you are creating a 12 part sales interview based on previous inputs”
    "output format: {“question”: “AI created”, “a1”: “possible answer”, “a2”: “possible answer 2”,…}
  • user = q/a history
  • user += "step X ask an adaptive question to discover: {goal}
  • user += “Then create 5 likely answers, in answer output format”

The API software is acting as a user, the AI’s job is to compose for the software. Then you could always add your own “other” so user can write a non-AI answer in your form. Specifying the format to receive parseable answers is cake. At the end, you’ve got your information gathered with the dynamics of AI.

Sorry for being vague here; I didn’t want to make this more complex than necessary:
The actual prompt goes something like “Here’s up to 12 areas of interest to guide the user through, if you’re reasonably sure what the inquiry is about, you don’t need to ask about all of them”. So the process is really not strictly 12 steps, and both the order as well as the specific questions asked vary based on the user’s intent.

The model often suggests possible answers to its questions, which often is exactly what the user will respond with, so the UX guys are hellbent on offering those suggestions as chips below the message. Cool UI for sure, but hard to pull off. However, sometimes users expand on those suggestions, so the best we can do is copy the keywords into the text field for the user to amend.

That’s an interesting way to go at it though, and I’m going to try this! Thank you very much.

So I think this is what you want.

Here’s the function. I think the trick is to use ‘array’ as a the type.

{
  "name": "save_cities",
  "description": "City planner",
  "parameters": {
    "type": "object",
    "properties": {
      "location": {
        "type": "array",
        "description": "the optionss that you have for cities",
        "items": {
          "City": {
            "type": "string",
            "description": "Name of the city"
          }
        }
      }
    },
    "required": [
      "location"
    ]
  }
}