Skip to main content
Lesson 14 of 16 · Mastering Prompts with Mistral

Workshop: Text Analysis

Lesson 14 of 16 Updated July 28, 2026 Beginner
On this page
  1. Workshop objective
  2. Exercise 1: Analyze customer review sentiment
  3. Exercise 2: Extract structured data
  4. Exercise 3: Classify support tickets
  5. Tips for analysis tasks
  6. Key takeaways

Workshop objective

After writing, let’s switch gears: this workshop trains you to use Mistral for analysis tasks—analyzing text sentiment, extracting key information, and classifying content. These skills are core to automating text data processing in business. Whenever a human reads dozens of similar texts to extract the same information grid, you have a candidate for automation. You’ll notice a common thread across the three exercises: temperature stays low, because in analysis, consistency matters more than creativity.

Exercise 1: Analyze customer review sentiment

Imagine this scenario: you manage customer service for a marketplace and receive hundreds of reviews daily. Reading them all is impossible; you need to analyze them automatically to detect recurring issues and prioritize responses. The system prompt defines a fixed analysis grid—sentiment, themes, urgency, action—and enforces JSON output so your ticketing tool can process the result.

messages = [
    {
        "role": "system",
        "content": """You are a customer experience analyst.
For each review, provide:
1. Overall sentiment: positive / mixed / negative
2. Topics covered (max 3)
3. Urgency level: low / medium / high
4. Recommended action (1 sentence)

Respond in structured JSON."""
    },
    {
        "role": "user",
        "content": """Analyze these 3 customer reviews:

Review 1: "Order received in 2 days, careful packaging. However, the user
manual is only in English, which is a shame for a product sold in France.
The product itself works very well."

Review 2: "This is the THIRD time I've received a defective item. Support
has been giving me the runaround for 2 weeks. I will contact the DGCCRF if
nothing moves."

Review 3: "Good value for money. Nothing exceptional but does the job.
Standard delivery, no issues."

Return a JSON table with the analysis of each review."""
    }
]

response = client.chat.complete(
    model="mistral-large-latest",
    messages=messages,
    temperature=0.1
)

The expected result looks like this—note that review 1, generally satisfied but with a reservation, must come out as “mixed” not “positive”, and review 2, with its threat to contact the DGCCRF (France’s consumer protection agency), must trigger high urgency:

[
  {
    "review": 1,
    "sentiment": "mixed",
    "themes": ["delivery", "documentation", "product quality"],
    "urgency": "low",
    "action": "Translate the user manual to French for future batches."
  },
  {
    "review": 2,
    "sentiment": "negative",
    "themes": ["product quality", "customer service", "recurrence"],
    "urgency": "high",
    "action": "Escalate to support manager for priority handling."
  },
  {
    "review": 3,
    "sentiment": "positive",
    "themes": ["value for money", "delivery"],
    "urgency": "low",
    "action": "No action required, standard satisfied review."
  }
]

Exercise 2: Extract structured data

Second situation: you receive job application emails in free text and need to extract key information to feed your ATS (Applicant Tracking System). The main risk in extraction is invention: a model left without instructions will happily fill gaps with plausible deductions. Hence the two cardinal rules of the system prompt—“not provided” for any missing information, and an absolute prohibition on deduction.

messages = [
    {
        "role": "system",
        "content": """You extract structured data from free text.
Rules:
- If information is not mentioned, indicate "not provided"
- NEVER deduce information: stay strictly with the text
- Dates must be in YYYY-MM-DD format
- Skills must be normalized terms"""
    },
    {
        "role": "user",
        "content": """Extract information from this job application email:

"Hello,

I am submitting my application for the full-stack developer position
published on LinkedIn. My name is Sarah Benali and I have 6 years
of experience in web development. Currently a Lead Developer at DataViz (Paris),
I work primarily with React, Node.js, and PostgreSQL. I also have
strong experience with AWS and Docker. My current daily rate is
€650 and I am available starting May 15, 2026.

Best regards,
Sarah Benali"

Expected JSON format:
{
  "name": "",
  "target_role": "",
  "experience_years": 0,
  "current_role": "",
  "current_company": "",
  "location": "",
  "skills": [],
  "daily_rate": "",
  "availability": ""
}"""
    }
]

