> ## Documentation Index
> Fetch the complete documentation index at: https://ricardovelit.com/axon-docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Sentiment Analysis

> Analyze text sentiment with epistemic confidence tracking and multi-dimensional scoring

## Overview

This example demonstrates a sentiment analysis agent that goes beyond simple positive/negative classification. It tracks epistemic confidence, separates factual observations from subjective interpretations, and provides multi-dimensional sentiment scores.

## Use Case

Analyze text sentiment to:

* Classify overall sentiment (positive, negative, neutral)
* Provide quantified sentiment scores (-1.0 to 1.0)
* Identify emotional tone and intensity
* Separate factual content from opinion
* Track confidence in sentiment assessment
* Handle ambiguous or mixed sentiment

## Complete Code

```axon sentiment_analysis.axon theme={null}
// AXON Example — Sentiment Analysis
// Epistemic sentiment analysis with confidence tracking

persona SentimentAnalyst {
  domain: ["NLP", "psychology", "linguistics"]
  tone: analytical
  confidence_threshold: 0.75
}

context AnalysisMode {
  memory: none
  language: "en"
  depth: moderate
  max_tokens: 2048
  temperature: 0.2
}

anchor FactualGrounding {
  require: text_evidence
  confidence_floor: 0.70
  unknown_response: "Unable to determine sentiment with sufficient confidence"
  on_violation: raise AnchorBreachError
}

type SentimentScore(-1.0..1.0)

type EmotionalTone {
  primary: FactualClaim,
  intensity: Float,
  confidence: ConfidenceScore
}

type SentimentAnalysis {
  overall_score: SentimentScore,
  classification: FactualClaim,
  emotional_tone: EmotionalTone,
  factual_content: List<FactualClaim>,
  opinions: List<Opinion>,
  ambiguity_score: Float,
  confidence: ConfidenceScore
}

flow AnalyzeSentiment(text: Document) -> SentimentAnalysis {
  step ExtractContent {
    given: text
    ask: "Separate factual statements from opinions and emotional language"
    output: ContentMap
  }
  
  step ClassifySentiment {
    given: ContentMap
    ask: "Determine overall sentiment and emotional tone"
    output: SentimentClassification
  }
  
  reason EmotionalAssessment {
    given: [ContentMap, SentimentClassification]
    about: "emotional tone and intensity"
    ask: "What is the primary emotional tone and how intense is it?"
    depth: 2
    output: EmotionalTone
  }
  
  validate EmotionalAssessment against ToneSchema {
    if confidence < 0.75 -> refine(max_attempts: 2)
    if ambiguous -> warn "Mixed or unclear sentiment detected"
  }
  
  weave [
    ContentMap,
    SentimentClassification,
    EmotionalAssessment
  ] into SentimentAnalysis {
    format: StructuredReport
  }
}

run AnalyzeSentiment(inputText)
  as SentimentAnalyst
  within AnalysisMode
  constrained_by [FactualGrounding]
  on_failure: retry(backoff: linear)
  output_to: "sentiment.json"
  effort: medium
```

## Key Components

### Persona: SentimentAnalyst

```axon theme={null}
persona SentimentAnalyst {
  domain: ["NLP", "psychology", "linguistics"]
  tone: analytical
  confidence_threshold: 0.75
}
```

Defines an expert in:

* **Natural Language Processing**: Technical understanding of text analysis
* **Psychology**: Understanding of emotional expression
* **Linguistics**: Language structure and meaning
* **Analytical tone**: Objective, systematic approach

### Context: AnalysisMode

```axon theme={null}
context AnalysisMode {
  memory: none
  language: "en"
  depth: moderate
  max_tokens: 2048
  temperature: 0.2
}
```

Configures for consistent analysis:

* **Memory**: No memory (stateless analysis)
* **Depth**: Moderate analysis (not shallow, not exhaustive)
* **Temperature**: Low (0.2) for consistent classifications

### Custom Types

```axon theme={null}
type SentimentScore(-1.0..1.0)
```

Range-constrained sentiment score:

* `-1.0` = Very negative
* `0.0` = Neutral
* `1.0` = Very positive

```axon theme={null}
type EmotionalTone {
  primary: FactualClaim,
  intensity: Float,
  confidence: ConfidenceScore
}
```

Captures emotional characteristics:

* `primary`: Primary emotion (joy, anger, sadness, etc.)
* `intensity`: How strong the emotion is
* `confidence`: How confident we are in the assessment

```axon theme={null}
type SentimentAnalysis {
  overall_score: SentimentScore,
  classification: FactualClaim,
  emotional_tone: EmotionalTone,
  factual_content: List<FactualClaim>,
  opinions: List<Opinion>,
  ambiguity_score: Float,
  confidence: ConfidenceScore
}
```

Comprehensive analysis output:

* **overall\_score**: Quantified sentiment
* **classification**: Category (positive, negative, neutral)
* **emotional\_tone**: Detailed emotional assessment
* **factual\_content**: Factual statements found
* **opinions**: Opinion statements found
* **ambiguity\_score**: How unclear the sentiment is
* **confidence**: Overall confidence in the analysis

<Tip>
  Separating `factual_content` and `opinions` prevents conflating objective statements with subjective sentiment.
</Tip>

### Flow: AnalyzeSentiment

Three-step cognitive pipeline with validation:

**Step 1: ExtractContent**

```axon theme={null}
step ExtractContent {
  given: text
  ask: "Separate factual statements from opinions and emotional language"
  output: ContentMap
}
```

Separates:

* Factual statements (objective)
* Opinions (subjective)
* Emotional language (sentiment-bearing)

**Step 2: ClassifySentiment**

```axon theme={null}
step ClassifySentiment {
  given: ContentMap
  ask: "Determine overall sentiment and emotional tone"
  output: SentimentClassification
}
```

Determines:

* Overall sentiment polarity
* Primary sentiment category
* Sentiment score

**Step 3: EmotionalAssessment (Reasoning)**

```axon theme={null}
reason EmotionalAssessment {
  given: [ContentMap, SentimentClassification]
  about: "emotional tone and intensity"
  ask: "What is the primary emotional tone and how intense is it?"
  depth: 2
  output: EmotionalTone
}
```

Uses explicit reasoning to:

* Identify primary emotion
* Assess intensity
* Consider context

**Validation**

```axon theme={null}
validate EmotionalAssessment against ToneSchema {
  if confidence < 0.75 -> refine(max_attempts: 2)
  if ambiguous -> warn "Mixed or unclear sentiment detected"
}
```

Ensures quality:

* Refines if confidence too low
* Warns on ambiguous sentiment

**Synthesis**

```axon theme={null}
weave [
  ContentMap,
  SentimentClassification,
  EmotionalAssessment
] into SentimentAnalysis {
  format: StructuredReport
}
```

Combines all analyses into comprehensive output.

## Usage

### Validate and Run

```bash theme={null}
# Check syntax
axon check sentiment_analysis.axon

# Compile to IR
axon compile sentiment_analysis.axon

# Run with tracing
axon run sentiment_analysis.axon --backend openai --trace
```

### Example Input

```text theme={null}
"The new restaurant opened last week, and while the location is convenient 
and the decor is modern, the service was disappointingly slow. The food 
quality was acceptable but nothing special. I might give them another 
chance in a few months."
```

### Example Output

```json theme={null}
{
  "type": "SentimentAnalysis",
  "overall_score": -0.15,
  "classification": "mixed (slightly negative)",
  "emotional_tone": {
    "primary": "disappointment",
    "intensity": 0.6,
    "confidence": 0.82
  },
  "factual_content": [
    "The restaurant opened last week",
    "The location is convenient",
    "The decor is modern"
  ],
  "opinions": [
    "Service was disappointingly slow",
    "Food quality was acceptable but nothing special",
    "Might give them another chance in a few months"
  ],
  "ambiguity_score": 0.45,
  "confidence": 0.82,
  "explanation": "Mixed sentiment with both positive (location, decor) and negative (service, food) elements. Primary negative emotion is disappointment, moderated by openness to trying again."
}
```

## Advanced Patterns

### Aspect-Based Sentiment

Analyze sentiment for specific aspects:

