pvanand commited on
Commit
64dbe75
·
verified ·
1 Parent(s): fe17c5b

Update main.py

Browse files
Files changed (1) hide show
  1. main.py +140 -2
main.py CHANGED
@@ -1,4 +1,10 @@
 
1
  import os
 
 
 
 
 
2
  import time
3
  import asyncio
4
  import logging
@@ -7,9 +13,9 @@ import tiktoken
7
  from uuid import uuid4
8
  from functools import lru_cache
9
  from typing import Optional, List, Dict, Literal
10
- from fastapi import FastAPI, HTTPException, Depends, Security, BackgroundTasks, Query
11
  from fastapi.security import APIKeyHeader
12
- from fastapi.responses import StreamingResponse
13
  from pydantic import BaseModel, Field
14
  from openai import OpenAI
15
  # ============================================================================
@@ -32,6 +38,7 @@ app = FastAPI()
32
 
33
  # API key configuration
34
  API_KEY_NAME = "X-API-Key"
 
35
  API_KEY = os.environ.get("CHAT_AUTH_KEY", "default_secret_key")
36
  api_key_header = APIKeyHeader(name=API_KEY_NAME, auto_error=False)
37
 
@@ -69,6 +76,7 @@ class LLMAgentQueryModel(BaseModel):
69
  }
70
  }
71
 
 
72
  # API key and client setup
73
  @lru_cache()
74
  def get_api_keys():
@@ -264,6 +272,136 @@ async def text_to_speech(
264
 
265
  return StreamingResponse(generate(), media_type="audio/mpeg")
266
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
267
  # ============================================================================
268
  # Main Execution
269
  # ============================================================================
 
1
+ import re
2
  import os
3
+ from enum import Enum
4
+ from uuid import uuid4
5
+ import base64
6
+ import requests
7
+ from io import BytesIO
8
  import time
9
  import asyncio
10
  import logging
 
13
  from uuid import uuid4
14
  from functools import lru_cache
15
  from typing import Optional, List, Dict, Literal
16
+ from fastapi import FastAPI, HTTPException, Depends, Security, BackgroundTasks, Query, Header
17
  from fastapi.security import APIKeyHeader
18
+ from fastapi.responses import StreamingResponse, JSONResponse
19
  from pydantic import BaseModel, Field
20
  from openai import OpenAI
21
  # ============================================================================
 
38
 
39
  # API key configuration
40
  API_KEY_NAME = "X-API-Key"
41
+ PEXELS_API_KEY = os.environ["PEXELS_API_KEY"]
42
  API_KEY = os.environ.get("CHAT_AUTH_KEY", "default_secret_key")
43
  api_key_header = APIKeyHeader(name=API_KEY_NAME, auto_error=False)
44
 
 
76
  }
77
  }
78
 
79
+
80
  # API key and client setup
81
  @lru_cache()
82
  def get_api_keys():
 
272
 
273
  return StreamingResponse(generate(), media_type="audio/mpeg")
274
 
