Curso
Os LLMs locais chegaram a um ponto de virada. Com a Gemma 4, sua janela de contexto longa, suporte multimodal nativo e a acessibilidade do Ollama, agora é prático rodar um assistente de codificação com capacidades de agente totalmente na sua própria máquina.
Neste tutorial, vou mostrar como construir um assistente de codificação usando Gemma 4 via Ollama, com uma interface em Gradio. O app traz um layout em duas colunas, com um editor de código ao vivo à esquerda e um painel de chat com agente à direita. Você pode enviar imagens ou arquivos de código como contexto, ativar o uso de ferramentas para o modelo executar e validar código e alternar um modo de "raciocínio" para problemas mais difíceis.
Ao final, você terá um app local capaz de:
- Escrever, explicar e depurar código em 15+ linguagens
- Executar código Python em um subprocesso isolado e retornar os resultados
- Aceitar imagens e arquivos de texto como contexto multimodal
- Transmitir respostas em tempo real de um modelo Gemma 4 rodando localmente
- Operar em um loop de agente, chamando ferramentas e iterando com base nos resultados
O código completo deste tutorial está disponível aqui.
O que é o Gemma 4?
Gemma 4 é a família de modelos de pesos abertos do Google DeepMind, pensada para implantação local e pesquisa. Ela evolui a linhagem Gemma com melhor obediência a instruções, janelas de contexto maiores e entrada multimodal nativa, construída na mesma base de pesquisa do Gemini 3.

Figura: desempenho do modelo vs tamanho (fonte: blog Gemma 4)
Modelos como Gemma-4-26B(MOE) e Gemma-4-31B alcançam pontuações Elo comparáveis a modelos bem maiores, indicando forte desempenho por parâmetro. O 31B hoje ocupa a 3ª posição entre os modelos abertos no ranking de texto da Arena AI, e o 26B está em 6º lugar. Isso torna o Gemma 4 especialmente adequado para implantações locais e com recursos limitados, sem abrir mão de capacidade.
A família de modelos Gemma 4
O Gemma 4 é lançado em quatro tamanhos versáteis: Effective 2B (E2B), Effective 4B (E4B), 26B Mixture of Experts (MoE) e 31B Dense. A família se divide em dois níveis, de acordo com o alvo de implantação:
|
Modelo |
Arquitetura |
Parâmetros totais |
Parâmetros ativos/efetivos |
Comprimento do contexto |
Modalidades |
|
Gemma-4-31B |
Transformer denso |
31B |
31B |
256K tokens |
Texto, visão, vídeo |
|
Gemma-4-26B-A4B |
MoE (128 experts) |
26B |
3,8B ativos |
256K tokens |
Texto, visão, vídeo |
|
Gemma-4-E4B |
Transformer denso |
7,9B (com embeddings) |
4,5B efetivos |
128K tokens |
Texto, áudio, visão, vídeo |
|
Gemma-4-E2B |
Transformer denso |
5,1B (com embeddings) |
2,3B efetivos |
128K tokens |
Texto, áudio, visão, vídeo |
Vamos analisar mais a fundo cada variante:

