When you're processing Japanese text with AI and want to avoid sending sensitive data to the cloud, Gemma 4 is one of the best tools you have right now. As an open-source model from Google with strong multilingual capabilities, it handles Japanese surprisingly well — especially for tasks like summarization, sentiment analysis, and translation.
We will set up a Python environment inside Antigravity and implement two practical NLP features: Japanese text summarization and sentiment analysis. If you have been curious about Gemma 4 but weren't sure what to build first, these two make for a solid starting point.
Why Gemma 4 Works Well for Japanese
Gemma 4 was trained on a diverse multilingual corpus that includes Japanese, Chinese, Korean, and other major languages alongside English. Compared to Gemma 3, the Japanese language understanding has improved noticeably — particularly around implicit subjects (a common feature in Japanese grammar) and the varied use of sentence-ending particles.
The model also comes in multiple sizes, which matters when you're deciding between API access and local deployment. For getting started, the API approach is the fastest path since you don't need to manage model weights or hardware requirements.
Setting Up the Python Environment in Antigravity
Open a new project in Antigravity and install the required packages from the terminal:
# Install Google GenAI SDK
pip install google-genai python-dotenv
# Create the environment file — never hardcode API keys
touch .envAdd your API key to the .env file:
GEMINI_API_KEY=YOUR_GEMINI_API_KEY
Antigravity automatically picks up .env files from the project root, so you don't need any additional configuration. Here's the base setup for your Python file:
import os
from dotenv import load_dotenv
from google import genai
load_dotenv()
client = genai.Client(api_key=os.environ["GEMINI_API_KEY"])Implementing Japanese Text Summarization
Let's build a summarization function first. The goal is to take a long piece of Japanese text — a news article, a report, an email thread — and condense it to a specified number of sentences.
def summarize_japanese(text: str, max_sentences: int = 3) -> str:
"""
Summarize Japanese text within the specified sentence count.
Args:
text: Japanese text to summarize
max_sentences: Maximum number of sentences in the summary (default: 3)
Returns:
Summarized text
"""
if not text.strip():
raise ValueError("Input text is empty")
prompt = f"""Summarize the following Japanese text in {max_sentences} sentences or fewer.
Prioritize the most important information. Do not add information not present in the original.
Output only the summary — no preamble or explanation.
Text:
{text}"""
response = client.models.generate_content(
model="gemma-4-27b-it", # Gemma 4 27B instruction-tuned variant
contents=prompt,
config={"temperature": 0.3} # Lower temperature for stable, consistent output
)
return response.text.strip()
# Test it
sample_text = """
東京都は19日、2026年度の予算案を発表した。総額は15兆3千億円で、
前年度比で約3%増となる。重点項目として、子育て支援の充実と
デジタルインフラの整備が挙げられた。子育て支援では、
保育所の定員を2万人分増やす計画が盛り込まれた。
デジタルインフラでは、5G基地局の拡充と行政手続きの
オンライン化を推進する方針が示された。
"""
result = summarize_japanese(sample_text, max_sentences=2)
print(result)
# Expected output (in Japanese):
# Tokyo announced its FY2026 budget of 15.3 trillion yen, a 3% increase.
# Key priorities include childcare expansion (20,000 new nursery spots) and digital infrastructure.One detail worth noting: the prompt explicitly says "no preamble or explanation." Without this instruction, the model will often start with something like "Certainly, here is the summary:" — which is annoying to strip out programmatically, so it's better to prevent it upfront.
Adding Sentiment Analysis
Now let's add a sentiment analysis function. This is useful for review monitoring, customer feedback processing, and social media analysis — all common use cases in Japanese B2C products.
from dataclasses import dataclass
import json
@dataclass
class SentimentResult:
label: str # "positive" / "negative" / "neutral"
score: float # Confidence score from 0.0 to 1.0
reason: str # Explanation in Japanese
def analyze_sentiment(text: str) -> SentimentResult:
"""
Analyze the sentiment of Japanese text.
Returns:
SentimentResult with label, confidence score, and reasoning
Raises:
ValueError: If the model output cannot be parsed as JSON
"""
prompt = f"""Analyze the sentiment of the following Japanese text and return a JSON object.
Required JSON format:
{{
"label": "positive" or "negative" or "neutral",
"score": confidence from 0.0 to 1.0 (two decimal places),
"reason": "one-sentence explanation in Japanese"
}}
Return only the JSON object — no other text.
Text:
{text}"""
response = client.models.generate_content(
model="gemma-4-27b-it",
contents=prompt,
config={"temperature": 0.1} # Very low temperature for deterministic classification
)
# Parse JSON, handling potential code block wrapping
raw = response.text.strip()
if raw.startswith("```"):
raw = raw.split("```")[1]
if raw.startswith("json"):
raw = raw[4:]
try:
data = json.loads(raw)
return SentimentResult(
label=data["label"],
score=float(data["score"]),
reason=data["reason"]
)
except (json.JSONDecodeError, KeyError) as e:
raise ValueError(f"Failed to parse model output: {raw}") from e
# Test with Japanese reviews
reviews = [
"このカフェ、雰囲気も良くてコーヒーも美味しかったです。また来たいです!",
"注文してから40分待たされた上に、料理が冷めていた。二度と行かない。",
"普通の定食屋さんです。価格相応かと思います。",
]
for review in reviews:
result = analyze_sentiment(review)
print(f"[{result.label.upper()}] score={result.score:.2f} | {result.reason}")What I've found in practice is that Gemma 4 handles the subtleties of Japanese sentiment reasonably well — phrases like まあまあ (so-so), 悪くはない (not bad), or 普通 (ordinary) tend to land in the neutral range with appropriate confidence scores, rather than being misclassified as positive.
Things That Will Trip You Up
The -it suffix matters: You need to specify the instruction-tuned variant (gemma-4-27b-it) rather than the base model. The base model won't follow instructions reliably, and the quality difference is significant.
JSON output can be inconsistent: Even with a clear prompt, the model occasionally wraps JSON in a markdown code block or adds a brief preamble. The cleaning logic in the code above handles the most common cases. If you want a more robust solution, the Google GenAI SDK supports response_schema to enforce structured output at the API level.
Context window limits on long documents: Gemma 4 has a large context window, but very long documents (100,000+ characters) will need to be chunked before processing. For handling large-scale API interactions in Antigravity, the Antigravity Python SDK Function Calling Guide covers batching and retry patterns worth applying here too.
What to Build Next
With these two functions working, a natural next step is wrapping them in a FastAPI endpoint — you can then call the NLP features from a frontend or integrate with other internal tools. Antigravity's built-in web server preview makes this kind of prototyping fast.
If your use case involves data you can't send to a cloud API, running Gemma 4 locally is worth exploring. The process is more involved, but once set up, you get fully offline inference with the same model.
Start with whichever piece of Japanese text you have nearby — an email, a note, a product review — and run it through summarize_japanese(). The feedback loop of testing in Antigravity's inline chat while iterating on the prompt is genuinely enjoyable.