Within the fast-paced digital panorama, companies usually face the problem of promptly responding to buyer emails whereas sustaining accuracy and relevance. Leveraging superior instruments like LangGraph, Llama 3, and Groq, we will streamline e mail workflows by automating duties reminiscent of categorization, contextual analysis, and drafting considerate replies. This information demonstrates the best way to construct an automatic system to deal with these duties successfully, together with integration with search engines like google and APIs for seamless operations.
Studying Goals
- Learn to outline, handle, and execute multi-step workflows utilizing LangGraph, together with using nodes, edges, and conditional routing.
- Discover the method of incorporating exterior API like GROQ and internet search instruments into LangGraph workflows to reinforce performance and streamline operations.
- Acquire insights into managing shared states throughout workflow steps, together with passing inputs, monitoring intermediate outcomes, and making certain constant outputs.
- Perceive the significance of intermediate evaluation , suggestions loops, and refinement in producing high-quality outputs utilizing massive language fashions(LLMs).
- Learn to implement conditional logic for routing duties, dealing with errors, and adapting workflows dynamically based mostly on intermediate outcomes.
This text was printed as part of the Knowledge Science Blogathon.
Getting Began: Setup and Set up
Begin by putting in the mandatory Python libraries for this venture. These instruments will permit us to create a extremely purposeful and clever e mail reply system.
!pip -q set up langchain-groq duckduckgo-search
!pip -q set up -U langchain_community tiktoken langchainhub
!pip -q set up -U langchain langgraph tavily-python
You’ll be able to verify the profitable set up of langgraph by operating:
!pip present langgraph
Purpose
The system goals to automate e mail replies utilizing a step-by-step course of:
- Retrieve the incoming e mail.
- Categorize the e-mail into one of many following varieties:
- Gross sales
- Customized Inquiry
- Off-topic
- Buyer Criticism
- Generate key phrases for related analysis based mostly on the e-mail class and content material.
- Draft a reply utilizing researched info.
- Validate the draft reply.
- Rewrite the reply if vital.
This structured strategy ensures the e-mail response is tailor-made, correct, {and professional}.
Setting Up the Surroundings
To proceed, arrange the surroundings with the required API keys:
import os
from google.colab import userdata
from pprint import pprint
os.environ["GROQ_API_KEY"] = userdata.get('GROQ_API_KEY')
os.environ["TAVILY_API_KEY"] = userdata.get('TAVILY_API_KEY')
Implementing an Superior Electronic mail Reply System
To energy the e-mail processing pipeline, we use Groq’s Llama3-70b-8192 mannequin. This mannequin is very able to dealing with complicated duties like pure language understanding and era.
from langchain_groq import ChatGroq
GROQ_LLM = ChatGroq(
mannequin="llama3-70b-8192",
)
The Groq-powered LLM acts because the spine for categorizing emails, producing analysis key phrases, and drafting polished replies.
Constructing Immediate Templates
Utilizing LangChain’s ChatPromptTemplate and output parsers, we outline templates for producing and decoding outcomes. These templates be certain that the mannequin’s output aligns with our system’s necessities.
from langchain_core.prompts import ChatPromptTemplate
from langchain.prompts import PromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_core.output_parsers import JsonOutputParser
These instruments present the flexibleness wanted to deal with each free-form textual content and structured information, making them ideally suited for multi-step processes.
Utilities: Saving Outputs
As a part of the system, it’s helpful to log outputs for debugging or documentation functions. The next utility perform saves content material into markdown recordsdata:
def write_markdown_file(content material, filename):
"""Writes the given content material as a markdown file to the native listing.
Args:
content material: The string content material to jot down to the file.
filename: The filename to avoid wasting the file as.
"""
with open(f"{filename}.md", "w") as f:
f.write(content material)
This utility helps protect drafts, analysis outcomes, or evaluation stories for additional assessment or sharing.
Designing the Primary Chains
Our system consists of a sequence of logical chains, every addressing a particular side of the e-mail reply course of. Right here’s a quick overview:
- Categorize Electronic mail : Determine the kind of e mail(e.g., gross sales,customized inquiry,and so forth.)
- Analysis Router : Direct the e-mail’s context to the suitable search methodology.
- Search Key phrases : Extract related key phrases for gathering further info.
- Write Draft Electronic mail : Use the analysis and e mail context to generate a considerate reply.
- Rewrite Router : Decide if the draft requires rewriting or additional enchancment.
- Draft Electronic mail Evaluation : Consider the draft’s coherence, relevance, and tone.
- Rewrite Electronic mail : Finalize the e-mail by refining its tone and content material.
Categorizing Emails
Step one in our pipeline is categorizing the incoming e mail. Utilizing a customized immediate template, we information the Llama3 mannequin to research the e-mail and assign it to one of many predefined classes:
- price_enquiry : Questions associated to pricing.
- customer_complaint: Points or grievances.
- product_enquiry: Questions on options, advantages , or providers(excluding pricing).
- customer_feedback : Basic suggestions a few services or products.
- off_topic : Emails that don’t it every other class.
Defining the Immediate Template
We create a structured immediate to assist the mannequin concentrate on the categorization activity:
from langchain.prompts import PromptTemplate
immediate = PromptTemplate(
template="""<|begin_of_text|><|start_header_id|>system<|end_header_id|>
You might be an Electronic mail Categorizer Agent. You're a grasp at understanding what a buyer needs after they write an e mail and are capable of categorize it in a helpful approach.
<|eot_id|><|start_header_id|>person<|end_header_id|>
Conduct a complete evaluation of the e-mail supplied and categorize it into one of many following classes:
price_enquiry - used when somebody is asking for details about pricing
customer_complaint - used when somebody is complaining about one thing
product_enquiry - used when somebody is asking for details about a product characteristic, profit, or service however not about pricing
customer_feedback - used when somebody is giving suggestions a few product
off_topic - when it doesn’t relate to every other class.
Output a single class solely from the kinds ('price_enquiry', 'customer_complaint', 'product_enquiry', 'customer_feedback', 'off_topic')
e.g.:
'price_enquiry'
EMAIL CONTENT:nn {initial_email} nn
<|eot_id|>
<|start_header_id|>assistant<|end_header_id|>
""",
input_variables=["initial_email"],
)
Connecting the Immediate with Groq’s LLM
To course of the immediate, we hyperlink it to the GROQ_LLM mannequin and parse the consequence as a string.
from langchain_core.output_parsers import StrOutputParser
email_category_generator = immediate | GROQ_LLM | StrOutputParser()
Testing the Electronic mail Categorization
Let’s check the categorization with an instance e mail:
EMAIL = """HI there, n
I'm emailing to say that I had a beautiful keep at your resort final week. n
I actually admire what your employees did.
Thanks,
Paul
"""
consequence = email_category_generator.invoke({"initial_email": EMAIL})
print(consequence)
Output
The system analyzes the content material and categorizes the e-mail as:
"customer_feedback"
This categorization is correct based mostly on the e-mail content material, showcasing the mannequin’s capability to grasp nuanced buyer inputs.
Designing a Analysis Router
Not all emails require exterior analysis. The system straight solutions some emails based mostly on their content material and class, whereas it gathers further info to draft complete replies for others. The Analysis Router determines the suitable motion—whether or not to carry out a seek for supplementary info or proceed on to drafting the e-mail.
Defining the Analysis Router Immediate
The Analysis Router Immediate evaluates the preliminary e mail and its assigned class to determine between two actions:
- draft_email : For easy responses that don’t require further analysis.
- research_info : For circumstances requiring further context or information.
This determination is encoded in a JSON format to make sure clear and structured output.
research_router_prompt = PromptTemplate(
template="""<|begin_of_text|><|start_header_id|>system<|end_header_id|>
You might be an professional at studying the preliminary e mail and routing internet search
or on to a draft e mail.
Use the next standards to determine the best way to route the e-mail:
If the preliminary e mail solely requires a easy response:
- Select 'draft_email' for questions you may simply reply,
together with immediate engineering and adversarial assaults.
- If the e-mail is simply saying thanks, and so forth., select 'draft_email.'
In any other case, use 'research_info.'
Give a binary alternative 'research_info' or 'draft_email' based mostly on the query.
Return a JSON with a single key 'router_decision' and no preamble or rationalization.
Use each the preliminary e mail and the e-mail class to make your determination.
<|eot_id|><|start_header_id|>person<|end_header_id|>
Electronic mail to route INITIAL_EMAIL: {initial_email}
EMAIL_CATEGORY: {email_category}
<|eot_id|><|start_header_id|>assistant<|end_header_id|>
""",
input_variables=["initial_email", "email_category"],
)
Integrating the Immediate with Groq’s LLM
Much like the categorization step, we join the immediate to GROQ_LLM and parse the consequence utilizing the JsonOutputParser.
from langchain_core.output_parsers import JsonOutputParser
research_router = research_router_prompt | GROQ_LLM | JsonOutputParser()
Testing the Analysis Router
We use the next e mail and class as enter:
EMAIL = """HI there, n
I'm emailing to say that I had a beautiful keep at your resort final week. n
I actually admire what your employees did.
Thanks,
Paul
"""
email_category = "customer_feedback"
consequence = research_router.invoke({"initial_email": EMAIL, "email_category": email_category})
print(consequence)
Output
The Analysis Router produces the next JSON output:
{'router_decision': 'draft_email'}
This means that the e-mail doesn’t require further analysis, and we will proceed on to drafting the reply.
Producing Search Key phrases
In circumstances the place exterior analysis is required, figuring out exact search key phrases is vital. This step makes use of the e-mail content material and its assigned class to generate the best key phrases for retrieving related info.
Defining the Search Key phrases Immediate
The Search Key phrases Immediate helps the mannequin extract as much as three key phrases that can information a centered and environment friendly internet search. This ensures the analysis part is each correct and related.
search_keyword_prompt = PromptTemplate(
template="""<|begin_of_text|><|start_header_id|>system<|end_header_id|>
You're a grasp at understanding the perfect key phrases for an online search
to seek out essentially the most related info for the shopper.
Given the INITIAL_EMAIL and EMAIL_CATEGORY, work out the perfect
key phrases that can discover essentially the most related info to assist write
the ultimate e mail.
Return a JSON with a single key 'key phrases' containing not more than
3 key phrases, and no preamble or rationalization.
<|eot_id|><|start_header_id|>person<|end_header_id|>
INITIAL_EMAIL: {initial_email}
EMAIL_CATEGORY: {email_category}
<|eot_id|><|start_header_id|>assistant<|end_header_id>
""",
input_variables=["initial_email", "email_category"],
)
Constructing the Search Key phrase Chain
We join the search_keyword_prompt to the GROQ_LLM mannequin and parse the outcomes as JSON for structured output.
search_keyword_chain = search_keyword_prompt | GROQ_LLM | JsonOutputParser()
Testing the Search Key phrases Technology
Utilizing the identical e mail and class from earlier:
EMAIL = """HI there, n
I'm emailing to say that I had a beautiful keep at your resort final week. n
I actually admire what your employees did.
Thanks,
Paul
"""
email_category = "customer_feedback"
consequence = search_keyword_chain.invoke({"initial_email": EMAIL, "email_category": email_category})
print(consequence)
Output
The system generates a JSON response with as much as three key phrases:
{'key phrases': ['hotel customer feedback', 'resort appreciation email', 'positive travel review']}
These key phrases replicate the essence of the e-mail and can assist retrieve focused and helpful info for crafting the ultimate response.
By producing exact search key phrases, the system streamlines the analysis part, making it simpler to collect related information for e mail replies. Subsequent, we’ll discover the best way to draft the e-mail based mostly on analysis and context. Let me know if you happen to’d like to maneuver on!
Writing the Draft Electronic mail
With the analysis full (if wanted) and the e-mail categorized, the subsequent step is to draft a considerate {and professional} response. This step ensures that the response aligns with the shopper’s intent and maintains a pleasant tone.
Defining the Draft Author Immediate
The Draft Author Immediate takes into consideration the preliminary e mail, its class, and any supplementary analysis info to craft a customized reply. The template contains particular directions based mostly on the e-mail class to make sure applicable responses:
- off_topic : Ask clarifying questions.
- customer_complaint : Reassure the shopper and deal with their considerations.
- customer_feedback: Acknowledge the suggestions and specific gratitude.
- product_enquiry : Present concise and pleasant info based mostly on the analysis.
- price_enquiry : Ship the requested pricing info.
The draft is returned as a JSON object with the important thing email_draft.
draft_writer_prompt = PromptTemplate(
template="""<|begin_of_text|><|start_header_id|>system<|end_header_id|>
You're the Electronic mail Author Agent. Take the INITIAL_EMAIL beneath from a human that has emailed our firm e mail deal with, the email_category
that the categorizer agent gave it, and the analysis from the analysis agent, and
write a useful e mail in a considerate and pleasant approach.
If the shopper e mail is 'off_topic' then ask them inquiries to get extra info.
If the shopper e mail is 'customer_complaint' then attempt to guarantee we worth them and that we're addressing their points.
If the shopper e mail is 'customer_feedback' then thank them and acknowledge their suggestions positively.
If the shopper e mail is 'product_enquiry' then attempt to give them the data the researcher supplied in a succinct and pleasant approach.
If the shopper e mail is 'price_enquiry' then attempt to give the pricing data they requested.
You by no means make up info that hasn't been supplied by the research_info or within the initial_email.
At all times log off the emails in an applicable method and from Sarah, the Resident Supervisor.
Return the e-mail as a JSON with a single key 'email_draft' and no preamble or rationalization.
<|eot_id|><|start_header_id|>person<|end_header_id|>
INITIAL_EMAIL: {initial_email} n
EMAIL_CATEGORY: {email_category} n
RESEARCH_INFO: {research_info} n
<|eot_id|><|start_header_id|>assistant<|end_header_id>""",
input_variables=["initial_email", "email_category", "research_info"],
)
Constructing the Draft Electronic mail Chain
The immediate is related to the GROQ_LLM mannequin, and the output is parsed as structured JSON.
draft_writer_chain = draft_writer_prompt | GROQ_LLM | JsonOutputParser()
Testing the Draft Electronic mail Author
We offer the system with the e-mail, class, and analysis info. For this check, no further analysis is required:
email_category = "customer_feedback"
research_info = None
consequence = draft_writer_chain.invoke({
"initial_email": EMAIL,
"email_category": email_category,
"research_info": research_info,
})
print(consequence)
Output:
{
"email_draft": "Pricey Paul,nnThank you a lot to your
form phrases and suggestions about your current keep at our
resort. We’re thrilled to listen to that you simply had a beautiful
expertise and that our employees made your keep particular.
It really means so much to us.nnYour satisfaction is our
high precedence, and we’re all the time right here to make sure each
go to is memorable.nnLooking ahead to welcoming
you again sooner or later!nnWarm regards,nSarahn
Resident Supervisor"
}
Output:
{'email_draft': "Pricey Paul,nnThank you a lot for taking the time to share your great expertise at our resort! We're thrilled to listen to that our employees made a constructive impression on
This response displays the system’s capability to create a considerate and applicable reply whereas adhering to the supplied context.
With the draft e mail generated, the pipeline is nearly full. Within the subsequent step, we’ll analyze and, if vital, refine the draft for optimum high quality. Let me know if you happen to’d prefer to proceed!
Rewrite Router
Not all draft emails are excellent on the primary try. The Rewrite Router evaluates the draft e mail to find out if it adequately addresses the shopper’s considerations or requires rewriting for higher readability, tone, or completeness.
Defining the Rewrite Router Immediate
The Rewrite Router Immediate evaluates the draft e mail towards the next standards:
- No Rewrite Required (
- The draft e mail offers a easy response matching the necessities.
- The draft e mail addresses all considerations from the preliminary e mail.
- Rewrite Required (
- The draft e mail lacks info wanted to handle the shopper’s considerations.
- The draft e mail’s tone or content material is inappropriate.
- The response is returned in JSON format with a single key, router_decision.
rewrite_router_prompt = PromptTemplate(
template="""<|begin_of_text|><|start_header_id|>system<|end_header_id|>
You might be an professional at evaluating emails which might be draft emails for the shopper and deciding in the event that they
should be rewritten to be higher. n
Use the next standards to determine if the DRAFT_EMAIL must be rewritten: nn
If the INITIAL_EMAIL solely requires a easy response which the DRAFT_EMAIL comprises, then it does not should be rewritten.
If the DRAFT_EMAIL addresses all of the considerations of the INITIAL_EMAIL, then it does not should be rewritten.
If the DRAFT_EMAIL is lacking info that the INITIAL_EMAIL requires, then it must be rewritten.
Give a binary alternative 'rewrite' (for must be rewritten) or 'no_rewrite' (for does not should be rewritten) based mostly on the DRAFT_EMAIL and the factors.
Return a JSON with a single key 'router_decision' and no preamble or rationalization.
<|eot_id|><|start_header_id|>person<|end_header_id|>
INITIAL_EMAIL: {initial_email} n
EMAIL_CATEGORY: {email_category} n
DRAFT_EMAIL: {draft_email} n
<|eot_id|><|start_header_id|>assistant<|end_header_id>""",
input_variables=["initial_email", "email_category", "draft_email"],
)
Constructing the Rewrite Router Chain
This chain combines the immediate with the GROQ_LLM mannequin to judge the draft e mail and decide if additional refinement is important.
rewrite_router = rewrite_router_prompt | GROQ_LLM | JsonOutputParser()
Testing the Rewrite Router
For testing, let’s consider a draft e mail that clearly falls wanting expectations:
email_category = "customer_feedback"
draft_email = "Yo we will not show you how to, finest regards Sarah"
consequence = rewrite_router.invoke({
"initial_email": EMAIL,
"email_category": email_category,
"draft_email": draft_email
})
print(consequence)
Output
The system identifies the necessity for rewriting:
{'router_decision': 'rewrite'}
This ensures that inappropriate or incomplete drafts don’t attain the shopper.
By implementing the Rewrite Router, the system ensures that each e mail response meets a excessive commonplace of high quality and relevance.
Draft Electronic mail Evaluation
The Draft Electronic mail Evaluation step evaluates the standard of the draft e mail, making certain that it successfully addresses the shopper’s points and offers actionable suggestions for enchancment.
Defining the Draft Evaluation Immediate
The Draft Evaluation Immediate inspects the draft e mail utilizing the next standards:
- Does the draft e mail adequately deal with the shopper’s considerations based mostly on the e-mail class?
- Does it align with the context and tone of the preliminary e mail?
- Are there any particular areas the place the draft could be improved (e.g., tone, readability, completeness)?
The output is structured as a JSON object containing a single key, draft_analysis, with suggestions and recommendations.
draft_analysis_prompt = PromptTemplate(
template="""<|begin_of_text|><|start_header_id|>system<|end_header_id|>
You're the High quality Management Agent. Learn the INITIAL_EMAIL beneath from a human that has emailed
our firm e mail deal with, the email_category that the categorizer agent gave it, and the
analysis from the analysis agent, and write an evaluation of the e-mail.
Verify if the DRAFT_EMAIL addresses the shopper's points based mostly on the e-mail class and the
content material of the preliminary e mail.n
Give suggestions on how the e-mail could be improved and what particular issues could be added or modified
to make the e-mail simpler at addressing the shopper's points.
You by no means make up or add info that hasn't been supplied by the research_info or within the initial_email.
Return the evaluation as a JSON with a single key 'draft_analysis' and no preamble or rationalization.
<|eot_id|><|start_header_id|>person<|end_header_id|>
INITIAL_EMAIL: {initial_email} nn
EMAIL_CATEGORY: {email_category} nn
RESEARCH_INFO: {research_info} nn
DRAFT_EMAIL: {draft_email} nn
<|eot_id|><|start_header_id|>assistant<|end_header_id|>""",
input_variables=["initial_email", "email_category", "research_info", "draft_email"],
)
Constructing the Draft Evaluation Chain
This chain pairs the immediate with the GROQ_LLM mannequin and parses the output.
draft_analysis_chain = draft_analysis_prompt | GROQ_LLM | JsonOutputParser()
Testing the Draft Evaluation Chain
We check the chain with a intentionally poor draft e mail to look at the system’s suggestions:
email_category = "customer_feedback"
research_info = None
draft_email = "Yo we will not show you how to, finest regards Sarah"
email_analysis = draft_analysis_chain.invoke({
"initial_email": EMAIL,
"email_category": email_category,
"research_info": research_info,
"draft_email": draft_email
})
pprint(email_analysis)
Output
The system offers constructive evaluation:
Evaluation
The suggestions emphasizes the necessity for professionalism, alignment with buyer sentiment, and correct acknowledgment of their message. It additionally offers a concrete instance of how the draft e mail could be improved.
With the Draft Evaluation in place, the system ensures steady enchancment and better high quality in buyer communication.
The Rewrite Electronic mail with Evaluation step refines the draft e mail utilizing the suggestions supplied within the Draft Electronic mail Evaluation. This ultimate step ensures that the e-mail is polished and applicable for sending to the shopper.
Defining the Rewrite Electronic mail Immediate
The Rewrite Electronic mail Immediate combines the draft e mail with the suggestions from the Draft Electronic mail Evaluation. The objective is to use the prompt modifications and enhance the tone, readability, and effectiveness of the response with out introducing any new info.
The output is a JSON containing a single key, final_email, which comprises the refined model of the draft e mail.
rewrite_email_prompt = PromptTemplate(
template="""<|begin_of_text|><|start_header_id|>system<|end_header_id|>
You're the Remaining Electronic mail Agent. Learn the e-mail evaluation beneath from the QC Agent
and use it to rewrite and enhance the draft_email to create a ultimate e mail.
You by no means make up or add info that hasn't been supplied by the research_info or within the initial_email.
Return the ultimate e mail as JSON with a single key 'final_email' which is a string and no preamble or rationalization.
<|eot_id|><|start_header_id|>person<|end_header_id|>
EMAIL_CATEGORY: {email_category} nn
RESEARCH_INFO: {research_info} nn
DRAFT_EMAIL: {draft_email} nn
DRAFT_EMAIL_FEEDBACK: {email_analysis} nn
<|eot_id|>"""
input_variables=["initial_email", "email_category", "research_info", "email_analysis", "draft_email"],
)
Constructing the Rewrite Chain
This chain combines the immediate with GROQ_LLM to generate the ultimate model of the e-mail based mostly on the evaluation.
rewrite_chain = rewrite_email_prompt | GROQ_LLM | JsonOutputParser()
Testing the Rewrite Electronic mail Chain
To check, we use the customer_feedback class and a draft e mail that requires substantial revision.
email_category = 'customer_feedback'
research_info = None
draft_email = "Yo we will not show you how to, finest regards Sarah"
final_email = rewrite_chain.invoke({
"initial_email": EMAIL,
"email_category": email_category,
"research_info": research_info,
"draft_email": draft_email,
"email_analysis": email_analysis
})
print(final_email['final_email'])
Instance Output
'Pricey Paul, thanks a lot for taking the time to share your great expertise at our resort. We're thrilled to listen to that our employees have been capable of make your keep particular. If ther e's anything we will help you with, please do not hesitate to achieve out. Greatest regards, Sarah'
By implementing the Rewrite Electronic mail with Evaluation step, the system delivers a elegant ultimate draft that successfully addresses the shopper’s suggestions and maintains knowledgeable tone.
The Instrument Setup part configures the instruments wanted for your entire course of. Right here, the search software is initialized and the state of the graph is outlined. These instruments permit for interplay with exterior information sources and make sure the e mail era course of follows a structured circulate.
The TavilySearchResults software is about as much as deal with internet searches and retrieve related outcomes.
from langchain_community.instruments.tavily_search import TavilySearchResults
web_search_tool = TavilySearchResults(ok=1)
The ok=1 parameter ensures that just one result’s fetched per search.
State Setup
The GraphState class, outlined as a TypedDict, represents the state of the method. It tracks the mandatory information throughout the completely different levels of e mail processing.
from langchain.schema import Doc
from langgraph.graph import END, StateGraph
from typing_extensions import TypedDict
from typing import Listing
class GraphState(TypedDict):
"""
Represents the state of our graph.
Attributes:
initial_email: e mail
email_category: e mail class
draft_email: LLM era
final_email: LLM era
research_info: record of paperwork
info_needed: whether or not so as to add search data
num_steps: variety of steps
"""
initial_email: str
email_category: str
draft_email: str
final_email: str
research_info: Listing[str]
info_needed: bool
num_steps: int
draft_email_feedback: dict
- initial_email : The content material of the shopper’s e mail.
- email_category : The class assigned to the e-mail(e.g., gross sales, criticism, suggestions).
- draft_email : The e-mail generated by the system in response to the shopper’s message.
- final_email : The ultimate model of the e-mail after revisions based mostly on evaluation.
- research_info: A listing of related paperwork gathered in the course of the analysis part.
- info_needed : A boolean flag indicating if further info is required for the e-mail response.
- num_steps : A counter for the variety of steps accomplished.
- draft_email_feedback : Suggestions from the draft evaluation stage.
This state setup helps in monitoring the method, making certain that every one vital info is offered and up-to-date as the e-mail response evolves.
The Nodes part defines the important thing steps within the e mail dealing with course of. These nodes correspond to completely different actions within the pipeline, from categorizing the e-mail to researching and drafting the response. Every perform manipulates the GraphState, performs an motion, after which updates the state.
Categorize Electronic mail
The categorize_email node categorizes the incoming e mail based mostly on its content material.
def categorize_email(state):
"""Take the preliminary e mail and categorize it"""
print("---CATEGORIZING INITIAL EMAIL---")
initial_email = state['initial_email']
num_steps = int(state['num_steps'])
num_steps += 1
# Categorize the e-mail
email_category = email_category_generator.invoke({"initial_email": initial_email})
print(email_category)
# Save class to native disk
write_markdown_file(email_category, "email_category")
return {"email_category": email_category, "num_steps": num_steps}
- This perform calls the email_category_generator to categorize the e-mail based mostly on its content material.
- The class is saved to a file for record-keeping.
- It returns the up to date state with the email_category and an incremented num_steps.
Analysis Data Search
The research_info_search node performs an online search based mostly on key phrases derived from the preliminary e mail and its class.
def research_info_search(state):
print("---RESEARCH INFO SEARCHING---")
initial_email = state["initial_email"]
email_category = state["email_category"]
research_info = state["research_info"]
num_steps = state['num_steps']
num_steps += 1
# Internet seek for key phrases
key phrases = search_keyword_chain.invoke({"initial_email": initial_email,
"email_category": email_category })
key phrases = key phrases['keywords']
full_searches = []
for key phrase in key phrases[:1]: # Solely taking the primary key phrase
print(key phrase)
temp_docs = web_search_tool.invoke({"question": key phrase})
web_results = "n".be part of([d["content"] for d in temp_docs])
web_results = Doc(page_content=web_results)
if full_searches will not be None:
full_searches.append(web_results)
else:
full_searches = [web_results]
print(full_searches)
print(sort(full_searches))
return {"research_info": full_searches, "num_steps": num_steps}
- The perform generates an inventory of key phrases based mostly on the initial_email and email_category utilizing search_keyword_chain.
- It then performs an online seek for every key phrase utilizing TravilySearchResults.
- The outcomes are gathered into an inventory of Doc objects and saved to the state as research_info.
Subsequent Steps within the Course of
To finish the e-mail pipeline, we have to outline further nodes that deal with drafting, analyzing, and rewriting the e-mail. As an illustration:
- Draft Electronic mail Author: Makes use of the categorized e mail, analysis data, and LLMs to generate the primary draft of the e-mail.
- Analyze Draft Electronic mail: Critiques the draft e mail and offers suggestions for enhancements.
- Rewrite Electronic mail: Makes use of the suggestions to rewrite the draft e mail right into a ultimate model.
- No Rewrite: If no rewrite is important, this node would go the draft to the subsequent stage with out modifications.
- State Printer: Prints or logs the present state for debugging functions.
Instance of Additional Steps
def draft_email_writer(state):
print("---WRITING DRAFT EMAIL---")
# Implement logic to generate draft e mail based mostly on analysis and class.
return {"draft_email": draft_email_content, "num_steps": state['num_steps']}
def analyze_draft_email(state):
print("---ANALYZING DRAFT EMAIL---")
# Implement logic to research draft e mail, offering suggestions.
return {"draft_email_feedback": draft_feedback, "num_steps": state['num_steps']}
def rewrite_email(state):
print("---REWRITING EMAIL---")
# Use suggestions to rewrite the e-mail.
return {"final_email": final_email_content, "num_steps": state['num_steps']}
def state_printer(state):
print("---STATE---")
print(state)
return state
These further nodes would guarantee a easy transition via your entire e mail processing pipeline.
features draft_email_writer and analyze_draft_email are set as much as generate and consider e mail drafts based mostly on the present state, which incorporates the preliminary e mail, its class, analysis info, and the present step within the course of. Right here’s a fast evaluation of the 2 features:
Draft Electronic mail Author (draft_email_writer)
This perform creates a draft e mail based mostly on the preliminary e mail, e mail class, and analysis data.
def draft_email_writer(state):
print("---DRAFT EMAIL WRITER---")
## Get the state
initial_email = state["initial_email"]
email_category = state["email_category"]
research_info = state["research_info"]
num_steps = state['num_steps']
num_steps += 1
# Generate draft e mail utilizing the draft_writer_chain
draft_email = draft_writer_chain.invoke({"initial_email": initial_email,
"email_category": email_category,
"research_info": research_info})
print(draft_email)
email_draft = draft_email['email_draft'] # Extract the e-mail draft from response
write_markdown_file(email_draft, "draft_email") # Save draft to a markdown file
return {"draft_email": email_draft, "num_steps": num_steps}
- The perform first extracts vital particulars from the state (initial_email, email_category, research_info).
- It then calls the draft_writer_chain to generate a draft e mail.
- The draft e mail is printed and saved to a markdown file for assessment.
- The up to date state with the generated draft e mail and incremented num_steps is returned.
Draft Electronic mail Analyzer (analyze_draft_email)
This perform analyzes the draft e mail and offers suggestions on the best way to enhance it.
def analyze_draft_email(state):
print("---DRAFT EMAIL ANALYZER---")
## Get the state
initial_email = state["initial_email"]
email_category = state["email_category"]
draft_email = state["draft_email"]
research_info = state["research_info"]
num_steps = state['num_steps']
num_steps += 1
# Generate draft e mail suggestions utilizing the draft_analysis_chain
draft_email_feedback = draft_analysis_chain.invoke({"initial_email": initial_email,
"email_category": email_category,
"research_info": research_info,
"draft_email": draft_email})
# Save suggestions to a markdown file for later assessment
write_markdown_file(str(draft_email_feedback), "draft_email_feedback")
return {"draft_email_feedback": draft_email_feedback, "num_steps": num_steps}
- The perform takes the state and retrieves vital info like draft e mail, analysis data, and e mail class.
- It then invokes the draft_analysis_chain to research the draft e mail, offering suggestions on its high quality and effectiveness.
- The suggestions is saved as a markdown file for reference, and the up to date state (with suggestions and incremented num_steps) is returned.
rewrite_email perform is designed to take the draft e mail and its related suggestions, then use that to generate a ultimate e mail that comes with the mandatory modifications and enhancements.
Right here’s a breakdown of the perform:
def rewrite_email(state):
print("---REWRITE EMAIL ---")
# Extract vital state variables
initial_email = state["initial_email"]
email_category = state["email_category"]
draft_email = state["draft_email"]
research_info = state["research_info"]
draft_email_feedback = state["draft_email_feedback"]
num_steps = state['num_steps']
# Increment the step depend
num_steps += 1
# Generate the ultimate e mail utilizing the rewrite_chain
final_email = rewrite_chain.invoke({
"initial_email": initial_email,
"email_category": email_category,
"research_info": research_info,
"draft_email": draft_email,
"email_analysis": draft_email_feedback
})
# Save the ultimate e mail to a markdown file for assessment
write_markdown_file(str(final_email), "final_email")
# Return up to date state with the ultimate e mail and incremented steps
return {"final_email": final_email['final_email'], "num_steps": num_steps}
Key Factors
- Extract State Variables: It begins by extracting the required state variables reminiscent of initial_email, email_category, draft_email, research_info, and draft_email_feedback.
- Increment Step Rely: The num_steps counter is incremented to replicate that this can be a new step within the course of (i.e., producing the ultimate e mail).
- Generate Remaining Electronic mail: The rewrite_chain is used to generate the ultimate e mail based mostly on the preliminary e mail, e mail class, analysis data, draft e mail, and suggestions (from the earlier step, i.e., the draft_email_feedback).
This step improves the draft e mail based mostly on the evaluation suggestions.
- Write Remaining Electronic mail to Disk: The ultimate e mail is saved to a markdown file (for transparency and assessment).
- Return Up to date State: The perform returns the ultimate e mail and up to date num_steps to replace the general state for subsequent steps.
Rationalization of the New Capabilities
- no_rewrite: This perform is used when the draft e mail doesn’t require any additional modifications and is able to be despatched as the ultimate e mail.
- Inputs: It takes within the state, particularly specializing in the draft e mail.
- Course of:
- The draft_email is taken into account ultimate, so it’s saved as the ultimate e mail.
- The num_steps counter is incremented to trace the progress.
- Output: It returns the state with the final_email set to the draft e mail, and an up to date num_steps.
def no_rewrite(state):
print("---NO REWRITE EMAIL ---")
## Get the state
draft_email = state["draft_email"]
num_steps = state['num_steps']
num_steps += 1
# Save the draft e mail as ultimate e mail
write_markdown_file(str(draft_email), "final_email")
return {"final_email": draft_email, "num_steps": num_steps}
- state_printer: This perform prints out the present state of the method, giving an in depth overview of the variables and their values. This may be helpful for debugging or monitoring the progress in your e mail era pipeline.
- Inputs: It takes the total state as enter.
- Course of: It prints the values of the preliminary e mail, e mail class, draft e mail, ultimate e mail, analysis data, data wanted, and num_steps.
- Output: This perform doesn’t return something however helps in debugging or logging.
def state_printer(state):
"""print the state"""
print("---STATE PRINTER---")
print(f"Preliminary Electronic mail: {state['initial_email']} n" )
print(f"Electronic mail Class: {state['email_category']} n")
print(f"Draft Electronic mail: {state['draft_email']} n" )
print(f"Remaining Electronic mail: {state['final_email']} n" )
print(f"Analysis Data: {state['research_info']} n")
print(f"Num Steps: {state['num_steps']} n")
# Verify if 'info_needed' exists within the state
info_needed = state.get('info_needed', 'N/A')
print(f"Data Wanted: {info_needed} n")
return
How These Match Into the Workflow
- The no_rewrite perform is usually known as if the system determines that the draft e mail doesn’t want modifications, which means it’s prepared for ultimate supply.
- The state_printer perform is beneficial throughout debugging or to test your entire course of step-by-step.
Instance Stream
- If the rewrite_router or one other course of determines that no modifications are wanted, the no_rewrite perform is named.
- The state_printer could be invoked at any level within the workflow (sometimes after finishing the e-mail era) to examine the ultimate state of the system.
Rationalization of route_to_research Perform
This perform determines the subsequent step within the course of circulate based mostly on the routing determination made by the research_router. The choice will depend on the content material of the e-mail and its categorization. Right here’s the way it works:
- Inputs: The state dictionary, which comprises the present state of the e-mail processing workflow, together with the preliminary e mail and e mail class.
- Course of: The perform invokes the research_router to determine whether or not the e-mail requires further analysis (internet search) or if it might probably straight proceed to drafting a response.
The research_router returns a router_decision indicating whether or not to proceed with analysis (‘research_info’) or go straight to drafting the e-mail (‘draft_email’).
- Outputs: The perform returns the identify of the subsequent node to name within the workflow: “research_info” (if the e-mail wants additional analysis) or “draft_email” (if the e-mail could be drafted straight).
- Logging: There are print statements to show the choice made and the reasoning behind it. That is helpful for debugging and making certain that the routing logic works as meant.
Code Implementation
def route_to_research(state):
"""
Route e mail to internet search or not.
Args:
state (dict): The present graph state
Returns:
str: Subsequent node to name
"""
print("---ROUTE TO RESEARCH---")
initial_email = state["initial_email"]
email_category = state["email_category"]
# Route determination based mostly on the e-mail class and content material
router = research_router.invoke({"initial_email": initial_email, "email_category": email_category})
print(router)
# Retrieve the router's determination
print(router['router_decision'])
# Routing logic
if router['router_decision'] == 'research_info':
print("---ROUTE EMAIL TO RESEARCH INFO---")
return "research_info"
elif router['router_decision'] == 'draft_email':
print("---ROUTE EMAIL TO DRAFT EMAIL---")
return "draft_email"
How It Suits into the Graph
- Routing Resolution: Primarily based on the consequence from research_router, this perform routes the method to both:
- research_info: If the e-mail requires analysis to reply a buyer question.
- draft_email: If the e-mail could be answered straight with out additional analysis.
- Conditional Edge: This perform is usually a part of a decision-making step (conditional edge) in your state graph, serving to steer the workflow.
Instance Workflow
- Preliminary Electronic mail is acquired.
- Electronic mail Categorization occurs to categorise the e-mail into one of many outlined classes (e.g., buyer suggestions).
- Route Resolution: Primarily based on the e-mail’s class and content material, the route_to_research perform decides if additional analysis is required or if a draft e mail could be created.
- If analysis is required, it routes to research_info. In any other case, it proceeds to draft_email.
Rationalization of route_to_rewrite Perform
This perform determines the subsequent step within the course of circulate based mostly on the analysis of the draft e mail. Particularly, it decides whether or not the draft e mail must be rewritten or if it may be despatched as is. Right here’s the way it works:
Inputs
The state dictionary, which comprises:
- initial_email: The unique e mail from the shopper.
- email_category: The class assigned to the e-mail (e.g., buyer suggestions, product inquiry, and so forth.).
- draft_email: The e-mail draft generated earlier.
- research_info: Any related info retrieved from the analysis step, though it isn’t used straight right here.
Course of
The perform invokes the rewrite_router to evaluate whether or not the draft e mail wants rewriting based mostly on the initial_email, email_category, and draft_email.
The rewrite_router returns a router_decision, which could be both:
- rewrite: Signifies the draft e mail must be improved and despatched for evaluation.
- no_rewrite: Signifies the draft e mail is adequate and might proceed to the ultimate stage.
Outputs
- If the choice is rewrite, the perform routes to the rewrite step to revise the draft.
- If the choice is no_rewrite, the perform proceeds to finalize the e-mail.
Logging
There are print statements to log the choice and monitor the workflow progress.
Code Implementation
def route_to_rewrite(state):
"""
Route e mail to rewrite or not, based mostly on the draft e mail high quality.
Args:
state (dict): The present graph state
Returns:
str: Subsequent node to name (rewrite or no_rewrite)
"""
print("---ROUTE TO REWRITE---")
initial_email = state["initial_email"]
email_category = state["email_category"]
draft_email = state["draft_email"]
research_info = state["research_info"]
# Invoke the rewrite router to judge the draft e mail
router = rewrite_router.invoke({"initial_email": initial_email,
"email_category": email_category,
"draft_email": draft_email})
print(router)
# Retrieve the router's determination
print(router['router_decision'])
# Routing logic based mostly on the analysis
if router['router_decision'] == 'rewrite':
print("---ROUTE TO ANALYSIS - REWRITE---")
return "rewrite"
elif router['router_decision'] == 'no_rewrite':
print("---ROUTE EMAIL TO FINAL EMAIL---")
return "no_rewrite"
How It Suits into the Graph
- This perform is usually invoked after the draft e mail has been generated.
- It evaluates the standard of the draft e mail and decides if it wants additional revision or if it may be finalized instantly.
- Primarily based on the choice, it both routes to the rewrite step (the place the e-mail is revised) or the no_rewrite step (the place the draft is finalized).
Instance Workflow
- Preliminary Electronic mail: The shopper sends an e mail.
- Electronic mail Categorization: The e-mail is categorized based mostly on its content material.
- Draft Electronic mail Creation: A draft e mail is generated.
- Rewrite Resolution: The route_to_rewrite perform evaluates if the draft must be rewritten:
- If rewrite is required, the draft goes to the rewrite step.
- If no_rewrite is chosen, the draft strikes to the ultimate e mail stage.
This code defines the construction of the workflow for processing buyer emails utilizing a state graph, the place every step of the method is dealt with by completely different nodes. Let’s break down the workflow and clarify the way it works:
Workflow Overview
- StateGraph: This can be a directed graph the place nodes characterize duties (like categorizing emails, drafting replies, and so forth.), and edges outline the circulate of the method from one activity to the subsequent.
- Nodes: Every node corresponds to a perform or motion that might be carried out in the course of the workflow (e.g., categorizing the e-mail, producing a draft reply, analyzing the draft).
- Edges: These outline the transitions between nodes. Conditional edges permit routing based mostly on choices (e.g., whether or not to seek for analysis info or draft the e-mail).
Key Elements of the Graph
- Entry Level: The method begins on the categorize_email node.
- Categorizing the Electronic mail:
- The primary activity is to categorize the incoming e mail right into a predefined class (like “buyer suggestions”, “product inquiry”, and so forth.). That is carried out within the categorize_email node.
- As soon as categorized, a choice is made whether or not to seek for analysis data or straight draft a response based mostly on the class.
- Conditional Routing
From categorize_email:
If analysis data is required (based mostly on the e-mail class), the workflow strikes to research_info_search. In any other case, it goes to draft_email_writer to straight generate a response draft.
From draft_email_writer: After the draft is created:
- The system evaluates the draft and decides whether or not it requires rewriting.
- If rewriting is important, it sends the draft to analyze_draft_email for assessment and enchancment.
- If no rewrite is required, the system forwards the draft on to state_printer for ultimate output.
Finalization
After analyzing and rewriting the draft e mail or accepting it as-is, the system sends the e-mail to state_printer, which prints the ultimate state of the e-mail together with all related info.
Finish Level: The method concludes when state_printer has completed printing the ultimate e mail and state info.
# Outline the workflow (state graph)
workflow = StateGraph(GraphState)
# Add nodes to the workflow graph
workflow.add_node("categorize_email", categorize_email) # Categorize the e-mail
workflow.add_node("research_info_search", research_info_search) # Carry out internet seek for data
workflow.add_node("state_printer", state_printer) # Print the ultimate state
workflow.add_node("draft_email_writer", draft_email_writer) # Generate draft e mail
workflow.add_node("analyze_draft_email", analyze_draft_email) # Analyze the draft
workflow.add_node("rewrite_email", rewrite_email) # Rewrite the e-mail if vital
workflow.add_node("no_rewrite", no_rewrite) # No rewrite wanted, simply finalize
# Set the entry level to the "categorize_email" node
workflow.set_entry_point("categorize_email")
# Add conditional edges based mostly on the result of the categorization
workflow.add_conditional_edges(
"categorize_email",
route_to_research,
{
"research_info": "research_info_search", # If analysis data wanted, go to analysis
"draft_email": "draft_email_writer", # If no analysis wanted, go to draft e mail era
},
)
# Add edges between nodes
workflow.add_edge("research_info_search", "draft_email_writer") # After analysis, go to drafting
# Add conditional edges based mostly on whether or not the draft e mail wants rewriting or not
workflow.add_conditional_edges(
"draft_email_writer",
route_to_rewrite,
{
"rewrite": "analyze_draft_email", # If rewrite wanted, go to research draft
"no_rewrite": "no_rewrite", # If no rewrite wanted, go to ultimate e mail
},
)
# Add edges to finalize the e-mail or ship for rewriting
workflow.add_edge("analyze_draft_email", "rewrite_email") # After analyzing, rewrite the e-mail
workflow.add_edge("no_rewrite", "state_printer") # No rewrite, finalize the e-mail
workflow.add_edge("rewrite_email", "state_printer") # After rewriting, finalize the e-mail
# Lastly, add the tip node
workflow.add_edge("state_printer", END)
# Compile the workflow into an executable utility
app = workflow.compile()
Workflow Execution
- The method begins with categorizing the e-mail.
- Relying on the e-mail class, it both searches for related info or strikes on to drafting a response.
- As soon as the draft is prepared, it’s evaluated for any vital revisions.
- The method ends when the ultimate e mail (both rewritten or not) is printed.
This setup creates a versatile and automatic course of for dealing with buyer emails, permitting for personalised responses based mostly on their wants.
EMAIL = """HI there, n
I'm emailing to say that I had a beautiful keep at your resort final week. n
I actually appreaciate what your employees did
Thanks,
Paul
"""
EMAIL = """HI there, n
I'm emailing to say that the resort climate was technique to cloudy and overcast. n
I wished to jot down a track known as 'Right here comes the solar but it surely by no means got here'
What ought to be the climate in Arizona in April?
I actually hope you repair this subsequent time.
Thanks,
George
"""
# run the agent
inputs = {
"initial_email": EMAIL,
"research_info": None,
"num_steps": 0,
"info_needed": False # Guarantee this secret is added
}
for output in app.stream(inputs):
for key, worth in output.gadgets():
pprint(f"Completed operating: {key}:")
Output:
---CATEGORIZING INITIAL EMAIL---
'customer_complaint'
---ROUTE TO RESEARCH---
{'router_decision': 'research_info'} research_info
---ROUTE EMAIL TO RESEARCH INFO---
'Completed operating: categorize_email:'
---RESEARCH INFO SEARCHING--- Arizona climate April
[Document(metadata={}, page_content="{'location': {'name': 'Arizona', 'region': 'Atlantida', 'country': 'Honduras', 'lat: 15.6333, 'lon': -87.3167, 'tz_id': 'America/Tegucigalpa', 'localtime_epoch: 1731842866, 'localtime': '2824-11-17 05:27'), 'current': {'last_updated_epoch: 1731842100, 'last_updated': '2824-11-17 85:15', 'temp_c": 23.4, 'temp_f': 74.1, 'is_day': 0, 'cond:
'Finished running: research_info_search:
---DRAFT EMAIL WRITER---
{"email_draft": "Hi George, nnThank you for reaching out to us about the weather conditions during your recent resort stay. Sorry to hear that it was cloudy and overcast, and I can understand why you'd want to write a song about it!nnRegarding your question about the weather in Arizona in April, I can provide you with some information. Typically, Arizona's weather in April ---ROUTE TO REWRITE--- {'router_decision': 'no_rewrite"}
no_rewrite
---ROUTE EMAIL TO FINAL EMAIL---
'Finished running: draft_email_writer:"
---NO REWRITE EMAIL ---
'Finished running: no_rewrite:'
---STATE PRINTER---
Initial Email: HI there,
I am emailing to say that the resort weather was way to cloudy and overcast.
I wanted to write a song called 'Here comes the sun but it never came'
What should be the weather in Arizona in April?
I really hope you fix this next time.
Thanks, George
Email Category: 'customer_complaint'
Draft Email: Hi George,
Thank you for reaching out to us about the weather conditions during your recent resort stay. Sorry to hear that it was cloudy and overcast, and I can understand why you'd want to write a song about it!
Regarding your question about the weather in Arizona in April, I can provide you with some information. Typically, Arizona's weather in April is quite comfortable, with low temperatures around 64°F and highs up to 84°F. You can expect a few rainy days, but overall, the weather is usually pleasant during this time.
I want to assure you that we value your feedback and would like to make things right. Unfortunately, we can't control the weather, but we'll do our best to ensure that your next stay with us is more to your liking.
Thank you for your feedback, and I hope you get to write that song someday!
Best regards,
Sarah, Resident Manager
Final Email: Hi George,
Thank you for reaching out to us about the weather conditions during your recent resort stay. Sorry to hear that it was cloudy and overcast, and I can understand why you'd want to write a song about it!
Regarding your question about the weather in Arizona in April, I can provide you with some information. Typically, Arizona's weather in April is quite comfortable, with low temperatures around 64°F and highs up to 84°F. You can expect a few rainy days, but overall, the weather is usually pleasant during this time.
output = app.invoke(inputs)
print(output['final_email'])
Output:
---CATEGORIZING INITIAL EMAIL---
'customer_complaint'
---ROUTE TO RESEARCH---
{'router_decision': 'research_info"} analysis data
---ROUTE EMAIL TO RESEARCH INFO---
---RESEARCH INFO SEARCHING---
Arizona climate April
[Document(metadata={}, page_content="{'location': {'name': 'Arizona', 'region': 'Atlantida', 'country': 'Honduras', 'lat: 15.6333, 'lon': -87.3167, 'tz_id': 'America/Tegucigalpa', 'localtime_epoch: 1731842866, 'localtime': '2824-11-17 85:27"}, 'current': {'last_updated_epoch': 1731842188, 'last_updated': '2824-11-17 85:15', 'temp_c": 23.4, 'temp_f': 74.1, 'is_day': 0, 'cone
---DRAFT EMAIL WRITER---
---ROUTE TO REWRITE---
{"email_draft": "Hi George, nnI'm so sorry to hear that the weather didn't quite live up to your expectations during your recent stay at our resort. I can understand how frustrating it must be to experience cloudy and overcast weather, and I appreciate your sense of humor in wanting to write a song titled 'Here comes the sun but it never came'!nnRegarding your question ab {'router_decision': 'no_rewrite"}
no_rewrite
---ROUTE EMAIL TO FINAL EMAIL---
---NO REWRITE EMAIL ---
---STATE PRINTER---
Initial Email: HI there,
I am emailing to say that the resort weather was way to cloudy and overcast.
I wanted to write a song called 'Here comes the sun but it never came'
What should be the weather in Arizona in April?
I really hope you fix this next time.
Thanks, George
Email Category: 'customer_complaint"
Draft Email: Hi George,
I'm so sorry to hear that the weather didn't quite live up to your expectations during your recent stay at our resort. I can understand how frustrating it must be to experience cloudy and overcast weather, and I appreciate your sense of humor in wanting to write a song titled 'Here comes the sun but it never came'!
Regarding your question about the weather in Arizona in April, I'd be happy to help. According to our research, April is a great time to visit Arizona, with comfortable temperatures ranging from 64°F to 84°F. While it's not uncommon to experience some rainy days during the month, the weather is generally pleasant and comfortable. If you're planning a trip to Arizona in April, Once again, I apologize for any inconvenience the weather may have caused during your stay, and I hope you'll give us another chance to provide you with a more enjoyable experience in the future.
Thank you for reaching out to us, and I wish you all the best.
Best regards,
Sarah
Resident Manager
Final Email: Hi George,
I'm so sorry to hear that the weather didn't quite live up to your expectations during your recent stay at our resort. I can understand how frustrating it must be to experience cloudy and overcast weather, and I appreciate your sense of humor in wanting to write a song titled 'Here comes the sun but it never came'!
Regarding your question about the weather in Arizona in April, I'd be happy to help. According to our research, April is a great time to visit Arizona, with comfortable temperatures ranging from 64°F to 84°F. While it's not uncommon to experience some rainy days during the month, the weather is generally pleasant and comfortable. If you're planning a trip to Arizona in April, Once again, I apologize for any inconvenience the weather may have caused during your stay, and I hope you'll give us another chance to provide you with a more enjoyable experience in the future.
Thank you for reaching out to us, and I wish you all the best.
Best regards,
Sarah
Resident Manager
Research Info: [Document(metadata={}, page_content="{"location": {'name': 'Arizona', 'region': 'Atlantida', 'country': 'Honduras', 'lat': 15.6333, 'lon': -87.3167, 'tz_id": 'America/Tegucigalpa', 'localtime_epoch": 1731842866, 'localtime': '2824-11-17 85:27'), 'current': {'last_updated_epoch": 1731842180, "last_updated': '2824-11-17 05:15', 'temp_c": 23.4, 'temp_f': 74.1, 'is Info Needed: False
Num Steps: 4
Hi George,
I'm so sorry to hear that the weather didn't quite live up to your expectations during your recent stay at our resort. I can understand how frustrating it must be to experience cloudy and overcast weather, and I appreciate your sense of humor in wanting to write a song titled 'Here comes the sun but it never came'!
Regarding your question about the weather in Arizona in April, I'd be happy to help. According to our research, April is a great time to visit Arizona, with comfortable temperatures ranging from 64°F to 84°F. While it's not uncommon to experience some rainy days during the month, the weather is generally pleasant and comfortable. If you're planning a trip to Arizona in April, Once again, I apologize for any inconvenience the weather may have caused during your stay, and I hope you'll give us another chance to provide you with a more enjoyable experience in the future.
Thank you for reaching out to us, and I wish you all the best.
Best regards,
Sarah
Resident Manager
The system efficiently categorized the email as a ‘customer_complaint’ and routed it to research the weather information for Arizona in April. The research module gathered detailed data about expected weather patterns, including average temperatures and rainfall. Using this information, a polite and informative draft email was generated, directly addressing the concerns raised by the customer.
As the draft met quality expectations, it bypassed the rewrite process, finalizing with a well-crafted response that provided relevant weather insights and reassured the customer. The process concluded in just 4 steps, showcasing the system’s ability to deliver contextually accurate, customer-focused communication with minimal intervention.
Conclusion
Incorporating LangGraph and GROQ’s LLM into your email workflow provides a robust, scalable, and efficient solution for handling customer communications. By leveraging LangGraph’s flexible state management and GROQ’s advanced natural language processing capabilities, this workflow automates tasks like email categorization, research integration, and response drafting while ensuring quality control and customer satisfaction.
This approach not only saves time and resources but also enhances the accuracy and professionalism of your responses, fostering better relationships with your customers. Whether you’re handling simple inquiries or complex complaints, this workflow is adaptable, reliable, and future-proof, making it an invaluable tool for modern customer service operations.
As businesses continue to prioritize efficiency and customer experience, implementing such intelligent workflows is a step toward maintaining a competitive edge in today’s dynamic environment.
Key Takeaways
- LangGraph automates complex processes with modular, adaptable workflows.
- Steps like analysis and rewriting improve LLM output quality.
- Proper state tracking ensures smooth transitions and consistent results.
- Conditional routing tailors processes to input needs.
- Integrating research augments LLM outputs with relevant, informed content.
Frequently Asked Questions
A. LangGraph is a state management library designed for orchestrating and structuring workflows involving large language models (LLMs). It provides tools for building and managing complex workflows while keeping track of the state of each process step.
A. GROQ API provides access to GROQ-powered LLMs, offering high-performance natural language processing capabilities. It is used for tasks like text generation, summarization, classification, and more, making it an essential tool for AI-driven applications.
A. LangGraph provides the structure and control flow for workflows, while GROQ API delivers the LLM capabilities for processing tasks within those workflows. For example, LangGraph can define a workflow where GROQ’s LLM is used to categorize emails, draft responses, or perform analysis.
A. Yes, LangGraph allows you to define workflows with conditional paths based on intermediate outputs. This is useful for applications like routing customer inquiries based on their content.
A. GROQ API supports text-based inputs for tasks like text classification, generation, and summarization. It can also handle structured data when appropriately formatted.
The media shown in this article is not owned by Analytics Vidhya and is used at the Author’s discretion.