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

feat: action for twitter account details #23

Merged
merged 7 commits into from
Nov 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
from cdp_agentkit_core.actions.social.twitter.post_tweet import (
POST_TWEET_PROMPT as POST_TWEET_PROMPT,
from cdp_agentkit_core.actions.social.twitter.account_details import (
ACCOUNT_DETAILS_PROMPT as ACCOUNT_DETAILS_PROMPT,
)
from cdp_agentkit_core.actions.social.twitter.post_tweet import (
PostTweetInput as PostTweetInput,
from cdp_agentkit_core.actions.social.twitter.account_details import (
AccountDetailsInput as AccountDetailsInput,
)
from cdp_agentkit_core.actions.social.twitter.account_details import (
account_details as account_details,
)
from cdp_agentkit_core.actions.social.twitter.post_tweet import (
post_tweet as post_tweet,
POST_TWEET_PROMPT as POST_TWEET_PROMPT,
)
from cdp_agentkit_core.actions.social.twitter.post_tweet import PostTweetInput as PostTweetInput
from cdp_agentkit_core.actions.social.twitter.post_tweet import post_tweet as post_tweet
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import tweepy
from pydantic import BaseModel, Field

ACCOUNT_DETAILS_PROMPT = """
This tool will return account details for the currently authenticated Twitter (X) user context."""

class AccountDetailsInput(BaseModel):
stat marked this conversation as resolved.
Show resolved Hide resolved
"""Input argument schema for Twitter account details action."""

no_input: str = Field(
"",
description="No input required, e.g. `` (empty string).",
)

def account_details(client: tweepy.Client) -> str:
"""Get the authenticated Twitter (X) user account details.
Returns:
str: A message containing account details for the authenticated user context.
"""
message = ""

try:
response = client.get_me()
user = response.data

message = f"""Successfully retrieved authenticated user account details. Please present the following as json and not markdown:
id: {user.id}
name: {user.name}
username: {user.username}
link: https://x.com/{user.username}"""
except tweepy.errors.TweepyException as e:
message = f"Error retrieving authenticated user account details: {e}"

return message
10 changes: 10 additions & 0 deletions twitter-langchain/examples/account_details/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
ifneq (,$(wildcard ./.env))
include .env
endif

export

.PHONY: run
run:
poetry install --with dev
poetry run python account_details.py
59 changes: 59 additions & 0 deletions twitter-langchain/examples/account_details/account_details.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@

from langchain_core.messages import HumanMessage
from langchain_openai import ChatOpenAI
from langgraph.prebuilt import create_react_agent

from twitter_langchain import TwitterApiWrapper, TwitterToolkit

# Initialize TwitterApiwrapper
twitter_api_wrapper = TwitterApiWrapper()

# Create TwitterToolkit from the api wrapper
twitter_toolkit = TwitterToolkit.from_twitter_api_wrapper(twitter_api_wrapper)

# View available tools
tools = twitter_toolkit.get_tools()
for tool in tools:
print(tool.name)

# Initialize LLM
llm = ChatOpenAI(model="gpt-4o-mini")

# Create agent
agent_executor = create_react_agent(llm, tools)

# Example - get account details
events = agent_executor.stream(
{
"messages": [
HumanMessage(content="Please obtain my twitter account information"),
],
},
stream_mode="values",
)

for event in events:
event["messages"][-1].pretty_print()

# ================================ Human Message =================================
# Please obtain my twitter account information
# ================================== Ai Message ==================================
# Tool Calls:
# account_details (call_pYME8H1tHfdMakFZ1FTS0VBX)
# Call ID: call_pYME8H1tHfdMakFZ1FTS0VBX
# Args:
# ================================= Tool Message =================================
# Name: account_details

# Successfully retrieved authenticated user account details. Please present the following as json and not markdown:
# id: 1234567890123456789
# name: My Twitter Name
# username: MyTwitterUserName
# link: https://x.com/MyTwitterUserName
# ================================== Ai Message ==================================
# {
# "id": "1234567890123456789",
# "name": "My Twitter Name",
# "username": "MyTwitterUserName",
# "link": "https://x.com/MyTwitterUserName"
# }
7 changes: 2 additions & 5 deletions twitter-langchain/examples/post_tweet/post_tweet.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
import uuid

from langchain_openai import ChatOpenAI
from langchain_core.messages import HumanMessage
from langchain_openai import ChatOpenAI
from langgraph.prebuilt import create_react_agent

from twitter_langchain import (
TwitterApiWrapper,
TwitterToolkit
)
from twitter_langchain import TwitterApiWrapper, TwitterToolkit

# Initialize TwitterApiwrapper
twitter_api_wrapper = TwitterApiWrapper()
Expand Down
22 changes: 15 additions & 7 deletions twitter-langchain/twitter_langchain/twitter_api_wrapper.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,18 @@
"""Util that calls Twitter API."""


from typing import Any

from langchain_core.utils import get_from_dict_or_env
from pydantic import BaseModel, model_validator

from cdp_agentkit_core.actions.social.twitter import (
account_details,
post_tweet,
)
from langchain_core.utils import get_from_dict_or_env
from pydantic import BaseModel, model_validator


class TwitterApiWrapper(BaseModel):
"""Wrapper for Twitter API."""

bearer_token: str | None = None
client: Any | None = None

@model_validator(mode="before")
Expand Down Expand Up @@ -48,6 +46,15 @@ def validate_environment(cls, values: dict) -> Any:

return values

def account_details_wrapper(self) -> str:
"""Get the authenticated Twitter (X) user account details.

Returns:
str: A message containing account details for the authenticated user context in JSON format.

"""
return account_details(client=self.client)

def post_tweet_wrapper(self, tweet: str) -> str:
"""Post tweet to Twitter.

Expand All @@ -59,12 +66,13 @@ def post_tweet_wrapper(self, tweet: str) -> str:
str: A message containing the result of the post action and the tweet.

"""

return post_tweet(client=self.client, tweet=tweet)

def run(self, mode: str, **kwargs) -> str:
"""Run the action via the Twitter API."""
if mode == "post_tweet":
if mode == "account_details":
return self.account_details_wrapper()
elif mode == "post_tweet":
return self.post_tweet_wrapper(**kwargs)
else:
raise ValueError("Invalid mode: " + mode)
Expand Down
15 changes: 12 additions & 3 deletions twitter-langchain/twitter_langchain/twitter_toolkit.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
"""TwitterToolkit."""

from langchain_core.tools import BaseTool
from langchain_core.tools.base import BaseToolkit

from cdp_agentkit_core.actions.social.twitter import (
ACCOUNT_DETAILS_PROMPT,
POST_TWEET_PROMPT,
AccountDetailsInput,
PostTweetInput,
)
from langchain_core.tools import BaseTool
from langchain_core.tools.base import BaseToolkit

from twitter_langchain.twitter_action import TwitterAction
from twitter_langchain.twitter_api_wrapper import TwitterApiWrapper

Expand Down Expand Up @@ -55,6 +57,7 @@ class TwitterToolkit(BaseToolkit):

.. code-block:: none

account_details
post_tweet

Use within an agent:
Expand Down Expand Up @@ -120,6 +123,12 @@ def from_twitter_api_wrapper(cls, twitter_api_wrapper: TwitterApiWrapper) -> "Tw

"""
actions: list[dict] = [
{
"mode": "account_details",
"name": "account_details",
"description": ACCOUNT_DETAILS_PROMPT,
"args_schema": AccountDetailsInput,
},
{
"mode": "post_tweet",
"name": "post_tweet",
Expand Down
Loading