Sentry Support

This commit is contained in:
Vineeth Voruganti 2023-09-18 23:33:37 -04:00
parent 14920bbf04
commit 010778ff0f
7 changed files with 88 additions and 2 deletions

View File

@ -13,3 +13,8 @@ OPENAI_API_BASE=
OPENAI_API_VERSION=
OPENAI_API_DEPLOYMENT_NAME=
# Sentry
SENTRY_DSN=
SENTRY_ENVIRONMENT=
SENTRY_RELEASE=

View File

@ -8,26 +8,32 @@ import uuid
from typing import List
from langchain.schema import BaseMessage, Document
from pydantic import BaseModel
import sentry_sdk
class Conversation:
"Wrapper Class for storing contexts between channels. Using an object to pass by reference avoid additional cache hits"
@sentry_sdk.trace
def __init__(self, mediator: SupabaseMediator, user_id: str, conversation_id: str = str(uuid.uuid4()), location_id: str = "web"):
self.mediator: SupabaseMediator = mediator
self.user_id: str = user_id
self.conversation_id: str = conversation_id
self.location_id: str = location_id
@sentry_sdk.trace
def add_message(self, message_type: str, message: BaseMessage,) -> None:
self.mediator.add_message(self.conversation_id, self.user_id, message_type, message)
@sentry_sdk.trace
def messages(self, message_type: str) -> List[BaseMessage]:
return self.mediator.messages(self.conversation_id, self.user_id, message_type)
# vector DB fn
@sentry_sdk.trace
def add_texts(self, texts: List[str]) -> None:
metadatas = [{"conversation_id": self.conversation_id, "user_id": self.user_id} for _ in range(len(texts))]
self.mediator.vector_table.add_texts(texts, metadatas)
# vector DB fn
@sentry_sdk.trace
def similarity_search(self, query: str, match_count: int = 5) -> List[Document]:
return self.mediator.vector_table.similarity_search(query=query, k=match_count, filter={"user_id": self.user_id})

View File

