Created
October 21, 2025 19:33
-
-
Save johnjosephhorton/eb427b494c7187b261461164b2fb12cd to your computer and use it in GitHub Desktop.
Analyze a customer call transcript, as macro
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import textwrap | |
from edsl.agents import Agent | |
from edsl.questions import ( | |
QuestionFreeText, | |
QuestionLinearScale, | |
QuestionMultipleChoice, | |
) | |
from edsl.surveys import Survey | |
from edsl.macros import Macro | |
from edsl.macros import OutputFormatter | |
# Initial survey to gather the transcript and optional parameters | |
initial_survey = Survey( | |
[ | |
QuestionFreeText( | |
question_name="transcript", | |
question_text="Please provide the transcript of the customer call to analyze", | |
), | |
QuestionFreeText( | |
question_name="persona", | |
question_text="What persona should the reviewer have? (Leave blank for default: expert business development representative)", | |
), | |
] | |
) | |
# Create the evaluator questions with transcript in question text | |
q1 = QuestionMultipleChoice( | |
question_name="understanding", | |
question_text=textwrap.dedent( | |
"""\ | |
You are being asked to review the following transcript of a business development call | |
between a representative and a potential customer and provide critical feedback. | |
Transcript: | |
{{ scenario.transcript }} | |
How would you rate the representative's understanding of the customer's needs? | |
""" | |
), | |
question_options=["Excellent", "Good", "Fair", "Poor"], | |
) | |
q2 = QuestionMultipleChoice( | |
question_name="explain_features", | |
question_text=textwrap.dedent( | |
"""\ | |
Based on this transcript: | |
{{ scenario.transcript }} | |
How well did the representative explain the features relevant to the customer's business? | |
""" | |
), | |
question_options=["Very clearly", "Somewhat clearly", "Unclear", "Not explained"], | |
) | |
q3 = QuestionMultipleChoice( | |
question_name="address_concerns", | |
question_text=textwrap.dedent( | |
"""\ | |
Based on this transcript: | |
{{ scenario.transcript }} | |
How well did the representative address the questions and concerns of the customer? | |
""" | |
), | |
question_options=[ | |
"Very effectively", | |
"Mostly effectively", | |
"Somewhat effectively", | |
"Not effectively", | |
], | |
) | |
q4 = QuestionMultipleChoice( | |
question_name="product_knowledge", | |
question_text=textwrap.dedent( | |
"""\ | |
Based on this transcript: | |
{{ scenario.transcript }} | |
How would you rate the representative's knowledge of the products and services discussed? | |
""" | |
), | |
question_options=["Excellent", "Good", "Fair", "Poor"], | |
) | |
q5 = QuestionMultipleChoice( | |
question_name="attentive", | |
question_text=textwrap.dedent( | |
"""\ | |
Based on this transcript: | |
{{ scenario.transcript }} | |
Did the representative appear attentive to the customer's needs and concerns? | |
""" | |
), | |
question_options=[ | |
"Very attentive", | |
"Mostly attentive", | |
"Somewhat attentive", | |
"Not attentive", | |
], | |
) | |
q6 = QuestionLinearScale( | |
question_name="likely_sale", | |
question_text=textwrap.dedent( | |
"""\ | |
Based on this transcript: | |
{{ scenario.transcript }} | |
On a scale from 1 to 10, how likely is the customer to use the products and services discussed? | |
""" | |
), | |
question_options=[1, 2, 3, 4, 5, 6, 7, 8, 9, 10], | |
) | |
q7 = QuestionMultipleChoice( | |
question_name="next_steps", | |
question_text=textwrap.dedent( | |
"""\ | |
Based on this transcript: | |
{{ scenario.transcript }} | |
Did the representative offer relevant next steps for implementation or testing products? | |
""" | |
), | |
question_options=[ | |
"Yes, very clear and actionable", | |
"Somewhat clear", | |
"Not clear", | |
"No next steps offered", | |
], | |
) | |
q8 = QuestionFreeText( | |
question_name="helpful_approaches", | |
question_text=textwrap.dedent( | |
"""\ | |
Based on this transcript: | |
{{ scenario.transcript }} | |
What aspects of the representative's approach were most helpful to the customer? | |
""" | |
), | |
) | |
q9 = QuestionFreeText( | |
question_name="inadequate_explanation", | |
question_text=textwrap.dedent( | |
"""\ | |
Based on this transcript: | |
{{ scenario.transcript }} | |
Were any features or details not adequately explained? | |
""" | |
), | |
) | |
q10 = QuestionFreeText( | |
question_name="improvements", | |
question_text=textwrap.dedent( | |
"""\ | |
Based on this transcript: | |
{{ scenario.transcript }} | |
How could the representative have improved their explanation of the products? | |
""" | |
), | |
) | |
q11 = QuestionFreeText( | |
question_name="confusing", | |
question_text=textwrap.dedent( | |
"""\ | |
Based on this transcript: | |
{{ scenario.transcript }} | |
Was there anything about the conversation that seemed unclear or confusing? | |
""" | |
), | |
) | |
q12 = QuestionFreeText( | |
question_name="confident", | |
question_text=textwrap.dedent( | |
"""\ | |
Based on this transcript: | |
{{ scenario.transcript }} | |
What additional information could have helped the customer feel more confident in the representative's offerings? | |
""" | |
), | |
) | |
# Combine questions into a survey | |
evaluation_survey = Survey([q1, q2, q3, q4, q5, q6, q7, q8, q9, q10, q11, q12]) | |
# Create the agent with expert persona | |
agent = Agent( | |
traits={ | |
"persona": "You are an expert business development representative with many years of experience at diverse companies." | |
} | |
) | |
# Create jobs object | |
jobs_object = evaluation_survey.by(agent) | |
# Create output formatters | |
# Summary table with ratings | |
ratings_formatter = ( | |
OutputFormatter(description="Ratings Summary", output_type="markdown") | |
.select( | |
"answer.understanding", | |
"answer.explain_features", | |
"answer.address_concerns", | |
"answer.product_knowledge", | |
"answer.attentive", | |
"answer.likely_sale", | |
"answer.next_steps", | |
) | |
.rename( | |
{ | |
"answer.understanding": "Understanding of Customer Needs", | |
"answer.explain_features": "Feature Explanation Quality", | |
"answer.address_concerns": "Addressing Concerns", | |
"answer.product_knowledge": "Product Knowledge", | |
"answer.attentive": "Attentiveness", | |
"answer.likely_sale": "Likelihood of Sale (1-10)", | |
"answer.next_steps": "Next Steps Clarity", | |
} | |
) | |
.table() | |
) | |
# .flip() | |
# .to_string() | |
#) | |
# Detailed feedback | |
feedback_formatter = ( | |
OutputFormatter(description="Detailed Feedback", output_type="markdown") | |
.select( | |
"answer.helpful_approaches", | |
"answer.inadequate_explanation", | |
"answer.improvements", | |
"answer.confusing", | |
"answer.confident", | |
) | |
.rename( | |
{ | |
"answer.helpful_approaches": "Most Helpful Aspects", | |
"answer.inadequate_explanation": "Inadequately Explained Features", | |
"answer.improvements": "Improvement Suggestions", | |
"answer.confusing": "Unclear or Confusing Elements", | |
"answer.confident": "Additional Info Needed for Confidence", | |
} | |
) | |
.table(tablefmt="github") | |
.flip() | |
.to_string() | |
) | |
# Complete report combining both | |
complete_report_formatter = ( | |
OutputFormatter(description="Complete Report", output_type="markdown") | |
.select( | |
"answer.understanding", | |
"answer.explain_features", | |
"answer.address_concerns", | |
"answer.product_knowledge", | |
"answer.attentive", | |
"answer.likely_sale", | |
"answer.next_steps", | |
"answer.helpful_approaches", | |
"answer.inadequate_explanation", | |
"answer.improvements", | |
"answer.confusing", | |
"answer.confident", | |
) | |
.rename( | |
{ | |
"answer.understanding": "Understanding of Customer Needs", | |
"answer.explain_features": "Feature Explanation Quality", | |
"answer.address_concerns": "Addressing Concerns", | |
"answer.product_knowledge": "Product Knowledge", | |
"answer.attentive": "Attentiveness", | |
"answer.likely_sale": "Likelihood of Sale (1-10)", | |
"answer.next_steps": "Next Steps Clarity", | |
"answer.helpful_approaches": "Most Helpful Aspects", | |
"answer.inadequate_explanation": "Inadequately Explained Features", | |
"answer.improvements": "Improvement Suggestions", | |
"answer.confusing": "Unclear or Confusing Elements", | |
"answer.confident": "Additional Info Needed for Confidence", | |
} | |
) | |
.table(tablefmt="github") | |
.flip() | |
.to_string() | |
) | |
# Create the macro | |
macro = Macro( | |
application_name="analyze_customer_call", | |
display_name="Customer Call Analyzer", | |
short_description="Analyze and provide feedback on customer call transcripts.", | |
long_description=textwrap.dedent( | |
"""\ | |
This application analyzes transcripts of customer calls (e.g., business development, sales, support) | |
and provides comprehensive feedback on the representative's performance. | |
The analysis covers multiple dimensions including: | |
- Understanding of customer needs | |
- Quality of feature explanations | |
- Effectiveness in addressing concerns | |
- Product knowledge demonstration | |
- Attentiveness to customer needs | |
- Likelihood of successful sale | |
- Clarity of next steps | |
It also provides detailed qualitative feedback on: | |
- What approaches were most helpful | |
- What was inadequately explained | |
- How the representative could improve | |
- What was unclear or confusing | |
- What additional information would build confidence | |
The reviewer can be customized with different personas (e.g., sales expert, technical expert, customer service expert). | |
""" | |
), | |
initial_survey=initial_survey, | |
jobs_object=jobs_object, | |
output_formatters={ | |
"ratings": ratings_formatter, | |
"feedback": feedback_formatter, | |
"complete": complete_report_formatter, | |
}, | |
default_formatter_name="complete", | |
) | |
if __name__ == "__main__": | |
# Example usage with a sample transcript | |
sample_transcript = """ | |
Alex (Quick Representative): | |
Hi, Jamie! Thanks so much for taking the time to chat today. How's everything going with your website? | |
Jamie (Customer): | |
Hi, Alex. It's going okay, I think. We're getting some users, but honestly, I'm just trying to figure out the best way to manage payments. It's all new to me. | |
Alex: | |
Got it, no worries! Quick can really help simplify things for you. Our platform allows you to accept payments easily and has a subscription option, which I think you mentioned you were interested in, right? | |
Jamie: | |
Yeah, we're thinking about offering different subscription levels for our software, but I'm not sure how to set it all up. And we have some international users, so that's been a bit confusing too. | |
Alex: | |
Right, right. So, with Quick, you can definitely do subscriptions, and it handles multiple currencies, too. For example, if you have a customer in Europe, Quick can automatically handle the conversion. It's designed to make that part easy, so you don't need to worry too much about different currencies. | |
Jamie: | |
That sounds helpful. But I'm a bit concerned about the setup. I'm not a developer, so I'm worried this might be too complicated. | |
Alex: | |
Oh, yeah, I totally understand! Quick's setup is meant to be as easy as possible. We have plugins and a lot of guides to walk you through it. I'd say that most people get it up and running without too much trouble. And if you do need help, our support team is available. | |
Jamie: | |
Okay, that's a relief. I've heard some stories about people getting stuck for weeks with payment systems. I don't want that to happen. | |
Alex: | |
I get that completely. We try to make it as straightforward as possible. Also, if you're worried about fraud or security, Quick has a feature called Shield that helps detect fraud. It's built in, so it's automatically protecting you from day one. | |
Jamie: | |
Oh, that sounds good. I don't know much about fraud detection. Is it something I'd have to set up? | |
Alex: | |
Nope! Shield is on by default, so you don't have to configure anything special unless you want to. It uses machine learning to detect unusual activity based on data from many transactions, which helps catch fraudulent transactions without much work on your end. | |
Jamie: | |
That's nice to know. What about fees? I'd like to have a clear idea of what this will cost. | |
Alex: | |
Absolutely. So, Quick charges 2.9% plus 30 cents per transaction. For subscriptions, there's no extra fee beyond the normal transaction cost. Also, if you start processing a lot of payments, we do offer some discounts, but those kick in at a higher volume. | |
Jamie: | |
Alright, that makes sense. And what about invoicing? A few customers have asked about getting invoices instead of just a credit card charge. | |
Alex: | |
Yes, we can do that too. With Quick Invoicing, you can send out one-time or recurring invoices, which is nice if you have larger clients who prefer an invoice. It's all within the Quick system, so it integrates well. | |
Jamie: | |
Good to know. I think this covers most of my questions. It sounds like Quick could be a good fit. I'd just need to make sure I'm able to actually set it up without a ton of back-and-forth. | |
Alex: | |
I totally understand, Jamie. I'll send over some guides and set you up with a sandbox account to test things out. Let's reconnect in a couple of weeks to go over any questions you might have. | |
Jamie: | |
Sounds good, thanks, Alex. Looking forward to trying it out. | |
Alex: | |
Great! Thanks for your time, Jamie. I'll follow up soon. Have a good one! | |
""" | |
output = macro.output({"transcript": sample_transcript}) | |
print(output) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment