Faculytics Docs

Sentiment Worker Contract

Full request/response schemas for the temporary OpenAI-based sentiment worker, including RunPod envelope format.

Status: Live (temporary OpenAI implementation). When the fine-tuned model ships on RunPod, only SENTIMENT_WORKER_URL in the API changes — the envelope format is already compatible.

Source of Truth: src/sentiment/dto/sentiment-request.dto.ts and src/sentiment/dto/sentiment-response.dto.ts

Endpoint

POST {SENTIMENT_WORKER_URL}/runsync

The worker simulates a RunPod serverless /runsync endpoint. The API sends a RunPod envelope and receives a RunPod-style response.

RunPod Envelope

The API wraps the batch message inside an input field:

{
  "input": {
    "jobId": "550e8400-e29b-41d4-a716-446655440000",
    "version": "1.0",
    "type": "sentiment",
    "items": [
      {
        "submissionId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
        "text": "The professor was very helpful and engaging."
      },
      {
        "submissionId": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
        "text": "Too fast. Couldn't keep up."
      }
    ],
    "metadata": {
      "pipelineId": "p1p2p3p4-e5f6-7890-abcd-ef1234567890",
      "runId": "r1r2r3r4-e5f6-7890-abcd-ef1234567890"
    },
    "publishedAt": "2026-03-13T10:00:00.000Z"
  }
}

Request Fields

FieldTypeRequiredDescription
jobIdUUID stringYesUnique job identifier assigned by BullMQ
versionstringYesContract version (e.g. "1.0")
typestringYesAlways "sentiment" for this worker
itemsarrayYesSubmissions to analyze
items[].submissionIdstringYesUnique submission identifier
items[].textstring (min 1)YesCleaned qualitative comment text
metadata.pipelineIdstringYesParent analysis pipeline ID
metadata.runIdstringYesCurrent sentiment run ID
publishedAtISO 8601 datetimeYesWhen the job was dispatched

The request schema uses .passthrough(), so extra fields from the BatchAnalysisJobMessage envelope are accepted but ignored.

Success Response

{
  "output": {
    "jobId": "550e8400-e29b-41d4-a716-446655440000",
    "version": "1.0.0-openai",
    "status": "completed",
    "results": [
      {
        "submissionId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
        "positive": 0.85,
        "neutral": 0.10,
        "negative": 0.05
      },
      {
        "submissionId": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
        "positive": 0.05,
        "neutral": 0.15,
        "negative": 0.80
      }
    ],
    "completedAt": "2026-03-13T10:30:00.000Z"
  }
}

Response Fields

FieldTypeRequiredDescription
jobIdUUID stringAlwaysEchoes the input jobId
versionstringAlwaysWorker version (e.g. "1.0.0-openai")
statusenumAlways"completed" or "failed"
resultsarrayOn successPer-submission sentiment scores
results[].submissionIdstringYesMatches input submissionId
results[].positivenumber (0–1)YesPositive sentiment score
results[].neutralnumber (0–1)YesNeutral sentiment score
results[].negativenumber (0–1)YesNegative sentiment score
errorstringOn failureError message when status is "failed"
completedAtISO 8601 datetimeAlwaysProcessing completion timestamp

Scores for each submission sum to approximately 1.0.

Failure Response (Domain Error)

Domain errors return HTTP 200 with status: "failed" to prevent BullMQ retries:

{
  "output": {
    "jobId": "550e8400-e29b-41d4-a716-446655440000",
    "version": "1.0.0-openai",
    "status": "failed",
    "error": "Rate limit exceeded after 3 retry attempts",
    "completedAt": "2026-03-13T10:30:00.000Z"
  }
}

Domain errors include:

  • OpenAI rate limit (after retry exhaustion)
  • OpenAI API errors (invalid request, authentication)
  • Empty or unparseable model response
  • Input validation failures

Infrastructure Errors

Unexpected failures (network errors, unhandled exceptions) return HTTP 500, which triggers BullMQ retry logic on the API side.

Versioning

The version field in responses tracks the worker implementation version (WORKER_VERSION env var). The current OpenAI-based worker uses 1.0.0-openai. This value is stored on SentimentRun.workerVersion in the API for provenance tracking.

Health Check

GET /health returns { "status": "ok" } for liveness probes.