Figura: guia visual do Gemma 4 (fonte)
- 31B Dense é o modelo principal, otimizado para data centers e cargas de trabalho de raciocínio complexas. Ele suporta janela de contexto de 256K tokens, com janela deslizante de 1024 tokens para processamento eficiente de contexto longo.
- 26B-A4B (MoE) é o primeiro modelo MoE do Gemma, roteando tokens por 128 experts mantendo apenas 3,8B de parâmetros ativos por forward pass. Isso entrega qualidade próxima ao 31B com uma fração do custo computacional por token, ideal para serving de alto throughput.
- E4B e E2B são a camada para dispositivo e mobile. Diferente das variantes maiores, incluem entrada de áudio nativa para reconhecimento de fala, além de visão e vídeo, tornando-os os modelos mais multimodais da família para edge.
Todos os quatro modelos estão sob licença Apache 2.0 e podem ser executados localmente via Ollama, vLLM, llama.cpp ou Unsloth.
Para tarefas de código, o Gemma 4 se destaca em:
- Escrever código completo e estruturado, com explicações
- Raciocinar sobre bases de código existentes quando fornecidas como contexto
- Uso de ferramentas e fluxos de trabalho com agente quando acoplado a uma camada de orquestração
- Manipular imagens junto com código (ex.: ler um print da UI e gerar HTML correspondente)
Neste tutorial, usamos a variante gemma4:e4b (9,6GB) via Ollama, uma versão quantizada, ideal para inferência local em hardware de consumo.
Executando o Gemma 4 via Ollama
O Ollama cuida do download do modelo, quantização, serving e oferece uma API HTTP compatível com OpenAI. Neste tutorial, o Ollama atua como backend de inferência e nosso app se comunica com ele em localhost:11434.
Para puxar e rodar o modelo:
curl -fsSL https://ollama.com/install.sh | sh
ollama pull gemma4:e4b
ollama serve
Os comandos acima instalam o Ollama localmente usando o script oficial. Em seguida, baixamos a variante gemma 4:e4b para inferência no dispositivo. Por fim, ollama serve inicia o servidor do Ollama, permitindo que nosso app envie requisições ao modelo.
Com o servidor no ar, o app em Gradio se conecta automaticamente.
Demo Gemma 4: construa um assistente de código com Ollama
Nesta seção, vamos construir o assistente de código passo a passo. Em alto nível, o app faz o seguinte:
-
Recebe uma mensagem em linguagem natural no painel de chat, com opção de anexar imagem ou arquivo
-
Injeta o código atual do editor como contexto para o modelo
-
Envia uma requisição em streaming ao Gemma 4 pelo endpoint
/api/chatdo Ollama -
Opcionalmente chama ferramentas (execução de código, avaliação matemática) em um loop de agente
-
Empurra blocos de código extraídos da resposta para o editor ao vivo
Vamos construir isso passo a passo.

