neuralgeekroot commited on
Commit
8d96be9
1 Parent(s): 7c3bb7a

Converted the application to mutlimodel. Generate Image through OpenAI for the blog.

Browse files
Files changed (2) hide show
  1. app.py +80 -4
  2. requirements.txt +3 -2
app.py CHANGED
@@ -10,6 +10,7 @@ from langgraph.constants import Send
10
  import operator
11
  from langchain_core.messages import SystemMessage, HumanMessage
12
  from langsmith import traceable
 
13
 
14
  # Load environment variables
15
  load_dotenv()
@@ -17,9 +18,13 @@ os.environ['GROQ_API_KEY'] = os.getenv('GROQ_API_KEY')
17
  os.environ['LANGCHAIN_API_KEY'] = os.getenv('LANGCHAIN_API_KEY')
18
  os.environ['LANGSMITH_TRACING_V2'] = 'true'
19
  os.environ['LANGCHAIN_PROJECT_NAME'] = os.getenv('LANGCHAIN_PROJECT_NAME')
 
20
 
21
  # Initialize LLM
22
- llm = ChatGroq(model='llama3-70b-8192')
 
 
 
23
 
24
  # Define section structure
25
  class Section(BaseModel):
@@ -43,11 +48,35 @@ class BlogState(TypedDict):
43
  finalize_blog: str
44
  step: str
45
  final_blog: str
 
 
46
 
47
  class BlogStateSection(TypedDict):
48
  section: Section
49
  completed_sections: Annotated[list, operator.add]
50
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
51
  # Orchestrator node to generate an outline
52
  @traceable
53
  def generate_outline(state: BlogState):
@@ -68,6 +97,28 @@ def write_section(state: BlogStateSection):
68
  ])
69
  return {"completed_section": [section_content.content]}
70
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
71
  # Review node to check the quality of sections
72
  @traceable
73
  def review_section(state: BlogState):
@@ -91,6 +142,10 @@ def review_section(state: BlogState):
91
  def revise_section(state: BlogState):
92
  st.write("Revising the section content...")
93
  if state['step'] == "revise_section_content":
 
 
 
 
94
  revised_content = llm.invoke([
95
  SystemMessage(content="Based on the review feedback, improve the content further."),
96
  HumanMessage(content=f"Section Name: {state['sections'][0].section_name}, Description: {state['sections'][0].description}")
@@ -101,6 +156,9 @@ def revise_section(state: BlogState):
101
  @traceable
102
  def assign_writers(state: BlogState):
103
  st.write("Assigning writers to sections...")
 
 
 
104
  return [Send('write_section', {'section': s}) for s in state['outline']]
105
 
106
  # Decision function for routing after review
@@ -118,7 +176,21 @@ def seo_optimization(state: BlogState):
118
  @traceable
119
  def publish_blog(state: BlogState):
120
  st.write("Finalizing and publishing the blog...")
121
- return {"final_blog": state['finalize_blog']}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
122
 
123
  # Build LangGraph workflow
124
  builder = StateGraph(BlogState)
@@ -128,6 +200,7 @@ builder.add_node('generate_outline', generate_outline)
128
 
129
  # Add worker and review nodes
130
  builder.add_node('write_section', write_section)
 
131
  builder.add_node('review_section', review_section)
132
  builder.add_node('revise_section', revise_section)
133
 
@@ -138,7 +211,8 @@ builder.add_node('publish_blog', publish_blog)
138
  # Define workflow edges
139
  builder.add_edge(START, 'generate_outline')
140
  builder.add_conditional_edges('generate_outline', assign_writers, ['write_section'])
141
- builder.add_edge('write_section', 'review_section')
 
142
  builder.add_conditional_edges('review_section', should_revise, {'revise_section_content': 'revise_section', 'send_seo_optimization': 'seo_optimization'})
143
  builder.add_edge('revise_section', 'review_section') # Loop back after revision
144
  builder.add_edge('seo_optimization', 'publish_blog')
@@ -167,7 +241,9 @@ def main():
167
  'revise_section_content': [],
168
  'finalize_blog': "",
169
  'step': "",
170
- 'final_blog': ""
 
 
171
  }
172
 
173
  # Invoke workflow
 
10
  import operator
11
  from langchain_core.messages import SystemMessage, HumanMessage
12
  from langsmith import traceable
13
+ from openai import OpenAI
14
 
15
  # Load environment variables
16
  load_dotenv()
 
18
  os.environ['LANGCHAIN_API_KEY'] = os.getenv('LANGCHAIN_API_KEY')
19
  os.environ['LANGSMITH_TRACING_V2'] = 'true'
20
  os.environ['LANGCHAIN_PROJECT_NAME'] = os.getenv('LANGCHAIN_PROJECT_NAME')
21
+ os.environ['OPENAI_API_KEY'] = os.getenv('OPENAI_API_KEY')
22
 
23
  # Initialize LLM
24
+ llm = ChatGroq(model='gemma2-9b-it')
25
+
26
+ # Initialize OpenAI client for DALL路E
27
+ client = OpenAI()
28
 
29
  # Define section structure
30
  class Section(BaseModel):
 
48
  finalize_blog: str
49
  step: str
50
  final_blog: str
51
+ image_urls: list
52
+ fallback_links: list
53
 
54
  class BlogStateSection(TypedDict):
55
  section: Section
56
  completed_sections: Annotated[list, operator.add]
57
 
58
+ # Function to generate an image using DALL路E
59
+ def generate_image_with_dalle(prompt: str):
60
+ try:
61
+ response = client.images.generate(
62
+ model="dall-e-3",
63
+ prompt=prompt,
64
+ size="1024x1024",
65
+ quality="hd",
66
+ n=1,
67
+ )
68
+ image_url = response.data[0].url
69
+ return image_url
70
+ except Exception as e:
71
+ st.error(f"Failed to generate image: {e}")
72
+ return None
73
+
74
+ # Function to provide a fallback link for image search
75
+ def get_fallback_image_link(topic: str):
76
+ # Provide a Google Images search link for the topic
77
+ search_query = topic.replace(" ", "+")
78
+ return f"https://www.google.com/search?q={search_query}&tbm=isch"
79
+
80
  # Orchestrator node to generate an outline
81
  @traceable
82
  def generate_outline(state: BlogState):
 
97
  ])
