En esta publicación, voy a compartir cómo puedes crear una aplicación simple pero poderosa que usa LLM para convertir tu contenido escrito en diapositivas de PowerPoint concisas. La parte buena: incluso puedes ejecutar tu propio servicio LLM, por lo que
- Mantienes tus datos privados y
- No hay costo para llamar a las API de LLM.
Acceder al poder de GenSlide es muy sencillo. Siga estos pasos para configurar y ejecutar esta herramienta en su equipo.
Comience creando la carpeta del proyecto en su máquina local:
mkdir GenSlide
Después de completar todos los pasos, la estructura final del archivo se vería así:
GenSlide
├── frontend
│ ├── llm_call.py
│ ├── slide_deck.py
│ ├── slide_gen.py
│ └── ui.py
├── llm-service
│ ├── consts.py
│ └── gpt.py
└── requirements.txt
El primer archivo que creamos contiene una lista de paquetes. Crea un archivo llamado requirements.txtAgregue las siguientes dependencias del paquete al archivo.
pillow==10.3.0
lxml==5.2.2
XlsxWriter==3.2.0
python-pptx==0.6.23
gpt4all==2.7.0
Flask==2.2.5
Flask-Cors==4.0.0
streamlit==1.34.0
En concreto, estamos aprovechando la gpt4all Paquete para ejecutar un servidor de modelo de lenguaje grande (LLM) en una máquina local. Para profundizar en gpt4allconsulte su documentación oficial.
También usamos streamlit paquete para crear la interfaz de usuario.
A continuación, cree un entorno virtual e instale los paquetes necesarios:
python -m venv ./venv
source ./venv/bin/activate
pip install -r requirements.txt
Nota: Asegúrese de estar utilizando una versión de Python distinta a 3.9.7como streamlit es incompatible con esa versión. Para este tutorial usé la versión de Python 3.12.
Nuestro servicio LLM debería poder recibir un texto como entrada y generar un resumen de los puntos clave del texto como salida. Debería organizar la salida en una lista de objetos JSON. Especificaremos estos detalles en la definición del mensaje. Primero, crearemos una carpeta para el servicio LLM.
mkdir llm-service
Organizamos la implementación en dos .py archivos en esta carpeta.
- constantes.py
Aquí debemos definir el nombre del modelo LLM que queremos utilizar. Puedes ver la lista de modelos que se pueden utilizar aquí: https://docs.gpt4all.io/gpt4all_python/home.html#load-llmEl modelo Llama de Meta funciona bien para esta tarea.
LLM_MODEL_NAME = "Meta-Llama-3-8B-Instruct.Q4_0.gguf"
También definimos aquí el mensaje de aviso que incluye las instrucciones para el LLM, así como algunos ejemplos del resultado deseado. Solicitamos que el resultado esté en formato JSON, para que nos resulte más fácil procesarlo y crear una presentación.
PROMPT = """
Summarize the input text and arrange it in an array of JSON objects to to be suitable for a powerpoint presentation.
Determine the needed number of json objects (slides) based on the length of the text.
Each key point in a slide should be limited to up to 10 words.
Consider maximum of 5 bullet points per slide.
Return the response as an array of json objects.
The first item in the list must be a json object for the title slide.
This is a sample of such json object:
{
"id": 1,
"title_text": "My Presentation Title",
"subtitle_text": "My presentation subtitle",
"is_title_slide": "yes"
}
And here is the sample of json data for slides:
{"id": 2, title_text": "Slide 1 Title", "text": ["Bullet 1", "Bullet 2"]},
{"id": 3, title_text": "Slide 2 Title", "text": ["Bullet 1", "Bullet 2", "Bullet 3"]}Please make sure the json object is correct and valid.
Don't output explanation. I just need the JSON array as your output.
"""
2. gpt.py
Aquí queremos crear una aplicación Flask que reciba solicitudes HTTP POST de los clientes y llame al modelo LLM para extraer el resumen en una representación JSON.
Lo primero es lo primero: importar dependencias.
from flask import Flask, request
from flask_cors import CORS
import traceback
import logging
import os
from consts import LLM_MODEL_NAME, PROMPTfrom gpt4all import GPT4All
Defina la IP del host, el puerto, la aplicación Flask y permita el uso compartido de recursos entre orígenes.
logger = logging.getLogger()HOST = '0.0.0.0'
PORT = 8081
app = Flask(__name__)
CORS(app)
Defina una carpeta base para almacenar el modelo LLM. Aquí con “RUTA_DEL_MODELO” Variable de entorno: sobrescribimos la ubicación predeterminada de los modelos establecida por gpt4all. Ahora los modelos se almacenarán en la carpeta del proyecto en “gpt_models/gpt4all/”Cuando se crea una instancia de la clase GPT4All por primera vez, buscará la nombre del modelo en el ruta_del_modelo (su argumento), si no lo encuentra, lo buscaré RUTA_DEL_MODELO. Si no lo encuentra, comenzará a descargar el modelo.
try:
base_folder = os.path.dirname(__file__)
base_folder = os.path.dirname(base_folder)
gpt_models_folder = os.path.join(base_folder, "gpt_models/gpt4all/")
if not os.path.exists(gpt_models_folder):
os.makedirs(gpt_models_folder, exist_ok=True)
model_folder = os.environ.get("MODEL_PATH", gpt_models_folder)
llm_model = GPT4All(model_name=LLM_MODEL_NAME, model_path=model_folder)
except Exception:
raise ValueError("Error loading LLM model.")
Definir una función para llamar a la generar() función del modelo LLM y devolver la respuesta. Podemos establecer parámetros opcionales como temperatura y máximo_tokens.
def generate_text(content):
prompt = PROMPT + f"\n{content}"with llm_model.chat_session():
output = llm_model.generate(prompt, temp=0.7, max_tokens=1024)
output = output.strip()
return output
Defina una API POST para recibir las solicitudes de los clientes. Las solicitudes se presentan en forma de objetos JSON. {“contenido”:”…”}Usaremos esto “contenido” valor y llamar al generar_texto() Método definido anteriormente. Si todo va bien, enviamos la salida junto con un código de estado HTTP 200 (OK). De lo contrario, se devuelve un mensaje de “Error” y el código de estado 500.
@app.route('/api/completion', methods=['POST'])
def completion():
try:
req = request.get_json()
words = req.get('content')
if not words:
raise ValueError("No input word.")
output = generate_text(words)
return output, 200
except Exception:
logger.error(traceback.format_exc())
return "Error", 500
Ejecute la aplicación Flask.
if __name__ == '__main__':
# run web server
app.run(host=HOST,
debug=True, # automatic reloading enabled
port=PORT)
El frontend es donde recibimos la información del usuario e interactuamos con el servicio LLM y finalmente creamos las diapositivas de PowerPoint.
Dentro de la carpeta del proyecto, crea una carpeta llamada frontend.
mkdir frontend
La implementación se divide en cuatro archivos Python.
- llm_call.py
Aquí es donde enviamos las solicitudes POST al servidor LLM. Configuramos nuestro servidor LLM en servidor local puerto 8081Encerramos el texto de entrada en un objeto JSON con la clave “contenido”La salida de la llamada debe ser una cadena JSON.
import requestsURL = "http://127.0.0.1:8081"
CHAT_API_ENDPOINT = f"{URL}/api/completion"
def chat_completion_request(content):
headers = {'Content-type': 'application/json'}
data = {'content': content}
req = requests.post(url=CHAT_API_ENDPOINT, headers=headers, json=data)
json_extracted = req.text
return json_extracted
2. diapositiva_deck.py
Aquí usamos pptx Paquete para crear diapositivas de PowerPoint. La lista de objetos JSON contiene la información para agregar diapositivas a la presentación. Para obtener información detallada sobre pptx El paquete se refiere a su documentación.
import osfrom pptx import Presentation
from pptx.util import Inches
class SlideDeck:
def __init__(self, output_folder="generated"):
self.prs = Presentation()
self.output_folder = output_folder
def add_slide(self, slide_data):
prs = self.prs
bullet_slide_layout = prs.slide_layouts[1]
slide = prs.slides.add_slide(bullet_slide_layout)
shapes = slide.shapes
# Title
title_shape = shapes.title
title_shape.text = slide_data.get("title_text", "")
# Body
if "text" in slide_data:
body_shape = shapes.placeholders[1]
tf = body_shape.text_frame
for bullet in slide_data.get("text", []):
p = tf.add_paragraph()
p.text = bullet
p.level = 0
if "p1" in slide_data:
p = tf.add_paragraph()
p.text = slide_data.get("p1")
p.level = 1
if "img_path" in slide_data:
cur_left = 6
for img_path in slide_data.get("img_path", []):
top = Inches(2)
left = Inches(cur_left)
height = Inches(4)
pic = slide.shapes.add_picture(img_path, left, top, height=height)
cur_left += 1
def add_title_slide(self, title_page_data):
# title slide
prs = self.prs
title_slide_layout = prs.slide_layouts[0]
slide = prs.slides.add_slide(title_slide_layout)
title = slide.shapes.title
subtitle = slide.placeholders[1]
if "title_text" in title_page_data:
title.text = title_page_data.get("title_text")
if "subtitle_text" in title_page_data:
subtitle.text = title_page_data.get("subtitle_text")
def create_presentation(self, title_slide_info, slide_pages_data=[]):
try:
file_name = title_slide_info.get("title_text").\
lower().replace(",", "").replace(" ", "-")
file_name += ".pptx"
file_name = os.path.join(self.output_folder, file_name)
self.add_title_slide(title_slide_info)
for slide_data in slide_pages_data:
self.add_slide(slide_data)
self.prs.save(file_name)
return file_name
except Exception as e:
raise e
3. diapositiva_gen.py
Vamos a dividirlo en fragmentos más pequeños.
Aquí, después de importar los paquetes necesarios, cree una carpeta para almacenar los archivos generados. .pptx archivos.
import json
import osfrom slide_deck import SlideDeck
from llm_call import chat_completion_request
FOLDER = "generated"
if not os.path.exists(FOLDER):
os.makedirs(FOLDER)
Luego defina estos dos métodos:
- Un método para invocar
chat_completion_requesty enviar la solicitud al LLM y analizar la cadena JSON, - Un método que obtiene la salida del método anterior y crea una instancia.
SlideDeckPara rellenar las diapositivas de PowerPoint.
def generate_json_list_of_slides(content):
try:
resp = chat_completion_request(content)
obj = json.loads(resp)
return obj
except Exception as e:
raise edef generate_presentation(content):
deck = SlideDeck()
slides_data = generate_json_list_of_slides(content)
title_slide_data = slides_data[0]
slides_data = slides_data[1:]
return deck.create_presentation(title_slide_data, slides_data)
4. interfaz de usuario.py
Creamos una interfaz de usuario sencilla con un cuadro de entrada de texto. El usuario puede escribir o copiar/pegar su texto allí y pulsar Enter para iniciar la generación de la diapositiva. Una vez finalizada la generación de la diapositiva, se imprime un mensaje al final del cuadro de entrada de texto. streamlit Es muy útil aquí.
import traceback
import streamlit as stfrom slide_gen import generate_presentation
def create_ui():
st.write("""
# Gen Slides
### Generating powerpoint slides for your text
""")
content = st.text_area(label="Enter your text:", height=400)
try:
if content:
filename = generate_presentation(content)
st.write(f"file {filename} is generated.")
except Exception:
st.write("Error in generating slides.")
st.write(traceback.format_exc())
if __name__ == "__main__":
create_ui()
Navegar hasta el llm-service carpeta y ejecutar el gpt.py archivo:
cd llm-service
python gpt.py
Nota: La primera vez que ejecute esto, se descargará el modelo LLM, lo que puede tardar varios minutos en completarse.
Ahora es el momento de abrir la interfaz de usuario. Vaya a la frontend carpeta y ejecutar el ui.py archivo que utiliza Streamlit:
cd ..
cd frontend
streamlit run ui.py
Este comando iniciará la interfaz de usuario en su navegador web predeterminado.
Con la interfaz de usuario en funcionamiento, siga estos sencillos pasos para generar su presentación:
1. Texto de entrada: En el cuadro de texto provisto, ingrese el contenido que desea transformar en una presentación. Este es el ejemplo que puede utilizar:
Artificial Intelligence is an idea that has been captivating society since the mid-20th century.
It began with science fiction familiarizing the world with the concept but the idea wasn't fully seen in the scientific manner until Alan Turing, a polymath, was curious about the feasibility of the concept.
Turing's groundbreaking 1950 paper, "Computing Machinery and Intelligence," posed fundamental questions about machine reasoning similar to human intelligence, significantly contributing to the conceptual groundwork of AI.
The development of AI was not very rapid at first because of the high costs and the fact that computers were not able to store commands.
This changed during the 1956 Dartmouth Summer Research Project on AI where there was an inspiring call for AI research, setting the precedent for two decades of rapid advancements in the field.
2. Generar diapositivas: Una vez que ingrese el texto (seguido de las teclas Comando ⌘ + Enter en Mac), GenSlide lo procesará y creará la presentación. .pptxarchivo.
3. Acceda a sus diapositivas: El archivo de PowerPoint recién creado se guardará en lafrontend/generatedcarpeta.