Managing Multiple Tutoring Sessions with DeepSeek in Go

Welcome to the next step in building your personal tutor with DeepSeek! In previous lessons, you learned how to send queries to DeepSeek's language model, customize model parameters, maintain session history, and personalize your AI tutor using system prompts — all in Go. Now, you'll learn how to manage multiple tutoring sessions at once. This is essential for applications that serve several students simultaneously, such as an online tutoring platform. By the end of this lesson, you'll be able to create and manage multiple tutoring sessions using Go, setting the foundation for scalable educational applications.

Creating Unique Tutoring Sessions

In a tutoring application, each educational interaction should be treated as a separate session. To achieve this in Go, we use a map to store all active sessions, where each session is identified by a unique session ID. We generate these unique IDs using the github.com/google/uuid package. Each session's history is stored as a slice of Message structs.

Here's how you can set up session management in Go:

package main

import (
    "fmt"
    "github.com/google/uuid"
)

// Message struct represents a single message in the conversation
type Message struct {
    Role    string
    Content string
}

// Define a map to store all active tutoring sessions
// The key is a string representing the unique session ID
// The value is a slice of Message structs representing the conversation history
var tutoringSessions map[string][]Message

func init() {
    // Initialize the map to store tutoring sessions
    tutoringSessions = make(map[string][]Message)
}

// Common system prompt for all sessions
var systemPrompt = Message{
    Role:    "system",
    Content: "You are a knowledgeable and patient tutor, ready to assist with various academic subjects.",
}

// CreateSession creates a new tutoring session with a unique identifier
func CreateSession() string {
    sessionID := uuid.New().String() // Generate unique session ID
    // Initialize session history with the system prompt
    tutoringSessions[sessionID] = []Message{systemPrompt}
    return sessionID
}

In this setup, we define a map called tutoringSessions that stores all active tutoring sessions. Each key in the map is a unique session ID (a string), and each value is a slice of Message structs that represents the conversation history for that session. We initialize this map in the init() function, which runs automatically when the package is loaded.

When a new session is created using the CreateSession() function, we generate a unique ID using the UUID package, initialize the session's history with the system prompt, and store it in the map. This ensures that each student gets their own separate conversation context with the AI tutor.

Sending Queries and Receiving Explanations

Once a tutoring session is established, you can send queries and receive explanations from DeepSeek. In Go, you append each new message to the session's slice of Message structs. When sending a query, you pass the entire session history to the AI to maintain context.

It's important to remember that language models have a context window — they can process only a limited number of messages at once. If a session's history grows too large, you may need to implement a strategy to trim older messages while preserving important context.

Here's how you can implement query handling in Go, using the provided SendQuery function:

import (
    "errors"
    "strings"
    // ... other imports
)

// SendSessionQuery adds a user query to the session, sends it to DeepSeek, and updates the session history
func SendSessionQuery(client *openai.Client, sessionID string, userQuery string) (string, error) {
    // Check if the session exists
    session, ok := tutoringSessions[sessionID]
    if !ok {
        return "", errors.New("tutoring session not found")
    }

    // Add user's query to the session history
    session = append(session, Message{Role: "user", Content: userQuery})

    // Send the session history to DeepSeek
    reply, err := SendQuery(client, session)
    if err != nil {
        return "", err
    }
    reply = strings.TrimSpace(reply)

    // Add AI's reply to the session history
    session = append(session, Message{Role: "assistant", Content: reply})

    // Update the session in the map
    tutoringSessions[sessionID] = session

    return reply, nil
}

This function ensures that each session maintains its own history, allowing for contextually relevant responses from the AI tutor.

Handling Multiple Tutoring Sessions

Managing multiple sessions is straightforward in Go using maps and slices. Each session is independent, and you can create, query, and update them as needed. Below is a complete example demonstrating how to create two separate sessions and interact with each one:

package main

import (
    "context"
    "fmt"
    "log"
    "os"
    "strings"

    "github.com/google/uuid"
    "github.com/openai/openai-go"
    "github.com/openai/openai-go/option"
)

// (Message struct, tutoringSessions map, systemPrompt, CreateSession, SendQuery, and SendSessionQuery as defined above)

func main() {
    apiKey := os.Getenv("OPENAI_API_KEY")
    baseURL := os.Getenv("OPENAI_BASE_URL")
    if apiKey == "" {
        log.Fatal("Please set the OPENAI_API_KEY environment variable.")
    }

    client := openai.NewClient(
        option.WithAPIKey(apiKey),
        option.WithBaseURL(baseURL),
    )

    // Create the first tutoring session and send queries
    sessionID1 := CreateSession()
    answer1, err := SendSessionQuery(&client, sessionID1, "Can you explain the concept of limits in calculus?")
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println("Session 1, Query 1:", answer1)

    answer2, err := SendSessionQuery(&client, sessionID1, "How does the epsilon-delta definition work?")
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println("Session 1, Query 2:", answer2)

    // Create the second tutoring session and send queries
    sessionID2 := CreateSession()
    answer3, err := SendSessionQuery(&client, sessionID2, "What is the significance of chemical bonds in molecules?")
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println("Session 2, Query 1:", answer3)

    answer4, err := SendSessionQuery(&client, sessionID2, "Can you explain covalent bonding?")
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println("Session 2, Query 2:", answer4)
}

Sample output:

Session 1, Query 1: In calculus, a limit is the value that a function approaches as the input approaches a certain value. Formally, we write lim(x→a) f(x) = L, meaning that as x gets closer to a, f(x) gets closer to L.
Session 1, Query 2: The epsilon-delta definition formalizes the concept of limits. It states that lim(x→a) f(x) = L if for every ε > 0, there exists a δ > 0 such that if 0 < |x - a| < δ, then |f(x) - L| < ε.
Session 2, Query 1: Chemical bonds are forces of attraction that hold atoms together in molecules. They are crucial for determining a molecule's structure, properties, and reactivity.
Session 2, Query 2: Covalent bonding occurs when atoms share pairs of electrons to achieve a more stable electron configuration. In this type of bond, the shared electrons orbit around both atomic nuclei.

This approach keeps each tutoring session distinct and contextually accurate, making it ideal for scalable educational applications.

Summary and Preparation for Practice

In this lesson, you learned how to manage multiple tutoring sessions in Go using DeepSeek's API. You saw how to create unique sessions, maintain session history, and handle multiple sessions simultaneously using Go's map and slice types. These skills are essential for building scalable educational applications that can support many students at once. As you move on to practice exercises, try creating and managing your own tutoring sessions to reinforce your understanding and prepare for more advanced AI development. Keep up the great work as you continue building your personal tutor with DeepSeek!

Sign up
Join the 1M+ learners on CodeSignal
Be a part of our community of 1M+ users who develop and demonstrate their skills on CodeSignal