0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

GPT-Live時代の暫定文字起こしを商談メモに混ぜないPython

0
Posted at

OpenAI, “How we built a realtime system for responsive voice AI in six months”(2026年8月3日)

OpenAIは音声を途切れさせないため、会話中の表示用ログと、あとから使う確定ログを分けて扱う設計を紹介しています。営業の通話メモでも、ここはそのまま真似した方がいいです。

リアルタイム文字起こしは、商談メモの入力に直結させません。途中の文字列には聞き直しや言い直しが混じるからです。先に確定した発言だけを残す。これだけで「予算は月10万円」が「予算は月」に化ける事故を止められます。

公式記事: https://openai.com/index/continuous-voice-interaction-with-gpt-live/

なぜ暫定版を残すと困るのか

音声の文字起こしは、話している最中に何度も書き換わります。画面に出すぶんには速い方が助かります。ただ、商談メモは別です。後続の担当者が読み、案件の予算や導入時期を拾い、場合によってはCRMへ転記します。

ここで暫定版と確定版を同じ表に追加すると、同じ発言が二重に残ります。訂正前の数字を誰かが先に見れば、それだけで面倒です。音声AIが賢くなるほど、表示が速いことと記録が正しいことは別の仕事になります。

ストリーミングの文字起こしは、最終版だけを商談メモに渡せば足ります。

JSON Linesから確定版だけをCSVにする

下のスクリプトは、文字起こし配信から受け取ったJSON Linesを標準入力で読みます。statefinal の行だけを対象にし、同じ segment_id が更新されていたら version が大きいものを採用します。sequence で並べ直しているので、訂正イベントが後から届いても発言順は崩れません。

#!/usr/bin/env python3
"""Keep only the latest final version of each streamed transcript segment."""
import csv
import json
import sys

def latest_final_segments(lines):
    latest = {}
    for line_number, raw in enumerate(lines, start=1):
        if not raw.strip():
            continue
        item = json.loads(raw)
        if item.get("state") != "final":
            continue

        segment_id = item.get("segment_id")
        version = item.get("version")
        sequence = item.get("sequence")
        text = item.get("text")
        if not isinstance(segment_id, str) or not segment_id:
            raise ValueError("line {}: segment_id is required".format(line_number))
        if not isinstance(version, int):
            raise ValueError("line {}: version must be an integer".format(line_number))
        if not isinstance(sequence, int):
            raise ValueError("line {}: sequence must be an integer".format(line_number))
        if not isinstance(text, str) or not text.strip():
            raise ValueError("line {}: text is required".format(line_number))

        previous = latest.get(segment_id)
        if previous is None or version > previous["version"]:
            latest[segment_id] = item

    return sorted(latest.values(), key=lambda item: item["sequence"])

def main():
    writer = csv.DictWriter(sys.stdout, fieldnames=["sequence", "speaker", "text"])
    writer.writeheader()
    for item in latest_final_segments(sys.stdin):
        writer.writerow({
            "sequence": item["sequence"],
            "speaker": item.get("speaker", ""),
            "text": item["text"].strip(),
        })

if __name__ == "__main__":
    main()

入力は、たとえば次の形です。文字起こしサービスごとにキー名は違うので、受信側でこの4項目へ寄せます。partial は画面表示だけに使い、ファイルへ渡しません。

{"segment_id":"s-01","version":1,"sequence":1,"state":"partial","speaker":"顧客","text":"予算は月"}
{"segment_id":"s-02","version":1,"sequence":2,"state":"final","speaker":"営業","text":"導入希望はいつ頃ですか"}
{"segment_id":"s-01","version":2,"sequence":1,"state":"final","speaker":"顧客","text":"予算は月10万円です"}
{"segment_id":"s-01","version":3,"sequence":1,"state":"final","speaker":"顧客","text":"予算は月15万円です"}

実行はこうです。

python3 final_transcript_export.py < events.jsonl > meeting_notes.csv

今日、この4行をPython 3で流して確認した出力です。partial の「予算は月」は残らず、同じ発言の最新版だけになりました。

sequence,speaker,text
1,顧客,予算は月15万円です
2,営業,導入希望はいつ頃ですか

シートへ入れる前に決めること

CSVをスプレッドシートに取り込んだら、sequencespeakertext の3列を元データとして残します。その横に担当者が「予算」「導入希望日」「次回アクション」を埋める列を作ると、文字起こしの訂正があっても判断用の列を壊しません。

一つだけ注意があります。音声認識が確定と返した文も、内容まで正しいとは限りません。金額、固有名詞、日付は録音か相手への確認メールで照合します。コードが守るのは、配信途中の文字列を記録へ混ぜないところまでです。

現場に置くなら

GPT-Liveのように会話を流しながら処理する仕組みが広がると、通話中の速さは当たり前になります。営業で差が出るのは、速く見えた文字をどこで確定させるかです。

まずは通話1本分のイベントをこの形式で保存し、既存の商談メモと見比べてください。partialfinal を分けるだけで、後から読めるメモになります。ここ、地味に効きます。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?