Commit ·
78111fe
1
Parent(s): 47f0c94
feat: Transcribe using FLAME on a Fly GPU
Browse files- config/runtime.exs +11 -0
- lib/medicode/application.ex +17 -4
- lib/medicode/transcription_server.ex +16 -13
- mix.exs +2 -1
- mix.lock +1 -0
config/runtime.exs
CHANGED
|
@@ -72,6 +72,17 @@ if config_env() == :prod do
|
|
| 72 |
],
|
| 73 |
secret_key_base: secret_key_base
|
| 74 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 75 |
# ## SSL Support
|
| 76 |
#
|
| 77 |
# To get SSL working, you will need to add the `https` key
|
|
|
|
| 72 |
],
|
| 73 |
secret_key_base: secret_key_base
|
| 74 |
|
| 75 |
+
if config_env() == :prod do
|
| 76 |
+
config :flame, :backend, FLAME.FlyBackend
|
| 77 |
+
|
| 78 |
+
config :flame, FLAME.FlyBackend,
|
| 79 |
+
token: System.fetch_env!("MEDICODE_API_TOKEN"),
|
| 80 |
+
gpu_kind: "a100-pcie-40gb",
|
| 81 |
+
cpu_kind: "performance",
|
| 82 |
+
cpus: 8,
|
| 83 |
+
memory_mb: 20_480
|
| 84 |
+
end
|
| 85 |
+
|
| 86 |
# ## SSL Support
|
| 87 |
#
|
| 88 |
# To get SSL working, you will need to add the `https` key
|
lib/medicode/application.ex
CHANGED
|
@@ -9,12 +9,15 @@ defmodule Medicode.Application do
|
|
| 9 |
def start(_type, _args) do
|
| 10 |
Logger.add_backend(Sentry.LoggerBackend)
|
| 11 |
|
|
|
|
|
|
|
| 12 |
children =
|
| 13 |
[
|
| 14 |
{MedicodeWeb.MetricsStorage, MedicodeWeb.Telemetry.metrics()},
|
| 15 |
Medicode.Repo,
|
| 16 |
{DNSCluster, query: Application.get_env(:medicode, :dns_cluster_query) || :ignore},
|
| 17 |
{Phoenix.PubSub, name: :medicode_pubsub},
|
|
|
|
| 18 |
Medicode.ServingSupervisor,
|
| 19 |
{
|
| 20 |
Medicode.TranscriptionSupervisor,
|
|
@@ -30,12 +33,22 @@ defmodule Medicode.Application do
|
|
| 30 |
},
|
| 31 |
# Start the Finch HTTP client for sending emails
|
| 32 |
{Finch, name: Medicode.Finch}
|
| 33 |
-
] ++ chromic_pdf_spec()
|
| 34 |
|
| 35 |
# Start a worker by calling: Medicode.Worker.start_link(arg)
|
| 36 |
# {Medicode.Worker, arg},
|
| 37 |
# Start to serve requests, typically the last entry
|
| 38 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 39 |
|
| 40 |
# See https://hexdocs.pm/elixir/Supervisor.html
|
| 41 |
# for other strategies and supported options
|
|
@@ -51,8 +64,8 @@ defmodule Medicode.Application do
|
|
| 51 |
:ok
|
| 52 |
end
|
| 53 |
|
| 54 |
-
defp chromic_pdf_spec do
|
| 55 |
-
if Application.get_env(:medicode, :skip_chromic_pdf, false) do
|
| 56 |
[]
|
| 57 |
else
|
| 58 |
# NOTE: Security implications of using Chrome:
|
|
|
|
| 9 |
def start(_type, _args) do
|
| 10 |
Logger.add_backend(Sentry.LoggerBackend)
|
| 11 |
|
| 12 |
+
flame_parent = FLAME.Parent.get()
|
| 13 |
+
|
| 14 |
children =
|
| 15 |
[
|
| 16 |
{MedicodeWeb.MetricsStorage, MedicodeWeb.Telemetry.metrics()},
|
| 17 |
Medicode.Repo,
|
| 18 |
{DNSCluster, query: Application.get_env(:medicode, :dns_cluster_query) || :ignore},
|
| 19 |
{Phoenix.PubSub, name: :medicode_pubsub},
|
| 20 |
+
{FLAME.Pool, name: Medicode.OfflineServing, min: 0, max: 1},
|
| 21 |
Medicode.ServingSupervisor,
|
| 22 |
{
|
| 23 |
Medicode.TranscriptionSupervisor,
|
|
|
|
| 33 |
},
|
| 34 |
# Start the Finch HTTP client for sending emails
|
| 35 |
{Finch, name: Medicode.Finch}
|
| 36 |
+
] ++ chromic_pdf_spec(flame_parent)
|
| 37 |
|
| 38 |
# Start a worker by calling: Medicode.Worker.start_link(arg)
|
| 39 |
# {Medicode.Worker, arg},
|
| 40 |
# Start to serve requests, typically the last entry
|
| 41 |
+
|
| 42 |
+
# Since we don't need Endpoint running within FLAME nodes, we skip
|
| 43 |
+
# starting it under that condition.
|
| 44 |
+
children =
|
| 45 |
+
if flame_parent do
|
| 46 |
+
children
|
| 47 |
+
else
|
| 48 |
+
children ++ [MedicodeWeb.Endpoint]
|
| 49 |
+
end
|
| 50 |
+
|
| 51 |
+
children = Enum.filter(children, & &1)
|
| 52 |
|
| 53 |
# See https://hexdocs.pm/elixir/Supervisor.html
|
| 54 |
# for other strategies and supported options
|
|
|
|
| 64 |
:ok
|
| 65 |
end
|
| 66 |
|
| 67 |
+
defp chromic_pdf_spec(flame_parent) do
|
| 68 |
+
if flame_parent || Application.get_env(:medicode, :skip_chromic_pdf, false) do
|
| 69 |
[]
|
| 70 |
else
|
| 71 |
# NOTE: Security implications of using Chrome:
|
lib/medicode/transcription_server.ex
CHANGED
|
@@ -155,20 +155,23 @@ defmodule Medicode.TranscriptionServer do
|
|
| 155 |
# complete sentences based on punctuation. We may want to suggest codes for the entire audio as a single piece as
|
| 156 |
# well
|
| 157 |
defp stream_transcription_and_search(audio_file_path) do
|
| 158 |
-
|
| 159 |
-
|
| 160 |
-
|
| 161 |
-
|
| 162 |
-
|
| 163 |
-
|
| 164 |
-
|
| 165 |
-
|
| 166 |
-
|
| 167 |
-
|
| 168 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 169 |
end)
|
| 170 |
-
|
| 171 |
-
send(self(), :finished)
|
| 172 |
end
|
| 173 |
|
| 174 |
defp format_timestamp(seconds) when is_nil(seconds), do: nil
|
|
|
|
| 155 |
# complete sentences based on punctuation. We may want to suggest codes for the entire audio as a single piece as
|
| 156 |
# well
|
| 157 |
defp stream_transcription_and_search(audio_file_path) do
|
| 158 |
+
target_pid = self()
|
| 159 |
+
|
| 160 |
+
FLAME.call(Medicode.OfflineServing, fn ->
|
| 161 |
+
Medicode.TranscriptionServing
|
| 162 |
+
|> Nx.Serving.batched_run({:file, audio_file_path})
|
| 163 |
+
|> Enum.each(fn chunk ->
|
| 164 |
+
result = %{
|
| 165 |
+
start_mark: format_timestamp(chunk.start_timestamp_seconds),
|
| 166 |
+
end_mark: format_timestamp(chunk.end_timestamp_seconds),
|
| 167 |
+
text: chunk.text
|
| 168 |
+
}
|
| 169 |
+
|
| 170 |
+
send(target_pid, {:chunk, result})
|
| 171 |
+
end)
|
| 172 |
+
|
| 173 |
+
send(target_pid, :finished)
|
| 174 |
end)
|
|
|
|
|
|
|
| 175 |
end
|
| 176 |
|
| 177 |
defp format_timestamp(seconds) when is_nil(seconds), do: nil
|
mix.exs
CHANGED
|
@@ -78,7 +78,8 @@ defmodule Medicode.MixProject do
|
|
| 78 |
# NOTE: `override: true` avoids an issue that likely originates
|
| 79 |
# from `audio_tagger` depending on a different version of bumblebee:
|
| 80 |
# https://elixirforum.com/t/getting-a-weird-error-message-in-mix-ive-not-see-before-because-your-app-depends-on-xxx-empty/54475/8
|
| 81 |
-
{:bumblebee, "~> 0.5.3", override: true}
|
|
|
|
| 82 |
]
|
| 83 |
end
|
| 84 |
|
|
|
|
| 78 |
# NOTE: `override: true` avoids an issue that likely originates
|
| 79 |
# from `audio_tagger` depending on a different version of bumblebee:
|
| 80 |
# https://elixirforum.com/t/getting-a-weird-error-message-in-mix-ive-not-see-before-because-your-app-depends-on-xxx-empty/54475/8
|
| 81 |
+
{:bumblebee, "~> 0.5.3", override: true},
|
| 82 |
+
{:flame, "~> 0.1.12"}
|
| 83 |
]
|
| 84 |
end
|
| 85 |
|
mix.lock
CHANGED
|
@@ -31,6 +31,7 @@
|
|
| 31 |
"expo": {:hex, :expo, "0.5.2", "beba786aab8e3c5431813d7a44b828e7b922bfa431d6bfbada0904535342efe2", [:mix], [], "hexpm", "8c9bfa06ca017c9cb4020fabe980bc7fdb1aaec059fd004c2ab3bff03b1c599c"},
|
| 32 |
"file_system": {:hex, :file_system, "1.0.0", "b689cc7dcee665f774de94b5a832e578bd7963c8e637ef940cd44327db7de2cd", [:mix], [], "hexpm", "6752092d66aec5a10e662aefeed8ddb9531d79db0bc145bb8c40325ca1d8536d"},
|
| 33 |
"finch": {:hex, :finch, "0.18.0", "944ac7d34d0bd2ac8998f79f7a811b21d87d911e77a786bc5810adb75632ada4", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: false]}, {:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.3", [hex: :mint, repo: "hexpm", optional: false]}, {:nimble_options, "~> 0.4 or ~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:nimble_pool, "~> 0.2.6 or ~> 1.0", [hex: :nimble_pool, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "69f5045b042e531e53edc2574f15e25e735b522c37e2ddb766e15b979e03aa65"},
|
|
|
|
| 34 |
"floki": {:hex, :floki, "0.36.1", "712b7f2ba19a4d5a47dfe3e74d81876c95bbcbee44fe551f0af3d2a388abb3da", [:mix], [], "hexpm", "21ba57abb8204bcc70c439b423fc0dd9f0286de67dc82773a14b0200ada0995f"},
|
| 35 |
"fss": {:hex, :fss, "0.1.1", "9db2344dbbb5d555ce442ac7c2f82dd975b605b50d169314a20f08ed21e08642", [:mix], [], "hexpm", "78ad5955c7919c3764065b21144913df7515d52e228c09427a004afe9c1a16b0"},
|
| 36 |
"gettext": {:hex, :gettext, "0.24.0", "6f4d90ac5f3111673cbefc4ebee96fe5f37a114861ab8c7b7d5b30a1108ce6d8", [:mix], [{:expo, "~> 0.5.1", [hex: :expo, repo: "hexpm", optional: false]}], "hexpm", "bdf75cdfcbe9e4622dd18e034b227d77dd17f0f133853a1c73b97b3d6c770e8b"},
|
|
|
|
| 31 |
"expo": {:hex, :expo, "0.5.2", "beba786aab8e3c5431813d7a44b828e7b922bfa431d6bfbada0904535342efe2", [:mix], [], "hexpm", "8c9bfa06ca017c9cb4020fabe980bc7fdb1aaec059fd004c2ab3bff03b1c599c"},
|
| 32 |
"file_system": {:hex, :file_system, "1.0.0", "b689cc7dcee665f774de94b5a832e578bd7963c8e637ef940cd44327db7de2cd", [:mix], [], "hexpm", "6752092d66aec5a10e662aefeed8ddb9531d79db0bc145bb8c40325ca1d8536d"},
|
| 33 |
"finch": {:hex, :finch, "0.18.0", "944ac7d34d0bd2ac8998f79f7a811b21d87d911e77a786bc5810adb75632ada4", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: false]}, {:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.3", [hex: :mint, repo: "hexpm", optional: false]}, {:nimble_options, "~> 0.4 or ~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:nimble_pool, "~> 0.2.6 or ~> 1.0", [hex: :nimble_pool, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "69f5045b042e531e53edc2574f15e25e735b522c37e2ddb766e15b979e03aa65"},
|
| 34 |
+
"flame": {:hex, :flame, "0.1.12", "4d46b706d35d6eb22505d0e060fe41174052eaa38f778a4762fc74dd2c9df301", [:mix], [{:req, "~> 0.4.13", [hex: :req, repo: "hexpm", optional: false]}], "hexpm", "aa25de6614455ac01e33409c08db4560fa54dd837ad116aae16c8f7c011ccd76"},
|
| 35 |
"floki": {:hex, :floki, "0.36.1", "712b7f2ba19a4d5a47dfe3e74d81876c95bbcbee44fe551f0af3d2a388abb3da", [:mix], [], "hexpm", "21ba57abb8204bcc70c439b423fc0dd9f0286de67dc82773a14b0200ada0995f"},
|
| 36 |
"fss": {:hex, :fss, "0.1.1", "9db2344dbbb5d555ce442ac7c2f82dd975b605b50d169314a20f08ed21e08642", [:mix], [], "hexpm", "78ad5955c7919c3764065b21144913df7515d52e228c09427a004afe9c1a16b0"},
|
| 37 |
"gettext": {:hex, :gettext, "0.24.0", "6f4d90ac5f3111673cbefc4ebee96fe5f37a114861ab8c7b7d5b30a1108ce6d8", [:mix], [{:expo, "~> 0.5.1", [hex: :expo, repo: "hexpm", optional: false]}], "hexpm", "bdf75cdfcbe9e4622dd18e034b227d77dd17f0f133853a1c73b97b3d6c770e8b"},
|