Real-Time AI Text Summarization in Go with Streaming GPT Responses

by Didin J. on May 01, 2026 Real-Time AI Text Summarization in Go with Streaming GPT Responses

Build a real-time AI text summarizer in Go using streaming GPT responses, SSE, and Gin. Learn to stream AI output live for faster, modern web apps.

AI-powered applications are shifting from static responses to real-time streaming experiences. Instead of waiting seconds for a full response, users now expect results to appear instantly—token by token.

In this tutorial, you will build a real-time text summarization web app in Go that streams responses from GPT as they are generated.

By the end, you’ll have:

  • A Go backend using Gin
  • Real-time streaming using Server-Sent Events (SSE)
  • Integration with OpenAI GPT streaming API
  • A minimal frontend that updates live

What You Will Build

You will create:

User Input → Go Server → GPT Streaming API → SSE → Browser UI

The summary will appear progressively, just like ChatGPT typing.

Prerequisites

Before starting, make sure you have:

  • Go 1.22 or newer
  • An OpenAI API key
  • Basic knowledge of:
    • Go
    • HTTP APIs
    • JavaScript (for frontend)


Step 1: Create the Go Project

Create a new directory and initialize a Go module:

mkdir go-ai-summarizer
cd go-ai-summarizer
go mod init go-ai-summarizer

Project Structure

We’ll keep things simple:

go-ai-summarizer/
├── main.go
├── handler.go
├── openai.go
├── static/
│   └── index.html


Step 2: Install Dependencies

Install required libraries:

go get github.com/gin-gonic/gin
go get github.com/openai/openai-go

Why These Libraries?

  • Gin → Fast and minimal HTTP framework
  • openai-go → Official SDK with streaming support


Step 3: Create the Main Server

Create main.go:

package main

import (
	"github.com/gin-gonic/gin"
)

func main() {
	r := gin.Default()

	// Serve frontend
	r.Static("/static", "./static")

	// API route
	r.GET("/summarize", StreamSummaryHandler)

	r.Run(":8080")
}

What This Does

  • Serves static frontend files
  • Exposes /summarize endpoint
  • Runs server on port 8080


Step 4: Build the SSE Handler

Create handler.go:

package main

import (
	"net/http"

	"github.com/gin-gonic/gin"
)

func StreamSummaryHandler(c *gin.Context) {
	text := c.Query("text")

	if text == "" {
		c.JSON(http.StatusBadRequest, gin.H{
			"error": "text query parameter is required",
		})
		return
	}

	// Set SSE headers
	c.Writer.Header().Set("Content-Type", "text/event-stream")
	c.Writer.Header().Set("Cache-Control", "no-cache")
	c.Writer.Header().Set("Connection", "keep-alive")
	c.Writer.Header().Set("Transfer-Encoding", "chunked")

	streamSummary(text, c)
}


Step 5: Understand Server-Sent Events (SSE)

Before continuing, let’s clarify how SSE works.

Key Characteristics

  • One-way streaming (server → client)
  • Uses HTTP (no WebSocket needed)
  • Browser support via EventSource

SSE Format

Each message must follow:

data: your message here
Notice the double newline — this is critical.


Step 6: Implement OpenAI Streaming

Create openai.go:

package main

import (
	"bufio"
	"bytes"
	"fmt"
	"net/http"
	"os"

	"github.com/gin-gonic/gin"
)

func streamSummary(text string, c *gin.Context) {
	apiKey := os.Getenv("OPENAI_API_KEY")

	url := "https://api.openai.com/v1/responses"

	payload := []byte(fmt.Sprintf(`{
		"model": "gpt-4.1-mini",
		"input": "Summarize this text:\n\n%s",
		"stream": true
	}`, text))

	req, _ := http.NewRequest("POST", url, bytes.NewBuffer(payload))
	req.Header.Set("Authorization", "Bearer "+apiKey)
	req.Header.Set("Content-Type", "application/json")

	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		sendSSE(c, "ERROR: "+err.Error())
		return
	}
	defer resp.Body.Close()

	scanner := bufio.NewScanner(resp.Body)

	for scanner.Scan() {
		line := scanner.Text()

		// SSE format: lines start with "data: "
		if len(line) > 6 && line[:6] == "data: " {
			data := line[6:]

			if data == "[DONE]" {
				break
			}

			sendSSE(c, data)
		}
	}
}


Step 7: Create SSE Utility Function

Add a helper function in the main.go:

func sendSSE(c *gin.Context, message string) {
	fmt.Fprintf(c.Writer, "data: %s\n\n", message)
	c.Writer.Flush()
}

Why Flush Is Important

Without Flush():

  • Data stays buffered
  • No real-time streaming happens


Step 8: Build the Frontend

Create static/index.html:

<!doctype html>
<html>
  <head>
    <title>AI Summarizer</title>
    <style>
      body {
        font-family: Arial;
        max-width: 800px;
        margin: auto;
      }
      textarea {
        width: 100%;
      }
      pre {
        background: #f4f4f4;
        padding: 10px;
      }
    </style>
  </head>
  <body>
    <h1>Real-Time AI Summarizer</h1>

    <textarea id="input" rows="10" placeholder="Paste text here..."></textarea>
    <br /><br />
    <button onclick="summarize()">Summarize</button>

    <h2>Summary</h2>
    <pre id="output"></pre>

    <script>
      function summarize() {
        const text = document.getElementById("input").value;
        const output = document.getElementById("output");

        output.textContent = "";

        const url = `/summarize?text=${encodeURIComponent(text)}`;
        const eventSource = new EventSource(url);

        eventSource.onmessage = function (event) {
          output.textContent += event.data;
        };

        eventSource.onerror = function () {
          eventSource.close();
        };
      }
    </script>
  </body>
</html>


Step 9: Run the Application

Set API Key

export OPENAI_API_KEY=your_api_key_here

Run Server

go run .

Open Browser

http://localhost:8080/static/index.html


Step 10: Testing the App

Paste a long article or paragraph and click Summarize.

You should see:

  • Text appearing gradually
  • No waiting for full completion
  • Smooth real-time updates


Step 11: Common Pitfalls

1. No Streaming Output

Make sure:

c.Writer.Flush()

is called.

2. CORS Issues

If frontend is separate, add:

r.Use(cors.Default())

3. API Key Not Set

Check:

echo $OPENAI_API_KEY


Step 12: Enhancements

Here are ways to improve this project:

1. Switch to WebSockets

For bidirectional communication:

  • Chat apps
  • Interactive editing

2. Add Loading Indicator

Show the user that streaming has started.

3. Token Buffering

Improve formatting:

output.textContent += event.data + " ";

4. Rate Limiting

Prevent abuse using middleware.

5. Multi-User Sessions

Use session IDs or JWT.

6. Deploy to Production

  • Use Docker
  • Add HTTPS
  • Deploy on:
    • VPS
    • Fly.io
    • Railway


Step 13: Conclusion

You’ve built a real-time AI-powered summarization app in Go using:

  • Gin for backend
  • SSE for streaming
  • OpenAI GPT streaming API

This architecture is highly reusable for:

  • AI chat applications
  • Live content generation
  • Coding assistants
  • Document analysis tools

You can find the full source code on our GitHub.

We know that building beautifully designed Mobile and Web Apps from scratch can be frustrating and very time-consuming. Check Envato unlimited downloads and save development and design time.

That's just the basics. If you need more deep learning about Go/Golang, you can take the following cheap course:

Thanks!