HI ▾
API कुंजी पाएँ

LLM API मीटिंग नोट्स: पायथन में ट्रांसक्रिप्ट से सारांश

llm api meeting notes प्राप्त करने के लिए, आप ट्रांसक्रिप्ट को एक छोटे सिस्टम प्रॉम्प्ट के साथ चैट कंप्लीशंस एंडपॉइंट पर भेजते हैं और जवाब पढ़ते हैं। गुणवत्ता तय करने वाले हिस्से प्रॉम्प्ट, एक स्थिर आउटपुट आकार और लंबी रिकॉर्डिंग को कैसे संभाला जाता है, वे हैं।

अपडेट किया गया

समदृश्य बैठक टेबल जिसके ऊपर बबल एक चेकलिस्ट कार्ड में बदल रहे हैं

मुख्य बिंदु

  • एक चैट कंप्लीशंस कॉल ट्रांसक्रिप्ट को नोट्स में बदल देती है; JSON मोड आपको एक स्थिर आकार देता है।
  • 100,000-टोकन विंडो अधिकांश मीटिंग ट्रांसक्रिप्ट को बिना चंकिंग के रखती है।
  • मॉडल को बताएं कि गायब मालिकों और तारीखों के लिए null लिखें, ताकि वह उन्हें गढ़े नहीं।
  • एक पूर्ण कुंजी 8 समानांतर अनुरोधों की अनुमति देती है, जो मीटिंग्स के एक दिन को समानांतर में प्रोसेस करने के लिए पर्याप्त है।

चार चरणों में पाइपलाइन

  1. रिकॉर्ड करें और ट्रांसक्राइब करें। किसी भी स्पीच-टू-टेक्स्ट टूल का उपयोग करें। यह API केवल टेक्स्ट है और ऑडियो स्वीकार नहीं करता है।
  2. टेक्स्ट तैयार करें। मीटिंग के शीर्षक, तारीख और उपस्थितियों के नामों के साथ एक हेडर जोड़ें। स्पीकर लेबल्स, यदि आपके पास हैं, बहुत मदद करते हैं।
  3. मॉडल को कॉल करें। ट्रांसक्रिप्ट को एक सिस्टम प्रॉम्प्ट के साथ भेजें जो उन सेक्शनों को परिभाषित करता है जिन्हें आप चाहते हैं।
  4. परिणाम को स्टोर और शेयर करें। JSON को सेव करें, इसे Markdown या HTML के रूप में रेंडर करें, या उस जगह पोस्ट करें जहाँ टीम पढ़ती है।

एंडपॉइंट POST /v1/chat/completions पर https://api.whisperapis.com/v1 है, मॉडल ID uncensored है, और बेस URL और कुंजी बदलने के बाद कोई भी OpenAI SDK काम करता है। यदि आपको पहले स्पीच-टू-टेक्स्ट सेटअप करना है, तो क्विकस्टार्ट दस्तावेज़ टेक्स्ट हिस्से को कवर करते हैं और कोई भी Whisper-संगत सर्वर ट्रांसक्रिप्ट प्रदान कर सकता है।

JSON मोड के साथ संरचित नोट्स प्राप्त करें

फ्री-फॉर्म सारांश पढ़ने के लिए ठीक हैं, लेकिन एक पाइपलाइन को उन फ़ील्ड्स की आवश्यकता होती है जिन्हें आप स्टोर और फ़िल्टर कर सकें। JSON मोड, response_format को {"type": "json_object"} पर सेट करके सक्षम किया जाता है, मॉडल को एकल JSON ऑब्जेक्ट लौटने देता है। सिस्टम प्रॉम्प्ट में कीज़ का वर्णन करें, और वहां JSON शब्द कहें, क्योंकि प्रॉम्प्ट ही आकार को परिभाषित करता है।

import json
from openai import OpenAI

client = OpenAI(base_url="https://api.whisperapis.com/v1", api_key="YOUR_KEY")

SYSTEM = """You write meeting notes from raw transcripts.
Use only what the transcript says. If an owner or a date is not stated, write null.
Reply with a JSON object with the keys: summary (string), decisions (array of strings),
action_items (array of objects with task, owner, due), open_questions (array of strings)."""

transcript = open("standup.txt", encoding="utf-8").read()

resp = client.chat.completions.create(
    model="uncensored",
    messages=[
        {"role": "system", "content": SYSTEM},
        {"role": "user", "content": "Transcript:\n\n" + transcript},
    ],
    response_format={"type": "json_object"},
    temperature=0.2,
)

notes = json.loads(resp.choices[0].message.content)
for item in notes["action_items"]:
    print(item["owner"], "->", item["task"], item["due"])

