commit b3a619a898c300413e794f65c416938edf2534e4 Author: Damien A Date: Wed Apr 17 09:57:32 2024 +0200 Project push diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..11781e3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +# Virtual Env +.venv + +# Local data +.DS_Store diff --git a/README.md b/README.md new file mode 100644 index 0000000..fdc3536 --- /dev/null +++ b/README.md @@ -0,0 +1,78 @@ +# Audio Summary with local LLM + +This tool is designed to provide a quick and concise summary of audio and video files. It supports summarizing content either from a local file or directly from YouTube. The tool uses Whisper for transcription and a local version of Mistral AI (Ollama) for generating summaries. + +> [!TIP] +> It is possible to change the model you wish to use. +> To do this, change the `OLLAMA_MODEL` variable, and download the associated model via [ollama](https://github.com/ollama/ollama) + +## Features + +- **YouTube Integration**: Download and summarize content directly from YouTube. +- **Local File Support**: Summarize audio files available on your local disk. +- **Transcription**: Converts audio content to text using Whisper. +- **Summarization**: Generates a concise summary using Mistral AI (Ollama). + +## Prerequisites + +Before you start using this tool, you need to install the following dependencies: + +- Python 3.8 or higher +- `pytube` for downloading videos from YouTube. +- `pathlib`for local file +- `openai-whisper` for audio transcription. +- [Ollama](https://ollama.com) for LLM model management. +- `ffmpeg` (required for whisper) + +## Installation + +### Python Requirements + +Clone the repository and install the required Python packages: + +```bash +git clone https://github.com/damienarnodo/audio-summary-with-local-LLM.git +cd audio-summary-with-local-LLM +pip install -r src/requirements.txt +``` + +### LLM Requierement + +[Download and install](https://ollama.com) Ollama to carry out LLM Management +More details about LLM model supported can be discribe on the Ollama [github](https://github.com/ollama/ollama). + +Download and use Mistral model : + +```bash +ollama pull mistral + +## Test the access : +ollama run mistral "tell me a joke" +``` + +## Usage + +The tool can be executed with the following command line options: + +- `--from-youtube`: To download and summarize a video from YouTube. +- `--from-local`: To load and summarize an audio or video file from the local disk. + +### Examples + +1. **Summarizing a YouTube video:** + + ```bash + python src/summary.py --from-youtube + ``` + +2. **Summarizing a local audio file:** + + ```bash + python src/summary.py --from-local + ``` + +The output summary will be saved in a markdown file in the specified output directory. + +## Output + +The summarized content is saved as a markdown file named `summary.md` in the current working directory. This file includes the transcribed text and its corresponding summary. diff --git a/src/requirements.txt b/src/requirements.txt new file mode 100644 index 0000000..9822881 --- /dev/null +++ b/src/requirements.txt @@ -0,0 +1,3 @@ +openai-whisper==20231117 +pytube==15.0.0 +ollama==0.1.8 \ No newline at end of file diff --git a/src/summary.py b/src/summary.py new file mode 100644 index 0000000..fb5c252 --- /dev/null +++ b/src/summary.py @@ -0,0 +1,98 @@ +import whisper +import ollama +import argparse +from pytube import YouTube +from pathlib import Path + + +WHISPER_MODEL = "base" +OLLAMA_MODEL = "mistral" + +# Function to download a video from YouTube +def download_from_youtube(url: str, path: str): + yt = YouTube(url) + # Filter streams to get the highest resolution progressive mp4 stream + stream = yt.streams.filter(file_extension="mp4", only_audio=True).first() + # Download the video to the specified path + stream.download(Path(path), filename="to_transcribe.mp4") + +# Function to transcribe an audio file using the Whisper model +def transcribe_file(file_path: str, output_file: str) -> str: + # Load the Whisper model + model = whisper.load_model(WHISPER_MODEL) + # Transcribe the audio file + transcribe = model.transcribe(file_path) + # Save the transcribed text to the specified temporary file + with open(output_file, 'w') as tmp_file: + tmp_file.write(transcribe["text"]) + print(f"Transcription saved to file: {output_file}") + # Return the transcribed text + return transcribe["text"] + +# Function to summarize a text using the Ollama model +def summarize_text(text: str, output_path: str) -> str: + # Define the system prompt for the Ollama model + system_prompt = f"I would like for you to assume the role of a Technical Expert" + # Define the user prompt for the Ollama model + user_prompt = f"""Generate a concise summary of the text below. + Text : {text} + Add a title to the summary. + Make sure your summary has useful and true information about the main points of the topic. + Begin with a short introduction explaining the topic. If you can, use bullet points to list important details, + and finish your summary with a concluding sentence.""" + + # Use the Ollama model to generate a summary + response = ollama.chat( + model=OLLAMA_MODEL, + messages=[ + { + "role": "system", + "content": system_prompt, + }, + { + "role": "user", + "content": user_prompt, + }, + ], + ) + # Print the generated summary + return response["message"]["content"] + +def main(): + # Parse command line arguments + parser = argparse.ArgumentParser(description="Download, transcribe, and summarize audio or video files.") + group = parser.add_mutually_exclusive_group(required=True) + group.add_argument("--from-youtube", type=str, help="YouTube URL to download.") + group.add_argument("--from-local", type=str, help="Path to the local audio file.") + parser.add_argument("--output", type=str, default="./summary.md", help="Output markdown file path.") + + args = parser.parse_args() + + # Set up data directory + data_directory = Path("tmp") + + if args.from_youtube: + # Download from YouTube + print(f"Downloading YouTube video from {args.from_youtube}") + download_from_youtube(args.from_youtube, str(data_directory)) + file_path = data_directory / "to_transcribe.mp4" + elif args.from_local: + # Use local file + file_path = args.from_local + + print(f"Transcribing file: {file_path}") + # Transcribe the audio file + transcript = transcribe_file(str(file_path), data_directory / "transcript.txt") + + print("Generating summary...") + # Generate summary + summary = summarize_text(transcript, "./") + + # Write summary to a markdown file + with open(args.output, "w") as md_file: + md_file.write("# Summary\n\n") + md_file.write(summary) + print(f"Summary written to {args.output}") + +if __name__ == "__main__": + main()