Skip to main content

Notifications

Copilot Studio - Bot Extensibility
Answered

Set and update global variables using Bot Framework Composer and how to retain conversation context when interacting with OpenAI GPT models

(1) ShareShare
ReportReport
Posted on by

In the new unified authoring canvas of Power Virtual Agents – now in preview – it's very easy to set and update variables: Use variables (preview) - Power Virtual Agents | Microsoft Learn. So, keeping the conversation context when interacting with an OpenAPI GPT model is very easy, as demonstrated by @remidyon in this article: Connecting OpenAI to Power Virtual Agent - Part 2: keeping the conversation rolling! | LinkedIn.

 

Now, how to achieve the same when on the production version of Power Virtual Agents, when variable management is a bit trickier and requires using Bot Framework Composer?

 

Let me show you how to get to the below result:

HenryJammes_0-1677675043906.png

 

Categories:
  • HenryJammes Profile Picture
    HenryJammes on at
    Re: Set and update global variables using Bot Framework Composer and how to retain conversation context when interacting with OpenAI GPT models

    Hi @giorgiokatr, thanks!


    Have a look at this article: Revolutionize your Enterprise Data with ChatGPT: Next-gen Apps w/ Azure OpenAI and Cognitive Search - Microsoft Community Hub

    If you're using a ChatGPT model, I believe you can customize the initial system message prompt with instructions / scope / data, including what your documentation search could have initially returned.

     

    In this other post, I show an example of Azure OpenAI ChatGPT integration with PVA: Solved: Retain conversation context when interacting with ... - Power Platform Community (microsoft.com)

  • giorgiokatr Profile Picture
    giorgiokatr 25 on at
    Re: Set and update global variables using Bot Framework Composer and how to retain conversation context when interacting with OpenAI GPT models

    @HenryJammesthis is amazing! i was wondering how to feed the chat with some data from some pdfs so it can answer to specific questions on that data only and no as chat gpt. is there a tutorial for this?

  • Verified answer
    HenryJammes Profile Picture
    HenryJammes on at
    Re: Set and update global variables using Bot Framework Composer and how to retain conversation context when interacting with OpenAI GPT models

    I'm going to use the Fallback topic so that I can use Power Automate to ask OpenAI GPT davinci engine whenever PVA doesn't find a matching topic for a user utterance. To keep track of the full conversation and pass it the OpenAI API – so that it provides answers in context of past questions and answers – I'll initiate and update a global variable.

     

    To manage the global variable keeping track of the conversation with OpenAI, we're going to use Bot Framework Composer to do 2 things:

    1. Create an InitializeFullDialog dialog, that will create and set a new variable, FullDialog, in Power Virtual Agents, that will initially be empty
    2. Create a SetFullDialog dialog, that will update the FullDialog variable so that it contains the history of interactions (past questions and answers provided by OpenAI).

     

    I start by opening the Bot Framework Composer

    If you need help setting things up, refer to this: Getting started with Bot Framework Composer - Power Virtual Agents | Microsoft Learn

    HenryJammes_0-1677671108103.png

     

    I then add a new dialog to my chatbot

    HenryJammes_1-1677671198328.png


    I call it "InitializeFullDialog"

    I create one new Output for it, that I call FullDialog, of type string:

    HenryJammes_2-1677671262571.png

     

    In BeginDialog, I add a Manage properties > Set a property node, in order set the FullDialog variable to an empty value:

    Property: dialog.result.FullDialog
    Value: =''

    HenryJammes_3-1677671334803.png

     

    I then add another dialog, SetFullDialog, this time with no outputs.

    In the BeginDialog, I add a Manage properties > Set a property node, in order set the Power Virtual Agents ConversationFullDialog variable (the name of FullDialog within my PVA topic) as a concatenation of the previous ConversationFullDialog value as well as new values that Power Automate pass me back (I'm showing this later in this article, but they're OK to set up in advance).

    Property: virtualagent.ConversationFullDialog
    Value: =concat(virtualagent.ConversationFullDialog,' ',virtualagent.OriginalTriggerPhrase,' ',virtualagent.OpenAIResponseRaw)

    HenryJammes_4-1677671648285.png

     

    Now I simply need to publish my bot in Bot Framework Composer:

    HenryJammes_5-1677671778062.png

     

    As I interact in this example with the OpenAI Text Completion API, I'm using the Power Virtual Agents Fallback topic. This means that whenever a user asks a question that PVA doesn't know how to answer with an existing topic (i.e. there is no match with the topics trigger phrases), it goes to the Fallback topic, and in the Fallback topic we're calling the OpenAI API.

    If you haven't enabled the Fallback topic in your chatbot, learn how here: Use a system fallback topic - Power Virtual Agents | Microsoft Learn

     

    In the Fallback topic, I start by removing the existing nodes as we expect to change its behavior.

    Just after the 'Trigger Phrases' node, I add a "Redirect to another topic" node, and select the InitializeFullDialog dialog.

    I click on the variable name, name it ConversationFullDialog, and change its usage to "Bot (any topic can access)" and also check "External sources can set values":

    HenryJammes_6-1677672402539.png

     

    Next step is to call the OpenAI API using Power Automate.

    I add a new node, select Call an action > Create a flow.

    I assume you already have an OpenAI account and a developer API key, but if you don't, check: OpenAI for developers and where do I find my Secret API Key?.

     

    In your cloud flow, you'll first want to add 2 text inputsUnrecognizedTriggerPhrase and ConversationFullDialog:

    HenryJammes_7-1677672979415.png

     

    Then, to call the OpenAI APIs, I'll use the HTTP action, with this configuration

    Method: POST

    URI: https://api.openai.com/v1/completions

     

    Headers: 

    Authorization: Bearer {YourAPIKey}
    Content-Type: application/json

    Body:

    {
    "model": "text-davinci-003",
    "prompt": "",
    "max_tokens": 2000,
    "temperature": 0,
    "top_p": 1,
    "n": 1,
    "stream": false,
    "logprobs": null,
    "stop": "None"
    }

    For the prompt, this is where I need to pass the user question.

    To keep context, the trick is to provide past questions and answers, as well as the new question.

    So, in order to know if I should pass the initial value that triggered a fallback OR if I should pass the ConversationFullDialog that contains the history, I use an expression to check if the ConversationFullDialog is empty or not. If it is, I just used the UnrecognizedTriggerPhrase. If not, I append the ConversationFullDialog and the new UnrecognizedTriggerPhrase:

    if(
        empty(triggerBody()['text_1']),
        triggerBody()['text'],
        concat(
            triggerBody()['text_1'],
            ' ',
            triggerBody()['text']
        )
    )

    HenryJammes_8-1677673078378.png

     

    Now I need to pass back a few things to PVA.

    • The OpenAIResponse is the formatted response (typically to make sure PVA keeps line breaks).
      This is the expression I'm using:
      uriComponentToString(
          replace(
              encodeUriComponent(
                  body('HTTP:_POST_Request_to_OpenAI_Completions_API')?['choices'][0]?['text']
              ),
              '%0A',
              '%0A%0A'
          )
      )
    • The OpenAIResponseRaw - that's the original OpenAI response that I'll append to my ConversationFullDialog variable.
      This is the expression I'm using:
      body('HTTP:_POST_Request_to_OpenAI_Completions_API')?['choices'][0]?['text']
    • The OriginalTriggerPhrase - that's the individual question that was raised in this flow, that I also need to append to the ConversationFullDialog variable. I use the UnrecognizedTriggerPhrase value in dynamic content.

    I give my flow a name, and  save it.

     

    Back in PVA, still in my Fallback topic, I select my flow, and can map the UnrecognizedTriggerPhrase and ConversationFullDialog to the Power Automate inputs.

    I can see that Power Automate has 3 ouputs. I set their Usage to "Bot (any topic can access)":

    HenryJammes_9-1677673844783.png

     

    I now add a new Show a message node, where I select the bot.OpenAIResponse variable:

    HenryJammes_10-1677673927593.png

     

    The final step is to add a "Redirect to another topic" node, and select the SetFullDialog dialog, that will take care of updating the ConversationFullDialog variable with the past questions and answers.

     

    HenryJammes_11-1677674002576.png

     

    And that's it! 🎉

     

    HenryJammes_13-1677674742065.png

Under review

Thank you for your reply! To ensure a great experience for everyone, your content is awaiting approval by our Community Managers. Please check back later.

Helpful resources

Quick Links

Microsoft Kickstarter Events…

Register for Microsoft Kickstarter Events…

Announcing Our 2025 Season 1 Super Users!

A new season of Super Users has arrived, and we are so grateful for the daily…

Announcing Forum Attachment Improvements!

We're excited to announce that attachments for replies in forums and improved…

Leaderboard

#1
WarrenBelz Profile Picture

WarrenBelz 145,526

#2
RandyHayes Profile Picture

RandyHayes 76,287

#3
Pstork1 Profile Picture

Pstork1 64,907

Leaderboard

Featured topics