Introduction
AI. ChatGPT. OpenAI. That’s all over the internet these days. I presume you are being bombarded with AI tools from every direction too 😅. But it is not just hype, they are really powerful. Period.
Recently, I came across this YouTube teaser showing a ChatGPT integration with ERPNext and its mind blowing. I had a chat with Raaj, the developer of this integration to discuss more and turns out, he has much more in the works! Shortly after this, I received a message from another community member showing interest in building a similar AI powered tool for the Frappe ecosystem. The hype is real.
Raaj was not happy with the current UI/UX of the bot and he was not able to do much about it because he is not that much into UI. So, it struck to me! There are going to be many use cases for AI in the ecosystem. Why not build a template for such integrations/bots?! So, here it is: DoppioBot. You can use DoppioBot for interacting with ChatGPT right in the desk or use it as a starting point for building your own AI experiences for Frappe.
In this blog, we will start by covering how to install and use the app as is, then I will show you how it’s built and we will conclude by getting an overview of how you can customise/extend the app for your own specific needs. Let’s start!
Using DoppioBot
🚧 DoppioBot requires Frappe version ≥ v14.32.0
DoppioBot is MIT licensed and open source on GitHub. Just like any other Frappe app, if you have bench installed, you can execute the following commands to install the DoppioBot app on your Frappe site:
$ bench get-app NagariaHussain/doppio_bot
$ bench --site <your-site> install-app doppio_bot
Then add your OpenAI API key to the site_config.json
(of the site you have installed the app on):
"openai_api_key": "sk-your-secret-api-key"
And that’s it! You can now navigate to your site, search for Ask DoppioBot using the awesome bar and start talking to your friendly AI bot:
The Features
Here is a summary of some note-worthy features:
- Session Chat history management with Redis
- Formatting of markdown responses including tables and lists
- Code block responses are syntax-highlighted and have a click to copy button!
- A sleek loading skeleton is shown while the message is being fetched
- The prompt can be submitted through mouse as well as keyboard (
Cmd + Enter
)
… and more!
Building DoppioBot
Let me walk you through how I went about developing this thing!
DoppioBot has two core components: the ChatBot UI and the API. Thanks to LangChain, the API was very straightforward to implement. But the meat of this template is the feature-rich Chat UI built using Frappe custom pages and React.
Custom Pages in Frappe Framework
In my opinion, custom pages are one of the most underrated and underused feature of Frappe Framework. Don’t confuse them with Portal (web) pages. Custom Pages, created though the Page doctype, can help you build really custom UI experiences right in the Desk (the admin interface). If you have used the Print Format Builder or the Role Permissions Manager, you have already used a custom page.
Of course, you can customize the Form View or List View, but you can only go so far.. Custom Pages give you complete control. For example, the Print Format Builder (or even the new DocType Form builder) mount a Vue 3 application to its custom page!
The Ask DoppioBot Page
My first task was to get a React application running on a custom page. This can be done in two steps:
Setting Up The Page
In order to create a custom page, we just need to create a new Page document. Give it a title, module, and make sure Standard is set to Yes.
Once we save this document/page, a few files will be generated in our custom app (based on what Module you selected for the page). In case of DoppioBot, you can see those files in page/doppio_bot
directory:
The most important file here is the doppio_bot.js
. When you open up this file, you will see there are a few things going over here, but focus on the below annotated lines:
- We are using
frappe.require
to load a JavaScript bundle file nameddoppiobot_ui.bundle.jsx
- After the script is successfully loaded, we are creating an instance of a class called
DoppioBotUI
frappe.require
is a powerful utility function that can help you load JavaScript bundles on the fly. Here, I am loading a bundle file that contains our React application and then I am initialising an instance of a class which triggers the mounting of that React application. You can find the source of this bundle file on GitHub here.
Setting Up The React Application
As you have seen in the previous step, we were loading a JavaScript bundle file from the backend and it does all the magic of mounting and rendering our Chat interface.
Open up the public/js/doppiobot_ui.bundle.jsx
file and have a look. Since, we already have a build system in place (esbuild
) in Frappe Framework, it was as easy as installing the npm packages and importing React in the bundle file. When you run bench build
, the .jsx
files will be compiled and bundled properly to be served to our custom page.
After this, it was just a matter of writing React code. I have used ChakraUI, so I don’t have to write UI components from scratch and also the components are very polished, accessible and customisable.
A Powerful Thing
One more supercool thing about custom pages: you have access to the frappe
namespace in your React application! So, you can write this type of code in your React components and it will work flawlessly:
const ChatView = ({ sessionID }) => {
// from Frappe!
const userImageURL = frappe.user.image();
const userFullname = frappe.user.full_name();
const toast = useToast();
// ...
}
You can follow the trail from the bundle file to explore the React application in depth.
The API
The API call can be found in the ChatView.jsx file:
frappe
.call("doppio_bot.api.get_chatbot_response", {
prompt_message: promptMessage,
session_id: sessionID,
})
.then((response) => {...}
This code makes an API call to get the response based on the given prompt and processes the response.
If you open up the api.py
file (here), you will be able to see the surprisingly few lines of code that power this bot. Instead of directly calling the OpenAI API, managing message history and prompts, I have used LangChain python library, which makes it super easy and composable to build AI applications based on LLMs (like GPT):
llm = OpenAI(temperature=0, openai_api_key=opeai_api_key)
# For tracking chat message history
# Session ID is stored in the frontend
message_history = RedisChatMessageHistory(session_id=session_id)
memory = ConversationBufferMemory(memory_key="history", chat_memory=message_history)
conversation_chain = ConversationChain(llm=llm, memory=memory, prompt=prompt_template)
return conversation_chain.run(prompt_message)
Build Your Own!
Now that you know how DoppioBot works and how it is structured, you can extend it to build your own AI experiences for Frappe. Here are some of the ways you can get started:
- Change the API function’s code to get your desired results
- Customise the frontend (React) code to match your theme
- Take inspiration and rewrite the whole this, if you want!
You can either copy over the code for the page or fork the doppio_bot
to extend it according to your requirements. If you are editing the UI/React code, you can get live reload by running the following command in apps/frappe
directory:
$ yarn run watch --apps doppio_bot --live-reload
There are a variety of ways you can extend this, but I have included a “simple” example in the README file, that uses a custom tool to create ToDo documents on user’s behalf!
Conclusion
You can find the GitHub repo here. Please feel free to create an issue if you find one. If you end up using this as template, I will love to hear from you or even if just want to have a chat, don’t hesitate to reach me out on twitter @NagariaHussain.
Now it is time for you to explore! Have fun tinkering!