matsuap's picture
Upload folder using huggingface_hub
951d5c6 verified
import logging
import os
import asyncio
import tempfile
from typing import Optional
import openai
from core.config import settings
from core.prompts import get_mindmap_system_prompt
from services.s3_service import s3_service
logger = logging.getLogger(__name__)
class MindMapService:
def __init__(self):
self.openai_client = openai.OpenAI(api_key=settings.OPENAI_API_KEY)
async def generate_mindmap(
self,
file_key: Optional[str] = None,
text_input: Optional[str] = None
) -> str:
"""
Generates a Mermaid mindmap from either an S3 PDF or direct text input.
Uses asyncio.to_thread for all blocking I/O operations.
"""
try:
system_prompt = get_mindmap_system_prompt()
if file_key:
# Download PDF from S3 (non-blocking)
tmp = tempfile.NamedTemporaryFile(delete=False, suffix=".pdf")
tmp_path = tmp.name
tmp.close()
try:
await asyncio.to_thread(
s3_service.s3_client.download_file,
settings.AWS_S3_BUCKET,
file_key,
tmp_path
)
# Upload to OpenAI (non-blocking)
def upload_to_openai():
with open(tmp_path, "rb") as f:
return self.openai_client.files.create(
file=f,
purpose="assistants"
)
uploaded_file = await asyncio.to_thread(upload_to_openai)
messages = [
{"role": "system", "content": system_prompt},
{
"role": "user",
"content": [
{
"type": "file",
"file": {"file_id": uploaded_file.id}
}
]
}
]
# Call OpenAI (non-blocking)
response = await asyncio.to_thread(
self.openai_client.chat.completions.create,
model="gpt-4o-mini",
messages=messages,
temperature=0.7
)
# Clean up OpenAI file (non-blocking)
await asyncio.to_thread(
self.openai_client.files.delete,
uploaded_file.id
)
raw_content = response.choices[0].message.content
finally:
if os.path.exists(tmp_path):
await asyncio.to_thread(os.remove, tmp_path)
elif text_input:
messages = [
{"role": "system", "content": system_prompt},
{"role": "user", "content": text_input}
]
# Call OpenAI (non-blocking)
response = await asyncio.to_thread(
self.openai_client.chat.completions.create,
model="gpt-4o-mini",
messages=messages,
temperature=0.7
)
raw_content = response.choices[0].message.content
else:
raise ValueError("Either file_key or text_input must be provided")
# Clean up the output
if "```mermaid" in raw_content:
raw_content = raw_content.split("```mermaid")[1].split("```")[0].strip()
elif "```" in raw_content:
raw_content = raw_content.split("```")[1].split("```")[0].strip()
return raw_content.strip()
except Exception as e:
logger.error(f"Mind map generation failed: {e}")
raise
mindmap_service = MindMapService()