dc21bf59532057db560eaf54c0342635 Saravati

Como Criar um Agente de IA com a Unihiker K10 e a API da Groq

A Inteligência Artificial está cada vez mais presente em dispositivos embarcados e projetos eletrônicos. Neste projeto, vamos criar um agente de IA utilizando a Unihiker K10 capaz de:

  • Escutar comandos de voz
  • Converter voz em texto
  • Enviar a pergunta para uma Inteligência Artificial
  • Receber a resposta da IA
  • Exibir a resposta na tela da Unihiker K10

Tudo isso utilizando a poderosa API da Groq, que oferece modelos de IA extremamente rápidos.

Como o projeto funciona

O fluxo do sistema é o seguinte:

  1. O usuário fala a palavra de ativação (“Hi Telly”)
  2. A Unihiker K10 inicia a gravação de áudio
  3. O áudio é salvo no cartão SD
  4. O arquivo é enviado para a API da Groq
  5. O modelo Whisper realiza a transcrição
  6. O texto transcrito é enviado para um modelo LLM
  7. A IA gera uma resposta
  8. A resposta é exibida na tela

Materiais Utilizados

  • Unihiker K10
  • Cartão MicroSD
  • Conexão Wi-Fi
  • Conta gratuita na Groq
  • Arduino IDE

Criando sua conta na Groq

Acesse:

https://console.groq.com

Passo 1

Clique em “Sign Up”.

Passo 2

Crie sua conta utilizando:

  • E-mail
  • Conta Google
  • GitHub

Passo 3

Após entrar no painel, clique em:

API Keys

Passo 4

Clique em:

Create API Key

Passo 5

Defina um nome para sua chave.

Exemplo:

AgenteIA-Unihiker

Passo 6

Copie a chave gerada.

Ela terá um formato parecido com:

gsk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Guarde essa chave em local seguro.

Configurando o projeto

No código substitua:

const char* ssid = “SEU_WIFI”;

const char* password = “SUA_SENHA_WIFI”;

const char* groqApiKey = “SUA_API_GROQ”;

Pelos seus dados.

Modelos utilizados

Transcrição de Áudio

Modelo:

whisper-large-v3-turbo

Responsável por transformar voz em texto.

Inteligência Artificial

Modelo:

llama-3.1-8b-instant

Responsável por responder às perguntas.

Funcionamento da Transcrição

Quando o áudio é gravado:

music.recordSaveToTFCard(“S:/sound.wav”, 5);

O arquivo WAV é salvo no cartão SD.

Em seguida ele é enviado para:

https://api.groq.com/openai/v1/audio/transcriptions

Utilizando o modelo Whisper.

A resposta recebida possui formato:

{

  “text”: “Qual a capital do Brasil?”

}

Funcionamento da IA

Após a transcrição:

String resposta = perguntarIA(texto);

A pergunta é enviada para:

https://api.groq.com/openai/v1/chat/completions

Utilizando:

doc[“model”] = “llama-3.1-8b-instant”;

A IA processa a pergunta e retorna uma resposta curta para ser exibida na tela.

Código do Projeto

Substitua apenas as credenciais de Wi-Fi e a API Key.

const char* ssid = “SEU_WIFI”;

const char* password = “SUA_SENHA_WIFI”;

const char* groqApiKey = “SUA_API_GROQ”;

Código Completo:

#include "asr.h"

#include "unihiker_k10.h"

#include <WiFi.h>
#include <WiFiClientSecure.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>
#include <SD.h>

UNIHIKER_K10 k10;
ASR asr;
Music music;

uint8_t screen_dir = 2;

const char* ssid = "SEU_WIFI";
const char* password = "SUA_SENHA_WIFI";

const char* groqApiKey = "SUA_API_GROQ";

String wavPath = "/sound.wav";

String removerAcentos(String texto) {
  texto.replace("á", "a"); texto.replace("à", "a"); texto.replace("ã", "a"); texto.replace("â", "a");
  texto.replace("é", "e"); texto.replace("ê", "e");
  texto.replace("í", "i");
  texto.replace("ó", "o"); texto.replace("ô", "o"); texto.replace("õ", "o");
  texto.replace("ú", "u");
  texto.replace("ç", "c");
  texto.replace("Á", "A"); texto.replace("É", "E"); texto.replace("Í", "I");
  texto.replace("Ó", "O"); texto.replace("Ú", "U"); texto.replace("Ç", "C");
  return texto;
}

void mostrar(String texto) {
  texto = removerAcentos(texto);

  k10.canvas->canvasClear();
  k10.canvas->canvasText("AGENTE IA", 0, 0xFF0000);

  int row = 2;
  int maxChars = 18;

  while (texto.length() > 0 && row < 10) {
    String linha;

    if (texto.length() > maxChars) {
      int corte = texto.lastIndexOf(' ', maxChars);
      if (corte <= 0) corte = maxChars;

      linha = texto.substring(0, corte);
      texto = texto.substring(corte);
      texto.trim();
    } else {
      linha = texto;
      texto = "";
    }

    k10.canvas->canvasText(linha, row, 0x0000FF);
    row++;
  }

  k10.canvas->updateCanvas();
}

String transcreverGroq() {
  File audioFile = SD.open(wavPath, FILE_READ);

  if (!audioFile) return "Erro ao abrir audio";

  String boundary = "----K10Boundary";

  String head =
    "--" + boundary + "\r\n"
    "Content-Disposition: form-data; name=\"model\"\r\n\r\n"
    "whisper-large-v3-turbo\r\n"
    "--" + boundary + "\r\n"
    "Content-Disposition: form-data; name=\"file\"; filename=\"sound.wav\"\r\n"
    "Content-Type: audio/wav\r\n\r\n";

  String tail = "\r\n--" + boundary + "--\r\n";

  int contentLength = head.length() + audioFile.size() + tail.length();

  WiFiClientSecure client;
  client.setInsecure();

  if (!client.connect("api.groq.com", 443)) {
    audioFile.close();
    return "Erro conexao Groq";
  }

  client.println("POST /openai/v1/audio/transcriptions HTTP/1.1");
  client.println("Host: api.groq.com");
  client.print("Authorization: Bearer ");
  client.println(groqApiKey);
  client.print("Content-Type: multipart/form-data; boundary=");
  client.println(boundary);
  client.print("Content-Length: ");
  client.println(contentLength);
  client.println("Connection: close");
  client.println();

  client.print(head);

  uint8_t buffer[1024];

  while (audioFile.available()) {
    int len = audioFile.read(buffer, sizeof(buffer));
    client.write(buffer, len);
  }

  audioFile.close();
  client.print(tail);

  String response = "";
  unsigned long timeout = millis();

  while (client.connected() && millis() - timeout < 25000) {
    while (client.available()) {
      char c = client.read();
      response += c;
      timeout = millis();
    }
  }

  client.stop();

  int jsonStart = response.indexOf("{");
  if (jsonStart < 0) return "Sem JSON";

  String json = response.substring(jsonStart);

  DynamicJsonDocument doc(4096);
  DeserializationError error = deserializeJson(doc, json);

  if (error) return "Erro JSON";

  String texto = doc["text"].as<String>();
  if (texto.length() == 0) return "Sem texto";

  return texto;
}

