ATLBitLab / abbot-backup

Open-source Abbot (ATL BitLab Bot)
https://atlbitlab.com/abbot
MIT License
1 stars 1 forks source link

API crossplatform POC #3

Open bnonni opened 11 months ago

bnonni commented 11 months ago

Due date = 10/15/23

bnonni commented 11 months ago

Due date = 10/16/23 (updated)

API High Level

  1. Swap out Telegram and OpenAI SDKs for API calls to endpoints directly
  2. Keep Telegram and OpenAI SDKs and run python API that reuses existing code
  3. Use current build for Abbot and Abbit and build new API project for hackathon (TypeScript)

Will expand after thinking deeper about it

bnonni commented 11 months ago

API Deep Dive

Preface: By using python SDKs for Telegram and OpenAI/ChatGPT, I made an overly opinionated design decision that has locked us into using python. Using python to build a web API is do-able, but it may not be the right tool for the job. The python interpreter acts as a single, coordinated entity managing the execution environment. This is not ideal for APIs, so I'm wondering if the first step in the longer term vision of building an API-first Abbot is to take the time to swap all SDKs for naked API calls and rebuild Abbot for the hackathon using something more API native like Typescript. Granted, that will take a lot of time: time we don't have. The other extreme is to not change anything at the design level and forge ahead with python, then worry about the scalability of an API later.

Deep Dive Options

  1. Keep Python and Telegram + OpenAI SDKs in place

    • Build a very simple python flask API that reuses existing code for its backend logic.
    • API is a simple interface to the current functions for creating chat completions
    • Analysis: This is obviously the fastest solution for the hackathon. However, it comes with challenges.
    • Challenges: Python tooling is sparse for Nostr. Currently have not found a good package that works. Rebuilding that tooling ourselves would be just as time intensive as a full rebuild. Python APIs suck and could lead to a lot more pain.
  2. Build the Nostr integration completely separate from the Abbot (Telegram-Abbot) codebase

    • I'm finding the tooling for python + Nostr to be lacking (see 1.)
    • Lack of tooling will make our lives more difficult than necessary ultimately slowing down our progress
    • Instead, build a middle-man API between Abbot and Relays ("Relay-Abbot")
    • Relay-Abbot built using something like NestJS (TypeScript)
    • Process
      • Relay-Abbot API connects to relays
      • Nostr clients send notes to relays
      • Relays send notes to Relay-Abbot
      • Relay-Abbot filters for note kinds 4 (encrypted DMs) & 40-44 (channel stuff)
      • Relay-Abbot does a simple store+forward: store (in digital ocean mongo) + forward (to Telegram-Abbot)
      • Relay-Abbot can use the telegram API to simulate a chat message coming in from the app (see example 1)
      • Telegram-Abbot uses openai to create embeddings, store in pinecone, query similarity data and call openAI for chat completion
      • Telegram-Abbot uses basic Nostr class to create a nostr note, sign it and send back to Relay-Abbot
      • Relay-Abbot sends note to relays
      • Relays send note to client
      • Considerations
        • consider sending a DB collection name and record ID to Telegram-Abbot
          • instead of sending the entire nostr note
          • both Abbots (Relay and Telegram) can have access to the mongoDB
          • could be "cheaper" since querying simple data from noSQL is fast
        • consider having Telegram-Abbot store response to notes in mongoDB and then either:
          • send signed note directly to relays
          • send to Relay-Abbot for broadcast
          • sent to Relay-Abbot if doing it directly with pynost / python isn't easy
  3. Start from "scratch" and rebuild Abbot using TypeScript in an API-first manner.

    • Stabilize current builds for Abbot (ATL BitLab Bot) and Abbit (A Blixt Bot)
    • Keep those apps in place to support current channels
    • Convert all the python logic to typescript
    • Use Typescript API (Nest) to build an API
    • Swap out Telegram and OpenAI SDKs for API calls to endpoints directly

Example 1

    url = f"https://api.telegram.org/bot{token}/sendMessage"
    payload = {
        "chat_id": chat_id,
        "text": text
    }
    response = requests.post(url, data=payload)
    response.json()

My vote is #2. Going to start there and work my way through the options as necessary.

niteshbalusu11 commented 11 months ago

I think 2 is a good place to start. Just keeping the nostr logic separate for now is good.

bnonni commented 11 months ago

I think 2 is a good place to start. Just keeping the nostr logic separate for now is good.

Thanks for the input and confirmation @niteshbalusu11! Might need your help with the relay code if you can spare the time.

bnonni commented 11 months ago

High level architecture diagram image

jordan-bravo commented 10 months ago