```axon theme={null}
type AspectSentiment {
  aspect: FactualClaim,
  sentiment: SentimentScore,
  confidence: ConfidenceScore
}

flow AnalyzeAspects(text: Document) -> List<AspectSentiment> {
  step IdentifyAspects {
    given: text
    ask: "Identify all aspects mentioned (service, quality, price, etc.)"
    output: AspectList
  }
  
  step ScoreAspects {
    given: AspectList
    ask: "Rate sentiment for each aspect individually"
    output: List<AspectSentiment>
  }
}
```

### Comparative Sentiment

Compare sentiment across multiple texts:

```axon theme={null}
flow CompareSentiment(texts: List<Document>) -> ComparisonReport {
  step AnalyzeAll {
    given: texts
    ask: "Analyze sentiment for each text"
    output: List<SentimentAnalysis>
  }
  
  reason Comparison {
    given: AnalyzeAll.output
    about: "sentiment trends and differences"
    ask: "How do sentiments compare across texts?"
    depth: 3
    output: ComparisonReport
  }
}
```

### Temporal Sentiment Tracking

Track sentiment changes over time:

```axon theme={null}
context TimeSeriesAnalysis {
  memory: persistent
  language: "en"
  depth: moderate
}

flow TrackSentimentTrend(texts: List<Document>) -> TrendAnalysis {
  step AnalyzeEach {
    given: texts
    ask: "Analyze sentiment for each text with timestamp"
    output: TimestampedSentiments
  }
  
  step IdentifyTrends {
    given: AnalyzeEach.output
    ask: "Identify patterns and trends in sentiment over time"
    output: TrendAnalysis
  }
  
  remember(TrendAnalysis) -> SentimentHistory
}
```

### Multi-Language Sentiment

Handle multiple languages:

```axon theme={null}
flow MultilingualSentiment(text: Document, lang: String) -> SentimentAnalysis {
  step DetectLanguage {
    given: text
    ask: "What language is this text?"
    output: LanguageCode
  }
  
  if LanguageCode != "en" -> step Translate {
    given: text
    ask: "Translate to English"
    output: TranslatedText
  }
  
  step AnalyzeSentiment {
    given: TranslatedText
    ask: "Analyze sentiment"
    output: SentimentAnalysis
  }
}
```

## Best Practices

### 1. Separate Facts from Opinions

```axon theme={null}
// ✅ Good: Clear separation
type Analysis {
  facts: List<FactualClaim>,
  opinions: List<Opinion>
}

// ❌ Bad: Mixed
type Analysis {
  content: List<String>
}
```

### 2. Use Range-Constrained Scores

```axon theme={null}
// ✅ Good: Guaranteed valid
type SentimentScore(-1.0..1.0)

// ❌ Bad: Unbounded
type SentimentScore(Float)
```

### 3. Track Confidence

```axon theme={null}
type SentimentAnalysis {
  score: SentimentScore,
  confidence: ConfidenceScore  // Always include
}
```

### 4. Handle Ambiguity

```axon theme={null}
validate Result against Schema {
  if confidence < threshold -> refine(max_attempts: 2)
  if ambiguous -> warn "Mixed sentiment"
}
```

### 5. Use Low Temperature

```axon theme={null}
context AnalysisMode {
  temperature: 0.2  // Consistent classifications
}
```

## Related Examples

<CardGroup cols={2}>
  <Card title="Contract Analyzer" icon="file-contract" href="/axon-docs/axon-docs/examples/contract-analyzer">
    Legal contract analysis with risk assessment
  </Card>

  <Card title="Data Extraction" icon="table" href="/axon-docs/axon-docs/examples/data-extraction">
    Extract structured data from unstructured text
  </Card>

  <Card title="Multi-Step Reasoning" icon="brain" href="/axon-docs/axon-docs/examples/multi-step-reasoning">
    Complex reasoning with chain-of-thought
  </Card>
</CardGroup>

## Related Documentation

* [Types](/axon-docs/axon-docs/language/types) — Epistemic type system
* [Flow](/axon-docs/axon-docs/language/flow) — Cognitive pipelines
* [Persona](/axon-docs/axon-docs/language/persona) — Agent identities
* [Anchor](/axon-docs/axon-docs/language/anchor) — Hard constraints