response = client.chat.complete(
    model="mistral-large-latest",
    messages=messages,
    temperature=0.0
)

Here’s the output you should get:

{
  "name": "Sarah Benali",
  "target_role": "Full-stack developer",
  "experience_years": 6,
  "current_role": "Lead Developer",
  "current_company": "DataViz",
  "location": "Paris",
  "skills": ["React", "Node.js", "PostgreSQL", "AWS", "Docker"],
  "daily_rate": "€650",
  "availability": "2026-05-15"
}

Note the temperature at 0.0: for extraction, you want a deterministic response faithful to the source text. Also note the date conversion to ISO format, explicitly requested in the rules—without this instruction, the model would have copied “May 15, 2026” as is.

Exercise 3: Classify support tickets

Last situation: your support team receives uncategorized tickets that need automatic routing to the right department. The key to this exercise is the exhaustive definition of categories and priorities in the system prompt. If you let the model invent its own taxonomy, each batch of tickets will come out with different categories and your routing will become unmanageable.

messages = [
    {
        "role": "system",
        "content": """You classify technical support tickets.

Available categories:
- BILLING: payment issues, invoices, subscriptions, refunds
- TECHNICAL: bugs, errors, functionality issues, slowness
- ACCOUNT: login, password, settings, account deletion
- FEATURE: requests for new features, suggestions
- OTHER: anything that doesn't fit the categories above

Priorities:
- P1: service inaccessible, data loss, direct financial impact
- P2: degraded functionality, workaround possible
- P3: question, information request, suggestion

Respond ONLY in JSON, no text before or after."""
    },
    {
        "role": "user",
        "content": """Classify these 4 tickets:

Ticket A: "Unable to log in since this morning. I tried to
reset my password but I'm not receiving the email."

Ticket B: "Would it be possible to add an Excel export in addition to CSV?"

Ticket C: "I was charged twice for my March subscription."

Ticket D: "The app crashes when I import a file larger than 50 MB.
Error message: MEMORY_EXCEEDED."

Format:
[{"ticket": "A", "category": "", "priority": "", "service": "", "summary": ""}]"""
    }
]

response = client.chat.complete(
    model="mistral-large-latest",
    messages=messages,
    temperature=0.0
)

The expected result—note that ticket C, with its direct financial impact, goes to P1 while the technical crash in ticket D stays at P2 since a workaround exists:

[
  {
    "ticket": "A",
    "category": "ACCOUNT",
    "priority": "P2",
    "service": "Level 1 Support",
    "summary": "Unable to log in, reset email not received"
  },
  {
    "ticket": "B",
    "category": "FEATURE",
    "priority": "P3",
    "service": "Product",
    "summary": "Request for Excel export in addition to CSV"
  },
  {
    "ticket": "C",
    "category": "BILLING",
    "priority": "P1",
    "service": "Accounting",
    "summary": "Double charge March subscription, refund request"
  },
  {
    "ticket": "D",
    "category": "TECHNICAL",
    "priority": "P2",
    "service": "Development",
    "summary": "Crash importing large files (MEMORY_EXCEEDED)"
  }
]

Tips for analysis tasks

Four best practices summarize this workshop’s method. Work at temperature 0 for classification and extraction: you want consistency, not inspiration. Define categories explicitly in the system prompt, otherwise the model will invent its own. Always include the “not provided” instruction for missing data, otherwise the model will fill gaps with plausible inventions. And before any deployment, test on edge cases: ambiguous texts, tickets that fall into two categories, partial data—this is where your grid will show weaknesses, not on textbook cases.

Key takeaways

  • Text analysis with Mistral works best with low temperature (0-0.2)
  • Always define categories and output format in the prompt
  • Enforce the “not provided” rule to avoid hallucinations
  • Few-shot improves classification consistency
  • Test on representative real cases before deploying to production