Sebastien Rousseau

Àkàndé: GPT-Powered Voice Assistant for Executives

Ìpilẹ̀ṣẹ̀ olùrànlọ́wọ́ ohùn Python tí a ṣí silẹ̀: Whisper, GPT-4, SQLite cache, àti fpdf2

7 ìṣẹ́jú kíkà
Banner for: Àkàndé: GPT-Powered Voice Assistant for Executives

Àkopọ Alàgbà / Àwọn Ohun Pàtàkì Tí A Kọ́

  • Àkàndé ⧉ jẹ olùrànlọ́wọ́ ohùn Python orisun ṣíṣí tí ó ṣe ìjọpọ OpenAI Whisper ọrọ-sí-ọrọ-kíkọ, GPT-4 chat completions, àpèjọ ìdáhùn SQLite ìbílẹ̀, àti ìgbé jáde PDF fpdf2 sínú ìlànà iṣẹ́ ìdánilọ́kàn ohùn ẹyọkan tí kò nilo àkójọpọ àwọsanma àti iwuwo àwòdàlẹ̀ AI ìbílẹ̀.
  • Àpèjọ SQLite ń tọ́jú SHA-256 hashes ti awọn okun ibeere tí a ṣe idiwọn tí a ya sọ́tọ̀ pẹ̀lú ọrọ ìdáhùn API aise; àwọn àbáwọ̀n àpèjọ kò ná token àti padà wá ní ìsàlẹ̀ 10 ms, tí ó ṣe àwọn ibeere tí a tún ṣe (bí àtúnyẹwò ìpinnu láti ìbẹ̀rẹ̀ ìpàdé) ní pàtó ọ̀fẹ́.
  • Ìfọ̀rọ̀wérọ̀ ìlọ-padà ni a tọ́jú nípa ṣíṣẹ̀dá àtòjọ messages ní ìrántí àti ṣíṣe ì fún rẹ̀ lórí gbogbo ìpè Chat Completions API — àwòdàlẹ̀ n gba ìtàn ìpàdé kíkún kí ó le tọ̀ka sí àwọn pàṣipọ̀ iṣájú, ní ìdíyelé ìlọsíwájú ìlọ sókè lílò token nígbà gbogbo ìyípadà.
  • Ìpilẹ̀ṣẹ̀ àkopọ PDF ń ṣe jẹ́jẹ́ àtòjọ messages ìpàdé sí ìwé fpdf2 tí a ṣàfọ̀mọ̀: a fi àmì sí àwọn ìyípadà olùmúlò àti olùrànlọ́wọ́, a fi àwọn àmì àkókò sínú, àti ìdìpò ìwé àdáṣe ń bójú tó àwọn ìpàdé tí ó pọ̀ to; a kọ fáìlì sí ètò fáìlì ìbílẹ̀, a kò gbé e sókè.
  • Ààlà ìkọ̀kọ̀: ibeere tààrà nìkan (àti ìtàn ìpàdé sí ààlà fèrèsé ọ̀rọ̀ àsọye) ń kúrò ní ẹ̀rọ — a kò rán àwọn gbàdúrà ohùn, ìgbasilẹ, àti àwọn ìdáhùn tí a tọ́jú ní àpèjọ sí iṣẹ́ ìjìnnà kankan fàìsí API OpenAI.

Àkàndé ⧉ jẹ olùrànlọ́wọ́ ohùn Python orisun ṣíṣí tí a ṣe ní àyíká ẹ̀ka mẹta tí a lè ṣe ìjọpọ: OpenAI Whisper fún ìdámọ̀ ọrọ, GPT-4 Chat Completions API fún agbọye àti ṣíṣe ede, àti àkójọpọ ìdáhùn SQLite ìbílẹ̀ fún àpèjọ ìdáhùn àti ìdúró ìpàdé. Àbájáde jẹ ìlànà iṣẹ́ ìdánilọ́kàn ohùn tí a lè ṣe nínú kọmputa lápi láìsí iwuwo àwòdàlẹ̀ ìbílẹ̀, àwọn àwọn ẹ̀rọ àkójọpọ àti ẹ̀rọ aféfé.

Àpilẹ̀kọ yìí ṣàpèjúwe ọ̀nà àbáyọ ìmọ̀ ẹrọ ti ẹ̀ka kọọkan, àwọn ìpinnu ìṣètò tí ó yípo àpèjọ àti ọ̀rọ̀ àsọye ìlọ-padà, àti ìlànà ìgbé jáde PDF.