98
  return {"completed_section": [section_content.content]}
99
 
100
+ # Function to generate an image using DALL路E
101
+ @traceable
102
+ def generate_image(state: BlogState):
103
+ st.write("Generating an image for the section...")
104
+ if not state.get('completed_section'):
105
+ st.warning("No completed sections found to generate an image.")
106
+ return {"image_urls": state.get('image_urls', []), "fallback_links": state.get('fallback_links', [])}
107
+
108
+ section = state['topic']
109
+ prompt = f"Generate an image for the blog section: {section} with no text. More of a representation and informative image"
110
+
111
+ image_url = generate_image_with_dalle(prompt)
112
+ if image_url:
113
+ image_urls = state.get('image_urls', [])
114
+ image_urls.append(image_url)
115
+ return {"image_urls": image_urls, "fallback_links": state.get('fallback_links', [])}
116
+ else:
117
+ fallback_links = state.get('fallback_links', [])
118
+ fallback_link = get_fallback_image_link(state['topic'])
119
+ fallback_links.append(fallback_link)
120
+ return {"image_urls": state.get('image_urls', []), "fallback_links": fallback_links}
121
+
122
  # Review node to check the quality of sections
123
  @traceable
124
  def review_section(state: BlogState):
 
142
  def revise_section(state: BlogState):
143
  st.write("Revising the section content...")
144
  if state['step'] == "revise_section_content":
145
+ if not state.get('sections'):
146
+ st.warning("No sections found to revise.")
147
+ return {"completed_section": state['completed_section']}
148
+
149
  revised_content = llm.invoke([
150
  SystemMessage(content="Based on the review feedback, improve the content further."),
151
  HumanMessage(content=f"Section Name: {state['sections'][0].section_name}, Description: {state['sections'][0].description}")
 
156
  @traceable
157
  def assign_writers(state: BlogState):
158
  st.write("Assigning writers to sections...")
159
+ if not state.get('outline'):
160
+ st.warning("No outline found to assign writers.")
161
+ return []
162
  return [Send('write_section', {'section': s}) for s in state['outline']]
163
 
164
  # Decision function for routing after review
 
176
  @traceable
177
  def publish_blog(state: BlogState):
178
  st.write("Finalizing and publishing the blog...")
179
+ final_blog = state['finalize_blog']
180
+
181
+ # Add images to the blog
182
+ if state.get('image_urls'):
183
+ st.subheader("AI-Generated Images")
184
+ for image_url in state['image_urls']:
185
+ st.image(image_url, caption="AI-Generated Image")
186
+
187
+ # Add fallback links if images were not generated
188
+ if state.get('fallback_links'):
189
+ st.subheader("Fallback Image Search Links")
190
+ for link in state['fallback_links']:
191
+ st.markdown(f"[Search for related images on Google]({link})")
192
+
193
+ return {"final_blog": final_blog}
194
 
195
  # Build LangGraph workflow
196
  builder = StateGraph(BlogState)
 
200
 
201
  # Add worker and review nodes
202
  builder.add_node('write_section', write_section)
203
+ builder.add_node('generate_image', generate_image)
204
  builder.add_node('review_section', review_section)
205
  builder.add_node('revise_section', revise_section)
206
 
 
211
  # Define workflow edges
212
  builder.add_edge(START, 'generate_outline')
213
  builder.add_conditional_edges('generate_outline', assign_writers, ['write_section'])
214
+ builder.add_edge('write_section', 'generate_image')
215
+ builder.add_edge('generate_image', 'review_section')
216
  builder.add_conditional_edges('review_section', should_revise, {'revise_section_content': 'revise_section', 'send_seo_optimization': 'seo_optimization'})
217
  builder.add_edge('revise_section', 'review_section') # Loop back after revision
218
  builder.add_edge('seo_optimization', 'publish_blog')
 
241
  'revise_section_content': [],
242
  'finalize_blog': "",
243
  'step': "",
244
+ 'final_blog': "",
245
+ 'image_urls': [], # Initialize image URLs list
246
+ 'fallback_links': [] # Initialize fallback links list
247
  }
248
 
249
  # Invoke workflow
requirements.txt CHANGED
@@ -1,8 +1,9 @@
1
  langchain
2
  langgraph
3
- langchain-openai
4
  langsmith
5
  streamlit
6
- langgraph
7
  langchain_groq
8
  dotenv
 
 
 
 
1
  langchain
2
  langgraph
 
3
  langsmith
4
  streamlit
 
5
  langchain_groq
6
  dotenv
7
+ langchain_openai
8
+ langchain_community
9
+ faiss-cpu