Розробка AI-асистента у мобільному додатку на базі Claude (Anthropic)
Claude — моделі від Anthropic з одним із найбільших контекстних вікон серед комерційно доступних LLM. Claude 3.5 Sonnet підтримує 200K токенів контексту, що для мобільного асистента означає можливість завантажити в один запит усю переписку за кілька тижнів або великий документ без фрагментування. Це змінює підходи до управління історією діалогу.
Anthropic Messages API: структура та особливості
Anthropic API за структурою подібна до OpenAI, але з важливими відмінностями. Системні промпти в Claude — окремий параметр system, а не повідомлення з роллю system у масиві messages. Критично важливо: передача системного промпту всередину messages погіршує якість слідування інструкціям.
struct AnthropicRequest: Encodable {
let model: String // "claude-3-5-sonnet-20241022"
let maxTokens: Int // обов'язковий параметр, немає дефолту
let system: String // системний промпт — окремо
let messages: [Message]
let stream: Bool
enum CodingKeys: String, CodingKey {
case model, system, messages, stream
case maxTokens = "max_tokens"
}
}
max_tokens у Anthropic API — обов'язковий параметр без дефолту. Якщо забути його передати, API повернеу ошибку 400. Це відмінність від OpenAI, де max_tokens опціональний.
Аутентифікація: заголовок x-api-key (не Authorization: Bearer). Версіонування API через anthropic-version: 2023-06-01. Без цього заголовка — 400 Bad Request.
Потокова передача через SSE
Claude підтримує потокову передачу через Server-Sent Events. Структура потоку відрізняється від OpenAI: content_block_start, content_block_delta, content_block_stop, message_delta — кожне містить свої поля.
На iOS обробка SSE через URLSession + AsyncBytes:
for try await line in response.bytes.lines {
guard line.hasPrefix("data: ") else { continue }
let jsonString = String(line.dropFirst(6))
guard jsonString != "[DONE]" else { break }
if let data = jsonString.data(using: .utf8),
let event = try? JSONDecoder().decode(StreamEvent.self, from: data),
event.type == "content_block_delta" {
let delta = event.delta?.text ?? ""
await MainActor.run { self.appendText(delta) }
}
}
Важливо обробляти всі типи подій, не лише content_block_delta — message_delta містить інформацію про stop_reason (наприклад, max_tokens), яку потрібно показувати користувачеві.
Великий контекст: переваги та обмеження на мобільному
200K токенів — приблизно 150 000 слів або ~500 сторінок тексту. Для мобільного асистента можливість працювати з повним документом без RAG-пайплайну. Користувач прикріпив PDF договору — його можна цілком передати в контекст та задавати запитання.
Зворотна сторона: великий контекст = довгий time-to-first-token. При 50K токенів у запиті перший токен відповіді може прийти через 3–5 секунд навіть на гарному з'єднанні. На мобільному потрібен індикатор прогресу, який появляється одразу, до першого токена, інакше користувач думає, що додаток зависнув.
Вартість також зростає лінійно з контекстом — для додатків з користувацькою оплатою це важливо враховувати при проектуванні UI лічильника токенів.
Vision: передача зображень
Claude 3.5 Sonnet підтримує зображення через base64 у content block:
let imageContent = ContentBlock(
type: "image",
source: ImageSource(
type: "base64",
mediaType: "image/jpeg",
data: imageBase64
)
)
Обмеження: максимум 20 зображень у одному запиті, кожне до 5 МБ. На мобільному перед відправленням зображення потрібно стиснути до розумного розміру — UIGraphicsImageRenderer або BitmapFactory.Options з inSampleSize.
Процес впровадження
Ключові запитання перед початком розробки: потрібна ліле робота з документами (PDF, зображення), очікуваний обсяг діалогу, потрібен ліле серверний проксі (так — обов'язково, API-ключ не зберігається в додатку).
Реалізація: Anthropic API клієнт → потоковий UI → управління історією з урахуванням 200K ліміту → опціональна робота з файлами.
Часові орієнтири
Базовий текстовий асистент — 1–2 тижні. З підтримкою документів та зображень, серверним проксі — 3–4 тижні.