275
+
276
+
277
+ # ============================================================================
278
+ # PPT AGENT
279
+ # ============================================================================
280
+
281
+ class PresentationChatModel(BaseModel):
282
+ prompt: str
283
+ conversation_id: Optional[str] = None
284
+ model_id: str
285
+ user_id: str
286
+
287
+ # Enum for output formats
288
+ class OutputFormatEnum(str, Enum):
289
+ html = "html"
290
+ pdf = "pdf"
291
+ pptx = "pptx"
292
+
293
+ # Class model for presentation data
294
+ class PresentationModel(BaseModel):
295
+ markdown: str
296
+ output_format: OutputFormatEnum = OutputFormatEnum.html
297
+
298
+ def get_pexels_image(query):
299
+ default_img_url = "https://images.pexels.com/photos/593158/pexels-photo-593158.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2"
300
+ url = f"https://api.pexels.com/v1/search?query={query}&per_page=1"
301
+ headers = {"Authorization": PEXELS_API_KEY}
302
+ try:
303
+ response = requests.get(url, headers=headers)
304
+ if response.status_code == 200:
305
+ data = response.json()
306
+ if data["total_results"] > 0:
307
+ return data["photos"][0]["src"]["medium"]
308
+ return default_img_url
309
+ except:
310
+ return default_img_url
311
+
312
+ def replace_image_keywords(text):
313
+ def replace_match(match):
314
+ bg_params = match.group(1)
315
+ keyword = re.sub(r'[^\w\s]', ' ', match.group(2)).strip()
316
+ image_url = get_pexels_image(keyword)
317
+ return f"![bg {bg_params}]({image_url})"
318
+
319
+ pattern = r'!\[bg (.*?)\]\((.*?)\)'
320
+ return re.sub(pattern, replace_match, text)
321
+
322
+ def convert_markdown_marp(markdown, output_format='html'):
323
+ API_URL = "https://pvanand-marpit-backend.hf.space/convert"
324
+ if output_format not in ['html', 'pdf', 'pptx']:
325
+ raise ValueError(f"Invalid output format. Supported formats are: html, pdf, pptx")
326
+
327
+ data = {
328
+ "markdown": markdown,
329
+ "outputFormat": output_format,
330
+ "options": []
331
+ }
332
+
333
+ try:
334
+ response = requests.post(API_URL, json=data, timeout=30)
335
+ response.raise_for_status()
336
+ return response.content
337
+ except requests.exceptions.RequestException as e:
338
+ logger.error(f"An error occurred while connecting to the API: {e}")
339
+ return None
340
+
341
+
342
+ @app.post("/convert-md-to-presentation")
343
+ async def create_presentation(data: PresentationModel):
344
+ if not data.markdown:
345
+ raise HTTPException(status_code=400, detail="Please provide Markdown text.")
346
+
347
+ markdown_with_images = replace_image_keywords(extract_data_from_tag(markdown, "marp_presentation"))
348
+ result = convert_markdown_marp(markdown_with_images, output_format)
349
+
350
+ if result:
351
+ if output_format == 'html':
352
+ return {"html": result.decode()}
353
+ elif output_format == 'pdf':
354
+ return StreamingResponse(BytesIO(result), media_type="application/pdf")
355
+ elif output_format == 'pptx':
356
+ return StreamingResponse(BytesIO(result), media_type="application/vnd.openxmlformats-officedocument.presentationml.presentation")
357
+ else:
358
+ raise HTTPException(status_code=500, detail="Failed to create presentation.")
359
+
360
+
361
+ @app.post("/presentation-agent")
362
+ async def presentation_chat(query: PresentationChatModel, background_tasks: BackgroundTasks, api_key: str = Depends(verify_api_key)):
363
+ """
364
+ Presentation chat endpoint that generates a presentation based on user queries.
365
+ Uses the llm_agent function and returns both markdown and HTML output.
366
+ Requires API Key authentication via X-API-Key header.
367
+ """
368
+ logger.info(f"Received presentation chat query: {query.prompt}")
369
+
370
+ # Create a new LLMAgentQueryModel with a specific system message for presentation generation
371
+ llm_query = LLMAgentQueryModel(
372
+ prompt=query.prompt,
373
+ conversation_id=query.conversation_id,
374
+ system_message="You are a presentation creation assistant. Generate a Marp-formatted presentation based on the user's request. Use the Marp format provided earlier.",
375
+ model_id=query.model_id,
376
+ user_id=query.user_id
377
+ )
378
+
379
+ # Use the llm_agent function to generate the presentation content
380
+ response_stream = await llm_agent(llm_query, background_tasks, api_key)
381
+
382
+ # Collect the entire response
383
+ full_response = ""
384
+ async for chunk in response_stream.body_iterator:
385
+ full_response += chunk.decode()
386
+
387
+ # Extract the Marp presentation content
388
+ marp_content = extract_data_from_tag(full_response, "marp_presentation")
389
+
390
+ # Replace image keywords
391
+ marp_content_with_images = replace_image_keywords(marp_content)
392
+
393
+ # Convert Markdown to HTML
394
+ html_content = convert_markdown_marp(marp_content_with_images, 'html')
395
+
396
+ if html_content:
397
+ return JSONResponse({
398
+ "markdown": marp_content_with_images,
399
+ "html": html_content.decode()
400
+ })
401
+ else:
402
+ raise HTTPException(status_code=500, detail="Failed to create presentation.")
403
+
404
+
405
  # ============================================================================
406
  # Main Execution
407
  # ============================================================================