Skip to content

Commit

Permalink
Merge pull request #3 from talkdai/feature/phone-number-independency
Browse files Browse the repository at this point in the history
Fixes independency for phone numbers
  • Loading branch information
vmesel authored Feb 19, 2024
2 parents a7867a9 + 39af6b1 commit e775b96
Show file tree
Hide file tree
Showing 10 changed files with 312 additions and 22 deletions.
162 changes: 162 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# C extensions
*.so

# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST

# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/

# Translations
*.mo
*.pot

# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal

# Flask stuff:
instance/
.webassets-cache

# Scrapy stuff:
.scrapy

# Sphinx documentation
docs/_build/

# PyBuilder
.pybuilder/
target/

# Jupyter Notebook
.ipynb_checkpoints

# IPython
profile_default/
ipython_config.py

# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version

# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock

# poetry
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
#poetry.lock

# pdm
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
#pdm.lock
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
# in version control.
# https://pdm.fming.dev/#use-with-ide
.pdm.toml

# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
__pypackages__/

# Celery stuff
celerybeat-schedule
celerybeat.pid

# SageMath parsed files
*.sage.py

# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/

# Spyder project settings
.spyderproject
.spyproject

# Rope project settings
.ropeproject

# mkdocs documentation
/site

# mypy
.mypy_cache/
.dmypy.json
dmypy.json

# Pyre type checker
.pyre/

# pytype static type analyzer
.pytype/

# Cython debug symbols
cython_debug/

# PyCharm
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/
data/db/
data/
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -174,4 +174,5 @@ poetry.toml
pyrightconfig.json

# End of https://www.toptal.com/developers/gitignore/api/python
n
n
project_config.toml
11 changes: 11 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
FROM ghcr.io/talkdai/dialog:latest

# Copy the plugin code
WORKDIR /plugin
COPY . .

RUN pip install -e .

WORKDIR /app/src/

RUN mkdir /app/static
50 changes: 38 additions & 12 deletions main.py → dialog_whatsapp/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,22 @@
import hashlib

from typing import Any
from dialog.llm import get_llm_class
from fastapi import APIRouter, Body, HTTPException, Query, Depends, Request
from openai import OpenAI

from .settings import (
WHATSAPP_API_TOKEN,
WHATSAPP_ACCOUNT_NUMBER,
API_HOST
WHATSAPP_VERIFY_TOKEN,
API_HOST,
PROJECT_CONFIG,
DATASET,
OPENAI_API_KEY,
ROUTE_SUFFIX
)
from dialog.settings import PROJECT_CONFIG
from dialog.llm.default import DialogLLM

from dialog.models.helpers import create_session
from plugins.whats_audio.responses import whatsapp_get_response
from uuid import uuid4

client = OpenAI()
Expand Down Expand Up @@ -84,22 +87,33 @@ def transcribe_audio(audio_id):
logger.info(f"Got transcript back from OpenAI - {transcript}")
return transcript.text

@router.get("/whats-audio")
@router.get(f"/tenant-{ROUTE_SUFFIX}")
async def whats_audio_get(request: Request):
content = await whatsapp_get_response(request)
return content
logging.info(request.query_params.get("hub.verify_token"))
logging.info(WHATSAPP_VERIFY_TOKEN)
if request.query_params.get("hub.verify_token") == WHATSAPP_VERIFY_TOKEN:
return int(request.query_params.get("hub.challenge"))

@router.post("/whats-audio")
raise HTTPException(status_code=404)

@router.post(f"/tenant-{ROUTE_SUFFIX}")
async def whats_audio_post(body: Any = Body(None)):
logger.info("Started")
value = body["entry"][0]["changes"][0]["value"]
logging.info("Body: ", body)

try:
from_number = value["messages"][0]["from"]
message_type = value["messages"][0].get("type")
except KeyError:
return {}

phone_number_id = value["metadata"]["phone_number_id"]
logging.info(f"Got message for number {phone_number_id}")
if phone_number_id != WHATSAPP_ACCOUNT_NUMBER:
logger.info("Phone number not supported")
return {"status": "success"}

if message_type not in ["audio", "text"]:
logger.info("Message type not supported")
send_text_to_whatsapp("Ainda não consigo entender este tipo de mensagem", from_number)
Expand All @@ -114,10 +128,19 @@ async def whats_audio_post(body: Any = Body(None)):

logger.info(f"Got message from {from_number} - message: {message}")

create_session(identifier=from_number)
session_id = from_number
if DATASET:
session_id = f"{DATASET}_{from_number}"

create_session(identifier=session_id)

LLM = get_llm_class()
llm = LLM(config=PROJECT_CONFIG, session_id=from_number)
llm = DialogLLM(
config=PROJECT_CONFIG,
session_id=session_id,
dataset=DATASET,
llm_key=OPENAI_API_KEY
)
logger.info(f"Project config: {PROJECT_CONFIG}")
processed_message = llm.process(message)
processed_message = processed_message["text"]
logger.info("Processed message: %s", processed_message)
Expand All @@ -141,4 +164,7 @@ async def whats_audio_post(body: Any = Body(None)):
else:
send_text_to_whatsapp(processed_message, from_number)

