mubashirhussaindev commited on
Commit
ea77eb1
·
verified ·
1 Parent(s): 29576cb

Create agent.py

Browse files
Files changed (1) hide show
  1. agent.py +179 -0
agent.py ADDED
@@ -0,0 +1,179 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from langchain_google_genai import ChatGoogleGenerativeAI
2
+ from langchain_community.tools.tavily_search import TavilySearchResults
3
+ import requests
4
+ import os
5
+ from typing import List, TypedDict
6
+ from langgraph.types import Command
7
+ from typing import Literal, List
8
+ from langgraph.graph import StateGraph, START, END
9
+ from dotenv import load_dotenv
10
+
11
+ load_dotenv()
12
+
13
+ def get_platform_tips(state) -> Command[Literal['web_search']]:
14
+ """Conduct a web search to find up-to-date information on how to write an effective post for the provided platform."""
15
+ tavily_tool=TavilySearchResults(max_results=5)
16
+ tavily_output = tavily_tool.invoke(f"tips on how to write an effective post on {state['platform']}")
17
+ prompt = f"""
18
+ Summarize the tips provided in {tavily_output}. These tips will be used to generate a {state['platform']} post
19
+ Output as plain text.
20
+ """
21
+ response = model.invoke(prompt).content
22
+ return Command(update={"tips": response}, goto="web_search")
23
+
24
+ def web_search(state) -> Command[Literal['generate_post']]:
25
+ """Conduct a web search to find up-to-date information about a provided topic to be used for a social media post."""
26
+ tavily_tool=TavilySearchResults(max_results=5)
27
+ response = tavily_tool.invoke(state["topic"])
28
+ return Command(update={"tavily_results": response}, goto="generate_post")
29
+
30
+ def generate_social_media_post(state) -> Command[Literal["evaluate_engagement"]]:
31
+ """Generate a social media post for a B2B bank."""
32
+ prompt = f"""
33
+ You are a social media strategist for a B2B bank. Generate a {state["platform"]} post.
34
+ The post should:
35
+ - Be engaging but professional.
36
+ - Provide value to corporate clients.
37
+ - Focus on {state["topic"]}.
38
+ - Incorporate information from {state["tavily_results"]}
39
+ Output as plain text.
40
+ """
41
+ response = model.invoke(prompt)
42
+ return Command(update={"post": response.content}, goto="evaluate_engagement")
43
+
44
+ def evaluate_engagement(state) -> Command[Literal["evaluate_tone"]]:
45
+ """Assess how engaging the post is for LinkedIn/Instagram."""
46
+ prompt = f"""
47
+ Score the following post on engagement (1-10) basd on the provided social media platform.
48
+ Consider clarity, readability, and compelling call-to-action.
49
+
50
+ Platform: {state["platform"]}
51
+ Post: {state["post"]}
52
+
53
+ Respond with just a number.
54
+ """
55
+ score = model.invoke(prompt)
56
+ return Command(update={"engagement_score": score.content}, goto="evaluate_tone")
57
+
58
+ def evaluate_tone(state) -> Command[Literal["evaluate_clarity"]]:
59
+ """Check if the post maintains a professional yet engaging tone."""
60
+ prompt = f"""
61
+ Score the post’s tone (1-10). Ensure it's:
62
+ - Professional but not too rigid.
63
+ - Trustworthy and aligned with B2B financial services.
64
+ - Aligns with the specified platform.
65
+ Platform: {state["platform"]}
66
+ Post: {state["post"]}
67
+
68
+ Respond with just a number.
69
+ """
70
+ score = model.invoke(prompt)
71
+ return Command(update={"tone_score": score.content}, goto="evaluate_clarity")
72
+
73
+ def evaluate_clarity(state) -> Command[Literal["revise_if_needed"]]:
74
+ """Ensure the post is clear and not overly technical."""
75
+ prompt = f"""
76
+ Score the post on clarity (1-10).
77
+ - Avoids jargon.
78
+ - Easy to read for busy corporate professionals.
79
+ - Appropriate for the social media platform.
80
+ Platform: {state["platform"]}
81
+ Post: {state["post"]}
82
+ Respond with just a number.
83
+ """
84
+ score = model.invoke(prompt)
85
+ return Command(update={"clarity_score": score.content}, goto="revise_if_needed")
86
+
87
+ def revise_if_needed(state) -> Command[Literal["get_image"]]:
88
+ """Revise post if average evaluation score is below a threshold."""
89
+ scores = [int(state["engagement_score"]), int(state["tone_score"]), int(state["clarity_score"])]
90
+ avg_score = sum(scores) / len(scores)
91
+
92
+ if avg_score < 7: # Arbitrary threshold for revision
93
+ prompt = f"""
94
+ Revise this post to improve clarity, engagement, and tone:
95
+
96
+ {state["post"]}
97
+
98
+ Improve based on the following scores:
99
+ Engagement: {state["engagement_score"]}
100
+ Tone: {state["tone_score"]}
101
+ Clarity: {state["clarity_score"]}
102
+ """
103
+ revised_post = model.invoke(prompt)
104
+ return Command(update={"post": revised_post.content}, goto="get_image")
105
+
106
+ return Command(goto="get_image")
107
+
108
+ def fetch_image(state) -> Command[Literal[END]]:
109
+ """Fetch an image from Unsplash based on the provided text."""
110
+ prompt = f"""
111
+ You are a search optimization assistant. Your task is to take a topic and improve it to ensure the best image results from an image search API like Unsplash. Follow these steps:
112
+ 1. **Normalize the input**: Convert all text to lowercase and remove special characters (except for spaces).
113
+ 2. **Add more descriptive terms**: If the query is broad (e.g., "nature"), add more specific keywords like "landscape" or "outdoor" to help refine the search.
114
+ 3. **Use synonyms and related terms**: For terms that could have multiple meanings or common synonyms, expand the query to include variations. For example, if the user queries "car", you can add "vehicle" or "automobile".
115
+ 4. **Specify style and tone**: If the user provides a vague description, suggest adding words to define the style or mood of the image, such as "peaceful", "dramatic", or "colorful".
116
+ 5. **Categorize the query**: If applicable, categorize the query into domains like "nature", "architecture", or "people" and add related terms (e.g., "urban", "portrait", "scenic").
117
+ **Example Inputs and Outputs:**
118
+ 1. Input: "sunset over a beach"
119
+ Output: "sunset beach ocean horizon landscape"
120
+ 2. Input: "car"
121
+ Output: "car vehicle automobile road transport"
122
+ 3. Input: "nature"
123
+ Output: "nature landscape outdoor scenic green"
124
+ Topic: {state['topic']}
125
+ """
126
+
127
+ url = "https://api.pexels.com/v1/search"
128
+
129
+ params = {
130
+ "query": model.invoke(prompt).content,
131
+ "per_page": 5,
132
+ "page": 1
133
+ }
134
+
135
+ headers = {
136
+ "Authorization": os.getenv("PEXELS_API_KEY")
137
+ }
138
+
139
+ response = requests.get(url, headers=headers, params=params)
140
+ if response.status_code == 200:
141
+ data = response.json()
142
+ urls = []
143
+ for _, photo in enumerate(data['photos']):
144
+ urls.append(photo['url'])
145
+
146
+ return Command(update={"image_url": urls}, goto=END)
147
+ return Command(goto=END)
148
+
149
+ class State(TypedDict):
150
+ topic: str
151
+ platform: str
152
+ tips: str
153
+ tavily_results: List[dict]
154
+ post: str
155
+ engagement_score: int
156
+ tone_score: int
157
+ clarity_score: int
158
+ image_url: str
159
+
160
+ model = ChatGoogleGenerativeAI(
161
+ model="gemini-1.5-flash",
162
+ temperature=0,
163
+ max_tokens=None,
164
+ timeout=None,
165
+ max_retries=2,
166
+ )
167
+
168
+ workflow = StateGraph(State)
169
+ workflow.add_node("get_tips", get_platform_tips)
170
+ workflow.add_node("web_search", web_search)
171
+ workflow.add_node("generate_post", generate_social_media_post)
172
+ workflow.add_node("evaluate_engagement", evaluate_engagement)
173
+ workflow.add_node("evaluate_tone", evaluate_tone)
174
+ workflow.add_node("evaluate_clarity", evaluate_clarity)
175
+ workflow.add_node("revise_if_needed", revise_if_needed)
176
+ workflow.add_node("get_image", fetch_image)
177
+
178
+ workflow.add_edge(START, "get_tips")
179
+ graph = workflow.compile()