microsoft / TypeChat

TypeChat is a library that makes it easy to build natural language interfaces using types.
https://microsoft.github.io/TypeChat/
MIT License
8.23k stars 389 forks source link

Is it possible to use the application state to construct schema? #41

Open ValeriyDyachenko opened 1 year ago

ValeriyDyachenko commented 1 year ago

Does the library allow the use of the current application state? For example, if a user requests "place an order from the basket".

steveluc commented 1 year ago

This is mechanically possible now. In these lines from calendar\src\main.ts:

const schema = fs.readFileSync(path.join(__dirname, "calendarActionsSchema.ts"), "utf8");
const translator = createJsonTranslator<CalendarActions>(model, schema, "CalendarActions");

The schema text comes from a file and createJsonTranslator is just taking the schema as a string.

You could build a schema with a static part plus dynamic parts such as adding an enum of available items.

We are looking at adding helper functions around dynamic schema and are open to suggestions.

ValeriyDyachenko commented 1 year ago

@steveluc Thank you for your response. Did I understand correctly that I can take a static string schema and dynamically add a generated string describing the type of items in the basket, for example:

type BasketItems = [
  {
    product: 'tv',
    id: '123',
    brand: 'noname',
  },
  {
    product: 'laptop',
    id: '234',
    brand: 'noname',
  }
]; 

So, every time the dynamic data changes, I would need to regenerate the string schema with the updated dynamic part and call createJsonTranslator again with it?

steveluc commented 1 year ago

Yes, that's one way to do it. Load a string template from a file, then apply the template to the dynamic data on update.

tyre commented 1 year ago

I wonder if this is an example of state that ought to be held outside of the typechat context. typechat seems optimal as a natural language interface for generating events that some other system can consume, while leaving the execution and state to those other systems.

For example, from the calendar example, this is the response for "Please add Jennifer to the scrum next Thursday":

{
  "actions": [
    {
      "actionType": "add event",
      "event": {
        "day": "Friday March 15, 2024",
        "timeRange": {
          "startTime": "12:00 pm",
          "endTime": "2:00 pm"
        },
        "description": "get my tires changed"
      }
    }
  ]
}

It might be that a user has out of office and events should be rejected. One way to do this is load everyone's out of office schedules into the context for the LLM. Another way to consume this event is to make multiple (non-model) API calls in response: pull the user's OOO schedule, check against it, schedule if no conflict.

In your basket example @ValeriyDyachenko, could you store the user's basket state outside of the context and use the agent solely for generating actions? If the user asked for the contents of their cart, that's returnable with a templatized response from an API call. I would guess that this pattern should improve latency and lower LLM costs.