Spaces:
Sleeping
Sleeping
Made changes to the files that need it for testing on huggingface, Dockerfile included
Browse files- Dockerfile +26 -41
- main.py +107 -101
- utils/caption_utils.py +61 -39
- utils/topic_generation.py +36 -42
Dockerfile
CHANGED
@@ -1,49 +1,34 @@
|
|
1 |
-
#
|
|
|
2 |
|
3 |
-
#
|
4 |
-
|
5 |
-
|
|
|
|
|
6 |
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
# Prevents Python from writing pyc files.
|
11 |
-
ENV PYTHONDONTWRITEBYTECODE=1
|
12 |
-
|
13 |
-
# Keeps Python from buffering stdout and stderr to avoid situations where
|
14 |
-
# the application crashes without emitting any logs due to buffering.
|
15 |
-
ENV PYTHONUNBUFFERED=1
|
16 |
|
|
|
17 |
WORKDIR /app
|
18 |
|
19 |
-
#
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
--gecos "" \
|
25 |
-
--home "/nonexistent" \
|
26 |
-
--shell "/sbin/nologin" \
|
27 |
-
--no-create-home \
|
28 |
-
--uid "${UID}" \
|
29 |
-
appuser
|
30 |
-
|
31 |
-
# Download dependencies as a separate step to take advantage of Docker's caching.
|
32 |
-
# Leverage a cache mount to /root/.cache/pip to speed up subsequent builds.
|
33 |
-
# Leverage a bind mount to requirements.txt to avoid having to copy them into
|
34 |
-
# into this layer.
|
35 |
-
RUN --mount=type=cache,target=/root/.cache/pip \
|
36 |
-
--mount=type=bind,source=requirements.txt,target=requirements.txt \
|
37 |
-
python -m pip install -r requirements.txt
|
38 |
-
|
39 |
-
# Switch to the non-privileged user to run the application.
|
40 |
-
USER appuser
|
41 |
-
|
42 |
-
# Copy the source code into the container.
|
43 |
COPY . .
|
44 |
|
45 |
-
#
|
46 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
47 |
|
48 |
-
# Run the application
|
49 |
-
CMD uvicorn
|
|
|
1 |
+
# Use a lightweight Python image
|
2 |
+
FROM python:3.10.12
|
3 |
|
4 |
+
# Install system dependencies
|
5 |
+
RUN apt-get update && apt-get install -y \
|
6 |
+
libgl1-mesa-glx \
|
7 |
+
libglib2.0-0 \
|
8 |
+
&& rm -rf /var/lib/apt/lists/*
|
9 |
|
10 |
+
# Create a non-root user
|
11 |
+
RUN useradd -m -u 1000 user
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
12 |
|
13 |
+
# Set up the working directory
|
14 |
WORKDIR /app
|
15 |
|
16 |
+
# Copy the requirements and install dependencies
|
17 |
+
COPY requirements.txt .
|
18 |
+
RUN pip install --no-cache-dir --upgrade -r requirements.txt
|
19 |
+
|
20 |
+
# Copy the rest of the application
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
21 |
COPY . .
|
22 |
|
23 |
+
# Create and set permissions for the cache directory
|
24 |
+
RUN mkdir -p /.cache /app/.cache && \
|
25 |
+
chown -R user:user /.cache /app/.cache && \
|
26 |
+
chmod -R u+w,go-w /.cache /app/.cache
|
27 |
+
i
|
28 |
+
ENV TORCH_HOME=/app/.cache/torch
|
29 |
+
|
30 |
+
# Switch to the non-root user
|
31 |
+
USER user
|
32 |
|
33 |
+
# Run the application, including the migration step
|
34 |
+
CMD ["bash", "-c", "alembic upgrade head && uvicorn main:app --host 0.0.0.0 --port 7860"]
|
main.py
CHANGED
@@ -1,128 +1,134 @@
|
|
1 |
import base64
|
2 |
-
|
3 |
-
from
|
4 |
-
|
5 |
from fastapi.middleware.cors import CORSMiddleware
|
6 |
from fastapi.responses import JSONResponse
|
7 |
-
from pydantic import AnyHttpUrl, UrlConstraints
|
|
|
8 |
|
9 |
-
from config import
|
10 |
import uvicorn
|
11 |
from utils.audio_utils import AudioUtils
|
12 |
from utils.caption_utils import ImageCaptioning
|
13 |
from utils.image_utils import UrlTest
|
14 |
from utils.topic_generation import TopicGenerator
|
15 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
16 |
app = FastAPI(
|
17 |
-
title=
|
|
|
18 |
)
|
19 |
|
20 |
# CORS
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
audio_utils = AudioUtils()
|
33 |
-
utils = UrlTest()
|
34 |
-
|
35 |
|
36 |
@app.get("/")
|
37 |
-
def root():
|
38 |
return {"message": "Welcome To Rediones API"}
|
39 |
|
40 |
-
|
41 |
@app.get("/health")
|
42 |
-
def health():
|
43 |
-
return {"
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
# regex=r"^.+\.(jpg|png|jpeg)$"
|
52 |
-
),
|
53 |
-
text: Annotated[Optional[str], Form()] = None,
|
54 |
-
img_url: Annotated[
|
55 |
-
Optional[AnyHttpUrl],
|
56 |
-
UrlConstraints(allowed_schemes=["https"]),
|
57 |
-
Form(description=(
|
58 |
-
"Image url only accepts https scheme. It mutually excludes Img"
|
59 |
-
))
|
60 |
-
] = None,
|
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 |
-
# decide whether text is provided
|
90 |
-
if text is None:
|
91 |
-
capt = img_caption.get_caption(img_file_object)
|
92 |
-
else:
|
93 |
-
capt = str(text) + "." + img_caption.get_caption(img_file_object)
|
94 |
-
|
95 |
-
generated_topics = topic_generator.generate_topics(capt)
|
96 |
-
return {"topics": generated_topics}
|
97 |
-
|
98 |
-
else:
|
99 |
raise HTTPException(
|
100 |
status_code=status.HTTP_400_BAD_REQUEST,
|
101 |
-
detail="
|
102 |
-
"imageurl and img are mutually exclusive"
|
103 |
)
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
):
|
110 |
-
|
111 |
-
audio_bytes = audio_utils.speak(text)
|
112 |
audio_base64 = base64.b64encode(audio_bytes).decode("utf-8")
|
113 |
-
return
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
)
|
121 |
):
|
122 |
-
|
123 |
-
audio_transcribe = audio_utils.improved_transcribe(0.8, audio_file=audio.file)
|
124 |
-
return
|
125 |
-
|
|
|
|
|
126 |
|
127 |
if __name__ == "__main__":
|
128 |
-
uvicorn.run(app, host="
|
|
|
1 |
import base64
|
2 |
+
import logging
|
3 |
+
from typing import List, Optional
|
4 |
+
from fastapi import Depends, FastAPI, File, Form, HTTPException, UploadFile, status
|
5 |
from fastapi.middleware.cors import CORSMiddleware
|
6 |
from fastapi.responses import JSONResponse
|
7 |
+
from pydantic import AnyHttpUrl, BaseModel, UrlConstraints
|
8 |
+
from contextlib import asynccontextmanager
|
9 |
|
10 |
+
from config import Settings, get_settings
|
11 |
import uvicorn
|
12 |
from utils.audio_utils import AudioUtils
|
13 |
from utils.caption_utils import ImageCaptioning
|
14 |
from utils.image_utils import UrlTest
|
15 |
from utils.topic_generation import TopicGenerator
|
16 |
|
17 |
+
# Setup logging
|
18 |
+
logging.basicConfig(level=logging.INFO)
|
19 |
+
logger = logging.getLogger(__name__)
|
20 |
+
|
21 |
+
# Pydantic models for request/response
|
22 |
+
class TopicResponse(BaseModel):
|
23 |
+
topics: List[str]
|
24 |
+
caption: Optional[str]
|
25 |
+
|
26 |
+
class AudioResponse(BaseModel):
|
27 |
+
audio_base64: str
|
28 |
+
|
29 |
+
class TranscriptionResponse(BaseModel):
|
30 |
+
audio_transcription: str
|
31 |
+
|
32 |
+
# Context manager for startup and shutdown events
|
33 |
+
@asynccontextmanager
|
34 |
+
async def lifespan(app: FastAPI):
|
35 |
+
# Startup
|
36 |
+
app.state.topic_generator = TopicGenerator()
|
37 |
+
app.state.img_caption = ImageCaptioning()
|
38 |
+
app.state.audio_utils = AudioUtils()
|
39 |
+
app.state.url_utils = UrlTest()
|
40 |
+
logger.info("Application startup complete")
|
41 |
+
yield
|
42 |
+
# Shutdown
|
43 |
+
logger.info("Application shutdown")
|
44 |
+
|
45 |
app = FastAPI(
|
46 |
+
title="Rediones API",
|
47 |
+
lifespan=lifespan,
|
48 |
)
|
49 |
|
50 |
# CORS
|
51 |
+
@app.on_event("startup")
|
52 |
+
async def startup_event():
|
53 |
+
settings = get_settings()
|
54 |
+
if settings.ALLOWED_ORIGINS:
|
55 |
+
app.add_middleware(
|
56 |
+
CORSMiddleware,
|
57 |
+
allow_origins=settings.ALLOWED_ORIGINS,
|
58 |
+
allow_credentials=True,
|
59 |
+
allow_methods=["*"],
|
60 |
+
allow_headers=["*"],
|
61 |
+
)
|
|
|
|
|
|
|
62 |
|
63 |
@app.get("/")
|
64 |
+
async def root():
|
65 |
return {"message": "Welcome To Rediones API"}
|
66 |
|
|
|
67 |
@app.get("/health")
|
68 |
+
async def health():
|
69 |
+
return {"status": "OK"}
|
70 |
+
|
71 |
+
@app.post("/topicgen", response_model=TopicResponse)
|
72 |
+
async def generate_topic(
|
73 |
+
img: UploadFile = File(None),
|
74 |
+
text: Optional[str] = Form(None),
|
75 |
+
img_url: Optional[AnyHttpUrl] = Form(None),
|
76 |
+
settings: Settings = Depends(get_settings)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
77 |
):
|
78 |
+
try:
|
79 |
+
if img_url and img:
|
80 |
+
raise HTTPException(
|
81 |
+
status_code=status.HTTP_400_BAD_REQUEST,
|
82 |
+
detail="Only one of image_url or img can be accepted"
|
83 |
+
)
|
84 |
+
|
85 |
+
if text and not (img or img_url):
|
86 |
+
generated_topics = app.state.topic_generator.generate_topics(text)
|
87 |
+
return TopicResponse(topics=generated_topics, caption=None)
|
88 |
+
|
89 |
+
if img or img_url:
|
90 |
+
img_file_object = None
|
91 |
+
if img:
|
92 |
+
if not img.filename.lower().endswith((".jpg", ".png", ".jpeg")):
|
93 |
+
raise HTTPException(
|
94 |
+
status_code=status.HTTP_400_BAD_REQUEST,
|
95 |
+
detail="Image file must be ended with .jpg, .png, .jpeg"
|
96 |
+
)
|
97 |
+
img_file_object = img.file
|
98 |
+
elif img_url:
|
99 |
+
img_file_object = app.state.url_utils.load_image(img_url)
|
100 |
+
|
101 |
+
capt = app.state.img_caption.combo_model(img_file_object, text)
|
102 |
+
return TopicResponse(topics=capt.topics, caption=capt.caption)
|
103 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
104 |
raise HTTPException(
|
105 |
status_code=status.HTTP_400_BAD_REQUEST,
|
106 |
+
detail="Enter text or image. Image URL and image file are mutually exclusive."
|
|
|
107 |
)
|
108 |
+
except Exception as e:
|
109 |
+
logger.error(f"Error in generate_topic: {str(e)}")
|
110 |
+
raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail="An unexpected error occurred")
|
111 |
+
|
112 |
+
@app.post("/audioverse", response_model=AudioResponse)
|
113 |
+
async def generate_audio(text: str):
|
114 |
+
try:
|
115 |
+
audio_bytes = app.state.audio_utils.speak(text)
|
116 |
audio_base64 = base64.b64encode(audio_bytes).decode("utf-8")
|
117 |
+
return AudioResponse(audio_base64=audio_base64)
|
118 |
+
except Exception as e:
|
119 |
+
logger.error(f"Error in generate_audio: {str(e)}")
|
120 |
+
raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail="An unexpected error occurred")
|
121 |
+
|
122 |
+
@app.post("/transcribe", response_model=TranscriptionResponse)
|
123 |
+
async def transcribe_audio(
|
124 |
+
audio: UploadFile = File(..., description="Audio file to be transcribed.")
|
125 |
):
|
126 |
+
try:
|
127 |
+
audio_transcribe = app.state.audio_utils.improved_transcribe(0.8, audio_file=audio.file)
|
128 |
+
return TranscriptionResponse(audio_transcription=audio_transcribe)
|
129 |
+
except Exception as e:
|
130 |
+
logger.error(f"Error in transcribe_audio: {str(e)}")
|
131 |
+
raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail="An unexpected error occurred")
|
132 |
|
133 |
if __name__ == "__main__":
|
134 |
+
uvicorn.run("main:app", host="0.0.0.0", port=8000, reload=True)
|
utils/caption_utils.py
CHANGED
@@ -21,53 +21,75 @@ class ImageCaptioning:
|
|
21 |
def generate_caption(self, image):
|
22 |
# Generate Caption
|
23 |
input_text = self.blip_processor(image, return_tensors="pt")
|
24 |
-
outputs = self.blip_model.generate(pixel_values=input_text["pixel_values"], max_new_tokens=128, do_sample=True, temperature=0.
|
25 |
caption_output = [self.blip_processor.decode(output, skip_special_tokens=True) for output in outputs]
|
26 |
|
27 |
return outputs
|
28 |
|
29 |
|
30 |
-
def generate_topics(self,
|
31 |
-
|
32 |
-
The generated topics should portray the context or idea behind the given sentences or phrase.
|
33 |
-
For Instance,
|
34 |
-
- "Grocery Shopping" OR "Grocery List" OR "Shopping List": "I'm going grocery shopping tomorrow,
|
35 |
-
and I would like to get the following things on my grocery list: Milk, Soybeans, Cowpeas,
|
36 |
-
Saturated Water, Onions, Tomatoes, etc."
|
37 |
-
- "Studying For Exams" OR "Exams Studies": "Exams aare coming up and I have to prepare for the core
|
38 |
-
courses. I'll be studying for Control Systems, Software Engineering and Circuit Theory."
|
39 |
-
- "Healthy Breakfast": "To prepare a healthy breakfast, I need the appropriate combination of balanced
|
40 |
-
diet. I'll need oats, yogurt, fresh berries, honey and smoothies."
|
41 |
-
- "Fitness Routine": "Starting a fitness routine involves workout clothes, running shoes,
|
42 |
-
a water bottles, and a gym membership. With this, I can start a proper fitness plan."
|
43 |
-
- "Summer Vacation": "Packing swimsuits and enjoy the view of the ocean."
|
44 |
-
- "Coffee Break": "Sipping Coffee at the table."
|
45 |
-
- "Relaxation": "Sitting at the table enjoying."
|
46 |
-
|
47 |
-
This is what I'm expecting the model to do. Here is the input: {user_input}
|
48 |
-
"""
|
49 |
-
|
50 |
-
caption_input = self.topic_generator_processor(query, return_tensors="pt", padding=True, truncation=True, max_length=512)
|
51 |
-
caption_output = self.topic_generator_model.generate(**caption_input, temperature=0.1, num_return_sequences=num_topics, do_sample=True, max_length=50, top_k=50, top_p=0.95, num_beams=5)
|
52 |
-
caption_output = [self.topic_generator_processor.decode(output, skip_special_tokens=True) for output in caption_output]
|
53 |
|
54 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
55 |
|
56 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
57 |
image = img.load_image(image)
|
58 |
caption = self.generate_caption(image)
|
59 |
caption = self.blip_processor.decode(caption[0], skip_special_tokens=True)
|
60 |
-
topics = self.generate_topics(caption)
|
61 |
-
|
62 |
-
return {
|
63 |
-
|
|
|
|
|
64 |
|
65 |
-
|
66 |
-
if __name__ == "__main__":
|
67 |
-
# Initialize Model
|
68 |
-
model = ImageCaptioning()
|
69 |
-
# Test Image
|
70 |
-
image = "1071642.jpg"
|
71 |
-
# Generate Caption and Topics
|
72 |
-
outputs = model.combo_model(image)
|
73 |
-
print(outputs)
|
|
|
21 |
def generate_caption(self, image):
|
22 |
# Generate Caption
|
23 |
input_text = self.blip_processor(image, return_tensors="pt")
|
24 |
+
outputs = self.blip_model.generate(pixel_values=input_text["pixel_values"], max_new_tokens=128, do_sample=True, temperature=0.5, top_k=50, top_p=0.95)
|
25 |
caption_output = [self.blip_processor.decode(output, skip_special_tokens=True) for output in outputs]
|
26 |
|
27 |
return outputs
|
28 |
|
29 |
|
30 |
+
def generate_topics(self, caption, additional_text=None, num_topics=3):
|
31 |
+
base_prompt = "Generate short, creative titles or topics based on the detailed information provided:"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
32 |
|
33 |
+
# Construct the prompt based on whether additional context is provided
|
34 |
+
if additional_text:
|
35 |
+
full_prompt = (f"{base_prompt}\n\n"
|
36 |
+
f"Image description: {caption}\n\n"
|
37 |
+
f"Additional context: {additional_text}\n\n"
|
38 |
+
f"Task: Create {num_topics} inventive titles or topics (2-5 words each) that blend the essence of the image with the additional context. "
|
39 |
+
f"These titles should be imaginative and suitable for use as hashtags, image titles, or starting points for discussions."
|
40 |
+
f"IMPORTANT: Be imaginative and concise in your responses. Avoid repeating the same ideas in different words."
|
41 |
+
f"Also make sure to provide a title/topic that relates to every context provided while following the examples listed below as a way of being creative and intuitive."
|
42 |
+
)
|
43 |
+
else:
|
44 |
+
full_prompt = (f"{base_prompt}\n\n"
|
45 |
+
f"Image description: {caption}\n\n"
|
46 |
+
f"Task: Create {num_topics} inventive titles or topics (2-5 words each) that encapsulate the essence of the image. "
|
47 |
+
f"These titles should be imaginative and suitable for use as hashtags, image titles, or starting points for discussions."
|
48 |
+
f"IMPORTANT: Be imaginative and concise in your responses. Avoid repeating the same ideas in different words."
|
49 |
+
f"Also make sure to provide a title/topic that relates to every context provided while following the examples listed below as a way of being creative and intuitive."
|
50 |
+
)
|
51 |
|
52 |
+
# Provide creative examples to inspire the model
|
53 |
+
examples = """
|
54 |
+
Creative examples to inspire your titles/topics:
|
55 |
+
- "Misty Peaks at Dawn"
|
56 |
+
- "Graffiti Lanes of Urbania"
|
57 |
+
- "Chef’s Secret Ingredients"
|
58 |
+
- "Neon Future Skylines"
|
59 |
+
- "Puppy’s First Snow"
|
60 |
+
- "Edge of Adventure"
|
61 |
+
"""
|
62 |
+
|
63 |
+
# Append the examples to the prompt with a clear creative directive
|
64 |
+
full_prompt += f"\n{examples}\nNow, inspired by these examples, create {num_topics} short and descriptive titles/topics based on the information provided.\n"
|
65 |
+
|
66 |
+
print(full_prompt)
|
67 |
+
|
68 |
+
# Generate the topics using the T5 model with adjusted parameters
|
69 |
+
inputs = self.topic_generator_processor(full_prompt, return_tensors="pt", padding=True, truncation=True, max_length=512)
|
70 |
+
outputs = self.topic_generator_model.generate(
|
71 |
+
**inputs,
|
72 |
+
num_return_sequences=num_topics,
|
73 |
+
do_sample=True,
|
74 |
+
temperature=0.7,
|
75 |
+
max_length=32, # Reduced for shorter outputs
|
76 |
+
top_k=50,
|
77 |
+
top_p=0.95,
|
78 |
+
num_beams=5,
|
79 |
+
no_repeat_ngram_size=2
|
80 |
+
)
|
81 |
+
|
82 |
+
topics = [self.topic_generator_processor.decode(output, skip_special_tokens=True).strip() for output in outputs]
|
83 |
+
return [topic for topic in topics if topic and len(topic.split()) > 1]
|
84 |
+
|
85 |
+
def combo_model(self, image, additional_text=None):
|
86 |
image = img.load_image(image)
|
87 |
caption = self.generate_caption(image)
|
88 |
caption = self.blip_processor.decode(caption[0], skip_special_tokens=True)
|
89 |
+
topics = self.generate_topics(caption, additional_text)
|
90 |
+
|
91 |
+
return {
|
92 |
+
"caption": caption,
|
93 |
+
"topics": topics
|
94 |
+
}
|
95 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
utils/topic_generation.py
CHANGED
@@ -1,51 +1,45 @@
|
|
1 |
import requests
|
2 |
-
from
|
3 |
-
import os
|
4 |
|
5 |
-
load_dotenv()
|
6 |
-
|
7 |
-
huggingface = os.getenv("HUGGINGFACE")
|
8 |
|
9 |
|
10 |
class TopicGenerator:
|
11 |
|
12 |
def __init__(self):
|
13 |
-
# Initialize
|
14 |
-
self.
|
15 |
-
self.
|
16 |
-
|
17 |
-
def query(self, payload):
|
18 |
-
response = requests.post(self.url, headers=self.headers,
|
19 |
-
json=payload)
|
20 |
-
return response
|
21 |
|
22 |
def generate_topics(self, user_input, num_topics=3):
|
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 |
-
|
|
|
|
|
|
1 |
import requests
|
2 |
+
from transformers import AutoTokenizer, AutoModelForSeq2SeqLM
|
|
|
3 |
|
|
|
|
|
|
|
4 |
|
5 |
|
6 |
class TopicGenerator:
|
7 |
|
8 |
def __init__(self):
|
9 |
+
# Initialize Model and Tokenizer
|
10 |
+
self.topic_generator_processor = AutoTokenizer.from_pretrained("google/flan-t5-large")
|
11 |
+
self.topic_generator_model = AutoModelForSeq2SeqLM.from_pretrained("google/flan-t5-large")
|
12 |
+
self.topic_generator_model.eval()
|
|
|
|
|
|
|
|
|
13 |
|
14 |
def generate_topics(self, user_input, num_topics=3):
|
15 |
+
base_prompt = "Generate short, creative titles or topics based on the detailed information provided:"
|
16 |
+
|
17 |
+
# Construct the prompt based on whether additional context is provided
|
18 |
+
full_prompt = (f"{base_prompt}\n\n"
|
19 |
+
f"Context: {user_input}\n\n"
|
20 |
+
f"Task: Create {num_topics} inventive titles or topics (2-5 words each) that blend the essence of the image with the additional context. "
|
21 |
+
f"These titles should be imaginative and suitable for use as hashtags, image titles, or starting points for discussions."
|
22 |
+
f"IMPORTANT: Be imaginative and concise in your responses. Avoid repeating the same ideas in different words."
|
23 |
+
f"Also make sure to provide a title/topic that relates to every context provided while following the examples listed below as a way of being creative and intuitive."
|
24 |
+
)
|
25 |
+
|
26 |
+
# Provide creative examples to inspire the model
|
27 |
+
examples = """
|
28 |
+
Creative examples to inspire your titles/topics:
|
29 |
+
- "Misty Peaks at Dawn"
|
30 |
+
- "Graffiti Lanes of Urbania"
|
31 |
+
- "Chef’s Secret Ingredients"
|
32 |
+
- "Neon Future Skylines"
|
33 |
+
- "Puppy’s First Snow"
|
34 |
+
- "Edge of Adventure"
|
35 |
+
"""
|
36 |
+
|
37 |
+
full_prompt += examples
|
38 |
+
|
39 |
+
# Generate Topics
|
40 |
+
input_text = self.topic_generator_processor(full_prompt, return_tensors="pt")
|
41 |
+
outputs = self.topic_generator_model.generate(input_ids=input_text["input_ids"], max_length=20, num_return_sequences=num_topics, num_beams=5, no_repeat_ngram_size=5, top_k=50, top_p=0.95, temperature=0.9)
|
42 |
+
topics = [self.topic_generator_processor.decode(output, skip_special_tokens=True) for output in outputs]
|
43 |
+
|
44 |
+
return topics
|
45 |
+
|