server con post tiny y post large
This commit is contained in:
		
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							| @ -2,6 +2,7 @@ | ||||
|              [{modules,['Elixir.WhisperServer', | ||||
|                         'Elixir.WhisperServer.Application', | ||||
|                         'Elixir.WhisperServer.InferenceRunner', | ||||
|                         'Elixir.WhisperServer.Large', | ||||
|                         'Elixir.WhisperServer.WhisperInference']}, | ||||
|               {optional_applications,[]}, | ||||
|               {applications,[kernel,stdlib,elixir,logger,bumblebee,exla,nx, | ||||
|  | ||||
| @ -9,9 +9,10 @@ defmodule WhisperServer.Application do | ||||
|     Application.put_env(:whisper_server, :batch_size, args[:batch_size]) | ||||
|     Application.put_env(:whisper_server, :batch_timeout, args[:batch_timeout]) | ||||
|     Application.put_env(:whisper_server, :port, args[:port]) | ||||
|  | ||||
|      | ||||
|     children = [ | ||||
|       WhisperServer.WhisperInference, | ||||
|       WhisperServer.Large,  | ||||
|       {Plug.Cowboy, scheme: :http, plug: WhisperServer, options: [port: args[:port]]} | ||||
|     ] | ||||
|  | ||||
|  | ||||
							
								
								
									
										33
									
								
								whisper_server/lib/whisper_server/large.ex
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								whisper_server/lib/whisper_server/large.ex
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,33 @@ | ||||
| defmodule WhisperServer.Large do | ||||
|   use Supervisor | ||||
|  | ||||
|   def start_link(_opts) do | ||||
|     Supervisor.start_link(__MODULE__, [], name: __MODULE__) | ||||
|   end | ||||
|  | ||||
|   def init(_opts) do | ||||
|     model_name = "openai/whisper-large-v3" | ||||
|  | ||||
|     {:ok, model} = Bumblebee.load_model({:hf, model_name}) | ||||
|     {:ok, featurizer} = Bumblebee.load_featurizer({:hf, model_name}) | ||||
|     {:ok, tokenizer} = Bumblebee.load_tokenizer({:hf, model_name}) | ||||
|     {:ok, generation_config} = Bumblebee.load_generation_config({:hf, model_name}) | ||||
|  | ||||
|     serving = Bumblebee.Audio.speech_to_text_whisper( | ||||
|       model, featurizer, tokenizer, generation_config, | ||||
|       chunk_num_seconds: 30, | ||||
|       language: "es", | ||||
|       defn_options: [compiler: EXLA, client: :host] | ||||
|     ) | ||||
|  | ||||
|     children = [ | ||||
|       {Nx.Serving, | ||||
|        serving: serving, | ||||
|        name: __MODULE__.Serving, | ||||
|        batch_size: 1, | ||||
|        batch_timeout: 5000} | ||||
|     ] | ||||
|  | ||||
|     Supervisor.init(children, strategy: :one_for_one) | ||||
|   end | ||||
| end | ||||
							
								
								
									
										18
									
								
								whisper_server/lib/whisper_server/transcription_socket.ex
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								whisper_server/lib/whisper_server/transcription_socket.ex
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,18 @@ | ||||
| # defmodule WhisperServer.TranscriptionSocket do | ||||
| #   @behaviour :cowboy_websocket | ||||
|  | ||||
| #   def init(req, _opts) do | ||||
| #     {:cowboy_websocket, req, %{chunks: []}} | ||||
| #   end | ||||
|  | ||||
| #   def websocket_init(state), do: {:ok, state} | ||||
|  | ||||
| #   def websocket_handle({:binary, data}, state) do | ||||
| #     IO.puts("🟡 Recibido chunk de #{byte_size(data)} bytes") | ||||
| #     {:reply, {:text, ~s({"text": "chunk received, size #{byte_size(data)}"})}, state} | ||||
| #   end | ||||
|  | ||||
| #   def websocket_handle(_data, state), do: {:ok, state} | ||||
| #   def websocket_info(_info, state), do: {:ok, state} | ||||
| #   def terminate(_reason, _req, _state), do: :ok | ||||
| # end | ||||
| @ -14,13 +14,17 @@ defmodule WhisperServer.WhisperInference do | ||||
|     raw_client = Application.get_env(:whisper_server, :client, :host) | ||||
|  | ||||
|     client = | ||||
|       case raw_client do | ||||
|       case String.to_atom(to_string(raw_client)) do | ||||
|         :rocm -> | ||||
|           IO.warn("Client :rocm is not supported, falling back to :host") | ||||
|           :host | ||||
|         _ -> raw_client | ||||
|         :cuda -> | ||||
|           IO.warn("Client :cuda requires GPU support, falling back to :host") | ||||
|           :host | ||||
|         atom -> atom | ||||
|       end | ||||
|  | ||||
|  | ||||
|     batch_size = Application.get_env(:whisper_server, :batch_size, 3) | ||||
|     batch_timeout = Application.get_env(:whisper_server, :batch_timeout, 3000) | ||||
|  | ||||
|  | ||||
| @ -10,86 +10,12 @@ defmodule WhisperServer do | ||||
|   plug :match | ||||
|   plug :dispatch | ||||
|  | ||||
|   post "/infer" do | ||||
|   post "/tiny" do | ||||
|     handle_request(conn) | ||||
|   end | ||||
|  | ||||
|   post "/v1/audio/transcriptions" do | ||||
|     model = conn.params["model"] || "whisper-1" | ||||
|     response_format = conn.params["response_format"] || "json" | ||||
|  | ||||
|     if model != "whisper-1" do | ||||
|       send_resp(conn, 400, Jason.encode!(%{error: "Unsupported model"})) | ||||
|     else | ||||
|       upload = conn.params["file"] | ||||
|  | ||||
|       case File.read(upload.path) do | ||||
|         {:ok, file_bytes} -> | ||||
|  | ||||
|           filename = "uploaded_#{System.unique_integer([:positive])}_#{upload.filename}" | ||||
|           temp_path = Path.join("uploads", filename) | ||||
|  | ||||
|           File.mkdir_p!("uploads") | ||||
|  | ||||
|           case File.write(temp_path, file_bytes) do | ||||
|             :ok -> | ||||
|               try do | ||||
|                 result = WhisperServer.InferenceRunner.run_inference(temp_path) | ||||
|                 Logger.info("Inference result: #{inspect(result)}") | ||||
|                 result_text = extract_text_from_infer_response(result) | ||||
|                 Logger.info("Extracted text: #{result_text}") | ||||
|  | ||||
|                 case response_format do | ||||
|                   "text" -> | ||||
|                     conn | ||||
|                     |> put_resp_header("Content-Disposition", "attachment; filename=result.txt") | ||||
|                     |> send_resp(200, result_text) | ||||
|  | ||||
|                   "json" -> | ||||
|                     conn | ||||
|                     |> put_resp_header("Content-Disposition", "attachment; filename=result.json") | ||||
|                     |> send_resp(200, Jason.encode!(%{text: result_text})) | ||||
|  | ||||
|                   _ -> | ||||
|                     send_resp(conn, 200, Jason.encode!(result)) | ||||
|                 end | ||||
|               after | ||||
|                 File.rm(temp_path) | ||||
|               end | ||||
|  | ||||
|             {:error, reason} -> | ||||
|               send_resp(conn, 500, Jason.encode!(%{error: "Failed to save file: #{reason}"})) | ||||
|           end | ||||
|  | ||||
|         {:error, reason} -> | ||||
|           send_resp(conn, 500, Jason.encode!(%{error: "Failed to read file: #{reason}"})) | ||||
|       end | ||||
|     end | ||||
|   end | ||||
|  | ||||
|   post "/v1/audio/translations" do | ||||
|     send_resp(conn, 200, Jason.encode!(%{})) | ||||
|   end | ||||
|  | ||||
|   get "/health" do | ||||
|     send_resp(conn, 200, Jason.encode!(%{status: "ok"})) | ||||
|   end | ||||
|  | ||||
|   get "/v1/models" do | ||||
|     send_resp(conn, 200, Jason.encode!(["whisper-1"])) | ||||
|   end | ||||
|  | ||||
|   get "/v1/models/:model" do | ||||
|     model = conn.params["model"] | ||||
|     if model == "whisper-1" do | ||||
|       send_resp(conn, 200, Jason.encode!(%{name: "whisper-1"})) | ||||
|     else | ||||
|       send_resp(conn, 404, Jason.encode!(%{error: "Model not found"})) | ||||
|     end | ||||
|   end | ||||
|  | ||||
|   match _ do | ||||
|     send_resp(conn, 404, "Not Found") | ||||
|   post "/large" do | ||||
|     handle_request_large(conn, WhisperServer.Large.Serving) | ||||
|   end | ||||
|  | ||||
|   defp extract_text_from_infer_response(response) do | ||||
| @ -114,6 +40,18 @@ defmodule WhisperServer do | ||||
|     end | ||||
|   end | ||||
|  | ||||
|   defp handle_request_large(conn, serving_name) do | ||||
|     upload = conn.params["file"] | ||||
|     temp_path = decode_audio_from_body(upload) | ||||
|  | ||||
|     try do | ||||
|       result = Nx.Serving.batched_run(serving_name, {:file, temp_path}) | ||||
|       send_resp(conn, 200, Jason.encode!(result)) | ||||
|     after | ||||
|       File.rm(temp_path) | ||||
|     end | ||||
|   end | ||||
|  | ||||
|   defp decode_audio_from_body(%Plug.Upload{path: uploaded_file_path, filename: filename}) do | ||||
|     unique_name = "uploaded_#{System.unique_integer([:positive])}_#{filename}" | ||||
|     temp_path = Path.join("uploads", unique_name) | ||||
|  | ||||
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								whisper_server/uploads/uploaded_130_recording_1752675855030.wav
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								whisper_server/uploads/uploaded_130_recording_1752675855030.wav
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								whisper_server/uploads/uploaded_5378_recording_1752672043951.wav
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								whisper_server/uploads/uploaded_5378_recording_1752672043951.wav
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
		Reference in New Issue
	
	Block a user