Passo 1: instalar dependências
O app requer um conjunto enxuto de bibliotecas para a UI, tratamento de imagem e comunicação HTTP. Como o modelo roda localmente via Ollama, não há dependências de SDK na nuvem.
pip install gradio requests pillow
Neste projeto, vamos usar:
-
gradiopara o editor e a UI de chat em duas colunas -
requestspara conversar com a API HTTP do Ollama -
pillowpara suporte a imagens na UI
Isso mantém o ambiente leve e funciona em qualquer máquina com Ollama, incluindo macOS com Apple Silicon, Linux e Windows via WSL.
Passo 2: configuração e constantes
Antes da lógica, definimos os imports, o nome do modelo, a base URL do Ollama, as linguagens suportadas e um prompt de sistema padrão. Essas constantes controlam o comportamento do app.
import base64
import json
import math
import os
import re
import subprocess
import tempfile
from pathlib import Path
import gradio as gr
import requests
OLLAMA_BASE = "http://localhost:11434"
MODEL = "gemma4:e4b"
LANGUAGES = [
"python", "javascript", "typescript", "bash", "sql",
"rust", "go", "java", "c", "cpp", "html", "css",
"json", "yaml", "markdown", "plaintext",
]
TEXT_EXTS = {
".py", ".js", ".ts", ".jsx", ".tsx", ".html", ".css",
".json", ".yaml", ".yml", ".toml", ".md", ".txt",
".csv", ".sql", ".sh", ".bash", ".rs", ".go",
".java", ".c", ".cpp", ".h", ".hpp", ".rb", ".php",
}
IMAGE_EXTS = {".jpg", ".jpeg", ".png", ".webp", ".gif", ".bmp"}
DEFAULT_SYSTEM = """\
You are an expert coding assistant. When you write code:
- Always wrap it in a markdown code block with the language tag
- Write complete, working code — not fragments
- Briefly explain what the code does
You have a code-runner tool. Use it to validate logic when helpful.\
"""
Os conjuntos TEXT_EXTS e IMAGE_EXTS determinam dois comportamentos diferentes para anexos. Arquivos de texto/código são lidos e injetados como contexto no prompt, enquanto imagens são base64-encoded e enviadas no campo images para as capacidades de visão do Gemma 4.
O prompt DEFAULT_SYSTEM molda o estilo de geração de código do modelo, pedindo blocos completos com tags de linguagem, já que o app os analisa para enviar o código ao editor.
Passo 3: definir ferramentas de agente
O assistente pode operar em modo agente, chamando ferramentas durante a inferência. Definimos duas ferramentas no esquema padrão de function calling suportado pelo Ollama:
TOOLS = [
{
"type": "function",
"function": {
"name": "run_code",
"description": (
"Execute Python code in a sandboxed subprocess and return "
"stdout + stderr. Use this to validate, test, or demonstrate code."
),
"parameters": {
"type": "object",
"properties": {
"code": {
"type": "string",
"description": "Python code to run (max ~50 lines, 5 s timeout).",
}
},
"required": ["code"],
},
},
},
{
"type": "function",
"function": {
"name": "calculate",
"description": "Evaluate a mathematical expression precisely.",
"parameters": {
"type": "object",
"properties": {
"expression": {
"type": "string",
"description": "Python-compatible math expression, e.g. 'math.sqrt(2) * 100'",
}
},
"required": ["expression"],
},
},
},
]
O trecho acima define a ferramenta run_code, que executa Python em um arquivo temporário via subprocesso com timeout de 5 segundos e captura stdout e stderr. Assim, o modelo pode validar lógica, rodar exemplos ou produzir saída ao vivo, e não apenas gerar texto estático.
Já a ferramenta calculate avalia expressões matemáticas em um namespace restrito usando apenas o módulo math e built-ins seguros. Ela cobre casos em que o modelo precisa de resultados numéricos precisos sem abrir um processo Python completo.
Passo 4: execução das ferramentas
A camada de execução mapeia nomes de ferramentas para suas implementações. Ela é chamada durante o loop de agente sempre que o modelo retorna um bloco tool_calls.
def _run_python(code: str) -> str:
with tempfile.NamedTemporaryFile(mode="w", suffix=".py", delete=False) as f:
f.write(code)
tmp = f.name
try:
r = subprocess.run(
["python3", tmp],
capture_output=True, text=True, timeout=5,
)
out = (r.stdout + r.stderr).strip()
return out[:3000] if out else "(no output)"
except subprocess.TimeoutExpired:
return "⏱ Timed out (>5 s)"
except Exception as e:
return f"Error: {e}"
finally:
os.unlink(tmp)
def _calculate(expr: str) -> str:
ns = {k: getattr(math, k) for k in dir(math) if not k.startswith("_")}
ns.update({"abs": abs, "round": round})
try:
return str(eval(expr, {"__builtins__": {}}, ns)) # noqa: S307
except Exception as e:
return f"Error: {e}"
def execute_tool(name: str, args: dict) -> str:
if name == "run_code":
return _run_python(args.get("code", ""))
if name == "calculate":
return _calculate(args.get("expression", ""))
return f"Unknown tool: {name}"
Algumas escolhas de segurança importantes nessa pilha de execução:
-
_run_python()grava em arquivo temporário e faz a limpeza, evitando resíduos mesmo em caso de erro -
A saída é limitada a 3.000 caracteres para não inundar o contexto com dumps enormes
-
A função
_calculate()usaeval()com__builtins__vazio, bloqueando acesso a built-ins fora das funçõesmathexplicitamente permitidas -
O timeout é de 5 segundos: suficiente para validações rápidas e curto para evitar processos descontrolados
Passo 5: utilitários
Antes da lógica central de chat, precisamos de utilitários para caminhos de arquivos, codificação de imagens e extração de código. Essas funções dão suporte ao pipeline de streaming.
def encode_image(path: str) -> str | None:
if not path:
return None
try:
with open(path, "rb") as f:
return base64.b64encode(f.read()).decode()
except Exception:
return None
def file_as_context(path: str) -> str | None:
if not path:
return None
p = Path(path)
if p.suffix.lower() not in TEXT_EXTS:
return None
try:
content = p.read_text(encoding="utf-8", errors="replace")[:8000]
lang = p.suffix.lstrip(".")
return f"\n\n**Attached file — {p.name}:**\n```{lang}\n{content}\n```"
except Exception:
return None
def resolve_gradio_path(val) -> str | None:
if val is None:
return None
if isinstance(val, Path):
s = str(val)
return s if s.strip() else None
if isinstance(val, str):
s = val.strip()
return s if s else None
if isinstance(val, dict):
p = val.get("path")
if isinstance(p, str) and p.strip():
return p.strip()
nested = val.get("file")
if isinstance(nested, dict):
np = nested.get("path")
if isinstance(np, str) and np.strip():
return np.strip()
return None
name = getattr(val, "name", None)
if isinstance(name, str) and name.strip():
return name.strip()
return None
def is_image_path(path: str | None) -> bool:
return bool(path) and Path(path).suffix.lower() in IMAGE_EXTS
def extract_last_code_block(text: str) -> tuple[str | None, str]:
blocks = re.findall(r"```(\w*)\n(.*?)```", text, re.DOTALL)
if blocks:
lang, code = blocks[-1]
return code.strip(), lang.strip() or "python"
return None, "python"
def ollama_ok() -> bool:
try:
requests.get(f"{OLLAMA_BASE}/", timeout=2)
return True
except Exception:
return False
def _gradio_content_to_text(content) -> str:
if content is None:
return ""
if isinstance(content, str):
return content
if isinstance(content, list):
parts: list[str] = []
for block in content:
if isinstance(block, dict):
if block.get("type") == "text":
parts.append(str(block.get("text", "")))
elif "text" in block:
parts.append(str(block["text"]))
elif isinstance(block, str):
parts.append(block)
return "".join(parts)
return str(content)
def _append_chat_turn(
history: list | None, user_text: str, assistant_text: str
) -> list:
base = list(history) if history else []
return base + [
{"role": "user", "content": user_text},
{"role": "assistant", "content": assistant_text},
]
def run_code_btn(code: str) -> str:
if not code.strip():
return "Nothing to run."
result = _run_python(code)
return result
Esses utilitários viabilizam o fluxo entre entradas multimodais e saídas estruturadas:
-
encode_image(): converte uma imagem em stringbase64para ser enviada no campoimagesdo Ollama. Assim, o Gemma processa imagens junto com texto para raciocínio multimodal. -
file_as_context(): lê arquivos de texto/código e os injeta diretamente no prompt como markdown formatado. Dispensa um sistema de busca/recuperação separado, já que tudo vai inline como contexto. -
resolve_gradio_path(): normaliza diferentes formatos de arquivo retornados pelo Gradio em um caminho utilizável, evitando bugs de borda. -
is_image_path(): checa rapidamente se o arquivo é imagem para roteá-lo corretamente. -
extract_last_code_block(): extrai o último bloco de código da resposta do modelo. -
ollama_ok(): verifica se o servidor local do Ollama está rodando antes de enviar requisições. -
_gradio_content_to_text()e_append_chat_turn(): achatam o formato estruturado do Gradio em texto puro e mantêm o histórico do chat. -
run_code_btn(): executa o código gerado quando você clica no botão Run code na UI.
Agora que temos os utilitários, podemos implementar a função central chat().
Passo 6: gerador de streaming do chat
Essa função conduz todo o loop de interação, da preparação das entradas ao streaming das respostas e execução de ferramentas.
Em alto nível, a chat():
- constrói o histórico da conversa
- enriquece a entrada atual com contexto (código, arquivos, imagens)
- envia uma requisição em streaming ao Ollama
- opcionalmente executa ferramentas (modo agente)
- emite respostas parciais para atualização em tempo real da UI
def chat(
message, history, image_path, file_path,
editor_code, language, system_prompt,
agentic, thinking, temperature,
):
A função segue a sequência abaixo:
Passo 1: construir o histórico
Convertamos os turnos anteriores para o formato de mensagens do Ollama. O prompt de sistema é inserido no início para orientar o comportamento do modelo e garantir que ele tenha o contexto completo antes de responder.
for h in history or []:
if not isinstance(h, dict):
continue
role = h.get("role")
if role not in ("user", "assistant"):
continue
messages.append(
{"role": role, "content": _gradio_content_to_text(h.get("content"))}
)
content = message
Passo 2: compor a fala do usuário
Construímos a mensagem atual injetando contexto adicional. Se o usuário está trabalhando com código, anexamos o conteúdo do editor:
if editor_code.strip() and editor_code.strip() != STARTER_CODE.strip():
content += (
f"\n\n**Current code in editor ({language}):**\n"
f"```{language}\n{editor_code}\n```"
)
Da mesma forma, arquivos enviados são adicionados inline como contexto e imagens são codificadas em base64 e passadas via campo images. Assim, o modelo raciocina sobre texto, código e imagens em conjunto.
Passo 3: enviar a requisição ao Ollama
O payload inclui o nome do modelo, histórico, flag de streaming e opções, assim:
payload = {
"model": MODEL,
"messages": messages,
"stream": True,
"options": options,
}
if agentic:
payload["tools"] = TOOLS
Se o modo de raciocínio estiver ativado, define-se options["think"] = True, habilitando chain-of-thought estendido em modelos compatíveis.
Passo 4: tratar chamadas de ferramentas (modo agente)
Se o modo agente está ligado, o modelo pode retornar chamadas de ferramenta em vez de texto. Cada ferramenta é executada, resultados são anexados à conversa e uma nova requisição continua a geração.
if agentic and msg.get("tool_calls"):
for tc in msg["tool_calls"]:
fn_name = tc["function"]["name"]
fn_args = tc["function"]["arguments"]
result = execute_tool(fn_name, fn_args)
if fn_name == "run_code" and fn_args.get("code"):
new_code = fn_args["code"]
messages.append(msg)
messages.append({"role": "tool", "content": result})
resp2 = requests.post(f"{OLLAMA_BASE}/api/chat", ...)
Isso cria um loop agente de uma volta: o modelo chama a ferramenta, vê o resultado e segue gerando a resposta final. Os logs das ferramentas aparecem no chat para o usuário.
Passo 5: extrair código e atualizar o editor
Quando o streaming termina, extraímos o último bloco de código da resposta:
extracted, _ = extract_last_code_block(full_response)
if extracted:
new_code = extracted
Assim, o modelo gera o código, o editor se atualiza automaticamente e você não precisa copiar e colar manualmente.
Passo 7: layout da UI em Gradio
Com a lógica pronta, vamos desenhar a interface usando Gradio. A ideia é ter um layout que suporte o fluxo de codificação e a interação com IA lado a lado.
Usamos gr.Blocks para criar duas colunas:
- o painel esquerdo foca em edição e execução de código
- o painel direito cuida do chat, anexos e controles do modelo
with gr.Blocks(title="Gemma 4 · Code Assistant") as demo:
with gr.Row(equal_height=False):
# LEFT: Code Editor
with gr.Column(scale=11):
with gr.Row():
lang_sel = gr.Dropdown(choices=LANGUAGES, value="python", label="Language")
run_btn = gr.Button("Run Code", elem_classes=["run-btn"])
clear_ed = gr.Button("Clear")
code_editor = gr.Code(
value=STARTER_CODE,
language="python",
label="Editor",
lines=24,
interactive=True,
)
run_output = gr.Textbox(
label="Output",
lines=6,
interactive=False,
elem_id="run-output",
)
# RIGHT: Chat
with gr.Column(scale=9):
chatbot = gr.Chatbot(value=[], elem_id="chatbot", height=430)
with gr.Row():
image_upload = gr.Image(label="Image (vision)", type="filepath")
file_upload = gr.File(label="Code / text file")
with gr.Row():
msg_input = gr.Textbox(placeholder="Ask the agent...", scale=6)
send_btn = gr.Button("Send", variant="primary")
with gr.Row():
agentic_cb = gr.Checkbox(label="Enable Agentic", value=True)
thinking_cb = gr.Checkbox(label="Enable Thinking", value=False)
clear_chat = gr.Button("Clear chat")
with gr.Accordion("Settings", open=False):
sys_prompt = gr.Textbox(value=DEFAULT_SYSTEM, label="System prompt")
temperature = gr.Slider(minimum=0.0, maximum=2.0, value=0.7)
Veja como a UI trabalha em conjunto com os componentes acima:
- Espaço de código: o painel esquerdo inclui seletor de linguagem, editor de código e botões de executar/limpar. A saída aparece em uma caixa destacada.
- Chat e interação: o painel direito traz o chatbot, campo de entrada e suporte a anexos (imagens para raciocínio multimodal e arquivos para injeção de contexto). Há toggles para uso de ferramentas de agente e modos de raciocínio.
- Layout e usabilidade: duas colunas com divisão 55/45, priorizando o editor, mantendo o chat acessível. Esse equilíbrio facilita o fluxo entre codificação, ajuda da IA e execução.
Passo 8: eventos
Os eventos de enviar e submeter compartilham as mesmas entradas/saídas, então tanto o clique no botão quanto Enter no campo disparam o mesmo comportamento:
_inputs = [
msg_input, chatbot, image_upload, file_upload,
code_editor, lang_sel,
sys_prompt, agentic_cb, thinking_cb, temperature,
]
_outputs = [chatbot, code_editor, msg_input]
send_btn.click(fn=respond, inputs=_inputs, outputs=_outputs)
msg_input.submit(fn=respond, inputs=_inputs, outputs=_outputs)
O wrapper respond() resolve os paths retornados pelo Gradio em strings simples antes de passá-los ao gerador de streaming. Ele então emite (history, code, "") a cada chunk para limpar a caixa de mensagem logo na primeira atualização.
Passo 9: tema e CSS
Para melhorar a usabilidade e a consistência visual, adicionamos um tema e CSS customizados sobre o padrão do Gradio. Isso dá um visual polido, inspirado no GitHub, com suporte a modos claro e escuro. É totalmente opcional.
Começamos definindo um tema base com gr.themes.Base:
THEME = gr.themes.Base(
primary_hue = "blue",
secondary_hue = "slate",
neutral_hue = "slate",
font = [gr.themes.GoogleFont("Inter"), "system-ui", "sans-serif"],
font_mono = [gr.themes.GoogleFont("JetBrains Mono"), "monospace"],
)
Isso define uma paleta consistente e tipografia limpa (Inter) com monoespaçada amigável a devs (JetBrains Mono). Em seguida, sobrepomos variáveis CSS para ajustar a aparência:
gradio-app {
--body-background-fill: #f0f3f7;
--block-background-fill: #ffffff;
--body-text-color: #1f2328;
--button-primary-background-fill: #1a7f37;
}
body.dark gradio-app {
--body-background-fill: #0d1117;
--block-background-fill: #1c2128;
--body-text-color: #e6edf3;
--button-primary-background-fill: #238636;
}
O primeiro bloco define o tema claro, o segundo substitui valores para o modo escuro. Embora opcional, o tema customizado melhora bastante a experiência.
Com a UI estruturada e estilizada, vamos ao passo final: lançar a aplicação.
Passo 10: execução
Por fim, iniciamos o app com:
if __name__ == "__main__":
print(f"Model : {MODEL}")
print(f"Ollama : {OLLAMA_BASE}")
if not ollama_ok():
print("Ollama not detected — run ollama serve before chatting")
demo.launch(
server_name="0.0.0.0",
server_port=7860,
share=False,
theme=THEME,
css=CSS,
)
Aqui, server_name="0.0.0.0" deixa o app acessível na sua rede local e share=False mantém tudo local. A verificação ollama_ok() faz um GET rápido para localhost:11434 e avisa na inicialização se o Ollama não estiver rodando, em vez de falhar só na primeira mensagem.
Por fim, acesse http://localhost:7860 quando o app estiver no ar.
Fluxo completo do ponto de vista do usuário:

