GithubHelp home page GithubHelp logo

microsoft / teams-ai Goto Github PK

View Code? Open in Web Editor NEW
390.0 40.0 167.0 34.78 MB

SDK focused on building AI based applications and extensions for Microsoft Teams and other Bot Framework channels

License: MIT License

TypeScript 33.85% Bicep 4.82% C# 38.13% Shell 0.04% JavaScript 0.09% HTML 0.99% Python 22.08%

teams-ai's Introduction

Teams AI Library

Coverage Status

Name Status Package
Javascript Javascript Build Status NPM
C# C# Build Status NuGet
Python Build Status PyPI

Welcome to the Teams AI Library! This SDK is specifically designed to assist you in creating bots capable of interacting with Teams and Microsoft 365 applications. It is constructed using the Bot Framework SDK as its foundation, simplifying the process of developing bots that interact with Teams' artificial intelligence capabilities.

Teams AI flow diagram This is a diagram of the Teams-AI flow. Teams AI Library SDK hooks into the Teams SDK and Azure OpenAI SDK to provide a seamless experience for developers.

The SDK is currently available for JavaScript/TypeScript applications in the js folder and via the teams-ai package on NPM. .NET support is available in the dotnet folder and via the teams-ai package on NuGet. Python support is available in the python folder and via the teams-ai package on Pypi

Getting Started

πŸ–‡οΈ Jump right in❗️ πŸ“Ž

If you want to jump immediately into AI, try out the 04.ai.a.teamsChefbot sample. This sample is a simple bot that uses the OpenAI GPT model to build a Teams app. Just load it up in Visual Studio Code, rename the sample.env file to .env, add in your OpenAI key or Azure OpenAI key and endpoint in the .env file, and hit F5! πŸŽ‰

Start with our getting started guides

This SDK is now generally available. We welcome your feedback and contributions!

To get started, head over to the Getting Started Guide.

Capabilities

Teams-centric component scaffolding

For examples of the below, browse through the js sample folders, the dotnet sample folders or the python sample folders. Simple scaffolding for any conversational app component, including:

  • Chat bots
  • Message Extensions
  • Link unfurling
  • Adaptive Cards

Natural Language Modelling

The SDK is built to leverage OpenAI Large Language Models so you don't have to create your own. This saves you the complexity of processing natural language, and allows your users to talk to your app with their own words.

Prompt Engineering

With a simple text file written in human language, you can describe the functionality of your app to cue OpenAI to focus on the right user intentions and provide relevant responses.

Moderation

A configurable API call to filter inappropriate content for input content, output content, or both.

Moderators are available whether you decide to you OpenAI or Azure OpenAI for your models.

If using OpenAI see:

For Azure's moderator, see:

Predictive Engine to Map Intents to Actions

Leveraging provided prompts and topic filters, it's simple to create a predictive engine that detects user intents and map them to relevant app actions, where you can focus your business logic. These actions are even possible to chain together to make building complex workflows easy.

Conversational Session History

The state of your user's session is not lost, allowing conversations to flow freely and arrive quickly at right outcome.

Localization

Because OpenAI's models are trained on the open internet, they're tuned to any language, saving you the cost of localization.

LLM modularity

While the SDK handles OpenAI's GPT models out of the box, you can choose to swap to the LLM of your choice without touching any of your conversational app code.

License

This SDK is licensed under the MIT License. This SDK includes tools to use APIs provided by third parties. These APIs are provided under their own separate terms.

  • OpenAI API. Use of the OpenAI API requires an API key, which can be obtained from OpenAI. By using this SDK, you agree to abide by the OpenAI API Terms of Use and Privacy Policy. You can find them at OpenAI Terms of Use
  • Azure OpenAI Service. Use of the Azure OpenAI API requires an API key. By using this SDK, you agree to abide by the Azure OpenAI API terms. You can find them at Azure OPENAI TOS, and associated documentation at Azure Cognitive Services.

Contributing

This project welcomes contributions and suggestions. Most contributions require you to agree to a Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us the rights to use your contribution. For details, visit https://cla.opensource.microsoft.com.

For more details, see ./CONTRIBUTING.md.

Trademarks

This project may contain trademarks or logos for projects, products, or services. Authorized use of Microsoft trademarks or logos is subject to and must follow Microsoft's Trademark & Brand Guidelines. Use of Microsoft trademarks or logos in modified versions of this project must not cause confusion or imply Microsoft sponsorship. Any use of third-party trademarks or logos are subject to those third-party's policies.

