Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dev -> Main v0.0.9 #890

Merged
merged 101 commits into from
Jul 27, 2023
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
101 commits
Select commit Hold shift + click to select a range
e7026c3
first commit
Aryan-Singh-14 Jul 11, 2023
898c75f
instagram APIs implemented and AI generated caption utility added
Aryan-Singh-14 Jul 13, 2023
fce5808
Image upload to S3 and URL generation added
Aryan-Singh-14 Jul 14, 2023
ac457a5
added upload to s3 instagram bucket
Aryan-Singh-14 Jul 18, 2023
0ab34be
Merge branch 'dev' into instagram_tool
Aryan-Singh-14 Jul 18, 2023
59a95ed
fixing the send email attachement issue
Jul 18, 2023
35b5bc4
fixing schedule agent run
Jul 18, 2023
2551e8f
Refactored code
Aryan-Singh-14 Jul 19, 2023
281753f
Resource duplicate fix (#803)
luciferlinx101 Jul 19, 2023
6f3deb4
removed jpeg files used for testing
Aryan-Singh-14 Jul 19, 2023
c697937
Dalle fix (#812)
Tarraann Jul 19, 2023
2889187
fixed recurring run issues
Aryan-Singh-14 Jul 20, 2023
9f0a78d
Supercoder Improve tool addition (#755)
Autocop-Agent Jul 20, 2023
e37014e
fixed recurring issues
Aryan-Singh-14 Jul 20, 2023
0937ba5
Edit agent templates (#793)
anisha1607 Jul 20, 2023
ded659c
Readme added
Aryan-Singh-14 Jul 20, 2023
3708a30
instabot config folder deleted
Aryan-Singh-14 Jul 20, 2023
cdf3495
Read file s3 fix (#823)
luciferlinx101 Jul 20, 2023
0bb6000
refactored code
Aryan-Singh-14 Jul 20, 2023
1218fd6
Handled the case where stable diffusion generated multiple photos
Aryan-Singh-14 Jul 21, 2023
37bab8d
ui bug bash fixes
jedan2506 Jul 21, 2023
2607db3
docker compose.yaml version reverted to original
Aryan-Singh-14 Jul 21, 2023
9f6c045
removed the utility to add stable diffusion automatically
Aryan-Singh-14 Jul 21, 2023
e2dbae1
ui bug bash fixes
jedan2506 Jul 21, 2023
873a049
ui bug bash fixes
jedan2506 Jul 21, 2023
167c4bf
Edit agent templates fix (#838)
anisha1607 Jul 21, 2023
c76c453
ui bug bash fixes
jedan2506 Jul 21, 2023
8415dbe
Merge pull request #837 from TransformerOptimus/bugs_revamp_dev
nborthy Jul 21, 2023
b6587bf
added test cases and modified readme
Aryan-Singh-14 Jul 25, 2023
6595b1a
Frontend bugs (#849)
nborthy Jul 25, 2023
58355d3
Added instagram tool bucket entry in config_template.yaml
Aryan-Singh-14 Jul 25, 2023
bb0304f
added instagram tool bucket entry in config template
Aryan-Singh-14 Jul 25, 2023
e2c01bc
ui bug fixes
jedan2506 Jul 25, 2023
dab5ab7
Merge pull request #828 from TransformerOptimus/instagram_tool
Aryan-Singh-14 Jul 25, 2023
e57b8bc
ui bug fixes
jedan2506 Jul 25, 2023
802eeb1
ui bug fixes
jedan2506 Jul 25, 2023
de8189e
Merge pull request #853 from TransformerOptimus/apm_changes
nborthy Jul 25, 2023
1ea8d16
External repo support for marketplace (#847)
luciferlinx101 Jul 25, 2023
bddffb5
instagram image added
jedan2506 Jul 25, 2023
e3291fb
Merge pull request #856 from TransformerOptimus/instagram_pictures
nborthy Jul 25, 2023
84b593c
apm bug fixes
jedan2506 Jul 25, 2023
4b202ba
Dev rebase (#858)
nihiragarwal24 Jul 25, 2023
eca6e6d
apm bug fixes
jedan2506 Jul 25, 2023
8eeaca4
apm bug fixes
jedan2506 Jul 25, 2023
6392966
Merge pull request #859 from TransformerOptimus/instagram_pictures
nborthy Jul 25, 2023
97c5ee9
Docker image (#836)
Fluder-Paradyne Jul 25, 2023
b638d37
handled resource path change (#861)
Aryan-Singh-14 Jul 26, 2023
fdadbf0
Updated Expiry Time backward fix
luciferlinx101 Jul 26, 2023
a2d8e5e
Merge pull request #864 from TransformerOptimus/jwt-expiry-backward-fix
nborthy Jul 26, 2023
e105b2e
readme toolkit fix (#867)
luciferlinx101 Jul 26, 2023
d9c942f
Knowledge frontend (#860)
nborthy Jul 26, 2023
800bb30
Fixed Delete Agent Bug (#830)
anisha1607 Jul 26, 2023
20dfa29
close button fix
NishantBorthakur Jul 26, 2023
73fff67
Merge branch 'dev_fixes' of github.com:TransformerOptimus/SuperAGI in…
jedan2506 Jul 26, 2023
3fea732
refactor
NishantBorthakur Jul 26, 2023
799417e
centralise prevent default
NishantBorthakur Jul 26, 2023
b124288
Merge branch 'dev_fixes' of github.com:TransformerOptimus/SuperAGI in…
jedan2506 Jul 26, 2023
0ebd563
app.css fixes
jedan2506 Jul 26, 2023
c1f9ab9
Dev fixes (#869)
jedan2506 Jul 26, 2023
9973567
close icon issue
NishantBorthakur Jul 26, 2023
5707bdb
resolving conflcits
NishantBorthakur Jul 26, 2023
f74b781
Merge pull request #872 from TransformerOptimus/dev_fixes
nborthy Jul 26, 2023
ae6e620
Added tools.json (#868)
luciferlinx101 Jul 26, 2023
030e886
Updated Chat completion for tool selection prompt
luciferlinx101 Jul 26, 2023
9326e6c
Updated Prompt
luciferlinx101 Jul 26, 2023
32e31c0
Bug fixes afternoon (#875)
jedan2506 Jul 26, 2023
6eeb7f6
Docker image (#876)
Fluder-Paradyne Jul 26, 2023
b798985
Final knowledge backend (#870)
Tarraann Jul 26, 2023
caad111
very minor fix for naming
Jul 26, 2023
98ee15a
Merge pull request #877 from TransformerOptimus/minor_fix_knowledge
Tarraann Jul 26, 2023
4356fbc
Changes for HTTP EXception in Knowledge Controller
Jul 27, 2023
73efa91
HTTP changes for vector_dbs
Jul 27, 2023
db80c8c
Bug fixes afternoon (#878)
jedan2506 Jul 27, 2023
4c06c1d
Refactoring of vector embedding
Jul 27, 2023
f149e9b
adding of knowledge logo
namansleeps2 Jul 27, 2023
75930b2
Delete HTTP fixed
Jul 27, 2023
2d52781
Merge remote-tracking branch 'origin/knowledge_logo' into http_knowledge
Jul 27, 2023
a876859
Updated prompt
luciferlinx101 Jul 27, 2023
a59a1b6
changes in tests
Jul 27, 2023
d6bf83c
changes
Jul 27, 2023
7bc8e81
Merge pull request #882 from TransformerOptimus/prompt-fix
Jul 27, 2023
5085269
changes
Jul 27, 2023
129e00d
args fix in dalle
Jul 27, 2023
4672c07
bug fix
luciferlinx101 Jul 27, 2023
79928cb
Merge pull request #884 from TransformerOptimus/prompt-fix
Tarraann Jul 27, 2023
2fe3f0d
Merge remote-tracking branch 'origin/dev' into dalle_args_fix
Jul 27, 2023
1de727f
minor change
Jul 27, 2023
e440d63
Merge pull request #883 from TransformerOptimus/dalle_args_fix
Tarraann Jul 27, 2023
d80920e
Merge pull request #881 from TransformerOptimus/http_knowledge
Tarraann Jul 27, 2023
edec2f5
minor changes
namansleeps2 Jul 27, 2023
6a0df87
Merge pull request #885 from TransformerOptimus/knowledge_changes
Tarraann Jul 27, 2023
b901801
fixes (#886)
Tarraann Jul 27, 2023
98312be
the user will now be unable to select striked knowledges
namansleeps2 Jul 27, 2023
a1f2abe
minor fix
namansleeps2 Jul 27, 2023
bb27d3f
Merge pull request #888 from TransformerOptimus/minor_changes_launch
namansleeps Jul 27, 2023
a16526d
Fix for agent details - not fetching data
Jul 27, 2023
08d8ba1
minor change for details
Jul 27, 2023
7dfbe3a
Fixes
Jul 27, 2023
bb308fc
Merge pull request #889 from TransformerOptimus/agent_detail_fix
anisha1607 Jul 27, 2023
de12454
conflict resolved
luciferlinx101 Jul 27, 2023
d978a6a
Merge pull request #892 from TransformerOptimus/conflict-resolve-dev
nborthy Jul 27, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions config_template.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ RESOURCES_OUTPUT_ROOT_DIR: workspace/output/{agent_id}/{agent_execution_id} # Fo

#S3 RELATED DETAILS ONLY WHEN STORAGE_TYPE IS "S3"
BUCKET_NAME:
INSTAGRAM_TOOL_BUCKET_NAME: #Public read bucket, Images generated by stable diffusion are put in this bucket and the public url of the same is generated.
AWS_ACCESS_KEY_ID:
AWS_SECRET_ACCESS_KEY:

Expand Down
11 changes: 7 additions & 4 deletions superagi/tools/image_generation/stable_diffusion_image_gen.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@
import requests
from PIL import Image
from pydantic import BaseModel, Field

from superagi.helper.resource_helper import ResourceHelper
from superagi.resource_manager.file_manager import FileManager
from superagi.tools.base_tool import BaseTool


class StableDiffusionImageGenInput(BaseModel):
prompt: str = Field(..., description="Prompt for Image Generation to be used by Stable Diffusion.")
prompt: str = Field(..., description="Prompt for Image Generation to be used by Stable Diffusion. The prompt should be as descriptive as possible and mention all the details of the image to be generated")
height: int = Field(..., description="Height of the image to be Generated. default height is 512")
width: int = Field(..., description="Width of the image to be Generated. default width is 512")
num: int = Field(..., description="Number of Images to be generated. default num is 2")
Expand Down Expand Up @@ -46,7 +46,6 @@ def _execute(self, prompt: str, image_names: list, width: int = 512, height: int

if api_key is None:
return "Error: Missing Stability API key."

response = self.call_stable_diffusion(api_key, width, height, num, prompt, steps)

if response.status_code != 200:
Expand All @@ -59,6 +58,7 @@ def _execute(self, prompt: str, image_names: list, width: int = 512, height: int
for artifact in artifacts:
base64_strings.append(artifact['base64'])

image_paths=[]
for i in range(num):
image_base64 = base64_strings[i]
img_data = base64.b64decode(image_base64)
Expand All @@ -69,7 +69,10 @@ def _execute(self, prompt: str, image_names: list, width: int = 512, height: int

self.resource_manager.write_binary_file(image_names[i], img_byte_arr.getvalue())

return "Images downloaded and saved successfully"
for image in image_names:
image_paths.append(ResourceHelper.get_resource_path(image))

return f"Images downloaded and saved successfully at the following locations: {image_paths}"

def call_stable_diffusion(self, api_key, width, height, num, prompt, steps):
engine_id = self.get_tool_config("ENGINE_ID")
Expand Down
42 changes: 42 additions & 0 deletions superagi/tools/instagram_tool/README.MD
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<p align=center>
<a href="https://superagi.co"><img src=https://superagi.co/wp-content/uploads/2023/05/SuperAGI_icon.png></a>
</p>

# SuperAGI Instagram Tool

The SuperAGI Instagram Tool works with the stable diffusion tool, generates an image & caption based on the goals defined by the user and posts it on their instagram business account.

## ⚙️ Installation

### 🛠 **Setting Up of SuperAGI**
Set up the SuperAGI by following the instructions given (https://github.com/TransformerOptimus/SuperAGI/blob/main/README.MD)

If you've put the correct Google API key and Custom Search Engine ID, you'll be able to use the Google Search Tool as well.

### 🔧 **Instagram tool requirements**

Since the tool uses the official instagram graph API's to post media on user accounts, There are a few requirements:

You will need access to the following:

1. An Instagram Business Account or Instagram Creator Account
2. A Facebook Page connected to that account
3. A Facebook Developer account that can perform Tasks on that Page
4. A registered Facebook App with Basic settings configured

Once everything is set up, add the meta user access token (to be generated from facebook developer account), Facebook page ID (can be found on the facebook page connected to the instagram account under 'Page transparency' in 'About' section of the page ) and the stability API key to the correspponding toolkits.

Follow the steps given in the link to set up meta requirements: (https://developers.facebook.com/docs/instagram-api/getting-started)
Follow the link to generate stability API key: (https://dreamstudio.com/api/)

### 🔧 **Configuring in SuperAGI Dashboard:**

-You can add your meta user access token and facebook ID to the Instagram Toolkit Page and stability API key to the Image Generation Toolkit Page

## Running SuperAGI Instagram Tool

Once everything has been set up just run/schedule an agent with the goal explaining the media to be published and add instagram tool (which will automatically add stable diffusion tool)

## Warning

It is advised to run the instagram tool in restricted mode since it allows you to validate the photos generated. You can schedule agent runs (recurring runs are supported as well). Also, only one photo will be posted to your account in a run. To post multiple photos use recurring runs.
Empty file.
226 changes: 226 additions & 0 deletions superagi/tools/instagram_tool/instagram.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,226 @@
import json
import urllib
import boto3
import os
from superagi.config.config import get_config
from superagi.helper.resource_helper import ResourceHelper
from typing import Type, Optional
from pydantic import BaseModel, Field
from superagi.helper.token_counter import TokenCounter
from superagi.llms.base_llm import BaseLlm
from superagi.tools.base_tool import BaseTool
import os
import requests
from superagi.tools.tool_response_query_manager import ToolResponseQueryManager
import random

class InstagramSchema(BaseModel):
photo_description: str = Field(
...,
description="description of the photo",
)

class InstagramTool(BaseTool):
"""
Instagram tool

Attributes:
name : The name.
description : The description.
args_schema : The args schema.
"""
llm: Optional[BaseLlm] = None
name = "Instagram tool"
description = (
"A tool for posting an AI generated photo on Instagram"
)
args_schema: Type[InstagramSchema] = InstagramSchema
tool_response_manager: Optional[ToolResponseQueryManager] = None
agent_id:int =None
class Config:
arbitrary_types_allowed = True

def _execute(self, photo_description: str) -> str:
"""
Execute the Instagram tool.

Args:
photo_description : description of the photo to be posted

Returns:
Image posted successfully message if image has been posted on instagram or error message.
"""
meta_user_access_token = self.get_tool_config("META_USER_ACCESS_TOKEN")
facebook_page_id=self.get_tool_config("FACEBOOK_PAGE_ID")

if meta_user_access_token is None:
return "Error: Missing meta user access token."

if facebook_page_id is None:
return "Error: Missing facebook page id."
#create caption for the instagram
caption=self.create_caption(photo_description)

#get request for fetching the instagram_business_account_id
root_api_url="https://graph.facebook.com/v17.0/"
response=self.get_req_insta_id(root_api_url,facebook_page_id,meta_user_access_token)

if response.status_code != 200:
return f"Non-200 response: {str(response.text)}"

data = response.json()
insta_business_account_id=data["instagram_business_account"]["id"]
file_path=self.get_file_path_from_image_generation_tool()
#handling case where image generation generates multiple images
if(file_path=="resources"):
return "A photo has already been posted on your instagram account. To post multiple photos use recurring runs."

image_url,encoded_caption=self.get_img_url_and_encoded_caption(photo_description,file_path)
#post request for getting the media container ID
response=self.post_media_container_id(root_api_url,insta_business_account_id,image_url,encoded_caption,meta_user_access_token)

if response.status_code != 200:
return f"Non-200 response: {str(response.text)}"

data = response.json()
container_ID=data["id"]
#post request to post the media container on instagram account
response=self.post_media(root_api_url,insta_business_account_id,container_ID,meta_user_access_token)
if response.status_code != 200:
return f"Non-200 response: {str(response.text)}"
return "Photo posted successfully!"

def create_caption(self, photo_description: str) -> str:
"""
Create a caption for the instagram post based on the photo description

Args:
photo_description : Description of the photo to be posted

Returns:
Description of the photo to be posted
"""
caption_prompt ="""Generate an instagram post caption for the following text `{photo_description}`
Attempt to make it as relevant as possible to the description and should be different and unique everytime. Add relevant emojis and hashtags."""

caption_prompt = caption_prompt.replace("{photo_description}", str(photo_description))

messages = [{"role": "system", "content": caption_prompt}]
result = self.llm.chat_completion(messages, max_tokens=self.max_token_limit)
caption=result["content"]

encoded_caption=urllib. parse. quote(caption)

return encoded_caption

def get_image_from_s3(self,s3,file_path):
"""
Gets the image from the s3 bucket

Args:
s3: S3 client
file_path: path of the image file in s3

Returns
The image file from s3
"""

response = s3.get_object(Bucket=get_config("BUCKET_NAME"), Key=file_path)
content = response["Body"].read()

return content

def get_file_path_from_image_generation_tool(self):
"""
Parses the output of the previous tool (Stable diffusion) and returns the path of the image file

Args:

Returns:
The path of the image file generated by the image generation toolkit
"""

last_tool_response = self.tool_response_manager.get_last_response()
file_path="resources"+last_tool_response.partition("['")[2].partition("']")[0]

if ',' in file_path:
# Split the string based on the comma and get the first element (substring before the comma)
file_path = file_path.split(',')[0].strip()
file_path=file_path[:-1]

return file_path

def create_s3_client(self):
"""
Creates an s3 client

Args:

Returns:
The s3 client
"""

s3 = boto3.client(
's3',
aws_access_key_id=get_config("AWS_ACCESS_KEY_ID"),
aws_secret_access_key=get_config("AWS_SECRET_ACCESS_KEY"),
)

return s3

def get_img_public_url(self,s3,file_path,content):
"""
Puts the image generated by image generation tool in the s3 bucket and returns the public url of the same
Args:
s3 : S3 bucket
file_path: Path of the image file in s3
content: Image file

Returns:
The public url of the image put in s3 bucket
"""

bucket_name = get_config("INSTAGRAM_TOOL_BUCKET_NAME")
object_key=f"instagram_upload_images/{file_path.split('/')[-1]}{random.randint(0, 1000)}"
s3.put_object(Bucket=bucket_name, Key=object_key, Body=content)

image_url = f"https://{bucket_name}.s3.amazonaws.com/{object_key}"
return image_url

def get_img_url_and_encoded_caption(self,photo_description,file_path):
#creating an s3 client
s3 = self.create_s3_client()

#fetching the image from the s3 using the file_path
content = self.get_image_from_s3(s3,file_path)

#storing the image in a public bucket and getting the image url
image_url = self.get_img_public_url(s3,file_path,content)
#encoding the caption with possible emojis and hashtags and removing the starting and ending double quotes
encoded_caption=self.create_caption(photo_description)

return image_url,encoded_caption

def get_req_insta_id(self,root_api_url,facebook_page_id,meta_user_access_token):
url_to_get_acc_id=f"{root_api_url}{facebook_page_id}?fields=instagram_business_account&access_token={meta_user_access_token}"
response=requests.get(
url_to_get_acc_id
)

return response

def post_media_container_id(self,root_api_url,insta_business_account_id,image_url,encoded_caption,meta_user_access_token):
url_to_create_media_container=f"{root_api_url}{insta_business_account_id}/media?image_url={image_url}&caption={encoded_caption}&access_token={meta_user_access_token}"
response = requests.post(
url_to_create_media_container
)

return response

def post_media(self,root_api_url,insta_business_account_id,container_ID,meta_user_access_token):
url_to_post_media_container=f"{root_api_url}{insta_business_account_id}/media_publish?creation_id={container_ID}&access_token={meta_user_access_token}"
response = requests.post(
url_to_post_media_container
)

return response
18 changes: 18 additions & 0 deletions superagi/tools/instagram_tool/instagram_toolkit.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
from abc import ABC
from typing import List
from superagi.tools.base_tool import BaseTool, BaseToolkit
from superagi.tools.instagram_tool.instagram import InstagramTool

class InstagramToolkit(BaseToolkit, ABC):
name: str = "Instagram Toolkit"
description: str = "Toolkit containing tools for posting AI generated photo on Instagram. Posts only one photo in a run "

def get_tools(self) -> List[BaseTool]:
return [InstagramTool()]

def get_env_keys(self) -> List[str]:
return [
"META_USER_ACCESS_TOKEN",
"FACEBOOK_PAGE_ID"
# Add more config keys specific to your project
]
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,7 @@ def test_execute(stable_diffusion_tool):


result = tool._execute('prompt', ['img1.png', 'img2.png'])

assert result == 'Images downloaded and saved successfully'
assert result.startswith('Images downloaded and saved successfully')
tool.resource_manager.write_binary_file.assert_called()

def test_call_stable_diffusion(stable_diffusion_tool):
Expand Down
Empty file.
Loading