base on # TypeChat.NET
TypeChat.NET brings the ideas of [TypeChat](https://github.com/microsoft/TypeChat) to .NET.
TypeChat.NET provides **cross platform** libraries that help you build natural language interfaces with language models using strong types, type validation and simple type safe programs (plans). Strong typing may help make software that uses language models more deterministic and reliable.
```
// Translates user intent into strongly typed Calendar Actions
var model = new LanguageModel(Config.LoadOpenAI());
var translator = new JsonTranslator<CalendarActions>(model);
// Translate natural language request
CalendarActions actions = await translator.TranslateAsync(requestText);
```
TypeChat.NET is in **active development** with frequent updates. The framework will evolve as the team explores the space and incorporates feedback. Supported scenarios are shown in the included [Examples](./examples). Documentation will also continue to improve. When in doubt, please look at the code.
# Assemblies
TypeChat.NET currently consists of the following assemblies:
* **Microsoft.TypeChat**: Classes that translate user intent into strongly typed and validated objects.
* **Microsoft.TypeChat.Program**: Classes to synthesize, validate and run ***JSON programs***.
* **Microsoft.TypeChat.SemanticKernel**: Integration with Microsoft Semantic Kernel for models, plugins, embeddings and other features.
## Microsoft.TypeChat ##
TypeChat uses language models to translate user intent into JSON that conforms to a schema. This JSON is then validated and deserialized into a typed object. Additional constraint checking is applied as needed. Validation errors are sent back to the language model, which uses them to **repair** the Json it originally returned.
TypeChat provides:
* Json translation, validation, repair and deserialization.
* Extensibility: interfaces for customizing schemas, validators and prompts.
* Schema export: classes to generate schema for the .NET Type you want to translate to. Exported schema includes dependencies and base classes. The exported schema is specified using **Typescript**, which can concisely express schema for JSON objects.
* Support for common scenarios shown in TypeChat examples. When you encounter limitations (such as how generics are currently exported), you can supply schema text, such as Typescript authored by hand.
* Helper attributes for Vocabularies and Comments. Vocabularies are string tables that constrain the values that can be assigned to string properties. Dynamic loading of vocabularies enables scenarios where they vary at runtime.
* **Note**: Like TypeChat, TypeChat.NET has only been tested with schema specified in Typescript.
```
[Comment("Milks currently in stock")]
public class Milks
{
[JsonVocab("whole milk | two percent milk | nonfat milk | soy milk | almond milk")]
public string Name { get; set; }
}
```
## Microsoft.TypeChat.Program ##
TypeChat.Program translates natural language requests into simple programs (***Plans***), represented as JSON.
JSON programs can be thought of as a [DSL](https://en.wikipedia.org/wiki/Domain-specific_language) or [Plan](https://learn.microsoft.com/en-us/semantic-kernel/ai-orchestration/planners/?tabs=Csharp), expressed in JSON, with an associated [**grammar**](src/typechat.program/ProgramSchema.ts) that is enforced. JSON programs can be type checked against the APIs they target. They can then be run using an interpreter, or compiled into .NET code.
TypeChat.Program includes:
* Program Translator: translates user intent into programs that follow the [Program Grammar](src/typechat.program/ProgramSchema.ts)
* Program Interpreter: runs programs generated by ProgramTranslator using an interpreter.
* Program Compiler: uses the dynamic language runtime (DLR) to compile programs/plans with type checking. Compilation diagnostics are used to repair programs.
```
// Translates user intent into typed Programs that call methods on a Math API
var model = new LanguageModel(Config.LoadOpenAI());
var api = new MathAPI();
var translator = new ProgramTranslator<IMathAPI>(model, api);
// Translate natural language request
Program program = await translator.TranslateAsync(requestText);
// Run the program
program.Run(api);
```
## Microsoft.TypeChat.SemanticKernel ##
TypeChat.SemanticKernel uses [Semantic Kernel 1.0](https://github.com/microsoft/semantic-kernel). It includes classes for:
* **Json Programs for Plugins**: turn registered plugins into **APIs** that Json programs can target. See the [Plugins Example](examples/Plugins/Program.cs).
* Language model and embeddings access using Semantic Kernel.
Prior versions of TypeChat.NET used the pre-release programming model of Semantic Kernel. You can access this deprecated version using the [sk_prerelease](https://github.com/microsoft/typechat.net/tree/sk_0.22.230905.3-preview) branch.
# Getting Started
## Prerequisite: OpenAI
* **OpenAI Language Models**: TypeChat.NET and its examples currently require familiarity with and access to language models from OpenAI.
* TypeChat.NET has been tested with and supports the following models:
* gpt-35-turbo
* gpt-4
* ada-002
* Some examples and scenarios will work best with gpt-4
## Building
* Visual Studio 2022.
* Load **typechat.sln** from the root directory.
* Restore packages
* Build
* dotnet build
* Launch a command prompt / terminal
* Go to the root directory of the project
* dotnet build Typechat.sln
## Nuget Packages
* Microsoft.Typechat
```
dotnet add package Microsoft.TypeChat
```
* Microsoft.TypeChat.Program
```
dotnet add package Microsoft.TypeChat.Program
```
* Microsoft.Typechat.SemanticKernel
```
dotnet add package Microsoft.TypeChat.SemanticKernel
```
## Examples
To see TypeChat.NET in action, explore the [Example projects](./examples) and [TypeChat.Examples Library](./examples/typechat.examplesLib).
Each example includes an **input.txt** with sample input. Pass the input file as an argument to run the example in **batch mode**.
The sections below describe which examples will best introduce which concept. Some examples or scenarios may work ***best with gpt-4***.
### Hello World
The [Sentiment](./examples/Sentiment/Program.cs) example is TypeChat's Hello World and a minimal introduction to JsonTranslator.
### JsonTranslator
The following examples demonstrate how to use JsonTranslator, Schemas and Vocabularies:
* [CoffeeShop](./examples/CoffeeShop): Natural language ordering at a coffee shop. Demonstrates a complex schema with polymorphic deserialzation.
* [Calendar](./examples/Calendar): Transform language into calendar actions
* [Restaurant](./examples/Restaurant): Order processing at a pizza restaurant
### Hierarchical schemas
* [MultiSchema](./examples/MultiSchema): dynamically route user intent to other 'sub-apps'
* [SchemaHierarchy](./examples/SchemaHierarchy): A Json Translator than uses multiple child JsonTranslators. For each user request, it picks the semantically ***nearest*** child translator and routes the input to it.
* [TextClassifier](./examples/typechat.examplesLib/Classification/TextClassifier.cs) and [VectorTextIndex](./examples/typechat.examplesLib/VectorTextIndex.cs) show how to build a simple classifiers to route input.
### Json Programs
* [Math](./examples/Math): How to turn user requests into simple calculator programs
* [Plugins](./examples/Plugins): How to translate user intent into programs programs that call Semantic Kernel Plugins
### Interactive agents
* [HealthData](./examples/HealthData): how to use an interactive bot to collect a user's health information.
* [Agent Classes](./examples/typechat.examplesLib/Dialog) for working with interactive agents that have history. These classes emonstrate how TypeChat.NET may be used for strongly typed interactions with message passing agents or bots. These agents can include features such as built in interaction history.
## Api Key and Configuration
To use TypeChat.net or run the examples, you need **either**:
* An **API key** for an OpenAI service. Azure OpenAI and the OpenAI service are both supported.
* An Azure identity with access to the Azure OpenAI service. To use Azure identities, you must configure your OpenAI service to use role based access and grant access to the identity.
### Configure Api Key or Azure Identity for examples
* Go to the **[examples](./examples)** folder in the solution
* Make a copy of the [appSettings.json](./examples/appSettings.json) file and name it **appSettings.Development.json**. Ensure it is in the same folder as appSettings.json
* appSettings.Development.json is a local development only override of the settings in appSettings.json and is **never** checked in.
* Add your **Api Key** to **appSettings.Development.json**.
* To use Azure identity: use the well-known key **"identity"**. The code will use access tokens returned by the default Azure credentials: [DefaultAzureCredential](https://learn.microsoft.com/en-us/dotnet/api/azure.identity.defaultazurecredential?view=azure-dotnet). You can provide these using **az login**.
A typical appSettings.Development.json will look like this:
```
// For Azure OpenAI service
{
"OpenAI": {
"Azure": true,
"ApiKey": "YOUR API KEY",
"Endpoint": "https://YOUR_RESOURCE_NAME.openai.azure.com",
"Model": "gpt-35-turbo" // Name of Azure deployment
}
}
// For Azure OpenAI service with Azure Identity: DefaultCredentials
{
"OpenAI": {
"Azure": true,
"ApiKey": "identity",
"Endpoint": "https://YOUR_RESOURCE_NAME.openai.azure.com",
"Model": "gpt-35-turbo" // Name of Azure deployment
}
}
// For OpenAI Service:
{
"OpenAI": {
"Azure": false,
"ApiKey": "YOUR API KEY",
"Endpoint": "https://api.openai.com/v1/chat/completions",
"Model": "gpt-3.5-turbo" // Name of OpenAI model
}
}
```
### OpenAIConfig
TypeChat examples accesses language models using the [LanguageModel](./src/typechat/LanguageModel.cs) class. The OpenAIConfig class supplies configuration for LanguageModel. You initialize OpenAIConfig from your application's configuration, from a Json file or from environment variables.
See [OpenAIConfig.cs](./src/typechat/OpenAIConfig.cs) for a list of :
* Configurable properties
* Supported environment variables.
```
// Your configuration
OpenAIConfig config = Config.LoadOpenAI();
// Or Json file
OpenAIConfig config = OpenAIConfig.LoadFromJsonFile(...);
// Or from config
config = OpenAIConfig.FromEnvironment();
var model = new LanguageModel(config);
```
## Using Semantic Kernel
You can also access a LanguageModel using the SemanticKernel Kernel object you created using a KernelBuilder.
```
const string modelName = "gpt-35-turbo";
new ChatLanguageModel(_kernel.GetService<IChatCompletionService>(modelName), modelName);
```
## Using your own client
TypeChat accesses language models using the [ILanguageModel](src/typechat/ILanguageModel.cs) interface. [LanguageModel](src/typechat/LanguageModel.cs) implements ILanguageModel.
You can use your own model client by implementing ILanguageModel. If you don't use one of the Open AI models listed above, you will likely also need to supply [JsonTranslatorPrompts](./src/typechat/IJsonTranslatorPrompts.cs) that work best with your model.
# Code of Conduct
This project has adopted the
[Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
For more information see the
[Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/)
or contact [
[email protected]](mailto:
[email protected])
with any additional questions or comments.
# License
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the [MIT](LICENSE) license.
# 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](https://www.microsoft.com/en-us/legal/intellectualproperty/trademarks/usage/general).
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.
", Assign "at most 3 tags" to the expected json: {"id":"3279","tags":[]} "only from the tags list I provide: [{"id":77,"name":"3d"},{"id":89,"name":"agent"},{"id":17,"name":"ai"},{"id":54,"name":"algorithm"},{"id":24,"name":"api"},{"id":44,"name":"authentication"},{"id":3,"name":"aws"},{"id":27,"name":"backend"},{"id":60,"name":"benchmark"},{"id":72,"name":"best-practices"},{"id":39,"name":"bitcoin"},{"id":37,"name":"blockchain"},{"id":1,"name":"blog"},{"id":45,"name":"bundler"},{"id":58,"name":"cache"},{"id":21,"name":"chat"},{"id":49,"name":"cicd"},{"id":4,"name":"cli"},{"id":64,"name":"cloud-native"},{"id":48,"name":"cms"},{"id":61,"name":"compiler"},{"id":68,"name":"containerization"},{"id":92,"name":"crm"},{"id":34,"name":"data"},{"id":47,"name":"database"},{"id":8,"name":"declarative-gui "},{"id":9,"name":"deploy-tool"},{"id":53,"name":"desktop-app"},{"id":6,"name":"dev-exp-lib"},{"id":59,"name":"dev-tool"},{"id":13,"name":"ecommerce"},{"id":26,"name":"editor"},{"id":66,"name":"emulator"},{"id":62,"name":"filesystem"},{"id":80,"name":"finance"},{"id":15,"name":"firmware"},{"id":73,"name":"for-fun"},{"id":2,"name":"framework"},{"id":11,"name":"frontend"},{"id":22,"name":"game"},{"id":81,"name":"game-engine "},{"id":23,"name":"graphql"},{"id":84,"name":"gui"},{"id":91,"name":"http"},{"id":5,"name":"http-client"},{"id":51,"name":"iac"},{"id":30,"name":"ide"},{"id":78,"name":"iot"},{"id":40,"name":"json"},{"id":83,"name":"julian"},{"id":38,"name":"k8s"},{"id":31,"name":"language"},{"id":10,"name":"learning-resource"},{"id":33,"name":"lib"},{"id":41,"name":"linter"},{"id":28,"name":"lms"},{"id":16,"name":"logging"},{"id":76,"name":"low-code"},{"id":90,"name":"message-queue"},{"id":42,"name":"mobile-app"},{"id":18,"name":"monitoring"},{"id":36,"name":"networking"},{"id":7,"name":"node-version"},{"id":55,"name":"nosql"},{"id":57,"name":"observability"},{"id":46,"name":"orm"},{"id":52,"name":"os"},{"id":14,"name":"parser"},{"id":74,"name":"react"},{"id":82,"name":"real-time"},{"id":56,"name":"robot"},{"id":65,"name":"runtime"},{"id":32,"name":"sdk"},{"id":71,"name":"search"},{"id":63,"name":"secrets"},{"id":25,"name":"security"},{"id":85,"name":"server"},{"id":86,"name":"serverless"},{"id":70,"name":"storage"},{"id":75,"name":"system-design"},{"id":79,"name":"terminal"},{"id":29,"name":"testing"},{"id":12,"name":"ui"},{"id":50,"name":"ux"},{"id":88,"name":"video"},{"id":20,"name":"web-app"},{"id":35,"name":"web-server"},{"id":43,"name":"webassembly"},{"id":69,"name":"workflow"},{"id":87,"name":"yaml"}]" returns me the "expected json"