Àkopọ Ìlànà #

Ìbáṣepọ̀ Àkàndé ẹyọkan ń tẹle ọ̀nà àtẹle yìí:

  1. Àṣàpamọ́ ohùn — olùmúlò ń sọ; ohun èlò ń gbàsilẹ ohùn sí fáìlì WAV ìgbàní ní lílo sounddevice tàbí ibi ìkóhun ohùn tó bá mu.
  2. Ọrọ-sí-ọrọ-kíkọ — a fi fáìlì WAV sí openai.audio.transcriptions.create() (Whisper API); a pada ìgbasilẹ gẹ́gẹ́ bí okun aṣa.
  3. Ìwádìí àpèjọ — a ṣe idiwọn ìgbasilẹ (a ṣe lẹta kékeré, a ṣe àmúkò àlàfo) àti SHA-256 hashed; a wá hash ní tábìlì SQLite response_cache ìbílẹ̀.
  4. Ìpè API tàbí àbáwọ̀n àpèjọ — lórí àdánù, a ṣafikun ìgbasilẹ sí àtòjọ messages ìpàdé àti fún un sí openai.chat.completions.create(); a tọ́jú ọrọ ìdáhùn ní àpèjọ.
  5. Ọrọ-sí-ohùn — a yí ọrọ ìdáhùn padà sí ohùn ní lílo endpoint openai.audio.speech.create() (TTS) tàbí ibi ìkóhun TTS ìbílẹ̀, a sì tún ṣe.
  6. Ìgbé jáde PDF (lórí ìbéèrè) — a ṣe jẹ́jẹ́ àtòjọ messages kíkún sí ìwé fpdf2 tí a ṣàfọ̀mọ̀ àti kọ sí diski.

Ìṣọpọ OpenAI: Chat Completions àti Whisper #

Àkàndé ń lo Python SDK openai fún ìdámọ̀ ọrọ àti ṣíṣe ọrọ. Ìpè ìgbasilẹ Whisper:

with open(audio_file_path, "rb") as f:
    transcript = openai.audio.transcriptions.create(
        model="whisper-1",
        file=f,
        language=None  # auto-detect
    )
user_text = transcript.text

Ìpè Chat Completions ń tọ́jú àtòjọ messages tí a ṣe ní àwọn ìpàdé:

messages.append({"role": "user", "content": user_text})

response = openai.chat.completions.create(
    model="gpt-4-turbo-preview",
    messages=messages,
    temperature=0.2,
    max_tokens=1024
)

assistant_text = response.choices[0].message.content
messages.append({"role": "assistant", "content": assistant_text})

A fi ìbéèrè ètò kọ ẹ̀ẹ̀kan ní ìbẹ̀rẹ̀ ìpàdé àti ń ṣàkóso ènìyàn Àkàndé, ọ̀nà ìṣafilọ, àti àwọn ìdíwọ̀n pàtàkì ti ìmọ̀ aapọn:

messages = [
    {
        "role": "system",
        "content": (
            "You are Àkàndé, a concise executive assistant. "
            "Respond in plain prose. Do not use markdown. "
            "If asked to summarise, produce three bullet points maximum."
        )
    }
]

Ṣíṣeto temperature=0.2 ń pàṣipàṣi ìyípadà ìdásílẹ̀ fún ìpinnu — pàtàkì fún àwọn ibeere àlàyé bí iranti ìpinnu láti ìbẹ̀rẹ̀ ìpàdé.

Àpèjọ Ìdáhùn SQLite #

Ìlànà àpèjọ jẹ ìsàlẹ̀ kékeré:

CREATE TABLE IF NOT EXISTS response_cache (
    query_hash  TEXT PRIMARY KEY,
    response    TEXT NOT NULL,
    created_at  INTEGER NOT NULL  -- Unix timestamp
);

Ọ̀nà ìwádìí àti kíkọ:

import hashlib, sqlite3, time

def _normalise(text: str) -> str:
    return " ".join(text.lower().split())

def cache_get(conn: sqlite3.Connection, query: str) -> str | None:
    h = hashlib.sha256(_normalise(query).encode()).hexdigest()
    row = conn.execute(
        "SELECT response FROM response_cache WHERE query_hash = ?", (h,)
    ).fetchone()
    return row[0] if row else None

def cache_set(conn: sqlite3.Connection, query: str, response: str) -> None:
    h = hashlib.sha256(_normalise(query).encode()).hexdigest()
    conn.execute(
        "INSERT OR REPLACE INTO response_cache VALUES (?, ?, ?)",
        (h, response, int(time.time()))
    )
    conn.commit()