उस प्रॉम्प्ट में दो पंक्तियां ज्यादातर काम करती हैं। "ट्रांसक्रिप्ट में जो कहा गया है, उसका ही उपयोग करें" मॉडल को संभावित विवरण जोड़ने से रोकता है। "यदि कोई मालिक या तिथि निर्दिष्ट नहीं है, तो null लिखें" इसे एक वैध तरीका देता है कि यह बताए कि उसे नहीं पता, जो एक गलत नाम से बेहतर है। 0.2 जैसा कम तापमान रन के बीच भिन्नता को कम करता है, जो आप तब चाहते हैं जब एक ही ट्रांसक्रिप्ट को दो बार प्रोसेस किया जा सकता है।

हमेशा सावधानीपूर्वक पार्स करें। json.loads को एक try ब्लॉक में लपेटें, और विफलता पर एक बार पुनः प्रयास करें। विफल अनुरोधों का शुल्क नहीं लिया जाता है, और एक अकेला पुनः प्रयास अधिकांश एकल प्रारूपण त्रुटियों को ठीक कर देता है।

प्रतीक्षा कर रहे व्यक्ति को परिणाम स्ट्रीम करें

यदि कोई बटन पर क्लिक करता है और नोट्स का इंतज़ार करता है, तो आने पर टेक्स्ट दिखाएं। stream को true पर सेट करें और API सर्वर-सेंट इवेंट्स भेजता है; उपयोग स्ट्रीम के अंत में शामिल है।

from openai import OpenAI

client = OpenAI(base_url="https://api.whisperapis.com/v1", api_key="YOUR_KEY")
transcript = open("standup.txt", encoding="utf-8").read()

stream = client.chat.completions.create(
    model="uncensored",
    messages=[
        {"role": "system", "content": "Write concise meeting notes in Markdown with headings: Summary, Decisions, Actions."},
        {"role": "user", "content": transcript},
    ],
    stream=True,
    temperature=0.3,
)

for chunk in stream:
    if chunk.choices and chunk.choices[0].delta.content:
        print(chunk.choices[0].delta.content, end="", flush=True)

स्ट्रीमिंग में एक ऑपरेशनल विवरण है: एक स्ट्रीम किए गए अनुरोध में समानांतर अनुरोध स्थल तब तक बंधा रहता है जब तक स्ट्रीम समाप्त न हो जाए। एक पूर्ण कुंजी एक साथ 8 की अनुमति देती है, एक ट्रायल कुंजी 2। यदि एक ब्राउज़र टैब बंद हो जाता है और आपका सर्वर पढ़ना जारी रखता है, तो वह स्थल व्यस्त रहता है, इसलिए जब क्लाइंट डिस्कनेक्ट हो जाए तो अपस्ट्रीम अनुरोध को रद्द करें।

बैच जॉब्स के लिए जिन्हें कोई नहीं देखता, स्ट्रीमिंग छोड़ दें। एक साधारण अनुरोध अधिक सरल है और आपको पूरा उत्तर एक ऑब्जेक्ट में मिलता है।

लंबी मीटिंग और 100k विंडो

कॉन्टेक्स्ट विंडो 100,000 टोकन की है, प्रॉम्प्ट और रिप्लाई को मिलाकर गिना जाता है। एक घंटे की मीटिंग लगभग 9,000 शब्दों की होती है, या लगभग 12,000 टोकन, इसलिए एक दिन भर की वर्कशॉप भी एक अनुरोध में फिट हो जाती है। यह उस सामान्य map-and-reduce डिज़ाइन को हटा देता है जहां आप ट्रांसक्रिप्ट को विभाजित करते हैं, प्रत्येक भाग का सारांश देते हैं और फिर सारांशों का सारांश देते हैं। उस डिज़ाइन का प्रत्येक पार विवरण खो देता है, और मिनट 5 पर लिए गए निर्णय और मिनट 50 पर संशोधित निर्णय को गलत तरीके से रिपोर्ट करना आसान है।

फिर भी भेजने से पहले आकार की जांच करें। अंग्रेजी टेक्स्ट के लिए एक कच्ची जांच चार से विभाजित अक्षरों की है। यदि आप सीमा के करीब हैं, तो दो साफ विकल्प हैं:

  • एजेंडा आइटम्स जैसे प्राकृतिक ब्रेक पर विभाजित करें, प्रत्येक का सारांश दें, और उन्हें मर्ज करने वाले अंतिम कॉल के लिए आंशिक नोट्स पास करें।
  • ऐसे सामग्री को छोड़ दें जो मायने नहीं रखते, जैसे मीटिंग शुरू होने से पहले लंबे समय तक की छोटी बातचीत।

