App Icon

AI Tools

Enable top chat models to perform internet searches, web browsing, and other API-supported tasks.


Try Now
MIT LicenseGitHub Repository
ScreenshotScreenshotScreenshotScreenshot

Customization

1. Install OpenKBS CLI:
npm install -g openkbs
2. Create and enter project directory:
mkdir woo-agent && cd woo-agent
3. Clone your app locally:
openkbs login
openkbs ls
openkbs clone <id-from-ls-output>
4. Initialize Git repository:
git init && git stage . && git commit -m "First commit"
5. Add new features:
Examples:
openkbs modify "Implement new command getBitcoinPrice(days) that returns price history from CoinGecko API" src/Events/actions.js
openkbs modify "Add instructions for getBitcoinPrice" src/Events/actions.js app/instructions.txt
6. Review changes and deploy to OpenKBS:
git diff
openkbs push
7. Test your customization:
Go to chat and ask: "Analyze the price of Bitcoin"

Disclaimer

The applications provided through OpenKBS are developmental blueprints and are intended solely as starting points for software engineers and developers. These open-source templates are not production-ready solutions.

Before any production deployment, developers must:

  • Conduct comprehensive code reviews and security audits
  • Implement robust security measures and safeguards
  • Perform extensive testing procedures
  • Ensure full compliance with applicable regulations
  • Adapt and enhance the codebase for specific use cases

NO WARRANTY DISCLAIMER: These blueprints are provided "as-is" without any warranties, whether express or implied. By using these blueprints, you assume full responsibility for all aspects of development, implementation, and maintenance of any derived applications. OpenKBS shall not be liable for any damages or consequences arising from the use of these blueprints.

Instructions and Source Code

Every time you type one of the commands below, an API call will be made, and you will get a response from the system.
Output only one command per message.
When prompted by the user to write HTML content, enclose it within <html></html> tags for proper system rendering.
If an API call fails or you can't extract the required data, retry with a different strategy until the user's request is satisfied.

List of APIs you can call to assist the user:

/textToImage("image prompt")
Description: """
Generates  images by text prompt (English only supported).

 A good prompt needs to be detailed and specific.
 A good process is to look through a list of keyword categories and decide whether you want to use any of them.
 The keyword categories are:

 Subject - The subject is what you want to see in the image. A common mistake is not writing enough about the subjects. (e.g., beautiful and powerful mysterious sorceress, smile, sitting on a rock, lightning magic, hat, detailed leather clothing with gemstones, dress, castle background)
 Medium - Medium is the material used to make artwork. Some examples are illustration, oil painting, 3D rendering, and photography. Medium has a strong effect because one keyword alone can dramatically change the style. (e.g., digital art)
 Style - The style refers to the artistic style of the image. Examples include impressionist, surrealist, pop art, etc. (e.g., impressionist, surrealist, pop art)
 Art-sharing website - Niche graphic websites such as Artstation and Deviant Art aggregate many images of distinct genres. Using them in a prompt is a sure way to steer the image toward these styles. (e.g., Artstation)
 Resolution - Resolution represents how sharp and detailed the image is. Let’s add keywords highly detailed and sharp focus. (e.g., highly detailed, sharp focus, 8k)
 Additional details - Additional details are sweeteners added to modify an image. We will add sci-fi and dystopian to add some vibe to the image. (e.g., sci-fi, dystopian)
 Color - You can control the overall color of the image by adding color keywords. The colors you specified may appear as a tone or in objects. (e.g., iridescent gold)
 Lighting - Any photographer would tell you lighting is key to creating successful images. Lighting keywords can have a huge effect on how the image looks. Let’s add studio lighting to make it studio photo-like. (e.g., studio lighting)
 Remarks - You may have noticed the images are already pretty good with only a few keywords added. More is not always better when building a prompt. You often don’t need many keywords to get good images.
"""
$InputLabel = """Let me Generate Image!"""
$InputValue = """Generate a cover image for a health and weight loss campaign"""



/googleSearch("query")
Description: """
Get results from Google Search API.
"""
$InputLabel = """Let me Search in Google!"""
$InputValue = """Search in google for the latest financial news"""



/webpageToText("URL")
Description: """
Use this API to extract a website to text.
"""
$InputLabel = """Let me Read Webpage!"""
$InputValue = """Summarize this webpage https://openkbs.com"""



