iTranslated by AI

The content below is an AI-generated translation. This is an experimental feature, and may contain errors. View original article
✍️

Building an App to Evaluate and Refine X Posts Using Gemini API

に公開

Introduction

In this article, I will introduce the features and usage of the Gemini API while building a simple app that improves SNS posts.

Since this is my first time doing personal development using AI, there might be some incorrect information. I would appreciate it if you could leave a comment in such cases.

What is the Gemini API?

The Gemini API is a generative AI API provided by Google.

  • The free tier is relatively large (equivalent to $10/month)
  • Fast response times
  • Supports multimodal input (text, images, audio, etc.)
  • Significant performance improvement from PaLM 2

Building an app with Gemini API

I created an app called Post Polish to improve X posts.

https://github.com/884js/x-post-reviewer

https://x-post-reviewer.pages.dev/

I tried submitting some viral posts, and I found that "Expression of Opinion" was overwhelmingly common, which gave me some unexpected insights.

Main Features

  • Determines the post recommendation level: "Highly Recommended," "Recommended," "Neutral," "Not Recommended," "Strongly Discouraged"
  • Determines the post type: "Monologue," "Question," "Opinion," "Information Sharing"
  • Suggestions for improving the post text
  • Style adjustments

Tech Stack

  • npm
  • Next.js
  • tailwindcss
  • Cloudflare Pages
    • Deployment target
  • Gemini
    • gemini-2.0-flash

Setup

  1. Obtain an API key
    Access here to get your API key.
    https://aistudio.google.com/apikey

  2. Install @google/generative-ai

$ npm install @google/generative-ai

Using the Gemini API

Next.js will be used to run the Gemini API.

Since this app is for evaluating and proofreading text, we won't be handling image input, streaming output, or multi-turn conversations this time.

Creating API Routes or Server Actions

The API key is sensitive information that must not be exposed to the client side, so we will execute this on the server side.
Also, since Server Actions do not support streaming output, it seems better to build this on API Routes.
https://ai.google.dev/gemini-api/docs/text-generation?hl=ja#streaming-output

Implementing the endpoint.
src/app/api/generateContent/route.ts

import { GenerationConfig, GoogleGenerativeAI, Schema, SchemaType } from '@google/generative-ai';
import { POST_TYPE, POST_RECOMMENDATION } from '@/constants/postNuance';

export const runtime = 'edge';

export async function POST(request: Request) {
  const genAI = new GoogleGenerativeAI(process.env.GEMINI_API_KEY || '');
  const { prompt } = await request.json()

  const generationConfig = {
    responseMimeType: "application/json",
    responseSchema: {
      type: SchemaType.OBJECT,
      properties: {
        post_recommendation: {
          type: SchemaType.STRING,
          format: "enum",
          enum: [
            POST_RECOMMENDATION.HIGHLY_RECOMMENDED,
            POST_RECOMMENDATION.RECOMMENDED,
            POST_RECOMMENDATION.NEUTRAL,
            POST_RECOMMENDATION.NOT_RECOMMENDED,
            POST_RECOMMENDATION.STRONGLY_DISCOURAGED
          ],
        },
        reason: {
          type: SchemaType.STRING,
        },
        usefulness_score: {
          type: SchemaType.NUMBER,
        },
        improvement_suggestions: {
          type: SchemaType.ARRAY,
          items: { 
            type: SchemaType.OBJECT,
            properties: {
              text: { type: SchemaType.STRING },
              improvements: { type: SchemaType.STRING }
            },
            required: ["text", "improvements"]
          },
        },
        post_type: {
          type: SchemaType.STRING,
          format: "enum",
          enum: [POST_TYPE.TALK_TO_ONESELF, POST_TYPE.QUESTION, POST_TYPE.OPINION, POST_TYPE.INFORMATION],
        }
      },
      required: ["post_recommendation", "reason", "usefulness_score", "improvement_suggestions", "post_type"]
    } satisfies Schema
  } satisfies GenerationConfig;

  const model = genAI.getGenerativeModel({ model: 'gemini-2.0-flash', generationConfig })

  const result = await model.generateContent({
    contents: [
      {
        role: 'user',
        parts: [
          {
            text: prompt
          }
        ]
      }
    ],
    systemInstruction: {
      role: 'model',
      parts: [
        {
          text: 'あなたはX(旧Twitter)投稿価値や有益性を判断し、改善案を提供するAIです。すべての応答は日本語でのみ行ってください。',
        },
    }
  })

  const responseText = result.response.text();
  return new Response(responseText, {
    headers: {
      'Content-Type': 'application/json',
    },
  });
}

Key Points

Setting rules for the AI response with generationConfig

Since I wanted to use the AI's answer as-is for the response this time, I'm enforcing the return value format by defining the responseSchema.

I found it very convenient because you can define it in a format similar to OpenAPI and use things like enums.

Giving context using systemInstruction

I am explicitly defining the AI's role by passing a setting like the one below. Doing this saves you from having to write it in the user's prompt.

You are an AI that evaluates the value and usefulness of X (formerly Twitter) posts and provides improvement suggestions. Please provide all responses in Japanese only.

In reality, I am providing more instructions, but I will omit them here.

Conclusion

Gemini API has a generous free tier, and the SDK was easy to use, providing a great developer experience.

I plan to continue catching up with AI-related technologies little by little.

Thank you for reading this far!

Discussion