अधिकतम अनुरोध बॉडी 8 MB है, जो टेक्स्ट के लिए व्यावहारिक सीमा नहीं है। प्रॉम्प्ट को ट्रेनिंग के लिए उपयोग नहीं किया जाता है, जो तब मायने रखता है यदि रिकॉर्डिंग में आंतरिक योजनाएं या क्लाइंट के नाम शामिल हैं।

आउटपुट को बदलने वाले प्रॉम्प्ट विवरण

नोट्स किसके लिए हैं, यह बताएं

"मीटिंग में शामिल न हो सकने वाले इंजीनियर के लिए नोट्स" अलग विवरण देता है "एक पैराग्राफ अपडेट एक्जीक्यूटिव टीम के लिए"। पाठक को सिस्टम प्रॉम्प्ट में लिखें।

मॉडल को उपस्थितियों की सूची दें

स्पीच-टू-टेक्स्ट अक्सर नामों को खराब कर देता है। "Attendees: Priya Nair (PM), Tom Ortiz (backend), Lena Fischer (design)" जैसी एक पंक्ति मॉडल को "Tom Ortis" कहने वाली ट्रांसक्रिप्ट को ठीक करने और कार्यों को सही व्यक्ति से जोड़ने में सहायता करती है।

निर्णयों और कार्यों को अलग-अलग मांगें

निर्णय वह है जिस पर समूह सहमत हुआ। कार्य वह है जिसे एक व्यक्ति करेगा। जब दोनों एक सूची में रहते हैं, तो पाठक उसे छोड़ देते हैं। अलग-अलग कीज़ अंतर को स्पष्ट बनाते हैं, और मॉडल इसे लगातार फॉलो करता है।

संवेदनशील सामग्री को रखें

वास्तविक मीटिंग्स में कठोर भाषा, नामित लोगों के बारे में शिकायतें, कानूनी चिंताएं और गर्म बहस शामिल होती हैं। यहाँ मॉडल को कानूनी वयस्क उपयोग के लिए बिना सेंसर उत्तर देने के लिए ट्यून्ड किया गया है, इसलिए यह अस्वीकार करने के बजाय जो कहा गया उसका सारांश देता है। आप अभी भी आउटपुट के मालिक हैं, इसलिए नोट्स को कमरे में न होने वाले लोगों के पास भेजने से पहले समीक्षा करें।

पूरे दिन की मीटिंग्स चलाना

एक टीम जो दिन में छह मीटिंग्स रिकॉर्ड करती है, उन्हें समानांतर प्रोसेस कर सकती है। 8 समानांतर अनुरोधों के साथ, एक बार में आठ भेजें; सेमाफोर के साथ एक छोटा वर्कर पूल यह काम कर देता है। एक पूर्ण कुंजी के लिए प्रति मिनट की सीमा 300 अनुरोध है, जिसे मीटिंग पाइपलाइन नहीं पार करेगी।

Node, Python की तरह ही काम करता है। यहाँ नॉन-स्ट्रीमिंग संस्करण है:

import OpenAI from "openai";
import { readFileSync } from "node:fs";

const client = new OpenAI({
  baseURL: "https://api.whisperapis.com/v1",
  apiKey: process.env.API_KEY,
});

const transcript = readFileSync("standup.txt", "utf8");

const resp = await client.chat.completions.create({
  model: "uncensored",
  messages: [
    { role: "system", content: "Summarize the meeting in five bullets, then list action items with owners." },
    { role: "user", content: transcript },
  ],
  temperature: 0.2,
});

console.log(resp.choices[0].message.content);

यदि आपको HTTP 429 मिलता है, तो त्रुटि कोड पढ़ें। concurrency का अर्थ है एक साथ बहुत सारे अनुरोध, इसलिए पूल का आकार कम करें। rate_limited का अर्थ है प्रति मिनट बहुत सारे अनुरोध। एक 429 जिसमें Retry-After: 5 हेडर होता है, अस्थायी ओवरलोड का संकेत देता है; पाँच सेकंड प्रतीक्षा करें और पुनः प्रयास करें।

उन नोट्स को जाँचें जिन पर आप भरोसा करने से पहले