Will the above architecture diagram look different in light of the new direction outlined in #5 ?

bnonni commented 10 months ago

Not sure yet. @w3irdrobot is taking lead here. He's going to drop the notes and ideas he came up with in our call this AM.

w3irdrobot commented 10 months ago

the basic setup will be the following

graph TD;
    NostrServer-->AbbotAPI;
    AbbotAPI-->AbbotBot;

    TelegramClient-->AbbotTGClient;
    AbbotTGClient-->AbbotBot;

    AbbotBot-->OpenAIAPI;
    OpenAIAPI-->AbbotBot;

    AbbotBot-->AbbotAPI;
    AbbotAPI-->NostrServer;

    AbbotBot-->AbbotTGClient;
    AbbotTGClient-->TelegramClient;

not my best diagram but it gets the point across. i'm going to abstract the actual business logic that Abbot does out into a central place. that way, we can abstract out the inputs for the commands to easily support more. obviously, telegram will continue to function as is. i'm just going to pull out the code so it implements some sort of interface that can be reproduced. then i'll make an API using flask that can be called into to run commands on Abbot. this will be able to be used by the nostr server, since it seems we will implement that as an external process since the python nostr sdks seem to be less than ideal.

the commands that are currently supported are as follows:

help
stop
summary
prompt
clean
both
unleash
status
rules
start

so for now, my plan is to just turn each of these into an endpoint that can be called into. for now, an easy way to auth would just be using a simple auth bearer token header using a shared secret. also i think it'd be good for the calling service to pass a request id using UUID version 4 and accept a webhook on a single endpoint that will be passed back to notify the calling service of the request for which we are passing data back to it.

Authorization: Bearer <token>

POST /v1/command/help
POST /v1/command/stop
POST /v1/command/summary
POST /v1/command/prompt
POST /v1/command/clean
POST /v1/command/both
POST /v1/command/unleash
POST /v1/command/status
POST /v1/command/rules
POST /v1/command/start
bnonni commented 10 months ago

@w3irdrobot updated list of commands based on master, which I'll be rebasing nostrasia branch against here shortly.

start
stop
rules
unleash
leash
help

Please kill the following

summary
prompt
clean
both
status
bnonni commented 10 months ago

the basic setup will be the following


graph TD;
NostrServer-->AbbotAPI;
AbbotAPI-->AbbotBot;
TelegramClient-->AbbotTGClient;
AbbotTGClient-->AbbotBot;

AbbotBot-->OpenAIAPI;
OpenAIAPI-->AbbotBot;

AbbotBot-->AbbotAPI;
AbbotAPI-->NostrServer;

AbbotBot-->AbbotTGClient;
AbbotTGClient-->TelegramClient;

> not my best diagram but it gets the point across. i'm going to abstract the actual business logic that Abbot does out into a central place. that way, we can abstract out the inputs for the commands to easily support more. obviously, telegram will continue to function as is. i'm just going to pull out the code so it implements some sort of interface that can be reproduced. then i'll make an API using flask that can be called into to run commands on Abbot. this will be able to be used by the nostr server, since it seems we will implement that as an external process since the python nostr sdks seem to be less than ideal.
> 
> the commands that are currently supported are as follows:
> 
> ```
> help
> stop
> summary
> prompt
> clean
> both
> unleash
> status
> rules
> start
> ```
> 
> so for now, my plan is to just turn each of these into an endpoint that can be called into. for now, an easy way to auth would just be using a simple auth bearer token header using a shared secret. also i think it'd be good for the calling service to pass a request id using UUID version 4 and accept a webhook on a single endpoint that will be passed back to notify the calling service of the request for which we are passing data back to it.
> 
> ```
> Authorization: Bearer <token>
> 
> POST /v1/command/help
> POST /v1/command/stop
> POST /v1/command/summary
> POST /v1/command/prompt
> POST /v1/command/clean
> POST /v1/command/both
> POST /v1/command/unleash
> POST /v1/command/status
> POST /v1/command/rules
> POST /v1/command/start
> ```

Questions about the actors in the diagram:
- NostrServer: Is this a relay? Or the server we plan to build to handle nostr connections?
- AbbotAPI and AbbotBot: I assume the API is the flask api, and bot is the current python logic, correct?
- AbbotTGClient: Not clear on what this is. Can you elaborate?
bnonni commented 10 months ago

Update: @annieseth and I got pynostr to work last night!! So with that working, we can kill the Nostr Server and simply write a AbbotNostr class to handle the processing of incoming note events kinds 4, 40-44 and the creation of response note events. The initial skeleton code for this class is pushed to the nostrasia branch.