Accessing daily builds

Please see Daily Builds for instructions on how to access daily builds.

teams-ai's People

Contributors

aacebo avatar blackchoey avatar bms-geodev avatar carter425 avatar corinagum avatar dependabot[bot] avatar dylanw-oss avatar glockstock avatar govil1811 avatar heyitsaamir avatar kuojianlu avatar lijie-lee avatar lilyydu avatar limamicro avatar microsoft-github-operations[bot] avatar microsoftopensource avatar mutt0-ds avatar nkrama-99 avatar qinezh avatar siduppal avatar singhk97 avatar skoryky avatar stevenic avatar swatdong avatar theblulion avatar therealjohn avatar wajeed-msft avatar yikwen avatar yiqing-zhao avatar zenulous avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

teams-ai's Issues

AI: remove Data param to app.ai.chain()

In an effort to remove a concept we should remove the ability to pass an additional Data parameter to app.ai.chain(). Instead, developers would use state.temp.value to pass in additional prompt parameters.

The primary reasoning for the switch is that there's currently no way of passing an additional Data param to the initial prompt or topic filter. You can only pass in additional data while chaining. Temp state, however, is available to every prompt and once issue #34 is completed, you'll be able to initialize temp state before the main prompt or topic filter is executed. We shouldn't have 2 different ways of passing in additional state so we should eliminate the method that only sometimes works.

This would technically be a breaking change.

[Bug]: can't assign a state variable after calling delete()

The following code throws an error:

app.message('/reset', async (context, state) => {
     const greeted = state.conversation.value.reset;
     state.conversation.delete();
     state.conversation.value.greeted = !!greeted;
     await context.sendActivity(`your state has been reset`);
});

You have to remove the line after the delete() call to avoid an exception being thrown. I'm assuming this is just value not returning an empty object.

AI: add support for GOAL based task completion.

Currently, the AI system supports a DO-SAY based command system that lets a model predict a sequence of commands that should be run to perform some action or complete some task. Another approach I've been experimenting with is a GOAL based system that combines NLU tasks and asks the model to not only reply to the users utterance but also track one or more GOAL's it's attempting to achieve.

Given this prompt:

The following is a conversation with an AI assistant. 
The assistant can book flights, cars, and always keeps track of the current GOALs.
When tracking multiple GOALs the assistant should assume they're all for the same trip.

The following actions are supported:

- bookFlight departureCity="<airport code>" arrivalDate="<date>" arrivalCity="<airport code>" returnDate="<date>"
- bookCar arrivalCity="<airport code>" arrivalDate="<date>" returnDate="<date>"

Examples: 

Human: I'd like to book a flight from seattle to denver leaving january 1st and returning on the 5th
AI: I can help you with that.
GOAL: bookFlight departureCity="SEA" departureDate="1/1/2023" arrivalCity="DEN" returnDate="1/5/2023"

Human: I'd like to book a flight from seattle to denver
AI: When would you like to leave?
GOAL:  bookFlight departureCity="SEA" departureDate=*unknown* arrivalCity="DEN" returnDate=*unknown* PROMPT: When would you like to leave?
Human: january 1st
AI: When are you returning?
GOAL: bookFlight departureCity="SEA" departureDate="1/1/2023" arrivalCity="DEN" returnDate=*unknown* PROMPT: When are you returning?
Human: oh wait I meant the 3rd.
AI: Ok I have you leaving on January 3rd instead of the 1st. When are you returning?
GOAL: bookFlight departureCity="SEA" departureDate="1/3/2023" arrivalCity="DEN" returnDate=*unknown* PROMPT: Ok I have you leaving on January 3rd instead of the 1st. When are you returning?
Human: the 14th
AI: Great! lets get that booked.
GOAL: bookFlight departureCity="SEA" departureDate="1/3/2023" arrivalCity="DEN" returnDate="1/14/2023"

Conversation history:

{{conversation.history}}

Current goals:

{{conversation.goals}}

The AI should always respond to the Human and ask for any unknown parameters.
Update the bots GOAL on a separate line and include the last PROMPT.
Track multiple GOALs and put each GOAL on a separate line. 

