Superkingjcj's picture
Upload 111 files
e679d69 verified
raw
history blame
8.46 kB
from typing import Dict, Optional, Type
from asyncer import asyncify
from lagent.actions.base_action import AsyncActionMixin, BaseAction, tool_api
from lagent.actions.parser import BaseParser, JsonParser
THEME_MAPPING = {
'Default': {
'template': None,
'title': 'Title Slide',
'single': 'Title and Content',
'two': 'Two Content',
}
}
class PPT(BaseAction):
"""Plugin to create ppt slides with text, paragraph, images in good looking styles."""
def __init__(
self,
theme_mapping: Optional[Dict[str, dict]] = None,
description: Optional[dict] = None,
parser: Type[BaseParser] = JsonParser,
):
super().__init__(description, parser)
self.theme_mapping = theme_mapping or THEME_MAPPING
self.pointer = None
self.location = None
@tool_api(explode_return=True)
def create_file(self, theme: str, abs_location: str) -> dict:
"""Create a pptx file with specific themes.
Args:
theme (:class:`str`): the theme used. The value should be one of ['Default'].
abs_location (:class:`str`): the ppt file's absolute location
Returns:
:class:`dict`: operation status
* status: the result of the execution
"""
from pptx import Presentation
self.location = abs_location
try:
self.pointer = Presentation(self.theme_mapping[theme]['template'])
self.pointer.slide_master.name = theme
# print('created')
except Exception as e:
print(e)
return dict(status='created a ppt file.')
@tool_api(explode_return=True)
def add_first_page(self, title: str, subtitle: str) -> dict:
"""Add the first page of ppt.
Args:
title (:class:`str`): the title of ppt
subtitle (:class:`str`): the subtitle of ppt
Returns:
:class:`dict`: operation status
* status: the result of the execution
"""
layout_name = self.theme_mapping[self.pointer.slide_master.name]['title']
layout = next(i for i in self.pointer.slide_master.slide_layouts if i.name == layout_name)
slide = self.pointer.slides.add_slide(layout)
ph_title, ph_subtitle = slide.placeholders
ph_title.text = title
if subtitle:
ph_subtitle.text = subtitle
return dict(status='added page')
@tool_api(explode_return=True)
def add_text_page(self, title: str, bullet_items: str) -> dict:
"""Add text page of ppt.
Args:
title (:class:`str`): the title of the page
bullet_items (:class:`str`): bullet_items should be string, for multiple bullet items, please use [SPAN] to separate them.
Returns:
:class:`dict`: operation status
* status: the result of the execution
""" # noqa: E501
layout_name = self.theme_mapping[self.pointer.slide_master.name]['single']
layout = next(i for i in self.pointer.slide_master.slide_layouts if i.name == layout_name)
slide = self.pointer.slides.add_slide(layout)
ph_title, ph_body = slide.placeholders
ph_title.text = title
ph = ph_body
tf = ph.text_frame
for i, item in enumerate(bullet_items.split('[SPAN]')):
if i == 0:
p = tf.paragraphs[0]
else:
p = tf.add_paragraph()
p.text = item.strip()
p.level = 0
return dict(status='added page')
@tool_api(explode_return=True)
def add_text_image_page(self, title: str, bullet_items: str, image: str) -> dict:
"""Add a text page with one image. Image should be a path.
Args:
title (:class:`str`): the title of the page
bullet_items (:class:`str`): bullet_items should be string, for multiple bullet items, please use [SPAN] to separate them.
image (:class:`str`): the path of the image
Returns:
:class:`dict`: operation status
* status: the result of the execution
""" # noqa: E501
from PIL import Image
layout_name = self.theme_mapping[self.pointer.slide_master.name]['two']
layout = next(i for i in self.pointer.slide_master.slide_layouts if i.name == layout_name)
slide = self.pointer.slides.add_slide(layout)
ph_title, ph_body1, ph_body2 = slide.placeholders
ph_title.text = title
ph = ph_body2
image = Image.open(image)
image_pil = image.to_pil()
left = ph.left
width = ph.width
height = int(width / image_pil.width * image_pil.height)
top = (ph.top + (ph.top + ph.height)) // 2 - height // 2
slide.shapes.add_picture(image.to_path(), left, top, width, height)
ph = ph_body1
tf = ph.text_frame
for i, item in enumerate(bullet_items.split('[SPAN]')):
if i == 0:
p = tf.paragraphs[0]
else:
p = tf.add_paragraph()
p.text = item.strip()
p.level = 0
return dict(status='added page')
@tool_api(explode_return=True)
def submit_file(self) -> dict:
"""When all steps done, YOU MUST use submit_file() to submit your work.
Returns:
:class:`dict`: operation status
* status: the result of the execution
"""
# file_path = os.path.join(self.CACHE_DIR, f'{self._return_timestamp()}.pptx')
# self.pointer.save(file_path)
# retreival_url = upload_file(file_path)
self.pointer.save(self.location)
return dict(status=f'submitted. view ppt at {self.location}')
class AsyncPPT(AsyncActionMixin, PPT):
"""Plugin to create ppt slides with text, paragraph, images in good looking styles."""
@tool_api(explode_return=True)
@asyncify
def create_file(self, theme: str, abs_location: str) -> dict:
"""Create a pptx file with specific themes.
Args:
theme (:class:`str`): the theme used. The value should be one of ['Default'].
abs_location (:class:`str`): the ppt file's absolute location
Returns:
:class:`dict`: operation status
* status: the result of the execution
"""
return super().create_file(theme, abs_location)
@tool_api(explode_return=True)
@asyncify
def add_first_page(self, title: str, subtitle: str) -> dict:
"""Add the first page of ppt.
Args:
title (:class:`str`): the title of ppt
subtitle (:class:`str`): the subtitle of ppt
Returns:
:class:`dict`: operation status
* status: the result of the execution
"""
return super().add_first_page(title, subtitle)
@tool_api(explode_return=True)
@asyncify
def add_text_page(self, title: str, bullet_items: str) -> dict:
"""Add text page of ppt.
Args:
title (:class:`str`): the title of the page
bullet_items (:class:`str`): bullet_items should be string, for multiple bullet items, please use [SPAN] to separate them.
Returns:
:class:`dict`: operation status
* status: the result of the execution
""" # noqa: E501
return super().add_text_page(title, bullet_items)
@tool_api(explode_return=True)
@asyncify
def add_text_image_page(self, title: str, bullet_items: str, image: str) -> dict:
"""Add a text page with one image. Image should be a path.
Args:
title (:class:`str`): the title of the page
bullet_items (:class:`str`): bullet_items should be string, for multiple bullet items, please use [SPAN] to separate them.
image (:class:`str`): the path of the image
Returns:
:class:`dict`: operation status
* status: the result of the execution
""" # noqa: E501
return super().add_text_image_page(title, bullet_items, image)
@tool_api(explode_return=True)
@asyncify
def submit_file(self) -> dict:
"""When all steps done, YOU MUST use submit_file() to submit your work.
Returns:
:class:`dict`: operation status
* status: the result of the execution
"""
return super().submit_file()