Skip to content

Instantly share code, notes, and snippets.

@vitouXY
Created March 5, 2023 20:18
Show Gist options
  • Save vitouXY/a39604541fbebf54087a1122c2fbfe6e to your computer and use it in GitHub Desktop.
Save vitouXY/a39604541fbebf54087a1122c2fbfe6e to your computer and use it in GitHub Desktop.
WhatsApp (Web) & OpenAI (API) Chat Bot | Golang & Python

Forked from: https://github.com/danielgross/whatsapp-gpt


OpenAI API

sudo apt update
sudo apt install curl
sudo apt install python3 python3-pip #python3-venv
#python3 -m venv --system-site-packages ./venv
#source ./venv/bin/activate
python3 -m pip install fastapi uvicorn[standard] aiohttp

https://beta.openai.com/account/api-keys

export OPENAI_API_KEY='sk-aBcD...xYZ'
mkdir -p wspHistory
uvicorn oaiRes:APP --host 127.0.0.1 --port 5001 --reload
curl http://localhost:5001/chat?q=Cual+es+la+capital+de+Chile?
curl "http://localhost:5001/chat?f=56900000000&q=Cual+es+la+capital+de+Chile?"

WhatsApp Web

sudo apt update
sudo apt search golang # >=1.19
sudo apt install git golang
#wget -c https://go.dev/dl/go1.19.4.linux-armv6l.tar.gz
#sudo rm -rf /usr/local/go && sudo tar -C /usr/local -xzf go1.19.4.linux-armv6l.tar.gz
#export PATH=/usr/local/go/bin:$PATH
go version # >=1.19
mkdir -p .gop
GOPATH=$(pwd)/.gop

GOPATH=$GOPATH go get

#GOPATH=$GOPATH go build -o wspReq
echo '{ "BlackList": ["56900000001"] }' > wspReq.json
GOPATH=$GOPATH go run main.go
#./wspReq

Scan the QR code from WhatsApp App.

Device name 'whatsmeow'.

