# Google Gemini

> Give your Gemini app a memory of each of your users with the Google Gen AI SDK. What is known goes in the system instruction, and each exchange is saved after the reply.

Give your Gemini app a memory of each of your users. Before Gemini answers, what is known about the user
goes in the system instruction; after it answers, the exchange is saved, so the next conversation starts
knowing it.

## Install

```bash
pip install google-genai geniffy
```

```bash
npm install @google/genai geniffy
```

Set `GEMINI_API_KEY`, and `GENIFFY_API_KEY` from **API keys** in the Geniffy app.

## Remember each user

```python
from geniffy import Geniffy
from google import genai
from google.genai import types

client = genai.Client()                  # reads GEMINI_API_KEY
geniffy = Geniffy()                      # reads GENIFFY_API_KEY


def chat(user_id: str, message: str, history: list) -> str:
    """history is the conversation so far, as types.Content."""
    mem = geniffy.space(f"user_{user_id}")
    context = mem.context(message)       # what is known that bears on the message
    system = f"You are a helpful assistant.\n\n<memory>\n{context}\n</memory>"

    conversation = client.chats.create(
        model="gemini-flash-latest",
        config=types.GenerateContentConfig(system_instruction=system),
        history=history,
    )
    reply = conversation.send_message(message).text

    mem.memories.add(messages=[{"role": "user", "content": message},
                               {"role": "assistant", "content": reply}])
    return reply
```

```ts
import { GoogleGenAI, type Content } from "@google/genai";
import { Geniffy } from "geniffy";

const ai = new GoogleGenAI({});              // reads GEMINI_API_KEY
const geniffy = new Geniffy();               // reads GENIFFY_API_KEY

// history is the conversation so far.
export async function chat(userId: string, message: string, history: Content[]) {
  const mem = geniffy.space(`user_${userId}`);
  const context = await mem.context(message);  // what is known that bears on the message
  const system = `You are a helpful assistant.\n\n<memory>\n${context}\n</memory>`;

  const response = await ai.models.generateContent({
    model: "gemini-flash-latest",
    contents: [...history, { role: "user", parts: [{ text: message }] }],
    config: { systemInstruction: system },
  });
  const reply = response.text ?? "";

  await mem.memories.add({
    messages: [
      { role: "user", content: message },
      { role: "assistant", content: reply },
    ],
  });
  return reply;
}
```

Gemini now sees what is known about this user before every reply, each line with where it came from. When
nothing is known, the block says so in one sentence, so Gemini says it doesn't know instead of guessing.

## Let Gemini look things up

To let Gemini decide when to look something up, give it a `recall` function. In Python, pass the function
itself to a chat, and the SDK calls it for you until Gemini has its answer; in TypeScript, answer each call
yourself.

```python
from geniffy import Geniffy
from google import genai
from google.genai import types

client = genai.Client()
geniffy = Geniffy()
INSTRUCTIONS = ("You are a helpful assistant. Use recall before answering anything "
                "that depends on what the user said before.")


def chat(user_id: str, message: str) -> str:
    mem = geniffy.space(f"user_{user_id}")

    def recall(query: str) -> str:
        """Look up what is known about the user, with where it came from.

        Args:
            query: What to look up
        """
        return mem.context(query)

    conversation = client.chats.create(
        model="gemini-flash-latest",
        config=types.GenerateContentConfig(
            system_instruction=INSTRUCTIONS, tools=[recall],
        ),
    )
    reply = conversation.send_message(message).text

    mem.memories.add(messages=[{"role": "user", "content": message},
                               {"role": "assistant", "content": reply}])
    return reply
```

```ts
import {
  GoogleGenAI,
  type Content,
  type FunctionDeclaration,
  type GenerateContentConfig,
} from "@google/genai";
import { Geniffy } from "geniffy";

const ai = new GoogleGenAI({});
const geniffy = new Geniffy();
const instructions =
  "You are a helpful assistant. Use recall before answering anything " +
  "that depends on what the user said before.";
const recall: FunctionDeclaration = {
  name: "recall",
  description: "Look up what is known about the user, with where it came from.",
  parametersJsonSchema: {
    type: "object",
    properties: { query: { type: "string", description: "What to look up" } },
    required: ["query"],
  },
};
const config: GenerateContentConfig = {
  systemInstruction: instructions,
  tools: [{ functionDeclarations: [recall] }],
};

export async function chat(userId: string, message: string) {
  const mem = geniffy.space(`user_${userId}`);
  const contents: Content[] = [{ role: "user", parts: [{ text: message }] }];

  for (;;) {
    const response = await ai.models.generateContent({
      model: "gemini-flash-latest",
      contents,
      config,
    });
    const calls = response.functionCalls ?? [];
    if (calls.length === 0) {
      const reply = response.text ?? "";
      await mem.memories.add({
        messages: [
          { role: "user", content: message },
          { role: "assistant", content: reply },
        ],
      });
      return reply;
    }
    const turn = response.candidates?.[0]?.content;
    if (turn) contents.push(turn);
    for (const call of calls) {
      const result = await mem.context(String(call.args?.query ?? ""));
      contents.push({
        role: "user",
        parts: [{ functionResponse: { name: call.name, response: { result } } }],
      });
    }
  }
}
```

The function answers with `context()`, so Gemini reads the same lines, with their sources, that the system
instruction would hold, and the same sentence when nothing is known.

Source: https://docs.geniffy.com/integrations/gemini