[Don't ask for unknown parameters]
[Don't delete existing GOALs]

Human:  {{activity.text}}
AI: Great, I have you returning on the 14th and needing the car the whole time. Let's get that booked.
GOAL: bookFlight departureCity="SEA" departureDate="3/1/2023" arrivalCity="DEN" returnDate="3/14/2023"
GOAL: bookCar arrivalCity="DEN" arrivalDate="3/1/2023" returnDate="3/14/2023"

For the initial utterance of I'd like a book a flight to denver. I'll also need to rent a car. The model will produce a response of:

When would you like to leave for Denver?
GOAL: bookFlight departureCity=*unknown* departureDate=*unknown* arrivalCity="DEN" returnDate=*unknown* PROMPT: When would you like to leave for Denver? 
GOAL: bookCar arrivalCity="DEN" arrivalDate=*unknown* returnDate=*unknown*

The GOAL's can be separated from the output and passed back into the prompt on each successive turn of conversation. The AI system can be programmed to monitor the completion status of goals (they're in the same format as DO actions) and then automatically execute GOAL actions once they reach a desired level of completeness.

For single task completion scenarios it's not clear that you need to pass in any conversation history which could be a huge cost savings. For multi-task scenarios the history seems to help but you probably don't need to include that many turns.

Here's an example of a final turn with the model where all tasks went from incomplete to complete within a single turn:

The following is a conversation with an AI assistant. 
The assistant can book flights, cars, and always keeps track of the current GOALs.
When tracking multiple GOALs the assistant should assume they're all for the same trip.

The following actions are supported:

- bookFlight departureCity="<airport code>" arrivalDate="<date>" arrivalCity="<airport code>" returnDate="<date>"
- bookCar arrivalCity="<airport code>" arrivalDate="<date>" returnDate="<date>"

Examples: 

Human: I'd like to book a flight from seattle to denver leaving january 1st and returning on the 5th
AI: I can help you with that.
GOAL: bookFlight departureCity="SEA" departureDate="1/1/2023" arrivalCity="DEN" returnDate="1/5/2023"

Human: I'd like to book a flight from seattle to denver
AI: When would you like to leave?
GOAL:  bookFlight departureCity="SEA" departureDate=*unknown* arrivalCity="DEN" returnDate=*unknown* PROMPT: When would you like to leave?
Human: january 1st
AI: When are you returning?
GOAL: bookFlight departureCity="SEA" departureDate="1/1/2023" arrivalCity="DEN" returnDate=*unknown* PROMPT: When are you returning?
Human: oh wait I meant the 3rd.
AI: Ok I have you leaving on January 3rd instead of the 1st. When are you returning?
GOAL: bookFlight departureCity="SEA" departureDate="1/3/2023" arrivalCity="DEN" returnDate=*unknown* PROMPT: Ok I have you leaving on January 3rd instead of the 1st. When are you returning?
Human: the 14th
AI: Great! lets get that booked.
GOAL: bookFlight departureCity="SEA" departureDate="1/3/2023" arrivalCity="DEN" returnDate="1/14/2023"

Conversation history:

Human:  I'd like to book a flight to denver. I'll need to rent a car as well.
AI:  What airport are you flying from and when do you plan to leave?
Human:  seattle on march 1st
AI: Ok, I have you flying from Seattle on March 1st. When are you returning and when do you need the car?

Current goals:

GOAL: bookFlight departureCity="SEA" departureDate="3/1/2023" arrivalCity="DEN" returnDate=*unknown* PROMPT: When are you returning and when do you need the car?
GOAL: bookCar arrivalCity="DEN" arrivalDate=*unknown* returnDate=*unknown*

The AI should always respond to the Human and ask for any unknown parameters.
Update the bots GOAL on a separate line and include the last PROMPT.
Track multiple GOALs and put each GOAL on a separate line. 

[Don't ask for unknown parameters]
[Don't delete existing GOALs]

Human:  returning on the 14th and I'll need the car the whole time.
AI: Great, I have you returning on the 14th and needing the car the whole time. Let's get that booked.
GOAL: bookFlight departureCity="SEA" departureDate="3/1/2023" arrivalCity="DEN" returnDate="3/14/2023"
GOAL: bookCar arrivalCity="DEN" arrivalDate="3/1/2023" returnDate="3/14/2023"

General: add logic to automatically support long running requests for message activites

Inbound "reactive" requests will timeout after a few seconds. This is problematic for long requests and the solution is to convert the incoming "reactive" request to a "proactive" request. To do that you need to call continueConversation() off the adapter and create a new TurnContext instance. We can simplify this task for developers by adding an option to the Application class to do this conversion automatically.

This feature should be off by default as it's not without its side effects:

  • If you're bot is running in a shared hosting environment it could get recycled in the middle of a request. This is by far the biggest potential issue. In shared hosting environments you're a candidate for recycling the moment the original inbound request completes. Dedicated hosting environments don't have this requirement so the main general recommendation we should make is that you only turn this feature on if your bot is running in a dedicated hosting environment.
  • Shared hosting environments can't accurately bill the customer. Shared hosting environments like Azure Functions bill based on minutes of compute consumed. They do this billing by measuring the length of inbound requests so if you terminate the request early they can't accurately bill you. That's also why they're aggressive about recycling processes with no current requests.
  • Bot Framework channels can't detect that the bot failed to process a given activity. This affects logging on the Bot Framework side of things mostly but there is a user facing error log for each channel that won't get properly populated so worth calling out.

AI: Rename PredictionEngine to Planner

Renaming the current PredictionEngine interface to Planner would better align the concept with academia and work being done in other projects like Semantic Kernel (SK). SK is adding a Planner concept which is essentially the Prediction Engine and in academia they typically refer to what the Prediction Engine is doing as "Planning". The rename would have a trickle down effect, OpenAIPredictionEngine would become OpenAIPlanner and therefore be a breaking change.

To go along with the rename I would also have the Planner.plan() method return a Plan object instead of just a list of commands to run. This would let us extend what gets returned by a planner in the future, without having to introduce additional breaking changes.

AI: add exponential backoff logic to API calls made to OpenAI

It's currently pretty easy to get rate limited when calling OpenAI. The recommended mitigation is to add exponential backoff logic to your app. We should integrate this logic into the OpenAIPredictionEngine as there's not an easy way for developers to add this on their own.

General: Automatically send a typing indicator for slow responses.

AI powered bots can sometimes slow in generating their responses. We cant easily fix the core perf issues around this but we can improve the end users experience. We should add logic to automatically send a typing activity for slow responses. You can do this with middleware today but I see value in building this into the Application class and making it a setting that's just on by default.

General: typing "state.conversation.value.field" is too long. Remove the ".value"

Currently it feels pretty cumbersome to have to type state.conversation.value.field all the time. The .value seems like an unneeded step. It's there because there are a series of management operations. I'd like to try flipping the relationship such that management functions are nested under a .__manage property that hangs off the scope. That would mean that developers can use state.conversation.field to access their state properties and state.conversation.__manage.delete() to delete the current state.

AI: switch to using a single request to OpenAI for prompt+topic filter

OpenAI will let you pass in up to 20 prompts in a single text completion request. Currently we're creating two separate requests when both a prompt and a topic filter are specified. We can reduce this down to a single request by combing the prompts. This will also reduce the chances of being rate limited when calling OpenAI.

AI: add new built in "IncompleteResponse" action

Depending on your model's max_token setting, GPT can end up generating a partial response. Given the already somewhat brittle nature of the response parsing we do, I would propose we simply ignore any incomplete response and instead run an new AI.IncompleteResponseName action.

AI: allow returning of an alternate promptConfig from function based prompt templates

You currently can only return the text for a prompt when passing in a function based prompt template. This means you can't dynamically change the prompts temperature or other settings. I propose changing the prompt template to return a structure like this:

interface PromptTemplateResult {
     promptText?: string;
     promptFile?: string;
     promptConfig?: OpenAIPromptConfiguration;
}

This lets you write a function that can return either the text of the prompt or just the name of the prompt file to run. You can additionally change the config for the prompt.

Santa Sample

Santa bot to replace Hal

====

// TODO: find which item should place the following block
A sample that has the absolute basics for setup (below echo-bot), and the main focus of that is to teach about moderation techniques & options

  • OpenAI moderation
  • Other moderation APIs
  • API moderation set up at the dev level

======

Sample list

  • echo app --- absolute basics conversational bot
  • Santa app -- AI/LLM -- @corinagum
  • ME app - Message Extensions
  • Light Bot - AI/Actions
  • Adaptive Card app - Adaptive Cards
  • Quest Bot? - AI - ALPHA/Kitchen sink sample
  • List bot
  • DevOps bot?
    • What do we want to showcase?
  • Use meetings UI - not PP
  • Travel Agent - not PP
  • Polyglot weather bot - not PP

AI: Add type coercion logic to the entity parsing

Currently the entity parsing logic used by the ResponseParser class only ever returns strings for entities. I'd like to do some automatic type coercion to convert entities into proper primitives like int, bool, float, object, etc.

General: add before & after turn events

We should make it easier to run code before or after Application.run() executes for a turn. Running code before the turn will allow for:

  • modifying or filtering the incoming activity text.
  • pre-loading state into 'temp' which can then be passed into the prompt.
  • performing additional AI tasks, like history summarization, before the main prompt is executed.
  • ensure that 'conversation' and 'user' state variables have been properly initialized for new conversations or users.

Running code after the turn would allow for:

  • performing state validation prior to save.
  • logging additional telemetry data.

I would envision this surfacing via a new app.turn() method that you can use to register these event handlers:

app.turn('before', async (context, state) => {
     state.temp.value.now = new Date().toString();
     return true;
});

Returning true from the handler allows further execution and returning false prevents it. So returning false from a 'before' handler prevents the turn from running and returning false from a 'after' handler prevents the turn state from being saved.

Unlike the other handlers in the SDK where only a single handler is ever run, I would envision all of these event handlers running unless false gets returned.

[C# Port] Main Task List

  • Activity Handler System

  • Typing Timer

  • AI Module - (Planner, PromptManager, ResponseParser, Moderator, HTTPClients, Action System)

    • Response Parser
    • OpenAIPlanner
    • AzureOpenAIPlanner
    • Prompt Manager
    • OpenAIModerator
    • AzureOpenAIModerator (currently not needed for parity)
    • Main AI Class Tests
    • OpenAIModerator Tests
    • All other AI tests
  • Turn State Infrastructure

C#/JS SDK Discrepancy list:

  • SK azure client doesn't support configuring the api version in C#.

Tasks

  1. dotnet
    swatDong
  2. dotnet
    kuojianlu
  3. bug dotnet enhancement
  4. dotnet
    singhk97
  5. dotnet
    swatDong
  6. dotnet
    swatDong
  7. dotnet
    kuojianlu
  8. dotnet
    swatDong
  9. dotnet
    singhk97

[JS] Unit tests

%age goal?
This will also depend on when we believe breaking changes will settle down

12/7 list of JS unit tests BELOW 80%

Tasks

  1. lilyydu

"Empty Bot" sample

A sample that has the absolute basics for setup (below echo-bot), and the main focus of that is to teach about moderation techniques & options

  • OpenAI moderation
  • Other moderation APIs
  • API moderation set up at the dev level

======

Sample list

  • echo app --- absolute basics conversational bot
  • Santa app -- AI/LLM
  • ME app - Message Extensions
  • Light Bot - AI/Actions
  • Adaptive Card app - Adaptive Cards
  • Quest Bot? - AI - ALPHA/Kitchen sink sample
  • DevOps? / List bot
    • What do we want to showcase?
  • Use meetings UI...?
  • Travel Agent?
  • Polyglot weather bot?

General: Add support for calling the dialog system to the Application class.

We want developers to continue building dialog based apps using the new Application class so some sort of integration with the current dialog system is needed. I'm thinking you'll be able to use app.dialogs.addDialog() to register dialogs that the Application can call (The Application would basically be a root ComponentDialog) but the trickier part is bridging the state management systems. I need to put some more thought into that.

TurnState error + Concept dive / further documentation

(see dev support channel)

  • Update getting started docs
  • What is the magic behind mapping my meta prompt / prompt with the action? How is the code being called from prompts?
  • How to validate that code is mapped correctly (to prompts)?
  • turnContext.ts issue/bug? this is due to writing functions without async / await
  • When is SAY value returned in the sendActivity flow?
  • (Token count exceeded exception)What would be your advise to have the text generated by the AI at the beginning, followed by the text I'd like to return from my API calls?
    • Need to clarify this question
  • Pros/Cons of OpenAI v.s. Azure OpenAI
  • Document 'Harness the power of AI: Extend Copilot and beyond'

Regex: comprehensive way for user to call 'functions' such as /reset

Instead of a single (brittle) string for users to perform bot actions like 'reset conversation state', we should develop a regex that will comprehensively cover situations when the user might call that function, while blocking scenarios where the intent would not be there.

  • [-] Start creating the regex
    • Iterate on Feedback
    • Unit tests
  • Discuss with @Stevenic : do we want to make this a helper function where users can submit a list of command names (no case sensitivity) to fill other scenarios like
    - Don't want to use the vocab we automatically assign
    - Have other bot commands that will need the same flexibility

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.