Update public-apps/summarine.livemd
Browse files- public-apps/summarine.livemd +64 -39
public-apps/summarine.livemd
CHANGED
@@ -17,30 +17,80 @@ Mix.install(
|
|
17 |
|
18 |
Audio to text, then summary.
|
19 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
20 |
## App
|
21 |
|
22 |
```elixir
|
23 |
-
|
24 |
-
|
25 |
-
{:ok,
|
26 |
-
{:ok,
|
|
|
|
|
27 |
generation_config = Bumblebee.configure(generation_config, max_new_tokens: 100)
|
28 |
|
29 |
serving =
|
30 |
Bumblebee.Audio.speech_to_text(model_info, featurizer, tokenizer, generation_config,
|
31 |
-
compile: [batch_size:
|
32 |
defn_options: [compiler: EXLA]
|
33 |
)
|
34 |
```
|
35 |
|
36 |
```elixir
|
37 |
-
audio_input = Kino.Input.audio("
|
38 |
-
form = Kino.Control.form([audio: audio_input], submit: "
|
39 |
-
|
|
|
40 |
|
41 |
Kino.listen(form, fn %{data: %{audio: audio}} ->
|
42 |
if audio do
|
43 |
-
Kino.Frame.render(
|
44 |
|
45 |
audio =
|
46 |
audio.data
|
@@ -49,40 +99,15 @@ Kino.listen(form, fn %{data: %{audio: audio}} ->
|
|
49 |
|> Nx.mean(axes: [1])
|
50 |
|
51 |
%{results: [%{text: generated_text}]} = Nx.Serving.run(serving, audio)
|
52 |
-
Kino.Frame.render(
|
53 |
-
|
54 |
-
payload = %{
|
55 |
-
model: "llama2-uncensored",
|
56 |
-
prompt: "Please summary the text: #{generated_text}"
|
57 |
-
}
|
58 |
-
|
59 |
-
{:ok, response} = Req.post("http://localhost:11434/api/generate", json: payload)
|
60 |
-
|
61 |
-
result =
|
62 |
-
response.body
|
63 |
-
|> String.split("\n")
|
64 |
-
|> Enum.map(fn
|
65 |
-
"" ->
|
66 |
-
nil
|
67 |
-
|
68 |
-
line ->
|
69 |
-
{:ok, data} = Jason.decode(line)
|
70 |
|
71 |
-
|
72 |
-
end)
|
73 |
-
|> Enum.reject(&is_nil/1)
|
74 |
-
|> Enum.map(fn
|
75 |
-
%{"response" => response} ->
|
76 |
-
response
|
77 |
|
78 |
-
|
79 |
-
""
|
80 |
-
end)
|
81 |
-
|> Enum.join("")
|
82 |
|
83 |
-
Kino.Frame.render(
|
84 |
end
|
85 |
end)
|
86 |
|
87 |
-
Kino.Layout.grid([form,
|
88 |
```
|
|
|
17 |
|
18 |
Audio to text, then summary.
|
19 |
|
20 |
+
## Setup Ollama module
|
21 |
+
|
22 |
+
```elixir
|
23 |
+
defmodule Ollama do
|
24 |
+
@api_endpoint "http://localhost:11434/api/generate"
|
25 |
+
@model "llama2-uncensored"
|
26 |
+
|
27 |
+
def generate(prompt) do
|
28 |
+
payload = %{
|
29 |
+
model: @model,
|
30 |
+
prompt: prompt
|
31 |
+
}
|
32 |
+
|
33 |
+
{:ok, response} = Req.post(@api_endpoint, json: payload)
|
34 |
+
|
35 |
+
process_response(response)
|
36 |
+
end
|
37 |
+
|
38 |
+
defp process_response(response) do
|
39 |
+
response.body
|
40 |
+
|> String.split("\n")
|
41 |
+
|> Enum.map(&process_chunk/1)
|
42 |
+
|> Enum.reject(&is_nil/1)
|
43 |
+
|> Enum.map(&get_content/1)
|
44 |
+
|> Enum.join("")
|
45 |
+
end
|
46 |
+
|
47 |
+
defp process_chunk("") do
|
48 |
+
nil
|
49 |
+
end
|
50 |
+
|
51 |
+
defp process_chunk(json_string) do
|
52 |
+
{:ok, data} = Jason.decode(json_string)
|
53 |
+
|
54 |
+
data
|
55 |
+
end
|
56 |
+
|
57 |
+
defp get_content(%{"response" => response}) do
|
58 |
+
response
|
59 |
+
end
|
60 |
+
|
61 |
+
defp get_content(_) do
|
62 |
+
""
|
63 |
+
end
|
64 |
+
end
|
65 |
+
```
|
66 |
+
|
67 |
## App
|
68 |
|
69 |
```elixir
|
70 |
+
model_name = "openai/whisper-base"
|
71 |
+
|
72 |
+
{:ok, model_info} = Bumblebee.load_model({:hf, model_name})
|
73 |
+
{:ok, featurizer} = Bumblebee.load_featurizer({:hf, model_name})
|
74 |
+
{:ok, tokenizer} = Bumblebee.load_tokenizer({:hf, model_name})
|
75 |
+
{:ok, generation_config} = Bumblebee.load_generation_config({:hf, model_name})
|
76 |
generation_config = Bumblebee.configure(generation_config, max_new_tokens: 100)
|
77 |
|
78 |
serving =
|
79 |
Bumblebee.Audio.speech_to_text(model_info, featurizer, tokenizer, generation_config,
|
80 |
+
compile: [batch_size: 4],
|
81 |
defn_options: [compiler: EXLA]
|
82 |
)
|
83 |
```
|
84 |
|
85 |
```elixir
|
86 |
+
audio_input = Kino.Input.audio("", sampling_rate: featurizer.sampling_rate)
|
87 |
+
form = Kino.Control.form([audio: audio_input], submit: "Summary the audio")
|
88 |
+
audio_frame = Kino.Frame.new(placeholder: false)
|
89 |
+
summary_frame = Kino.Frame.new(placeholder: false)
|
90 |
|
91 |
Kino.listen(form, fn %{data: %{audio: audio}} ->
|
92 |
if audio do
|
93 |
+
Kino.Frame.render(audio_frame, Kino.Text.new("Running..."))
|
94 |
|
95 |
audio =
|
96 |
audio.data
|
|
|
99 |
|> Nx.mean(axes: [1])
|
100 |
|
101 |
%{results: [%{text: generated_text}]} = Nx.Serving.run(serving, audio)
|
102 |
+
Kino.Frame.render(audio_frame, Kino.Markdown.new("**Audio Content**: #{generated_text}"))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
103 |
|
104 |
+
Kino.Frame.render(summary_frame, Kino.Markdown.new("Running"))
|
|
|
|
|
|
|
|
|
|
|
105 |
|
106 |
+
result = Ollama.generate("Please summary the text: #{generated_text}")
|
|
|
|
|
|
|
107 |
|
108 |
+
Kino.Frame.render(summary_frame, Kino.Markdown.new("**Summary**: #{result}"))
|
109 |
end
|
110 |
end)
|
111 |
|
112 |
+
Kino.Layout.grid([form, audio_frame, summary_frame], boxed: true, gap: 16)
|
113 |
```
|