It's possible to create a custom LLM chat bot per system, providing the LLM with the ability to execute functions within the system.
For a system to work as a ChatGPT chat bot it requires the PlaceOS LLM Interface driver.
This driver is used to define the system prompt and the initial message to display to the user.
Drivers implementing the ChatFunctions interface expose the available functionality to the LLM.
Building a capability
Each driver should encapsulate related functions that can easily be summarised. This summary is used by the LLM to discover the driver with the function it needs.
The key to building effective functions is to make them as human friendly as possible. If the parameters are hard to understand and not constructed for a human the LLM will produce more errors. An example would be to use parsable date strings over Unix timestamps.
Descriptions should explain how to use any non-obvious parameters and be firm when describing any order of operations:
# Capability examplegetter capabilities :StringdoString.build do |str| str <<"provides details of my daily schedule, meeting room bookings and events I'm attending.\n" str << "lookup or search for the email and phone numbers of other staff members if you haven't been provided their details. Do not guess.\n"
str <<"check schedules before booking or moving meetings to ensure no one is busy at that time\n"endend
# Parameter usage example, only functions with descriptions are provided to the LLM@[Description("search for a staff members phone and email addresses using odata filter queries, don't include `$filter=`, for example: `givenName eq 'mary' or startswith(surname,'smith')`, confrim with the user when there are multiple results, search for both givenName and surname using `or` if there is ambiguity")]
defsearch_staff_member(filter:String) # ...end
See the example TODO driver and spec as a template.
Configuring access to OpenAI or Azure APIs
Either OpenAI or Azure APIs can be used to provide LLM model functionality. API keys can be defined for each domain in the internal settings.
Settings
"openai": {# either the OpenAI or Azure API key"api_key":"",# specify your Azure API URI here. Don't include key if not in use."api_base":"","api_model":"gpt-4-1106-preview",# max tokens before the conversation needs to be truncated# this is a good default for GPT 4"max_tokens":11264}
Chat API
These HTTP and Websocket API routes available for interfacing with the LLM
Websocket
To establish a new chat, open a websocket to:
WS /api/engine/v2/chatgpt/chat/:system_id
Request messages are raw strings (frontend -> backend)
What do I have on today?
Response messages are JSON encoded (backend -> frontend)
{# use the chat_id to recover a chat if the websocket is disconnected"chat_id":"chats-GXs4_ynIhe","message":"checking Schedule capabilities",# progress messages are provided as the request is worked on"type":"progress","function":"list_function_schemas",# token usage is provided for debugging purposes# as you don't want requests exceeding your limits"usage": {"prompt_tokens":883,"completion_tokens":16,"total_tokens":899 }}
{"chat_id":"chats-GXs4_ynIhe","message":"condensing progress: Checked schedule for today, no meetings are present.","type":"progress","function":"task_complete","usage": {"prompt_tokens":2240,"completion_tokens":23,"total_tokens":2263 },# progress messages are pruned from the chat to minimize token usage"compressed_usage":883}
{"chat_id":"chats-GXs4_ynIhe","message":"You don't have any meetings scheduled for today. Is there anything else you would like to know or do?","type":"response","usage": {"prompt_tokens":931,"completion_tokens":23,"total_tokens":954 },"compressed_usage":954}
If the websocket is dropped you can resume the chat where you left off by re-establishing with the resume parameter:
WS /api/engine/v2/chatgpt/chat/:system_id?resume=chats-GXs4_ynIhe
REST API Routes
List your past chats
GET /api/engine/v2/chatgpt/
List the chat history
GET /api/engine/v2/chatgpt/:chat_id
Delete chat history
DELETE /api/engine/v2/chatgpt/:chat_id