जनरेट किए गए नोट्स भले ही गलत हों, आत्मविश्वास के साथ पढ़े जाते हैं, इसलिए किसी इंसान पर निर्भर रहने के बजाय पाइपलाइन में कुछ सस्ते जाँच जोड़ें।

  • उद्धरण जाँच। प्रत्येक एक्शन आइटम के लिए एक छोटा समर्थक उद्धरण माँगें, फिर उसकी ट्रांसक्रिप्ट में खोजें। एक ऐसा उद्धरण जो प्रकट नहीं होता, उसका अर्थ है कि आइटम गढ़ा गया है।
  • मालिक जाँच। प्रत्येक मालिक की तुलना अपने उपस्थित सूची से करें और उन नामों को फ्लैग करें जो उस सूची में नहीं हैं।
  • खाली जाँच। एक मीटिंग जिसमें कोई निर्णय नहीं है, संभव है, लेकिन 40 मिनट की ट्रांसक्रिप्ट पर सभी खाली सरणी वाला परिणाम आमतौर पर इस बात का संकेत देता है कि इनपुट ट्रंकेट हो गया था या गलत फ़ाइल थी।
  • लंबाई जाँच। ट्रांसक्रिप्ट के लगभग एक पंचांश से लंबे नोट्स नोट नहीं हैं; प्रॉम्प्ट को सख्त करें या max_tokens सेट करें।

प्रत्येक सहेजे गए परिणाम के बगल में X-Request-Id रिस्पॉन्स हेडर लॉग करें। जब कोई व्यक्ति कहता है कि एक एक्शन आइटम गलत है, तो वह पहचानकर्ता आपको अनुरोध खोजने और उसे ट्रांसक्रिप्ट से तुलना करने में सक्षम बनाता है। मूल ट्रांसक्रिप्ट को नोट्स के साथ रखना सस्ता है और अधिकांश विवादों को जल्दी सुलझा देता है।

लागत और एक प्रारंभिक परीक्षण

कीमत $0.15 प्रति मिलियन इनपुट टोकन और $0.50 प्रति मिलियन आउटपुट टोकन है। 12,000-टोकन की ट्रांसक्रिप्ट और 800-टोकन के नोट्स वाले एक घंटे की मीटिंग के लिए इनपुट की लागत $0.0018 और आउटपुट की $0.0004 होती है, इसलिए कुल $0.0022 आती है। उस दर पर $1 लगभग 454 ऐसी मीटिंग्स कवर करता है। टॉप-अप के लिए pricing page देखें, जो $20 से शुरू होते हैं और कार्ड या क्रिप्टो द्वारा भुगतान किए जा सकते हैं।

इसे आज़माने के लिए, साइन अप करें और API कुंजी पेज खोलें। $0.50 का एक-क्लिक ट्रायल हर व्यक्ति के लिए एक बार उपलब्ध है, जो 7 दिनों के लिए मान्य है, कार्ड की आवश्यकता नहीं है। वास्तविक ट्रांसक्रिप्ट पर ऊपर दिया गया Python स्क्रिप्ट चलाएं, JSON पढ़ें, और प्रॉम्प्ट को मीटिंग में हुए कार्यों से मेल खाने के लिए समायोजित करें। फिर शेष पर लूप चलाएं।

प्रश्न और उत्तर

क्या मैं ऑडियो रिकॉर्डिंग सीधे भेज सकता हूँ?

नहीं। API केवल टेक्स्ट लेता है। पहले रिकॉर्डिंग को स्पीच-टू-टेक्स्ट टूल से ट्रांसक्राइब करें, फिर ट्रांसक्रिप्ट भेजें।

आउटपुट फॉर्मेट को स्थिर कैसे बनाएं?

JSON मोड का उपयोग करें, जिसमें सिस्टम प्रॉम्प्ट में हर कुंजी का नाम दिया गया हो, और कम तापमान सेट करें। परिणाम को try ब्लॉक में पार्स करें और विफलता पर एक बार पुनः प्रयास करें।

एक अनुरोध में कितनी लंबी ट्रांसक्रिप्ट फिट होती है?

प्रॉम्प्ट और जवाब के लिए कॉन्टेक्स्ट विंडो 100,000 टोकन है। यह अधिकांश मामलों में एक पूरे दिन के कार्यशाला को कवर करता है।

क्या मेरी ट्रांसक्रिप्ट प्रशिक्षण के लिए उपयोग की जाती हैं?

नहीं, प्रॉम्प्ट्स ट्रेनिंग के लिए उपयोग नहीं किए जाते हैं।

प्रति बैठक लागत क्या है?

12,000-टोकन ट्रांसक्रिप्ट और 800-टोकन सारांश वाले एक घंटे की मीटिंग की लागत, प्रति मिलियन इनपुट और आउटपुट टोकन $0.15 और $0.50 पर लगभग $0.0022 है।

आपकी कुंजी बस एक फ़ॉर्म दूर है

एक खाता बनाएँ, कुंजी कॉपी करें, बेस URL बदलें। सेटअप यही है।

API कुंजी पाएँ