return {}
return {}

def register_plugin(app):
app.include_router(router, prefix="/whatsapp")
5 changes: 2 additions & 3 deletions responses.py → dialog_whatsapp/responses.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
WHATSAPP_VERIFY_TOKEN,
WHATSAPP_API_TOKEN,
WHATSAPP_ACCOUNT_NUMBER,
PROJECT_CONFIG
)
from dialog.settings import PROJECT_CONFIG

from dialog.models.helpers import create_session

Expand All @@ -26,7 +26,6 @@ async def whatsapp_get_response(request):

raise HTTPException(status_code=404)


async def whatsapp_post_response(request, body):
value = body["entry"][0]["changes"][0]["value"]
try:
Expand All @@ -41,7 +40,7 @@ async def whatsapp_post_response(request, body):
"Authorization": f"Bearer {WHATSAPP_API_TOKEN}",
"Content-Type": "application/json",
}
url = f"https://graph.facebook.com/v17.0/{WHATSAPP_ACCOUNT_NUMBER}/messages"
url = f"https://graph.facebook.com/v17.0/{phone_number_id}/messages"

create_session(identifier=from_number)

Expand Down
36 changes: 36 additions & 0 deletions dialog_whatsapp/settings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import os
import json
import tomllib
import logging

from pathlib import Path
from decouple import config
from dialog.settings import PROJECT_CONFIG as DIALOG_PROJECT_CONFIG

file_path = os.path.abspath(__file__)
dir_path = os.path.dirname(file_path)

if "config.json" in os.listdir(dir_path):
logging.info("Loading config file")
config_json = json.load(open(dir_path + "/config.json"))
WHATSAPP_VERIFY_TOKEN = config_json.get("WHATSAPP_VERIFY_TOKEN", "1234567890")
WHATSAPP_API_TOKEN = config_json.get("WHATSAPP_API_TOKEN", "1234567890")
WHATSAPP_ACCOUNT_NUMBER = config_json.get("WHATSAPP_ACCOUNT_NUMBER", "")
API_HOST = config_json.get("API_HOST")
PROJECT_CONFIG = tomllib.loads(Path(dir_path + "/" + config_json.get("PROJECT_CONFIG")).read_text())
DATASET = config_json.get("DATASET")
OPENAI_API_KEY = config_json.get("OPENAI_API_KEY")
ROUTE_SUFFIX = config_json.get("ROUTE_SUFFIX")
else:
WHATSAPP_VERIFY_TOKEN = config("WHATSAPP_VERIFY_TOKEN", "1234567890")
WHATSAPP_API_TOKEN = config("WHATSAPP_API_TOKEN", "1234567890")
WHATSAPP_ACCOUNT_NUMBER = config("WHATSAPP_ACCOUNT_NUMBER", "")
API_HOST = config("API_HOST", "http://localhost:8000")
PROJECT_CONFIG = config(
"PROJECT_CONFIG",
cast=lambda filename: tomllib.loads(Path(filename).read_text()),
default={}
)
DATASET = config("DATASET", None)
OPENAI_API_KEY = config("OPENAI_API_KEY", None)
ROUTE_SUFFIX = 1
33 changes: 33 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
version: '3.3'
services:
db:
image: ankane/pgvector:latest
restart: always
ports:
- '5432:5432'
environment:
POSTGRES_USER: talkdai
POSTGRES_PASSWORD: talkdai
POSTGRES_DB: talkdai
volumes:
- ./data/db:/var/lib/postgresql/data
- ./etc/db-ext-vector.sql:/docker-entrypoint-initdb.d/db-ext-vector.sql
healthcheck:
test: ["CMD-SHELL", "pg_isready", "-d", "talkdai", "-U", "talkdai"]
interval: 30s
timeout: 60s
retries: 5
start_period: 80s
dialog:
build: .
stdin_open: true
tty: true
ports:
- '8000:8000'
depends_on:
db:
condition: service_healthy
env_file:
- .env
volumes:
- ./data:/data/
13 changes: 13 additions & 0 deletions project_config.sample.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[model]
model = "gpt-3.5-turbo-1106"
temperature = 0.1

[prompt]
header = """Você está impersonando o Vitor, um operador de atendimento chamado Vitor."""
question_signalizer = "Responda a pergunta:"

fallback = """
Você está impersonando o Vitor, um operador de atendimento chamado Vitor.
Seja breve em suas respostas limitando-se ao máximo a 2 frases. Nunca fale que
você é um modelo (AI), assistente virtual ou qualquer coisa do genero.
"""
Loading

0 comments on commit e775b96

Please sign in to comment.