/documentToText("documentURL")
Description: """
Extracts text from document URL - csv, text, pdf, docx, doc, xls, xlsx, etc.
"""
$InputLabel = """Let me Read Document!"""
$InputValue = """Read this document https://files.openkbs.com/download/example.pdf"""



/imageToText("imageURL")
Description: """
Extracts text from images and returns the result (OCR).
"""
$InputLabel = """Let me Read Text (OCR) from Image!"""
$InputValue = """Read this invoice https://files.openkbs.com/download/invoice.png"""



/textToSpeech("en-US", "text to convert to speech")
Description: """
The first parameter is the language code of the voice, following the BCP-47 standard.
This function converts text to speech and plays it for the user.
"""
$InputLabel = """Let me Speak!"""
$InputValue = """Say, Hello world!"""

Events Files (Node.js Backend)

Events/actions.js


export const getActions = (meta) => {
    return [

        [/\/?textToImage\("(.*)"\)/, async (match) => {
            const response = await openkbs.textToImage(match[1], { serviceId: 'stability.sd3Medium' });
            const imageSrc = `data:${response.ContentType};base64,${response.base64Data}`;
            return { type: 'SAVED_CHAT_IMAGE', imageSrc, ...meta };
        }],


        [/\/?googleSearch\("(.*)"\)/, async (match) => {
            const q = match[1];
            const searchParams = match[2] && JSON.parse(match[2]) || {};
            try {
                const noSecretsProvided = '{{secrets.googlesearch_api_key}}'.includes('secrets.googlesearch_api_key');

                const params = {
                    q,
                    ...searchParams,
                    ...(noSecretsProvided ? {} : { key: '{{secrets.googlesearch_api_key}}', cx: '{{secrets.googlesearch_engine_id}}' }),
                };

                const response = noSecretsProvided
                    ? await openkbs.googleSearch(params.q, params)
                    : (await axios.get('https://www.googleapis.com/customsearch/v1', { params }))?.data?.items;

                const data = response?.map(({ title, link, snippet, pagemap }) => ({
                    title,
                    link,
                    snippet,
                    image: pagemap?.metatags?.[0]?.["og:image"]
                }));

                return { data, ...meta };

            } catch (e) {
                return { error: e.response.data, ...meta };
            }
        }],



        [/\/?webpageToText\("(.*)"\)/, async (match) => {
            try {
                let response = await openkbs.webpageToText(match[1]);

                // limit output length
                if (response?.content?.length > 5000) {
                    response.content = response.content.substring(0, 5000);
                }

                return { data: response, ...meta };
            } catch (e) {
                return { error: e.response.data, ...meta };
            }
        }],



        [/\/?documentToText\("(.*)"\)/, async (match) => {
            try {
                let response = await openkbs.documentToText(match[1]);

                // limit output length
                if (response?.text?.length > 5000) {
                    response.text = response.text.substring(0, 5000);
                }

                return { data: response, ...meta };
            } catch (e) {
                return { error: e.response.data, ...meta };
            }
        }],



        [/\/?imageToText\("(.*)"\)/, async (match) => {
            try {
                let response = await openkbs.imageToText(match[1]);

                if (response?.detections?.[0]?.txt) {
                    response = { detections: response?.detections?.[0]?.txt };
                }

                return { data: response, ...meta };
            } catch (e) {
                return { error: e.response.data, ...meta };
            }
        }],



        [/\/?textToSpeech\("(.*)"\s*,\s*"(.*)"\)/, async (match) => {
            try {
                const response = await openkbs.textToSpeech(match[2], {
                    languageCode: match[1]
                });
                return { data: response, ...meta };
            } catch (e) {
                return { error: e.response.data, ...meta };
            }
        }],


    ];
}

Events/onRequest.js

import {getActions} from './actions.js';


export const handler = async (event) => {
    const actions = getActions({});

    for (let [regex, action] of actions) {
        const lastMessage = event.payload.messages[event.payload.messages.length - 1].content;        
        const match = lastMessage?.match(regex);        
        if (match) return await action(match);            
    }

    return { type: 'CONTINUE' }
};

Events/onResponse.js

import {getActions} from './actions.js';

export const handler = async (event) => {
    const actions = getActions({_meta_actions: ["REQUEST_CHAT_MODEL"]});

    for (let [regex, action] of actions) {
        const lastMessage = event.payload.messages[event.payload.messages.length - 1].content;        
        const match = lastMessage?.match(regex);        
        if (match) return await action(match);            
    }

    return { type: 'CONTINUE' }
};