module example.com/m
go 1.19
require (
github.com/mattn/go-sqlite3 v1.14.16
github.com/mdp/qrterminal/v3 v3.0.0
go.mau.fi/whatsmeow v0.0.0-20221202110551-e067ee7293b0
google.golang.org/protobuf v1.28.1
)
require (
filippo.io/edwards25519 v1.0.0 // indirect
github.com/gorilla/websocket v1.5.0 // indirect
github.com/howeyc/fsnotify v0.9.0 // indirect
github.com/mattn/go-colorable v0.1.2 // indirect
github.com/mattn/go-isatty v0.0.8 // indirect
github.com/mdp/qrterminal v1.0.1 // indirect
github.com/pilu/config v0.0.0-20131214182432-3eb99e6c0b9a // indirect
github.com/pilu/fresh v0.0.0-20190826141211-0fa698148017 // indirect
go.mau.fi/libsignal v0.0.0-20221015105917-d970e7c3c9cf // indirect
golang.org/x/crypto v0.0.0-20221012134737-56aed061732a // indirect
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 // indirect
rsc.io/qr v0.2.0 // indirect
)
filippo.io/edwards25519 v1.0.0 h1:0wAIcmJUqRdI8IJ/3eGi5/HwXZWPujYXXlkrQogz0Ek=
filippo.io/edwards25519 v1.0.0/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/howeyc/fsnotify v0.9.0 h1:0gtV5JmOKH4A8SsFxG2BczSeXWWPvcMT0euZt5gDAxY=
github.com/howeyc/fsnotify v0.9.0/go.mod h1:41HzSPxBGeFRQKEEwgh49TRw/nKBsYZ2cF1OzPjSJsA=
github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU=
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y=
github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
github.com/mdp/qrterminal v1.0.1 h1:07+fzVDlPuBlXS8tB0ktTAyf+Lp1j2+2zK3fBOL5b7c=
github.com/mdp/qrterminal v1.0.1/go.mod h1:Z33WhxQe9B6CdW37HaVqcRKzP+kByF3q/qLxOGe12xQ=
github.com/mdp/qrterminal/v3 v3.0.0 h1:ywQqLRBXWTktytQNDKFjhAvoGkLVN3J2tAFZ0kMd9xQ=
github.com/mdp/qrterminal/v3 v3.0.0/go.mod h1:NJpfAs7OAm77Dy8EkWrtE4aq+cE6McoLXlBqXQEwvE0=
github.com/pilu/config v0.0.0-20131214182432-3eb99e6c0b9a h1:Tg4E4cXPZSZyd3H1tJlYo6ZreXV0ZJvE/lorNqyw1AU=
github.com/pilu/config v0.0.0-20131214182432-3eb99e6c0b9a/go.mod h1:9Or9aIl95Kp43zONcHd5tLZGKXb9iLx0pZjau0uJ5zg=
github.com/pilu/fresh v0.0.0-20190826141211-0fa698148017 h1:XXDLZIIt9NqdeIEva0DM+z1npM0Tsx6h5TYqwNvXfP0=
github.com/pilu/fresh v0.0.0-20190826141211-0fa698148017/go.mod h1:2LLTtftTZSdAPR/iVyennXZDLZOYzyDn+T0qEKJ8eSw=
go.mau.fi/libsignal v0.0.0-20221015105917-d970e7c3c9cf h1:mzPxXBgDPHKDHMVV1tIWh7lwCiRpzCsXC0gNRX+K07c=
go.mau.fi/libsignal v0.0.0-20221015105917-d970e7c3c9cf/go.mod h1:XCjaU93vl71YNRPn059jMrK0xRDwVO5gKbxoPxow9mQ=
go.mau.fi/whatsmeow v0.0.0-20221202110551-e067ee7293b0 h1:danzDOlj/KiDi8kNsaHOhwJ7IZdo7V7hXelkZXhJhsc=
go.mau.fi/whatsmeow v0.0.0-20221202110551-e067ee7293b0/go.mod h1:2yweL8nczvtlIxkrvCb0y8xiO13rveX9lJPambwYV/E=
golang.org/x/crypto v0.0.0-20221012134737-56aed061732a h1:NmSIgad6KjE6VvHciPZuNRTKxGhlPfD6OA87W/PLkqg=
golang.org/x/crypto v0.0.0-20221012134737-56aed061732a/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 h1:SrN+KX8Art/Sf4HNj6Zcz06G7VEz+7w9tdXTPOZ7+l4=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
rsc.io/qr v0.2.0 h1:6vBLea5/NRMVTz8V66gipeLycZMl/+UlFmk8DvqQ6WY=
rsc.io/qr v0.2.0/go.mod h1:IF+uZjkb9fqyeF/4tlBoynqmQxUoPfWEKh921coOuXs=
package main
/*
main.go go.mod go.sum
[!] https://github.com/tulir/whatsmeow
[!] https://github.com/tulir/whatsmeow/blob/main/client_test.go
[!] https://github.com/danielgross/whatsapp-gpt
[!] https://github.com/badboysm890/Whatsapp-GPT3-BOT
wspReq.db
$ echo '{ "BlackList": ["56900000001", "56900000004"] }' > wspReq.json
*/
import (
"bytes"
"context"
"encoding/json"
"fmt"
"net/http"
"net/url"
"os"
"os/signal"
"syscall"
_ "github.com/mattn/go-sqlite3"
"github.com/mdp/qrterminal/v3"
"go.mau.fi/whatsmeow"
waProto "go.mau.fi/whatsmeow/binary/proto"
"go.mau.fi/whatsmeow/store/sqlstore"
"go.mau.fi/whatsmeow/types"
"go.mau.fi/whatsmeow/types/events"
waLog "go.mau.fi/whatsmeow/util/log"
"google.golang.org/protobuf/proto"
)
type MyClient struct {
WAClient *whatsmeow.Client
eventHandlerID uint32
}
// { "phoneNumbers": [], "HotWord": [], "author": "" }
type Config struct {
BlackList []string
// PhoneNumbers []string
// HotWords []string
// Author string
}
func (mycli *MyClient) register() {
mycli.eventHandlerID = mycli.WAClient.AddEventHandler(mycli.eventHandler)
}
/*
// contains checks if a string is in an array of strings
func contains(arr []string, str string) bool {
// if the array is empty, return true
if len(arr) == 0 {
return true
}
for _, a := range arr {
if a == str {
return true
}
}
return false
}
*/
func readConfig() Config {
// Read the config file
file, err := os.Open("wspReq.json")
if err != nil {
fmt.Println("Error opening JSON file:", err)
}
defer file.Close()
decoder := json.NewDecoder(file)
config := Config{}
err = decoder.Decode(&config)
if err != nil {
fmt.Println("Error decoding JSON file:", err)
}
return config
}
func stringInArray(str string, arr []string) bool {
for _, element := range arr {
if element == str {
return true
}
}
return false
}
func (mycli *MyClient) eventHandler(evt interface{}) {
switch v := evt.(type) {
case *events.Message:
// Ignore group messages
// Group messages cause a panic, so we need to check if it's a group message
if v.Info.IsGroup {
return
}
//newMessage := v.Message
//msg := newMessage.GetConversation()
// Support quoted messages
// Whenever someone replies to your message by swiping left on it
var newMessage *waProto.Message
newMessage = v.Message
quoted := newMessage.ExtendedTextMessage
var msg string
if quoted == nil {
msg = newMessage.GetConversation()
} else {
msg = quoted.GetText()
}
// some messages are empty, so we need to check for that
//msg_raw := newMessage.GetExtendedTextMessage()
//fmt.Println("Message from - Raw:", v.Info.Sender.User, "->", msg_raw)
fmt.Println("Message from - Conv:", v.Info.Sender.User, "->", msg)
//fmt.Println("->", msg_raw.GetText())
if msg == "" {
//fmt.Println("TEST - msg - return")
//msg = msg_raw.GetText()
return
}
cfgData := readConfig()
denyPhoneNumbers := cfgData.BlackList
if stringInArray(v.Info.Sender.User, denyPhoneNumbers) {
//fmt.Println("TEST - found - return")
return
}
/*
phoneNumbers := cfgData.PhoneNumbers
if !contains(phoneNumbers, v.Info.Sender.User) {
//fmt.Println("TEST - contains PhoneNumbers - return")
return
}
if !contains(cfgData.HotWords, msg) {
//fmt.Println("TEST - contains HotWords - return")
return
}
// remove the hotwords from the message
for _, hotword := range cfgData.HotWords {
msg = msg[len(hotword):]
}
*/
// Make a http request to localhost:5001/chat?q= with the message, and send the response
// URL encode the message
urlEncoded := url.QueryEscape(msg)
// localhost:5001/chat?q={MSG}
//url := "http://localhost:5001/chat?q=" + urlEncoded
urlEncodedUser := url.QueryEscape(v.Info.Sender.User)
// localhost:5001/chat?f={FROM}&q={MSG}
url := "http://localhost:5001/chat?f=" + urlEncodedUser + "&q=" + urlEncoded
// Make the request
resp, err := http.Get(url)
if err != nil {
fmt.Println("Error making request:", err)
return
}
// Read the response
buf := new(bytes.Buffer)
buf.ReadFrom(resp.Body)
newMsg := buf.String()
// encode out as a string
response := &waProto.Message{Conversation: proto.String(string(newMsg))}
fmt.Println("Response:", response)
userJid := types.NewJID(v.Info.Sender.User, types.DefaultUserServer)
respp, err := mycli.WAClient.SendMessage(context.Background(), userJid, "", response)
if err != nil {
fmt.Println("Error sending message: %v", err)
} else {
fmt.Println("Message sent (server timestamp: %s)", respp.Timestamp)
}
}
}
/*
func eventHandler(evt interface{}) {
switch v := evt.(type) {
case *events.Message:
fmt.Println("Received a message!", v.Message.GetConversation())
}
}
*/
func main() {
dbLog := waLog.Stdout("Database", "INFO", true) // DEBUG INFO
// Make sure you add appropriate DB connector imports, e.g. github.com/mattn/go-sqlite3 for SQLite
container, err := sqlstore.New("sqlite3", "file:wspReq.db?_foreign_keys=on", dbLog)
if err != nil {
panic(err)
}
// If you want multiple sessions, remember their JIDs and use .GetDevice(jid) or .GetAllDevices() instead.
deviceStore, err := container.GetFirstDevice()
if err != nil {
panic(err)
}
clientLog := waLog.Stdout("Client", "INFO", true) // DEBUG INFO
client := whatsmeow.NewClient(deviceStore, clientLog)
//client.AddEventHandler(eventHandler)
// add the eventHandler
mycli := &MyClient{WAClient: client}
mycli.register()
if client.Store.ID == nil {
// No ID stored, new login
qrChan, _ := client.GetQRChannel(context.Background())
err = client.Connect()
if err != nil {
panic(err)
}
for evt := range qrChan {
if evt.Event == "code" {
// Render the QR code here
// e.g. qrterminal.GenerateHalfBlock(evt.Code, qrterminal.L, os.Stdout)
// or just manually `echo 2@... | qrencode -t ansiutf8` in a terminal
qrterminal.GenerateHalfBlock(evt.Code, qrterminal.L, os.Stdout)
//fmt.Println("QR code:", evt.Code)
} else {
fmt.Println("Login event:", evt.Event)
}
}
} else {
// Already logged in, just connect
err = client.Connect()
if err != nil {
panic(err)
}
}
// Listen to Ctrl+C (you can also do something else that prevents the program from exiting)
c := make(chan os.Signal)
signal.Notify(c, os.Interrupt, syscall.SIGTERM)
<-c
client.Disconnect()
}
#!/usr/bin/env python3
# -*- coding:utf-8 -*-
"""
[!] https://github.com/danielgross/whatsapp-gpt
56900000000.wspoai
$ mkdir wspHistory
$ echo '{ "BlackList": ["56900000001", "56900000004"] }' > wspReq.json
$ uvicorn oaiRes:APP --host 127.0.0.1 --port 5001 --reload
"""
import fastapi ## uvicorn
import asyncio
import aiohttp
import json
import datetime
import typing
import pathlib
import os
## OpenAI API Completions - ChatGPT
## https://platform.openai.com/docs/api-reference/chat/create
## https://platform.openai.com/docs/guides/chat/chat-vs-completions
OPENAI_URL = "https://api.openai.com/v1/chat/completions"
## https://beta.openai.com/account/api-keys
#OPENAI_API_KEY = "sk-aBcD...xYZ"
OPENAI_API_KEY = os.environ["OPENAI_API_KEY"]
## https://platform.openai.com/docs/models/models
OPENAI_MODEL = "gpt-3.5-turbo"
## https://beta.openai.com/tokenizer
#OPENAI_MAX_TOKENS = 4096
OPENAI_MAX_TOKENS = 400
async def get_response(messages: str, userid: str) -> str:
try:
data = json.dumps({
"model": OPENAI_MODEL,
"messages": messages,
"temperature": 0.5,
"top_p": 1.0,
"n": 1,
"stream": False,
"stop": None,
"max_tokens": OPENAI_MAX_TOKENS,
"presence_penalty": 0.0,
"frequency_penalty": 0.5,
"user": userid
})
headers = {
"Authorization": "Bearer " + OPENAI_API_KEY,
"Content-Type": "application/json",
}
async with aiohttp.ClientSession() as session:
async with session.post(
OPENAI_URL,
headers=headers,
data=data
) as response:
result = await response.text()
response = json.loads(result)
except:
raise fastapi.HTTPException(status_code=408, detail="🤖🗯️")
if "choices" in response:
if "message" in response["choices"][0]:
return response["choices"][0]["message"]["content"]
else:
raise fastapi.HTTPException(status_code=404, detail="🤖🗯️")
elif "error" in response:
raise fastapi.HTTPException(status_code=400, detail="🤖🗯️")
else:
raise fastapi.HTTPException(status_code=405, detail="🤖🗯️")
APP = fastapi.FastAPI(title=__name__)
@APP.on_event("startup")
async def startup_event():
print("INFO: ", OPENAI_MODEL)
"""
@APP.on_event("shutdown")
def shutdown_event():
print("Bye!")
"""
@APP.get("/chat") ## /chat?f=56900000000&q=Hola+Vito /chat?q=Hola+Vito
async def chat(q: str, f: typing.Optional[str] = ""):
api_request_from = f.strip()
api_request = q.strip()
if api_request_from and api_request_from is not None:
userid = str(api_request_from)
bfile_path = pathlib.Path("wspReq.json")
blackList = []
if bfile_path.exists():
with open(bfile_path, "r") as bfile:
blackList = json.load(bfile)["BlackList"]
if api_request_from in str(blackList):
raise fastapi.HTTPException(status_code=401, detail="📵")
#file_path = pathlib.Path("./wspHistory/" + api_request_from + ".wspoai")
file_path = pathlib.Path(api_request_from + ".wspoai")
print(" FROM_ID:", api_request_from)
else:
userid = "noneID"
if not api_request:
raise fastapi.HTTPException(status_code=400, detail="🤖💭")
print("FROM_MSG:", api_request)
#now = datetime.datetime.now()
now = datetime.datetime.now(datetime.timezone.utc).astimezone()
days_months = {
"Monday": "Lunes",
"Tuesday": "Martes",
"Wednesday": "Miércoles",
"Thursday": "Jueves",
"Friday": "Viernes",
"Saturday": "Sábado",
"Sunday": "Domingo",
"January": "Enero",
"February": "Febrero",
"March": "Marzo",
"April": "Abril",
"May": "Mayo",
"June": "Junio",
"July": "Julio",
"August": "Agosto",
"September": "Septiembre",
"October": "Octubre",
"November": "Noviembre",
"December": "Diciembre",
}
get_day = days_months[now.strftime("%A")]
get_month = days_months[now.strftime("%B")]
get_date = now.strftime("%d de " + get_month + " del %Y")
get_hours = now.strftime("%H:%M")
chat_format = []
chat_format = json.loads(
'[{"role": "system", "content": "' + (
"La siguiente es una conversación en WhatsApp"
" con un asistente virtual,"
" respondiendo en lugar de Vito,"
" quien no puede participar en este momento."
" El asistente es ingenioso y astuto,"
" pero puede ser un poco brusco con"
" sus respuestas sarcásticas a las preguntas planteadas."
" Hoy es {}, {}, y actualmente son las {} horas de Chile."
" En la conversacion se pueden utilizar emojis y texto con formato."
).format(get_day, get_date, get_hours) + '"}]'
)
## History
if api_request_from and api_request_from is not None:
if file_path.exists():
with open(file_path, "r") as rfile:
chat_format_msg = json.load(rfile)
chat_format = chat_format + chat_format_msg
##
chat_format.append({"role": "user", "content": f"{api_request}"})
api_response = await asyncio.create_task(get_response(chat_format, userid))
api_response = api_response.strip()
if api_response:
chat_format.append({"role": "assistant", "content": f"{api_response}"})
## History
if api_request_from and api_request_from is not None:
del chat_format[0]
with open(file_path, "w") as wfile:
json.dump(chat_format, wfile, indent=1, separators=(',', ': '))
##
return fastapi.Response(content="🤖💬 " + api_response, media_type="plain/text")
"""
${CURL:-curl} --request GET --url 'https://api.openai.com/v1/models' --header "Authorization: Bearer ${OPENAI_API_KEY:?}" |${JQ-jq} '.data[].id' - 2>/dev/null |${SED:-sed} -e 's#^"##g' -e 's#"$##g'
"""
#!/usr/bin/env python3
# -*- coding:utf-8 -*-
"""
[!] https://github.com/danielgross/whatsapp-gpt
56900000000.wspoai
$ mkdir wspHistory
$ echo '{ "BlackList": ["56900000001", "56900000004"] }' > wspReq.json
$ uvicorn oaiRes:APP --host 127.0.0.1 --port 5001 --reload
"""
import fastapi ## uvicorn
import asyncio
import aiohttp
import json
import datetime
import typing
import pathlib
#import re
import os
## OpenAI API Completions - Chat
## https://beta.openai.com/examples/default-chat
## https://beta.openai.com/docs/api-reference/completions/create
OPENAI_URL = "https://api.openai.com/v1/completions"
## https://beta.openai.com/account/api-keys
#OPENAI_API_KEY = "sk-aBcD...xYZ"
OPENAI_API_KEY = os.environ["OPENAI_API_KEY"]
## https://platform.openai.com/docs/models/models
OPENAI_MODEL = "text-davinci-003"
#OPENAI_MODEL = "text-babbage-001"
## https://beta.openai.com/tokenizer
#OPENAI_MAX_TOKENS = 4000
OPENAI_MAX_TOKENS = 400
async def get_response(prompt: str) -> str:
try:
data = json.dumps({
"stop": ["Humano:", "Asistente:"],
"frequency_penalty": 0.5,
"presence_penalty": 0.0,
"top_p": 1.0,
"temperature": 0.5,
"model": OPENAI_MODEL,
"max_tokens": OPENAI_MAX_TOKENS,
"echo": False,
"n": 1,
"best_of": 1,
"logprobs": None,
"stream": False,
"prompt": prompt,
})
headers = {
"Authorization": "Bearer " + OPENAI_API_KEY,
"Content-Type": "application/json",
}
async with aiohttp.ClientSession() as session:
async with session.post(
OPENAI_URL,
headers=headers,
data=data
) as response:
result = await response.text()
response = json.loads(result)
except:
raise fastapi.HTTPException(status_code=408, detail="🤖🗯️")
if "choices" in response:
return response["choices"][0]["text"]
elif "error" in response:
raise fastapi.HTTPException(status_code=400, detail="🤖🗯️")
else:
raise fastapi.HTTPException(status_code=405, detail="🤖🗯️")
APP = fastapi.FastAPI(title=__name__)
@APP.on_event("startup")
async def startup_event():
print("INFO: ", OPENAI_MODEL)
"""
@APP.on_event("shutdown")
def shutdown_event():
print("Bye!")
"""
@APP.get("/chat") ## /chat?f=56900000000&q=Hola+Vito /chat?q=Hola+Vito
async def chat(q: str, f: typing.Optional[str] = ""):
api_request_from = f.strip()
api_request = q.strip()
if api_request_from and api_request_from is not None:
bfile_path = pathlib.Path("wspReq.json")
blackList = []
if bfile_path.exists():
with open(bfile_path, "r") as bfile:
blackList = json.load(bfile)["BlackList"]
if api_request_from in str(blackList):
raise fastapi.HTTPException(status_code=401, detail="📵")
#file_path = pathlib.Path("./wspHistory/" + api_request_from + ".wspoai")
file_path = pathlib.Path(api_request_from + ".wspoai")
print(" FROM_ID:", api_request_from)
if not api_request:
raise fastapi.HTTPException(status_code=400, detail="🤖💭")
print("FROM_MSG:", api_request)
#now = datetime.datetime.now()
now = datetime.datetime.now(datetime.timezone.utc).astimezone()
days_months = {
"Monday": "Lunes",
"Tuesday": "Martes",
"Wednesday": "Miércoles",
"Thursday": "Jueves",
"Friday": "Viernes",
"Saturday": "Sábado",
"Sunday": "Domingo",
"January": "Enero",
"February": "Febrero",
"March": "Marzo",
"April": "Abril",
"May": "Mayo",
"June": "Junio",
"July": "Julio",
"August": "Agosto",
"September": "Septiembre",
"October": "Octubre",
"November": "Noviembre",
"December": "Diciembre",
}
get_day = days_months[now.strftime("%A")]
get_month = days_months[now.strftime("%B")]
get_date = now.strftime("%d de " + get_month + " del %Y")
get_hours = now.strftime("%H:%M")
chat_format = []
chat_format = json.loads(
'[{"role": "system", "content": "' + (
"La siguiente es una conversación en WhatsApp"
" con un asistente virtual,"
" respondiendo en lugar de Vito,"
" quien no puede participar en este momento."
" El asistente es ingenioso y astuto,"
" pero puede ser un poco brusco con"
" sus respuestas sarcásticas a las preguntas planteadas."
" Hoy es {}, {}, y actualmente son las {} horas de Chile."
" En la conversacion se pueden utilizar emojis y texto con formato."
).format(get_day, get_date, get_hours) + '"}]'
)
## History
if api_request_from and api_request_from is not None:
if file_path.exists():
with open(file_path, "r") as rfile:
chat_format_msg = json.load(rfile)
chat_format = chat_format + chat_format_msg
else:
chat_format.append({"role": "user", "content": "¡Hola!"})
chat_format.append({"role": "assistant", "content": "Hola, ¿en qué puedo ayudarte?"})
else:
##
chat_format.append({"role": "user", "content": "¡Hola!"})
chat_format.append({"role": "assistant", "content": "Hola, ¿en qué puedo ayudarte?"})
chat_format.append({"role": "user", "content": f"{api_request}"})
chat_plain_format = ""
for item in range(len(chat_format)):
item_role = chat_format[item]["role"].upper()
item_content = chat_format[item]["content"] + "\n"
if item_role == "SYSTEM":
item_role = ""
elif item_role == "USER":
item_role = "Humano: "
elif item_role == "ASSISTANT":
item_role = "Asistente: "
chat_plain_format = chat_plain_format + item_role + item_content
chat_plain_format = chat_plain_format + "Asistente:"
api_response = await asyncio.create_task(get_response(chat_plain_format.strip()))
api_response = api_response.lstrip("Asistente: ").strip().lstrip("Asistente: ").strip()
#api_response = re.sub(r"^\n+IA: ", "", api_response)
#api_response = re.sub(r"^\n+", "", api_response)
#api_response = re.sub(r"^ ", "", api_response)
if api_response:
chat_format.append({"role": "assistant", "content": f"{api_response}"})
## History
if api_request_from and api_request_from is not None:
del chat_format[0]
with open(file_path, "w") as wfile:
json.dump(chat_format, wfile, indent=1, separators=(',', ': '))
##
return fastapi.Response(content="🤖💬 " + api_response, media_type="plain/text")
"""
${CURL:-curl} --request GET --url 'https://api.openai.com/v1/models' --header "Authorization: Bearer ${OPENAI_API_KEY:?}" |${JQ-jq} '.data[].id' - 2>/dev/null |${SED:-sed} -e 's#^"##g' -e 's#"$##g'
"""
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment