В этом посте наши друзья из Cactus Compute показывают, как Needle 2, модель вызова функций размером 14 МБ, превращает простой английский в локальные действия на Raspberry Pi 5, используя только процессор. Вы также можете посмотреть только что вышедшую «Иглу 3».
Введите «Включить светодиод», и через 78 миллисекунд на нашем Raspberry Pi 5 загорится светодиод. Это Needle 2, работающий только на процессоре — без специальной AI HAT.

Начнем с того, что такое Игла нет. Это не чат-бот. Вместо этого команда Cactus Compute обучила его только одной задаче: надежным и структурированным действиям устройства.
«Игла 2 отличная»
– Эбен Аптон, генеральный директор Raspberry Pi
Настройка проста: вы объявляете функции Python, затем выбираете, какую Needle вызывать, и заполняете аргументы. Мы использовали его для написания локальных заметок, запросов vcgencmdвзаимодействовать со светодиодами и многое другое на Raspberry Pi 5 только с процессором.
python3 -m venv needle-env
source needle-env/bin/activate
python -m pip install cactus-needle
После первоначальной загрузки Needle запускается локально без облачного API или сетевого подключения. Этот первый пример не требует дополнительного оборудования.
import needle
from pathlib import Path
import subprocess
notes_path = Path("needle-notes.txt")
Needle класс принимает декорированные функции @needle.tool. Декоратор использует имя каждой функции, строку документации и аннотацию типа для построения схемы своего инструмента. В save_note ниже аннотация сообщает Needle, что text должна быть строкой.
@needle.tool
def save_note(text: str):
"""Append a note to a local text file."""
with notes_path.open("a", encoding="utf-8") as notes:
notes.write(text + "\n")
return {"text": text, "path": str(notes_path)}
@needle.tool
def get_temperature():
"""Return the current CPU temperature of this Raspberry Pi in Celsius."""
out = subprocess.check_output(["vcgencmd", "measure_temp"], text=True)
return {"temperature_c": float(out.split("=")[1].split("'")[0])}
agent = needle.Needle(tools=[save_note, get_temperature])
response = agent.run("Save a note that says the cooler is working.")
Внутри run()модель сначала выбирает этот инструмент (выходные данные обрезаны для ясности):
{
"type": "call",
"function_calls": [
{
"name": "save_note",
"arguments": { "text": "the cooler is working" }
}
]
}
run() выполняет функцию и включает ее возвращаемое значение в response["results"]:
[
{
"text": "the cooler is working",
"path": "needle-notes.txt"
}
]
В этом запуске первоначальный complete() внутри run() выбрал функцию и создал ее аргументы за 107 мс.
Мы также можем спросить:
agent.reset()
response = agent.run("How hot is this Raspberry Pi?")
Игла звонит:
{
"type": "call",
"function_calls": [
{"name": "get_temperature", "arguments": {}}
]
}
run() внедрение vcgencmd и включая чтение в его результатах:
{ "temperature_c": 49.9 }
Мы также заявили set_led(on), blink_led(times)и take_photo() через rpicam-still проверить выбор инструмента. Игла выбирает инструмент; Обычный код Python решает, что произойдет дальше. Вы также можете украсить любую функцию Python явным именем, аннотацией типа и описанием. @needle.tool.
Игла намеренно узкая. Спросите: «Какая столица Франции?» и он возвращается { "function_calls": [] } за 92 мс, потому что ни один из предоставленных нами инструментов не может ответить на этот вопрос. Для модели действия правильным ответом является отклонение нерелевантного запроса.
Собственный сеанс Needle занимает около 28 МБ. В этой демонстрации Python весь процесс занимает от 43 до 46,4 МБ, включая интерпретатор. Вот еще несколько запусков:
| Быстрый | Вызов | Предварительное заполнение (дол/с) | Декодирование (ударов/с) | Затраченное время (мс) |
| Включите светодиод. | set_led |
488 | 296 | 78 |
| Насколько горячий этот Raspberry Pi? | get_temperature |
487 | 303 | 149 |
| Мигните светодиодом 2 раза. | blink_led |
475 | 314 | 83 |
| Сфотографируйтесь. | take_photo |
461 | 248 | 76 |
| Сохраните заметку о том, что кулер работает. | save_note |
475 | 305 | 107 |
| Какая столица Франции? | (никто) | 470 | 297 | 92 |
Эти примеры запускались на Raspberry Pi 5, 8 ГБ, ОС Raspberry Pi, только процессор, cactus-needle 2.0.7. Предварительное заполнение и декодировать являются счетчиками сеансов Needle. Каждая задержка в Затраченное время Колонка настенные часы время для одного complete() вызов перед запуском выбранной функции Python.
Если вы уже написали функции GPIO Zero, вы можете украсить их и передать. То же самое касается и другой логики приложения. Иглу также можно правильно локализовать на ноутбуке под определенный набор инструментов.
Вы можете найти веса и код на сайтахhuggingface.co/Cactus-Compute/needle2, github.com/cactus-compute/needle. Оба были выпущены под Apache 2.0.