@ -7,6 +7,7 @@ from dotenv import load_dotenv
from collections.abc import AsyncIterator
from cache import Conversation
from typing import List
import sentry_sdk
load_dotenv()
@ -40,6 +41,7 @@ class BloomChain:
pass
@classmethod
@sentry_sdk.trace
def think(cls, cache: Conversation, input: str):
"""Generate Bloom's thought on the user."""
# load message history
@ -58,6 +60,7 @@ class BloomChain:
)
@classmethod
@sentry_sdk.trace
def revise_thought(cls, cache: Conversation, input: str, thought: str):
"""Revise Bloom's thought about the user with retrieved personal data"""
@ -80,6 +83,7 @@ class BloomChain:
)
@classmethod
@sentry_sdk.trace
def respond(cls, cache: Conversation, thought: str, input: str):
"""Generate Bloom's response to the user."""
response_prompt = ChatPromptTemplate.from_messages([
@ -97,6 +101,7 @@ class BloomChain:
)
@classmethod
@sentry_sdk.trace
async def think_user_prediction(cls, cache: Conversation, input: str):
"""Generate a thought about what the user is going to say"""
@ -117,6 +122,7 @@ class BloomChain:
return user_prediction_thought.content
@classmethod
@sentry_sdk.trace
async def revise_user_prediction_thought(cls, cache: Conversation, user_prediction_thought: str, input: str):
"""Revise the thought about what the user is going to say based on retrieval of VoE facts"""
@ -142,6 +148,7 @@ class BloomChain:
@classmethod
@sentry_sdk.trace
async def think_violation_of_expectation(cls, cache: Conversation, inp: str, user_prediction_thought_revision: str) -> None:
"""Assess whether expectation was violated, derive and store facts"""
@ -161,6 +168,7 @@ class BloomChain:
return voe_thought.content
@classmethod
@sentry_sdk.trace
async def violation_of_expectation(cls, cache: Conversation, inp: str, user_prediction_thought_revision: str, voe_thought: str) -> None:
"""Assess whether expectation was violated, derive and store facts"""
@ -185,6 +193,7 @@ class BloomChain:
return facts
@classmethod
@sentry_sdk.trace
async def check_voe_list(cls, cache: Conversation, facts: List[str]):
"""Filter the facts to just new ones"""
@ -218,6 +227,7 @@ class BloomChain:
cache.add_texts(data)
@classmethod
@sentry_sdk.trace
async def chat(cls, cache: Conversation, inp: str ) -> tuple[str, str]:
# VoE has to happen first. If there's user prediction history, derive and store fact(s)
if cache.messages('user_prediction_thought_revision'):
@ -246,6 +256,7 @@ class BloomChain:
return thought, response
@classmethod
@sentry_sdk.trace
async def stream(cls, cache: Conversation, inp: str ):
# VoE has to happen first. If there's user prediction history, derive and store fact(s)
try:

View File

@ -8,9 +8,18 @@ from chain import BloomChain
from mediator import SupabaseMediator
from cache import Conversation
import os
from dotenv import load_dotenv
import sentry_sdk
load_dotenv()
rate = 0.2 if os.getenv("SENTRY_ENVIRONMENT") == "production" else 1.0
sentry_sdk.init(
dsn=os.environ['SENTRY_DSN'],
traces_sample_rate=rate,
profiles_sample_rate=rate
)
app = FastAPI()
MEDIATOR = SupabaseMediator()

View File

@ -5,7 +5,7 @@ from langchain.vectorstores import SupabaseVectorStore
from langchain.embeddings.base import Embeddings
from langchain.embeddings.openai import OpenAIEmbeddings
import uuid
import urllib
import sentry_sdk
import os
from dotenv import load_dotenv
# Supabase for Postgres Management
@ -16,6 +16,8 @@ import json
load_dotenv()
class SupabaseMediator:
@sentry_sdk.trace
def __init__(self):
self.supabase: Client = create_client(os.environ['SUPABASE_URL'], os.environ['SUPABASE_KEY'])
self.memory_table = os.environ["MEMORY_TABLE"]
@ -42,15 +44,18 @@ class SupabaseMediator:
# self.vector_table.add_documents(seed_docs)
@sentry_sdk.trace
def messages(self, session_id: str, user_id: str, message_type: str) -> List[BaseMessage]: # type: ignore
response = self.supabase.table(self.memory_table).select("message").eq("session_id", session_id).eq("user_id", user_id).eq("message_type", message_type).order("id", desc=True).limit(10).execute()
items = [record["message"] for record in response.data]
messages = messages_from_dict(items)
return messages[::-1]
@sentry_sdk.trace
def add_message(self, session_id: str, user_id: str, message_type: str, message: BaseMessage) -> None:
self.supabase.table(self.memory_table).insert({"session_id": session_id, "user_id": user_id, "message_type": message_type, "message": _message_to_dict(message)}).execute()
@sentry_sdk.trace
def conversations(self, location_id: str, user_id: str) -> str | None:
response = self.supabase.table(self.conversation_table).select("id").eq("location_id", location_id).eq("user_id", user_id).eq("isActive", True).maybe_single().execute()
if response:
@ -58,11 +63,13 @@ class SupabaseMediator:
return conversation_id
return None
@sentry_sdk.trace
def add_conversation(self, location_id: str, user_id: str) -> str:
conversation_id = str(uuid.uuid4())
self.supabase.table(self.conversation_table).insert({"id": conversation_id, "user_id": user_id, "location_id": location_id}).execute()
return conversation_id
@sentry_sdk.trace
def delete_conversation(self, conversation_id: str) -> None:
self.supabase.table(self.conversation_table).update({"isActive": False}).eq("id", conversation_id).execute()

49
poetry.lock generated
View File

@ -1289,6 +1289,53 @@ urllib3 = ">=1.21.1,<3"
socks = ["PySocks (>=1.5.6,!=1.5.7)"]
use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"]
[[package]]
name = "sentry-sdk"
version = "1.31.0"
description = "Python client for Sentry (https://sentry.io)"
category = "main"
optional = false
python-versions = "*"
files = [
{file = "sentry-sdk-1.31.0.tar.gz", hash = "sha256:6de2e88304873484207fed836388e422aeff000609b104c802749fd89d56ba5b"},
{file = "sentry_sdk-1.31.0-py2.py3-none-any.whl", hash = "sha256:64a7141005fb775b9db298a30de93e3b83e0ddd1232dc6f36eb38aebc1553291"},
]
[package.dependencies]
certifi = "*"
fastapi = {version = ">=0.79.0", optional = true, markers = "extra == \"fastapi\""}
urllib3 = {version = ">=1.26.11", markers = "python_version >= \"3.6\""}
[package.extras]
aiohttp = ["aiohttp (>=3.5)"]
arq = ["arq (>=0.23)"]
asyncpg = ["asyncpg (>=0.23)"]
beam = ["apache-beam (>=2.12)"]
bottle = ["bottle (>=0.12.13)"]
celery = ["celery (>=3)"]
chalice = ["chalice (>=1.16.0)"]
clickhouse-driver = ["clickhouse-driver (>=0.2.0)"]
django = ["django (>=1.8)"]
falcon = ["falcon (>=1.4)"]
fastapi = ["fastapi (>=0.79.0)"]
flask = ["blinker (>=1.1)", "flask (>=0.11)", "markupsafe"]
grpcio = ["grpcio (>=1.21.1)"]
httpx = ["httpx (>=0.16.0)"]
huey = ["huey (>=2)"]
loguru = ["loguru (>=0.5)"]
opentelemetry = ["opentelemetry-distro (>=0.35b0)"]
opentelemetry-experimental = ["opentelemetry-distro (>=0.40b0,<1.0)", "opentelemetry-instrumentation-aiohttp-client (>=0.40b0,<1.0)", "opentelemetry-instrumentation-django (>=0.40b0,<1.0)", "opentelemetry-instrumentation-fastapi (>=0.40b0,<1.0)", "opentelemetry-instrumentation-flask (>=0.40b0,<1.0)", "opentelemetry-instrumentation-requests (>=0.40b0,<1.0)", "opentelemetry-instrumentation-sqlite3 (>=0.40b0,<1.0)", "opentelemetry-instrumentation-urllib (>=0.40b0,<1.0)"]
pure-eval = ["asttokens", "executing", "pure-eval"]
pymongo = ["pymongo (>=3.1)"]
pyspark = ["pyspark (>=2.4.4)"]
quart = ["blinker (>=1.1)", "quart (>=0.16.1)"]
rq = ["rq (>=0.6)"]
sanic = ["sanic (>=0.8)"]
sqlalchemy = ["sqlalchemy (>=1.2)"]
starlette = ["starlette (>=0.19.1)"]
starlite = ["starlite (>=1.48)"]
tornado = ["tornado (>=5)"]
[[package]]
name = "six"
version = "1.16.0"
@ -1798,4 +1845,4 @@ multidict = ">=4.0"
[metadata]
lock-version = "2.0"
python-versions = "^3.9"
content-hash = "8ccc4a9baa19404ab5a5c62d06ad07b760f17df6a7d6bc045f34bc38a45ab2bc"
content-hash = "79b717a6de797aab0ceb534b8ecf0b99ad17c2687ed0a2c8d6d97766ddf6d0e5"

View File

@ -16,6 +16,7 @@ openai = "^0.28.0"
pydantic = "^2.3.0"
python-dotenv = "^1.0.0"
uvicorn = "^0.23.2"
sentry-sdk = {extras = ["fastapi"], version = "^1.31.0"}
[build-system]