From fc633dadeb3ac7d5962a8d930f27a23c97508147 Mon Sep 17 00:00:00 2001 From: cachho Date: Mon, 28 Aug 2023 20:17:01 +0200 Subject: [PATCH] feat: poe bot (#492) Co-authored-by: Taranjeet Singh --- docs/examples/poe_bot.mdx | 40 ++++++++++++++++++++ docs/mint.json | 2 +- embedchain/bots/poe.py | 79 +++++++++++++++++++++++++++++++++++++++ pyproject.toml | 2 + 4 files changed, 122 insertions(+), 1 deletion(-) create mode 100644 docs/examples/poe_bot.mdx create mode 100644 embedchain/bots/poe.py diff --git a/docs/examples/poe_bot.mdx b/docs/examples/poe_bot.mdx new file mode 100644 index 00000000..19bf1c2b --- /dev/null +++ b/docs/examples/poe_bot.mdx @@ -0,0 +1,40 @@ +--- +title: '🔮 Poe Bot' +--- + +### 🚀 Getting started + +1. Install embedchain python package: + +```bash +pip install embedchain[poe] +``` + +2. Create a free account on [Poe](https://www.poe.com). +3. Click "create bot". +4. Give it a handle and an optional description. +5. Select `Use API`. +6. Under `API URL` enter your server or ngrok address. You can use your machine's public IP or DNS. Otherwise, employ a proxy server like [ngrok](https://ngrok.com/) to make your local bot accessible. +7. Copy your api key and paste it in `.env` as `POE_API_KEY`. +8. Start the bot. + +```bash +python -m embedchain.bots.poe --port 5000 +``` + +9. Click `Run check` to make sure your machine can be reached. +10. Make sure your bot is private if that's what you want. +11. Click `Create bot`. +12. Happy chatting! + +### 💬 How to use + +- To include data sources, use this command: +```text +/add +``` + +- To ask the bot questions, just type your query: +```text + +``` diff --git a/docs/mint.json b/docs/mint.json index d9d129ae..69e9dc1e 100644 --- a/docs/mint.json +++ b/docs/mint.json @@ -36,7 +36,7 @@ }, { "group": "Examples", - "pages": ["examples/full_stack", "examples/api_server", "examples/discord_bot", "examples/slack_bot", "examples/telegram_bot", "examples/whatsapp_bot"] + "pages": ["examples/full_stack", "examples/api_server", "examples/discord_bot", "examples/slack_bot", "examples/telegram_bot", "examples/whatsapp_bot", "examples/poe_bot"] }, { "group": "Contribution Guidelines", diff --git a/embedchain/bots/poe.py b/embedchain/bots/poe.py new file mode 100644 index 00000000..23ee383a --- /dev/null +++ b/embedchain/bots/poe.py @@ -0,0 +1,79 @@ +import argparse +import logging +import os +from typing import List, Optional + +from fastapi_poe import PoeBot, run + +from embedchain.config import QueryConfig + +from .base import BaseBot + + +class EcPoeBot(BaseBot, PoeBot): + def __init__(self): + self.history_length = 5 + super().__init__() + + async def get_response(self, query): + last_message = query.query[-1].content + try: + history = ( + [f"{m.role}: {m.content}" for m in query.query[-(self.history_length + 1) : -1]] + if len(query.query) > 0 + else None + ) + except Exception as e: + logging.error(f"Error when processing the chat history. Message is being sent without history. Error: {e}") + logging.warning(history) + answer = self.handle_message(last_message, history) + yield self.text_event(answer) + + def handle_message(self, message, history: Optional[List[str]] = None): + if message.startswith("/add "): + response = self.add_data(message) + else: + response = self.ask_bot(message, history) + return response + + def add_data(self, message): + data = message.split(" ")[-1] + try: + self.add(data) + response = f"Added data from: {data}" + except Exception: + logging.exception(f"Failed to add data {data}.") + response = "Some error occurred while adding data." + return response + + def ask_bot(self, message, history: List[str]): + try: + config = QueryConfig(history=history) + response = self.query(message, config) + except Exception: + logging.exception(f"Failed to query {message}.") + response = "An error occurred. Please try again!" + return response + + +def start_command(): + parser = argparse.ArgumentParser(description="EmbedChain PoeBot command line interface") + # parser.add_argument("--host", default="0.0.0.0", help="Host IP to bind") + parser.add_argument("--port", default=8080, type=int, help="Port to bind") + parser.add_argument("--api-key", type=str, help="Poe API key") + # parser.add_argument( + # "--history-length", + # default=5, + # type=int, + # help="Set the max size of the chat history. Multiplies cost, but improves conversation awareness.", + # ) + args = parser.parse_args() + + # FIXME: Arguments are automatically loaded by Poebot's ArgumentParser which causes it to fail. + # the port argument here is also just for show, it actually works because poe has the same argument. + + run(EcPoeBot(), api_key=args.api_key or os.environ.get("POE_API_KEY")) + + +if __name__ == "__main__": + start_command() diff --git a/pyproject.toml b/pyproject.toml index 9e0c97a3..26f48c8a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -98,6 +98,7 @@ gpt4all = { version = "^1.0.8", optional = true } elasticsearch = { version = "^8.9.0", optional = true } flask = "^2.3.3" twilio = "^8.5.0" +fastapi-poe = { version = "0.0.16", optional = true } @@ -116,6 +117,7 @@ streamlit = ["streamlit"] community = ["llama-index"] opensource = ["sentence-transformers", "torch", "gpt4all"] elasticsearch = ["elasticsearch"] +poe = ["fastapi-poe"] [tool.poetry.group.docs.dependencies]