-
Você digita uma mensagem no chat, podendo anexar imagem ou arquivo de código e ativar agente/raciocínio
-
Ao enviar, a função
respond()monta a requisição ao Ollama, incluindo o código do editor e anexos como contexto -
A resposta é transmitida token a token e exibida ao vivo no chatbot do Gradio
-
Se o modo agente estiver ativo e o modelo decidir chamar uma ferramenta, ela roda localmente, o resultado é anexado e uma nova requisição transmite a resposta final
-
Ao final do streaming, o último bloco de código cercado é extraído e enviado automaticamente ao editor
Conclusão
Neste tutorial, criamos um assistente de codificação em IA totalmente local usando Gemma 4, Ollama e Gradio. O app aceita entrada multimodal, usa ferramentas reais, transmite respostas e traz um editor de código ao vivo — tudo rodando na sua máquina, sem API externa.
A estratégia de contexto total — injetar o código do editor em todo prompt — é mais simples que RAG para um workflow de arquivo único e funciona muito bem para explicar, refatorar ou estender o código que você está editando.
A partir daqui, você pode estender o projeto em várias direções:
- Adicionar um painel de árvore de arquivos para projetos multi-arquivo e injetar selecionados como contexto
- Adicionar suporte a outros modelos do Ollama em um dropdown, permitindo alternar entre Gemma 4, Llama 3 e outros
- Persistir o histórico de conversa em disco para manter sessões após reiniciar o app
Sou Especialista Google Developers em ML (Gen AI), tricampeã no Kaggle e Embaixadora Women Techmakers, com mais de três anos de experiência na área de tecnologia. Cofundei uma startup de saúde em 2020 e atualmente faço um mestrado em ciência da computação na Georgia Tech, com foco em aprendizado de máquina.
Perguntas frequentes sobre o Gemma 4
Precisa de GPU para rodar?
Não necessariamente. O Gemma 4 e4b é um modelo quantizado que pode rodar em CPU, embora uma GPU melhore bastante a velocidade de inferência.
Qual a diferença entre o modo agente e o chat normal?
No modo regular, o modelo transmite apenas texto. No modo agente, ele pode chamar run_code ou calculate, conferir os resultados e incorporá-los antes de concluir a resposta.
Como o editor atualiza automaticamente quando o agente escreve código?
A função auxiliar extract_last_code_block() procura o último bloco de código cercado na resposta do assistente e o envia ao editor quando o streaming termina. Por isso o prompt de sistema instrui o modelo a sempre envolver o código em blocos cercados com tag de linguagem.
O que acontece se o Ollama não estiver rodando?
A checagem ollama_ok() detecta isso na inicialização e a cada envio no chat. Se o Ollama não estiver acessível, o chat retorna uma mensagem de erro formatada em vez de travar.



