Documentation Index
Fetch the complete documentation index at: https://runcrate.ai/docs/llms.txt
Use this file to discover all available pages before exploring further.
Classify sentiment in text — customer reviews, social media posts, support tickets — using structured output that returns typed JSON with scores and categories.
Single text analysis
from runcrate import Runcrate
import json
client = Runcrate(api_key="rc_live_YOUR_API_KEY")
review = "The laptop display is gorgeous. Battery life could be better — barely lasts 5 hours."
response = client.models.chat_completion(
model="deepseek-ai/DeepSeek-V3",
messages=[
{"role": "system", "content": "Analyze sentiment. Return JSON: {sentiment, score (-1 to 1), topics, summary}"},
{"role": "user", "content": review},
],
max_tokens=256,
temperature=0.1,
response_format={"type": "json_object"},
)
result = json.loads(response.choices[0].message.content)
print(f"Sentiment: {result['sentiment']} ({result['score']})")
print(f"Topics: {', '.join(result['topics'])}")
Batch analysis — customer reviews
from runcrate import Runcrate
from concurrent.futures import ThreadPoolExecutor
import json
client = Runcrate(api_key="rc_live_YOUR_API_KEY")
reviews = [
{"id": 1, "text": "Absolutely love this product. Best purchase this year."},
{"id": 2, "text": "Arrived broken. Support took 3 weeks to respond."},
{"id": 3, "text": "It's fine. Does what it says, nothing special."},
{"id": 4, "text": "Great build quality but the software is buggy."},
]
def analyze(review):
response = client.models.chat_completion(
model="deepseek-ai/DeepSeek-V3",
messages=[
{"role": "system", "content": "Return JSON: {sentiment, score, topics, summary}"},
{"role": "user", "content": review["text"]},
],
max_tokens=256, temperature=0.1,
response_format={"type": "json_object"},
)
return {"id": review["id"], **json.loads(response.choices[0].message.content)}
with ThreadPoolExecutor(max_workers=5) as pool:
results = list(pool.map(analyze, reviews))
avg_score = sum(r["score"] for r in results) / len(results)
print(f"Average score: {avg_score:.2f}")
for r in results:
print(f" #{r['id']}: {r['sentiment']} ({r['score']}) — {r['summary']}")
Next.js API route
// app/api/analyze-sentiment/route.ts
import { runcrate } from '@runcrate/ai';
import { generateText, Output } from 'ai';
import { z } from 'zod';
const SentimentResult = z.object({
sentiment: z.enum(['positive', 'negative', 'neutral', 'mixed']),
score: z.number().min(-1).max(1),
topics: z.array(z.string()),
summary: z.string(),
});
export async function POST(req: Request) {
const { text } = await req.json();
const { output } = await generateText({
model: runcrate('deepseek-ai/DeepSeek-V3'),
output: Output.object({ schema: SentimentResult }),
prompt: `Analyze the sentiment of this text:\n\n${text}`,
});
return Response.json(output);
}
from runcrate import Runcrate
import json
client = Runcrate(api_key="rc_live_YOUR_API_KEY")
posts = [
"Just tried @acme's new app — the onboarding is so smooth.",
"@acme your checkout is broken AGAIN. Third time this month.",
"The new @acme update fixed everything. Finally works on my phone.",
]
for post in posts:
response = client.models.chat_completion(
model="deepseek-ai/DeepSeek-V3",
messages=[
{"role": "system", "content": "Return JSON: {sentiment, score, urgency: low|medium|high, action_needed: bool}"},
{"role": "user", "content": post},
],
max_tokens=128, temperature=0.1,
response_format={"type": "json_object"},
)
r = json.loads(response.choices[0].message.content)
flag = " [ACTION]" if r.get("action_needed") else ""
print(f"{r['sentiment']:>8} ({r['score']:+.1f}) | {post[:55]}...{flag}")
Tips
- Temperature 0.1 gives the most consistent classifications.
response_format: json_object forces JSON output from the API.
- Vercel AI SDK
Output.object gives typed results with Zod validation.
- DeepSeek-V3 handles nuanced sentiment — it catches mixed reviews and sarcasm.
Next steps