File size: 2,090 Bytes
4553650 9f13621 4553650 9f13621 a7feaeb 9f13621 60bcf8d a7feaeb 60bcf8d 96c379c 9f13621 bdffcf8 99149d9 60bcf8d 99149d9 60bcf8d 99149d9 96c379c 60bcf8d bdffcf8 dd55ec1 9f13621 a227b91 9f13621 dd55ec1 bae3e66 60bcf8d bae3e66 9f13621 bae3e66 60bcf8d bae3e66 60bcf8d 9f13621 96d4a31 bdffcf8 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
defmodule MedicalTranscription.Transcription do
@moduledoc """
Takes a path to an audio file and transcribes it to text. As each chunk is available, it passes it to the `Coding`
context to look for possible matching codes.
"""
alias MedicalTranscription.Coding
defp get_tags_and_send_result(chunk, index, live_view_pid) do
tags = Coding.process_chunk(chunk.text)
result = build_result(index, chunk, tags)
send(live_view_pid, {:transcription_row, result})
end
# Ideas for future exploration:
# - Instead of storing the long description vectors in a binary file on disk, we could store them within a vector DB
# (such as pgvector or Pinecone.io)
# - A potential improvement would be to not code each chunk of transcribed audio separately, but to instead gather
# complete sentences based on punctuation. We may want to suggest codes for the entire audio as a single piece as
# well
def stream_transcription_and_search(live_view_pid, audio_file_path) do
# audio transcription + semantic search
summary_text =
audio_file_path
|> stream_transcription()
|> Enum.reduce("", fn {chunk, index}, acc ->
get_tags_and_send_result(chunk, index, live_view_pid)
acc <> chunk.text
end)
summary_chunk = %{
text: summary_text,
start_timestamp_seconds: nil,
end_timestamp_seconds: nil
}
get_tags_and_send_result(summary_chunk, 0, live_view_pid)
end
defp stream_transcription(audio_file_path) do
MedicalTranscription.TranscriptionServing
|> Nx.Serving.batched_run({:file, audio_file_path})
|> Stream.with_index()
end
defp build_result(index, chunk, tags) do
%{
id: index,
start_mark: format_timestamp(chunk.start_timestamp_seconds),
end_mark: format_timestamp(chunk.end_timestamp_seconds),
text: chunk.text,
tags: tags
}
end
defp format_timestamp(seconds) when is_nil(seconds), do: nil
defp format_timestamp(seconds) do
seconds |> round() |> Time.from_seconds_after_midnight() |> Time.to_string()
end
end
|