String perguntarIA(String pergunta) {
  WiFiClientSecure client;
  client.setInsecure();

  HTTPClient http;
  http.begin(client, "https://api.groq.com/openai/v1/chat/completions");

  http.addHeader("Content-Type", "application/json");
  http.addHeader("Authorization", "Bearer " + String(groqApiKey));

  DynamicJsonDocument doc(4096);

  doc["model"] = "llama-3.1-8b-instant";
  doc["temperature"] = 0.4;
  doc["max_tokens"] = 120;

  JsonArray messages = doc.createNestedArray("messages");

  JsonObject systemMsg = messages.createNestedObject();
  systemMsg["role"] = "system";
  systemMsg["content"] = "Voce e um assistente curto, direto e didatico. Responda em portugues do Brasil com no maximo 3 frases. Nao use acentos.";

  JsonObject userMsg = messages.createNestedObject();
  userMsg["role"] = "user";
  userMsg["content"] = pergunta;

  String body;
  serializeJson(doc, body);

  int httpCode = http.POST(body);

  if (httpCode != 200) {
    String erro = http.getString();
    Serial.println("Erro IA:");
    Serial.println(erro);
    http.end();
    return "Erro IA";
  }

  String payload = http.getString();
  http.end();

  DynamicJsonDocument respostaDoc(8192);
  DeserializationError error = deserializeJson(respostaDoc, payload);

  if (error) return "Erro JSON IA";

  String resposta = respostaDoc["choices"][0]["message"]["content"].as<String>();

  if (resposta.length() == 0) return "Sem resposta";

  return resposta;
}

void setup() {
  Serial.begin(115200);

  k10.begin();
  k10.initScreen(screen_dir);
  k10.creatCanvas();
  k10.initSDFile();

  mostrar("Conectando WiFi");

  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  mostrar("WiFi conectado");
  delay(1000);

  mostrar("Iniciando voz");

  asr.asrInit(CONTINUOUS, EN_MODE, 6000);

  while (asr._asrState == 0) {
    delay(100);
  }

  mostrar("Diga Hi Telly");

  Serial.println("Diga Hi Telly para fazer uma pergunta");
}

void loop() {
  if (asr.isWakeUp()) {
    Serial.println("Wake word reconhecida");

    mostrar("Pode falar");
    delay(700);

    mostrar("Gravando");
    music.recordSaveToTFCard("S:/sound.wav", 5);

    mostrar("Transcrevendo");

    String texto = transcreverGroq();
    texto = removerAcentos(texto);

    Serial.print("Pergunta transcrita: ");
    Serial.println(texto);

    mostrar("Pensando");

    String resposta = perguntarIA(texto);
    resposta = removerAcentos(resposta);

    Serial.print("Resposta final: ");
    Serial.println(resposta);

    mostrar(resposta);

    // Mantem a resposta na tela ate falar Hi Telly novamente
  }

  delay(50);
}

Possíveis Melhorias

A partir dessa base você pode criar:

  • Assistente pessoal
  • Chatbot embarcado
  • Automação residencial com voz
  • Controle de dispositivos por linguagem natural
  • Robôs inteligentes
  • Sistemas educacionais
  • IA embarcada para indústria

Conclusão

Este projeto mostra como é possível integrar eletrônica, sistemas embarcados e Inteligência Artificial utilizando uma plataforma compacta como a Unihiker K10.

Com poucas linhas de código conseguimos capturar áudio, utilizar reconhecimento de fala, acessar modelos avançados de IA e exibir respostas em tempo real.

Esse tipo de aplicação representa uma das áreas mais promissoras da tecnologia atualmente e demonstra como a combinação entre hardware e IA abre possibilidades praticamente ilimitadas para novos projetos.

Saiba mais sobre a parceria Saravati e Sara Educação

Este “Guia de Montagem” é uma colaboração especial entre a Saravati e a Sara Educação, criado pelo Professor Felipe Rosa. Nosso objetivo é enriquecer a comunidade de entusiastas da eletrônica, IoT e automação com recursos educacionais de alta qualidade. Através dessa parceria, buscamos inspirar e capacitar criadores em seus projetos, disponibilizando esses guias em nosso blog e nas redes sociais.

@saravatirobotica no Instagram e Tiktok

@sara.educacao no Instagram e Tiktok

Leave a Reply

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *