Within the fast-paced digital panorama, companies typically face the problem of promptly responding to buyer emails whereas sustaining accuracy and relevance. Leveraging superior instruments like LangGraph, Llama 3, and Groq, we are able to streamline e-mail workflows by automating duties comparable to categorization, contextual analysis, and drafting considerate replies. This information demonstrates easy methods to construct an automatic system to deal with these duties successfully, together with integration with engines like google and APIs for seamless operations.
Studying Targets
- 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 net search instruments into LangGraph workflows to boost performance and streamline operations.
- Achieve insights into managing shared states throughout workflow steps, together with passing inputs, monitoring intermediate outcomes, and guaranteeing constant outputs.
- Perceive the significance of intermediate evaluation , suggestions loops, and refinement in producing high-quality outputs utilizing giant language fashions(LLMs).
- Learn to implement conditional logic for routing duties, dealing with errors, and adapting workflows dynamically primarily based on intermediate outcomes.
This text was printed as part of the Information Science Blogathon.
Getting Began: Setup and Set up
Begin by putting in the required Python libraries for this mission. 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 possibly can 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 primarily based on the e-mail class and content material.
- Draft a reply utilizing researched info.
- Validate the draft reply.
- Rewrite the reply if essential.
This structured strategy ensures the e-mail response is tailor-made, correct, {and professional}.
Setting Up the Setting
To proceed, arrange the atmosphere 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 advanced 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 deciphering outcomes. These templates be sure 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 pliability wanted to deal with each free-form textual content and structured knowledge, 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 information:
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 put in writing to the file.
filename: The filename to save lots of the file as.
"""
with open(f"{filename}.md", "w") as f:
f.write(content material)
This utility helps protect drafts, analysis outcomes, or evaluation reviews for additional overview or sharing.
Designing the Fundamental Chains
Our system consists of a collection 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 technique.
- 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 investigate 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 companies(excluding pricing).
- customer_feedback : Normal suggestions a couple of 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 give attention to the categorization job:
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 desires once they write an e-mail and are capable of categorize it in a helpful means.
<|eot_id|><|start_header_id|>person<|end_header_id|>
Conduct a complete evaluation of the e-mail offered 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 couple of 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 end result as a string.
from langchain_core.output_parsers import StrOutputParser
email_category_generator = immediate | GROQ_LLM | StrOutputParser()
Testing the Electronic mail Categorization
Let’s take a look at 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
"""
end result = email_category_generator.invoke({"initial_email": EMAIL})
print(end result)
Output
The system analyzes the content material and categorizes the e-mail as:
"customer_feedback"
This categorization is correct primarily based on the e-mail content material, showcasing the mannequin’s means to grasp nuanced buyer inputs.
Designing a Analysis Router
Not all emails require exterior analysis. The system straight solutions some emails primarily based 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 resolve between two actions:
- draft_email : For easy responses that don’t require further analysis.
- research_info : For circumstances requiring further context or knowledge.
This choice 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 net search
or on to a draft e-mail.
Use the next standards to resolve easy methods to route the e-mail:
If the preliminary e-mail solely requires a easy response:
- Select 'draft_email' for questions you possibly can 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 selection 'research_info' or 'draft_email' primarily based 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 choice.
<|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
Just like the categorization step, we join the immediate to GROQ_LLM and parse the end result 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"
end result = research_router.invoke({"initial_email": EMAIL, "email_category": email_category})
print(end result)
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 are able to 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 simplest 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 targeted and environment friendly net search. This ensures the analysis section 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 figuring out the perfect key phrases for an online search
to search out probably the most related info for the client.
Given the INITIAL_EMAIL and EMAIL_CATEGORY, work out the perfect
key phrases that can discover probably 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"
end result = search_keyword_chain.invoke({"initial_email": EMAIL, "email_category": email_category})
print(end result)
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 section, making it simpler to assemble related knowledge for e-mail replies. Subsequent, we’ll discover easy methods to draft the e-mail primarily based on analysis and context. Let me know when you’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 client’s intent and maintains a pleasant tone.
Defining the Draft Author Immediate
The Draft Author Immediate takes under consideration the preliminary e-mail, its class, and any supplementary analysis info to craft a personalised reply. The template contains particular directions primarily based on the e-mail class to make sure acceptable responses:
- off_topic : Ask clarifying questions.
- customer_complaint : Reassure the client and deal with their issues.
- customer_feedback: Acknowledge the suggestions and specific gratitude.
- product_enquiry : Present concise and pleasant info primarily based 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 under 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 means.
If the client e-mail is 'off_topic' then ask them inquiries to get extra info.
If the client e-mail is 'customer_complaint' then attempt to guarantee we worth them and that we're addressing their points.
If the client e-mail is 'customer_feedback' then thank them and acknowledge their suggestions positively.
If the client e-mail is 'product_enquiry' then attempt to give them the data the researcher offered in a succinct and pleasant means.
If the client e-mail is 'price_enquiry' then attempt to give the pricing information they requested.
You by no means make up info that hasn't been offered by the research_info or within the initial_email.
At all times log off the emails in an acceptable 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 take a look at, no further analysis is required:
email_category = "customer_feedback"
research_info = None
end result = draft_writer_chain.invoke({
"initial_email": EMAIL,
"email_category": email_category,
"research_info": research_info,
})
print(end result)
Output:
{
"email_draft": "Expensive Paul,nnThank you a lot in your
variety 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 actually means quite a bit to us.nnYour satisfaction is our
high precedence, and we’re at all times 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': "Expensive Paul,nnThank you a lot for taking the time to share your fantastic expertise at our resort! We're thrilled to listen to that our employees made a optimistic influence on
This response displays the system’s means to create a considerate and acceptable reply whereas adhering to the offered context.
With the draft e-mail generated, the pipeline is sort of full. Within the subsequent step, we’ll analyze and, if essential, refine the draft for optimum high quality. Let me know when you’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 client’s issues 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 issues from the preliminary e-mail.
- Rewrite Required (
- The draft e-mail lacks info wanted to deal with the client’s issues.
- 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 are draft emails for the client and deciding in the event that they
should be rewritten to be higher. n
Use the next standards to resolve if the DRAFT_EMAIL must be rewritten: nn
If the INITIAL_EMAIL solely requires a easy response which the DRAFT_EMAIL incorporates, then it would not should be rewritten.
If the DRAFT_EMAIL addresses all of the issues of the INITIAL_EMAIL, then it would not should be rewritten.
If the DRAFT_EMAIL is lacking info that the INITIAL_EMAIL requires, then it must be rewritten.
Give a binary selection 'rewrite' (for must be rewritten) or 'no_rewrite' (for would not should be rewritten) primarily based on the DRAFT_EMAIL and the standards.
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 guage the draft e-mail and decide if additional refinement is critical.
rewrite_router = rewrite_router_prompt | GROQ_LLM | JsonOutputParser()
Testing the Rewrite Router
For testing, let’s consider a draft e-mail that clearly falls in need of expectations:
email_category = "customer_feedback"
draft_email = "Yo we won't make it easier to, greatest regards Sarah"
end result = rewrite_router.invoke({
"initial_email": EMAIL,
"email_category": email_category,
"draft_email": draft_email
})
print(end result)
Output
The system identifies the necessity for rewriting:
{'router_decision': 'rewrite'}
This ensures that inappropriate or incomplete drafts don’t attain the client.
By implementing the Rewrite Router, the system ensures that each e-mail response meets a excessive customary of high quality and relevance.
Draft Electronic mail Evaluation
The Draft Electronic mail Evaluation step evaluates the standard of the draft e-mail, guaranteeing that it successfully addresses the client’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 client’s issues primarily based 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 under 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 client's points primarily based 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 client's points.
You by no means make up or add info that hasn't been offered 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 take a look at 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 won't make it easier to, greatest 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 offered within the Draft Electronic mail Evaluation. This remaining step ensures that the e-mail is polished and acceptable for sending to the client.
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 incorporates 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 under from the QC Agent
and use it to rewrite and enhance the draft_email to create a remaining e-mail.
You by no means make up or add info that hasn't been offered 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 primarily based 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 won't make it easier to, greatest 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
'Expensive Paul, thanks a lot for taking the time to share your fantastic expertise at our resort. We're thrilled to listen to that our employees had been capable of make your keep particular. If ther e's the rest we are able to help you with, please do not hesitate to succeed in out. Greatest regards, Sarah'
By implementing the Rewrite Electronic mail with Evaluation step, the system delivers a refined remaining draft that successfully addresses the client’s suggestions and maintains knowledgeable tone.
The Software Setup part configures the instruments wanted for the complete course of. Right here, the search instrument is initialized and the state of the graph is outlined. These instruments permit for interplay with exterior knowledge sources and make sure the e-mail era course of follows a structured circulate.
The TavilySearchResults instrument is about as much as deal with net searches and retrieve related outcomes.
from langchain_community.instruments.tavily_search import TavilySearchResults
web_search_tool = TavilySearchResults(okay=1)
The okay=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 required knowledge 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 Record
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 information
num_steps: variety of steps
"""
initial_email: str
email_category: str
draft_email: str
final_email: str
research_info: Record[str]
info_needed: bool
num_steps: int
draft_email_feedback: dict
- initial_email : The content material of the client’s e-mail.
- email_category : The class assigned to the e-mail(e.g., gross sales, grievance, suggestions).
- draft_email : The e-mail generated by the system in response to the client’s message.
- final_email : The ultimate model of the e-mail after revisions primarily based on evaluation.
- research_info: An inventory of related paperwork gathered through the analysis section.
- 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, guaranteeing that each one essential info is on the market 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 primarily based 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 primarily based 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 primarily based 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 shouldn't be None:
full_searches.append(web_results)
else:
full_searches = [web_results]
print(full_searches)
print(kind(full_searches))
return {"research_info": full_searches, "num_steps": num_steps}
- The perform generates a listing of key phrases primarily based 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 a listing 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. For example:
- Draft Electronic mail Author: Makes use of the categorized e-mail, analysis information, and LLMs to generate the primary draft of the e-mail.
- Analyze Draft Electronic mail: Evaluations 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 remaining model.
- No Rewrite: If no rewrite is critical, this node would move 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 primarily based 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 investigate 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 by means of the complete e-mail processing pipeline.
features draft_email_writer and analyze_draft_email are set as much as generate and consider e-mail drafts primarily based 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 primarily based on the preliminary e-mail, e-mail class, and analysis information.
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 essential 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 overview.
- 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 easy methods 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 overview
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 essential info like draft e-mail, analysis information, and e-mail class.
- It then invokes the draft_analysis_chain to investigate 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 remaining e-mail that comes with the required modifications and enhancements.
Right here’s a breakdown of the perform:
def rewrite_email(state):
print("---REWRITE EMAIL ---")
# Extract essential 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 rely
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 overview
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 comparable to 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 primarily based on the preliminary e-mail, e-mail class, analysis information, draft e-mail, and suggestions (from the earlier step, i.e., the draft_email_feedback).
This step improves the draft e-mail primarily based on the evaluation suggestions.
- Write Remaining Electronic mail to Disk: The ultimate e-mail is saved to a markdown file (for transparency and overview).
- 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 Features
- 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 remaining, 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 remaining 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, remaining e-mail, analysis information, information 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, that means it’s prepared for remaining supply.
- The state_printer perform is beneficial throughout debugging or to examine the complete course of step-by-step.
Instance Move
- If the rewrite_router or one other course of determines that no modifications are wanted, the no_rewrite perform is known as.
- 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 primarily based on the routing choice made by the research_router. The choice is determined by the content material of the e-mail and its categorization. Right here’s the way it works:
- Inputs: The state dictionary, which incorporates 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 resolve whether or not the e-mail requires further analysis (net 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 guaranteeing that the routing logic works as supposed.
Code Implementation
def route_to_research(state):
"""
Route e-mail to net 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 choice primarily based 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 choice
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 Choice: Based mostly on the end result 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 obtained.
- Electronic mail Categorization occurs to categorise the e-mail into one of many outlined classes (e.g., buyer suggestions).
- Route Choice: Based mostly 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 primarily based 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 incorporates:
- initial_email: The unique e-mail from the client.
- 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 primarily based 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 ample 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 observe the workflow progress.
Code Implementation
def route_to_rewrite(state):
"""
Route e-mail to rewrite or not, primarily based 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 guage 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 choice
print(router['router_decision'])
# Routing logic primarily based 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.
- Based mostly 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 client sends an e-mail.
- Electronic mail Categorization: The e-mail is categorized primarily based on its content material.
- Draft Electronic mail Creation: A draft e-mail is generated.
- Rewrite Choice: 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: It is a directed graph the place nodes signify duties (like categorizing emails, drafting replies, and so forth.), and edges outline the circulate of the method from one job to the subsequent.
- Nodes: Every node corresponds to a perform or motion that can be carried out through 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 primarily based 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 job is to categorize the incoming e-mail right into a predefined class (like “buyer suggestions”, “product inquiry”, and so forth.). That is completed within the categorize_email node.
- As soon as categorized, a call is made whether or not to seek for analysis information or straight draft a response primarily based on the class.
- Conditional Routing
From categorize_email:
If analysis information is required (primarily based 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 critical, it sends the draft to analyze_draft_email for overview and enchancment.
- If no rewrite is required, the system forwards the draft on to state_printer for remaining 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 net seek for information
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 essential
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 primarily based on the result of the categorization
workflow.add_conditional_edges(
"categorize_email",
route_to_research,
{
"research_info": "research_info_search", # If analysis information 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 primarily based 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 investigate draft
"no_rewrite": "no_rewrite", # If no rewrite wanted, go to remaining 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 top 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 essential 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 primarily based 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 solution to cloudy and overcast. n
I needed to put in writing a music known as 'Right here comes the solar however it by no means got here'
What needs 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 key's added
}
for output in app.stream(inputs):
for key, worth in output.objects():
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:
<class 'list'>
'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 information
---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 <class 'list'>
---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.