Skip to content

Commit

Permalink
chore: full tutorial review
Browse files Browse the repository at this point in the history
  • Loading branch information
leggetter committed Nov 18, 2024
1 parent bb41ba4 commit f60057e
Show file tree
Hide file tree
Showing 7 changed files with 201 additions and 118 deletions.
1 change: 1 addition & 0 deletions .env-example
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ MONGODB_CONNECTION_URI=""
# Hookdeck Project API Key
# Hookdeck Dashboard -> Settings -> Secrets
HOOKDECK_PROJECT_API_KEY=""
HOOKDECK_WEBHOOK_SECRET=

# Replicate API Token
REPLICATE_API_TOKEN=""
Expand Down
3 changes: 1 addition & 2 deletions allthethings/generators.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ def generate(self, id, text):


class SyncEmbeddingsGenerator:

def generate(self, text):
payload = {
"version": "b6b7585c9640cd7a9572c6e129c9549d79c9c31f0d3fdce7baac7c67ca38f305",
Expand All @@ -35,7 +34,7 @@ def generate(self, text):
"https://api.replicate.com/v1/predictions",
headers={**Config.REPLICATE_API_AUTH_HEADERS, "Prefer": "wait"},
json=payload,
timeout=60,
timeout=180,
)

return response.json()
62 changes: 51 additions & 11 deletions app.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
import httpx
from urllib.parse import urlparse
from bson import ObjectId
import hmac
import hashlib
import base64
from flask import Flask, jsonify, request, render_template, redirect, url_for, flash

from config import Config

from allthethings.mongo import Database
from allthethings.processors import get_asset_processor

from allthethings.generators import (
AsyncEmbeddingsGenerator,
SyncEmbeddingsGenerator,
Expand Down Expand Up @@ -136,18 +140,19 @@ def process():

@app.route("/search", methods=["GET"])
def search():
return render_template("search.html", results=[])


@app.route("/search", methods=["POST"])
def search_post():
query = request.form["query"]
query = request.args.get("query")
if query is None:
return render_template("search.html", results=[])

app.logger.info("Query submitted")
app.logger.debug(query)

results = query_vector_search(query)

if results is None:
flash("Search embeddings generation failed")
return redirect(url_for("search"))

results = format_results(results)

# TODO: look into warning logged here
Expand Down Expand Up @@ -194,8 +199,17 @@ def query_vector_search(q):
# Because the search is user-driven, we use the synchronous generator
generator = SyncEmbeddingsGenerator()

generator_response = generator.generate(q)
app.logger.debug(generator_response)
try:
generator_response = generator.generate(q)
app.logger.debug(generator_response)
except Exception as e:
app.logger.error("Error generating embeddings: %s", e)
return None

if generator_response["output"] is None:
app.logger.debug("Embeddings generation timed out")
return None

query_embedding = generator_response["output"][0]["embedding"]

app.logger.info("Query embedding generated")
Expand All @@ -205,8 +219,8 @@ def query_vector_search(q):
"index": "vector_index",
"path": "embedding",
"queryVector": query_embedding,
"numCandidates": 10,
"limit": 2,
"numCandidates": 100,
"limit": 10,
}

new_search_query = {"$vectorSearch": vs_query}
Expand Down Expand Up @@ -235,8 +249,30 @@ def query_vector_search(q):
return res


def verify_webhook(request):
if Config.HOOKDECK_WEBHOOK_SECRET is None:
app.logger.error("No HOOKDECK_WEBHOOK_SECRET found.")
return False

hmac_header = request.headers.get("x-hookdeck-signature")

hash = base64.b64encode(
hmac.new(
Config.HOOKDECK_WEBHOOK_SECRET.encode(), request.data, hashlib.sha256
).digest()
).decode()

verified = hash == hmac_header
app.logger.debug("Webhook signature verification: %s", verified)
return verified


@app.route("/webhooks/audio/<id>", methods=["POST"])
def webhook_audio(id):
if not verify_webhook(request):
app.logger.error("Webhook signature verification failed")
return jsonify({"error": "Webhook signature verification failed"}), 401

payload = request.json
app.logger.info("Audio payload received for id %s", id)
app.logger.debug(payload)
Expand Down Expand Up @@ -267,13 +303,17 @@ def webhook_audio(id):
app.logger.info("Transcription updated")
app.logger.debug(result)

request_embeddings(result["_id"])
request_embeddings(id)

return "OK"


@app.route("/webhooks/embedding/<id>", methods=["POST"])
def webhook_embeddings(id):
if not verify_webhook(request):
app.logger.error("Webhook signature verification failed")
return jsonify({"error": "Webhook signature verification failed"}), 401

payload = request.json
app.logger.info("Embeddings payload recieved")
app.logger.debug(payload)
Expand Down
1 change: 1 addition & 0 deletions config.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ class Config:
DB_NAME = "iaat"
COLLECTION_NAME = "assets"

HOOKDECK_WEBHOOK_SECRET = os.getenv("HOOKDECK_WEBHOOK_SECRET")
HOOKDECK_QUEUE_API_KEY_HEADER_NAME = "x-iaat-queue-api-key"
HOOKDECK_REPLICATE_API_QUEUE_API_KEY = os.getenv(
"HOOKDECK_REPLICATE_API_QUEUE_API_KEY"
Expand Down
2 changes: 1 addition & 1 deletion templates/search.html
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@

{% block content %}
<section>
<form action="/search" method="post" id="submit_form">
<form action="/search" method="get" id="submit_form">
<input required type="text" name="query" placeholder="Enter your search query" value="{{ query }}">
<button type="submit">Submit</button>
</form>
Expand Down
Loading

0 comments on commit f60057e

Please sign in to comment.