Spaces:
Build error
Build error
File size: 14,538 Bytes
f6a4838 9941726 f6a4838 9941726 9f063ed 5118ee2 9f063ed 9941726 9f063ed 5118ee2 9f063ed 9941726 9f063ed 5118ee2 9f063ed 9941726 5118ee2 9941726 9f063ed 5118ee2 9f063ed 9941726 d6240cf 9f063ed 5118ee2 9f063ed 9941726 d6240cf 9941726 d6240cf 9941726 a12de67 9941726 9f063ed 5118ee2 9f063ed 9941726 9f063ed 5118ee2 9f063ed 9941726 a12de67 9941726 d6240cf 9f063ed 5118ee2 9f063ed 9941726 a12de67 9941726 d6240cf 5118ee2 9941726 d6240cf 5118ee2 d6240cf 9f063ed 9941726 5118ee2 d6240cf 5118ee2 d6240cf 5118ee2 9941726 5118ee2 d6240cf 5118ee2 d6240cf 5118ee2 d6240cf 9941726 d6240cf f6a4838 5118ee2 d6240cf 5118ee2 | 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 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 | import gradio as gr
import requests
import base64
import json
import os
from typing import Dict, Any
from pydub import AudioSegment
#---------------------------------------------------------------------------------------------------------------------------------
def read_audio_file(file_path: str) -> bytes:
"""
Reads an audio file from the specified file path.
Args:
file_path (str): The path to the audio file.
Returns:
bytes: The content of the audio file.
Raises:
IOError: If there is an error reading the audio file.
"""
try:
with open(file_path, "rb") as audio_file:
return audio_file.read()
except IOError as e:
raise IOError(f"Erreur de lecture du fichier audio : {e}")
#---------------------------------------------------------------------------------------------------------------------------------
def prepare_config(diarization: bool = False, word_time_offsets: bool = False) -> Dict[str, Any]:
"""
Prepares the configuration for the audio transcription.
Args:
diarization (bool): Whether to add speaker diarization to the configuration.
word_time_offsets (bool): Whether to enable word time offsets in the configuration.
Returns:
Dict[str, Any]: The prepared configuration.
"""
return {
"add_speaker_diarization_to_config": diarization,
"enable_word_time_offsets": word_time_offsets,
"add_word_boosting_to_config": None,
}
#---------------------------------------------------------------------------------------------------------------------------------
def transcribe_audio(url: str, api_key: str, audio_content: bytes, config: Dict[str, Any]) -> Dict[str, Any]:
"""
Sends a request to the API to transcribe the audio content.
Args:
url (str): The API endpoint URL.
api_key (str): The API key for authentication.
audio_content (bytes): The audio content to be transcribed.
config (Dict[str, Any]): The configuration for the transcription.
Returns:
Dict[str, Any]: The transcription result.
Raises:
Exception: If there is an error during the API request.
"""
headers = {"X-Ovh-Application": api_key}
config_json = json.dumps(config)
files = {
'audio': ('audio.wav', audio_content, 'audio/wav'),
'config': ('config.json', config_json, 'application/json')
}
try:
response = requests.post(url, files=files, headers=headers)
response.raise_for_status() # Raise an exception for bad status codes
return response.json()
except requests.exceptions.RequestException as e:
raise Exception(f"Erreur lors de la requête à l'API : {e}")
#---------------------------------------------------------------------------------------------------------------------------------
def process_transcription(transcription: Dict[str, Any]) -> str:
"""
Processes the transcription result and returns a concatenated transcript.
Args:
transcription (Dict[str, Any]): The transcription result.
Returns:
str: The concatenated transcript.
"""
full_transcript = ""
for sentence in transcription:
for alternative in sentence["alternatives"]:
full_transcript += alternative["transcript"] + " "
return full_transcript.strip()
#---------------------------------------------------------------------------------------------------------------------------------
def summary(content: str, context: str, choice: str) -> str:
"""
Generates a summary for the given content using the specified language model.
Args:
content (str): The content to be summarized.
choice (str): The language model choice.
Returns:
str: The generated summary.
Raises:
Exception: If there is an error during the API request.
"""
if choice == "Llama-3-70B-Instruct":
url = "https://llama-3-70b-instruct.endpoints.kepler.ai.cloud.ovh.net/api/openai_compat/v1/chat/completions"
model="Meta-Llama-3-70B-Instruct"
elif choice == "Llama-3-8B-Instruct":
url = "https://Llama-3-8B-Instruct.endpoints.kepler.ai.cloud.ovh.net/api/openai_compat/v1/chat/completions"
model="Meta-Llama-3-8B-Instruct"
elif choice == "Mistral-7B-Instruct":
url = "https://Mistral-7B-Instruct-v02.endpoints.kepler.ai.cloud.ovh.net/api/openai_compat/v1/chat/completions"
model="Mistral-7B-Instruct-v0.2"
elif choice == "Mixtral-8x22b-Instruct":
url = "https://Mixtral-8x22B-Instruct-v01.endpoints.kepler.ai.cloud.ovh.net/api/openai_compat/v1/chat/completions"
model="Mixtral-8x22B-Instruct-v0.1"
elif choice == "Mixtral-8x7b-instruct":
url = "https://mixtral-8x7b-instruct-v01.endpoints.kepler.ai.cloud.ovh.net/api/openai_compat/v1/chat/completions"
model="Mixtral-8x7B-Instruct-v0.1"
else:
url = "https://llama-3-70b-instruct.endpoints.kepler.ai.cloud.ovh.net/api/openai_compat/v1/chat/completions"
model="Meta-Llama-3-70B-Instruct"
prompt = f"""
Vous êtes mon assistant et votre seule mission est de me fournir un résumé du texte situé entre <>.
Le texte supplémentaire présent entre ## (s'il n'est pas vide) fournit des éléments de contexte à ce texte.
Veuillez fournir votre réponse en français uniquement, avec une longueur maximale de 5 phrases.
Texte : <{content}>
Contexte : #{context}#
"""
payload = {
"max_tokens": 512,
"messages": [
{
"content": prompt,
"name": "User",
"role": "user"
}
],
"model": model,
"temperature": 0,
}
headers = {
"Content-Type": "application/json",
"Authorization": f"Bearer {os.getenv('OVH_API_KEY')}",
}
response = requests.post(url, json=payload, headers=headers)
if response.status_code == 200:
response_data = response.json()
choices = response_data["choices"]
for choice in choices:
return choice["message"]["content"]
else:
return f"Error: {response.status_code}"
#---------------------------------------------------------------------------------------------------------------------------------
def choose_language(choice: str) -> str:
"""
Returns the appropriate API URL based on the selected language.
Args:
choice (str): The language choice.
Returns:
str: The API URL for the selected language.
"""
languages = {
"fr": "https://nvr-asr-fr-fr.endpoints.kepler.ai.cloud.ovh.net/api/v1/asr/recognize",
"en": "https://nvr-asr-en-gb.endpoints.kepler.ai.cloud.ovh.net/api/v1/asr/recognize",
"en/us": "https://nvr-asr-en-us.endpoints.kepler.ai.cloud.ovh.net/api/v1/asr/recognize",
"de": "https://nvr-asr-de-de.endpoints.kepler.ai.cloud.ovh.net/api/v1/asr/recognize",
"es": "https://nvr-asr-es-es.endpoints.kepler.ai.cloud.ovh.net/api/v1/asr/recognize",
"it": "https://nvr-asr-it-it.endpoints.kepler.ai.cloud.ovh.net/api/v1/asr/recognize"
}
return languages.get(choice, "https://nvr-asr-fr-fr.endpoints.kepler.ai.cloud.ovh.net/api/v1/asr/recognize")
#---------------------------------------------------------------------------------------------------------------------------------
def convert_audio_to_16000hz(input_file: str) -> str:
"""
Converts the given audio file to 16000 Hz and returns the path to the converted file.
Args:
input_file (str): The path to the input audio file.
Returns:
str: The path to the converted audio file.
Raises:
Exception: If there is an error during the conversion.
"""
try:
audio = AudioSegment.from_file(input_file)
audio = audio.set_channels(1).set_frame_rate(16000)
output_file = "processed_audio.wav"
audio.export(output_file, format="wav")
return output_file
except Exception as e:
raise Exception(f"Erreur lors de la conversion du fichier audio : {e}")
#---------------------------------------------------------------------------------------------------------------------------------
def transcribe_and_summarize(audio_file, language_choice, llm_choice, context):
"""
Transcribes the audio file and summarizes the transcription using the specified language model.
Args:
audio_file: The path to the audio file.
language_choice: The selected language for transcription.
llm_choice: The selected language model for summarization.
Returns:
tuple: The transcription and the summary.
Raises:
Exception: If there is an error during the process.
"""
try:
api_key = os.environ.get("OVH_API_KEY", "") # Utiliser une variable d'environnement pour la clé API
processed_audio = convert_audio_to_16000hz(audio_file)
audio_content = read_audio_file(processed_audio)
url = choose_language(language_choice)
config = prepare_config()
transcription = transcribe_audio(url, api_key, audio_content, config)
result = process_transcription(transcription)
summary_result = summary(content=result, context=context, choice=llm_choice)
return result, summary_result[:-10]
except Exception as e:
return f"Une erreur est survenue : {e}", ""
#---------------------------------------------------------------------------------------------------------------------------------
# Gradio Interface
def process_input(choice, audio_file=None, text_input=None, lang_choice=None, llm_choice=None, context_input=None):
"""
Processes the input based on the user's choice (Audio or Text).
Args:
choice: The type of input (Audio or Text).
audio_file: The audio file input.
text_input: The text input.
lang_choice: The language choice for audio transcription.
llm_choice: The language model choice for summarization.
Returns:
tuple: The transcription (if audio) and the summary.
"""
max_chars = 200
if len(context_input) > max_chars:
return "", "Le contexte ne peut pas excéder 200 caractères."
else :
if choice == "Audio":
if audio_file is not None:
return transcribe_and_summarize(audio_file, lang_choice, llm_choice, context=context_input,)
return "Veuillez fournir une piste audio", ""
elif choice == "Texte":
summary_result = summary(content=text_input, context=context_input, choice=llm_choice)
return "", summary_result[:-10]
else:
return "Choix invalide", ""
#---------------------------------------------------------------------------------------------------------------------------------
language_choices = ["fr", "en", "en/us", "de", "es", "it"]
llm_choices = ["Llama-3-70B-Instruct", "Llama-3-8B-Instruct", "Mistral-7B-Instruct", "Mixtral-8x22b-Instruct", "Mixtral-8x7b-instruct"]
#---------------------------------------------------------------------------------------------------------------------------------
with gr.Blocks() as iface:
choice_input = gr.Radio(choices=["Audio", "Texte"], label="Type d'entrée")
audio_input = gr.Audio(sources=["microphone", "upload"], type="filepath", visible=False, label="Source audio")
text_input = gr.Textbox(lines=5, placeholder="Entrez le texte ici...", visible=False, label='Source texte')
lang_dropdown = gr.Dropdown(value=language_choices[0], choices=language_choices, label="Choisissez la langue de l'audio", visible=False)
llm_dropdown = gr.Dropdown(value=llm_choices[0], choices=llm_choices, label="Choisissez le LLM pour effectuer le résumé", visible=False)
context_input = gr.Textbox(lines=8, placeholder="Entrez le contexte ici (optionnel).\n\nExemples :\nIl s'agit d'un appel téléphonique professionnel entre...\nIl s'agit d'une émission de radio qui parle de...\nCe texte scientifique parle de...\n\nTaille du contexte limitée à 200 caractères", visible=False, label="Contexte du contenu")
transcription_output = gr.Textbox(label="Transcription", visible=False)
summary_output = gr.Textbox(label="Résumé", visible=False)
def update_visibility(choice):
if choice == "Audio":
return gr.update(value=None, visible=True), gr.update(visible=False), gr.update(visible=True), gr.update(visible=True), gr.update(visible=True), gr.update(visible=True), gr.update(value="", visible=True)
elif choice == "Texte":
return gr.update(visible=False), gr.update(value="", visible=True), gr.update(visible=False), gr.update(visible=True), gr.update(visible=True), gr.update(visible=False), gr.update(value="", visible=True)
else:
return gr.update(visible=False), gr.update(visible=False), gr.update(visible=False), gr.update(visible=False), gr.update(visible=False), gr.update(visible=False), gr.update(visible=False)
choice_input.change(fn=update_visibility, inputs=choice_input, outputs=[audio_input, text_input, lang_dropdown, llm_dropdown, context_input, transcription_output, summary_output])
gr.Interface(
fn=process_input,
inputs=[
choice_input,
audio_input,
text_input,
lang_dropdown,
llm_dropdown,
context_input
],
outputs=[
transcription_output,
summary_output
],
title="""
Créer un résumé à partir d'un texte ou d'un enregistrement audio<br>
Utilisation des <a href="https://endpoints.ai.cloud.ovh.net/" target="_blank">AI Endpoints d'OVHcloud</a><br><br>
Codé par <a href="https://emmanuelmancuso.com/" target="_blank">Emmanuel Mancuso</a>👋🏼
""",
description="""
Téléchargez un fichier audio 🔊 ou entrez un texte 📃<br>
choisissez la langue pour l'audio <br>
choisissez le modèle de LLM pour obtenir le résumé 🚀
""",
allow_flagging='never'
)
#---------------------------------------------------------------------------------------------------------------------------------
iface.launch()
|