INSERT OR REPLACE ń rí dájú pé a ṣe ìmúdójúìwọ̀n ìdáhùn tí a tọ́jú ní àpèjọ tí a bá fi ibeere kanna ránṣẹ́ lẹ́yìn ìgbé àwòdàlẹ̀ ga. A lè ṣètò ibeere ìlọ́kọ́ tí o da lórí TTL (DELETE WHERE created_at < ?) lórí ìbẹ̀rẹ̀ láti fi opin si iwọn àpèjọ.

Iṣẹ́ àbáwọ̀n àpèjọ: ìwádìí SQLite lórí SSD ìbílẹ̀ padà wá ní ìsàlẹ̀ 1 ms fún àwọn tábìlì sí ~100,000 ìlà. Ìdádúró ìrìnàjò ìpè API GPT-4 tààrà jẹ 600–900 ms ní gbogbogbo fún àwọn ìdáhùn kúkúrú. Fún ìpínrọ̀ ojoojumọ́ pẹ̀lú ọ̀pọ̀ àwọn ibeere tí a tún ṣe, àpèjọ ń mú jáde ọpọlọpọ àwọn ìpè API lẹ́yìn ìpàdé àkọkọ.

Ìpilẹ̀ṣẹ̀ Àkopọ PDF #

Ìgbé jáde PDF ń lo fpdf2, ibi ìkóhun Python PDF tí a ń tọ́jú láìsí àwọn ìgbẹkẹle binary:

from fpdf import FPDF
from datetime import datetime

def export_session_pdf(messages: list[dict], output_path: str) -> None:
    pdf = FPDF()
    pdf.add_page()
    pdf.set_font("Helvetica", size=11)
    pdf.set_margins(20, 20, 20)

    pdf.set_font("Helvetica", "B", 14)
    pdf.cell(0, 10, f"Àkàndé Session — {datetime.now():%Y-%m-%d %H:%M}", ln=True)
    pdf.ln(4)

    for msg in messages:
        if msg["role"] == "system":
            continue
        label = "You" if msg["role"] == "user" else "Àkàndé"
        pdf.set_font("Helvetica", "B", 10)
        pdf.cell(0, 6, label, ln=True)
        pdf.set_font("Helvetica", size=10)
        pdf.multi_cell(0, 5, msg["content"])
        pdf.ln(3)

    pdf.output(output_path)

multi_cell() ń bójú tó ìdìpò ìlà àti àwọn ìdíwọ̀n ìwé àdáṣe, nítorí naa àwọn ìpàdé tí ó pọ̀ to ń gba ìwé tí a ṣàfọ̀mọ̀ dára láìsí ìmọ̀ ìmúlò ìdìpò ìwé aláwọ̀. Àbájáde jẹ fáìlì tí ó bá mu PDF/A pọ̀ láìsí àwọn àwòrán tí a fi sínú ju àwọn àfọwọ́kọ Helvetica ìdiwọnwọn lọ.

Àwòdàlẹ̀ Ìkọ̀kọ̀ #

Ààlà ìkọ̀kọ̀ ní Àkàndé jẹ asọye nípasẹ̀ àwọn otítọ́ mẹta:

  1. A fi ohùn sí Whisper API lórí HTTPS àti OpenAI kò tọ́jú rẹ̀ lẹ́yìn ìpè API (gẹ́gẹ́ bí ìlànà lílò data API OpenAI bí ó ti wà ní Kínní 2024).
  2. Àwọn ìpè Chat Completions API ń tan àtòjọ messages ìpàdé jáde — èyí tí ó lè ní ìtàn ìfọ̀rọ̀wérọ̀ kíkún fún àwọn ìpàdé ìlọ-padà.
  3. Àkójọpọ ìdáhùn SQLite àti àwọn fáìlì PDF ń gbé ní pàtàpàtà lórí ètò fáìlì ìbílẹ̀; kò sí ìmúdójúìwọ̀n ẹ̀yìn sí iṣẹ́ àwọsanma kankan.

Fún àwọn ọ̀ràn lílo alàgbà tí ó kan àwọn àbájáde àfọwọ́kọ — àwọn ìjíròrò M&A, àwọn ọ̀rọ̀ ẹgbẹ́ iṣẹ́, ìlànà ìṣèlò — ìtàn ìpàdé tí a fi ránṣẹ́ sí API yẹ kí a tú àtúnyẹwò rẹ̀ gẹ́gẹ́ bí ìlànà lílò AI ti àjọ ṣáájú ìmúṣẹ. A lè lo ààlà max_tokens lórí ìbéèrè ètò láti dènà ìfún ọ̀rọ̀ àsọye tí kò wọpọ tí ó ju ìwọ̀n ìfihàn tí a pinnu lọ.

Àwọn Ìbéèrè Tí A Máa Ń Béèrè #

Ṣé Àkàndé ń tọ́jú ìtàn ìfọ̀rọ̀wérọ̀ lẹ́yìn ìpàdé tán? A sọ àtòjọ messages nínú ìrántí nù nígbà tí ìlànà bá jáde. A tọ́jú ìtàn ìfọ̀rọ̀wérọ̀ nìkan tí olùmúlò bá ṣe ìgbé jáde PDF tàbí tí a bá ṣafikun ìpele ìdúró àdáni. Àpèjọ SQLite ń tọ́jú àwọn hashes ibeere àti ọrọ ìdáhùn, kì í ṣe ọ̀rọ̀ àsọye ìfọ̀rọ̀wérọ̀ kíkún.

Báwo ni àpèjọ ṣe ń ṣàkóso àwọn ibeere tí ó jọra ṣùgbọ́n kì í ṣe kanna? Àpèjọ ń lo hashing tí ó bá pọ̀ lórí okun ibeere tí a ṣe idiwọn. Àwọn ibeere méjì tí ó yatọ̀ pẹ̀lú ọ̀rọ̀ ẹyọkan yóò gba àwọn hashes tí ó yatọ̀ àti ní àbájáde ní àwọn ìpè API tí ó yatọ̀. Àpèjọ ítumọ̀ (lílò ìfararọ̀ àmì ìhànsókè láti bá àwọn ibeere tí ó fẹ́rẹ̀ẹ̀ bọ̀) yóò nilo ìgbésẹ̀ ìwádìí vector àfikún àti kì í ṣe ara ìmúṣẹ ìpìlẹ̀.

Àwòdàlẹ̀ GPT wo ni Àkàndé ń lo gẹ́gẹ́ bí ìpilẹ̀ṣẹ̀? Ìpilẹ̀ṣẹ̀ jẹ gpt-4-turbo-preview bí ó ti wà ní Kínní 2024. Orúkọ àwòdàlẹ̀ jẹ ìpèsè ìṣètò, nítorí naa a lè rọpo àwòdàlẹ̀ chat completion OpenAI kankan. Ìyípadà sí gpt-3.5-turbo ń dínku ìdíyelé API ní ìsapprox 20× fún token ṣùgbọ́n ń dínku ìdára ọgbọ́n fún àwọn ibeere ìlọpo ọ̀pọ̀ ìgbésẹ̀ tí ó nira.

Ṣé a lè ṣe ìyípadà ọ̀nà ìgbé jáde PDF? Bẹ́ẹ̀ni. Iṣẹ́ ìgbé jáde fpdf2 gba àtòjọ messages gẹ́gẹ́ bí ìjẹwọ́ tí a nílò nìkan, nítorí naa a lè yípadà àwòrán, àwọn ẹ̀gbẹ́, iwọn ìwé, àkóbẹ̀rẹ̀ ìsórí, àti ìlà akọlé gbogbo nípa títúnṣe iṣẹ́ ìgbé jáde. fpdf2 tún ń ṣètìlẹyìn fún fífikún àwọn àwòrán, àwọn tábìlì, àti àwọn àwòrán Unicode, tí ó gbà fún àwọn ìgbékalẹ̀ ìwé ọlọ́rọ̀ fún àwọn àjọ tí ó ní àwọn ìbéèrè àmì pàtàkì.

Àwọn Ìtọkàsí #

  1. OpenAI. Audio Transcriptions — Whisper API. OpenAI Platform Documentation, 2024. https://platform.openai.com/docs/api-reference/audio/createTranscription
  2. OpenAI. Chat Completions API. OpenAI Platform Documentation, 2024. https://platform.openai.com/docs/api-reference/chat/create
  3. Voss, J. et al. fpdf2: Modern PDF generation for Python. GitHub, 2024. https://github.com/py-pdf/fpdf2
  4. SQLite Consortium. SQLite Documentation. sqlite.org, 2024. https://www.sqlite.org/docs.html

Àyẹ̀wò àkọ́kọ́ .

Àyẹ̀wò àkọ́kọ́ .