SwiftyAISwiftyAI

Search documentation

Find a docs page by title or section

2

Message Management

SwiftyAI uses ChatMessage for chat history. A message has a role, text content, optional multimodal parts, an id, and a creation date.

TypeRole
ChatMessageOne visible or model-sent message
ChatRole.system, .user, or .assistant
AIMessageContentText, image, PDF, file, audio, or video prompt parts
ContextWindowApproximate token budgeting for messages
maxMessagesSimple history pruning for chat helpers

Text Messages

let messages = [
    ChatMessage(role: .system, content: "Answer like a support engineer."),
    ChatMessage(role: .user, content: "Why did my export fail?")
]
 
for try await chunk in model.stream(messages: messages) {
    print(chunk.text, terminator: "")
}

Roles are .system, .user, and .assistant.

Multimodal Messages

let message = ChatMessage(
    role: .user,
    parts: [
        .text("Explain this screenshot."),
        .imageData(imageData, mediaType: .png, detail: .high)
    ]
)

content and parts stay synchronized. Text-only parts are joined into content; setting content replaces parts with a single .text value.

Built-In Chat Limits

AIChat and SwiftyChat accept maxMessages.

let chat = AIChat(
    model: "openai/gpt-4o-mini",
    systemPrompt: "Be concise.",
    maxMessages: 20
)

The visible message array stays in state, but the history sent to the model is pruned.

Context Estimates

let context = ContextWindow(maxTokens: 16_000)
 
if context.isNearLimit(for: chat.messages) {
    print("Consider summarizing older messages.")
}

The estimator uses a simple character-based approximation and assigns a fixed estimate to non-text parts. It is good for warnings, not exact billing.

StrategyUse
maxMessagesKeep the most recent turns for simple chats
ContextWindow warningShow UI warnings before the context gets too large
Manual summarizationReplace older turns with a summary when long sessions matter
Provider tokenizersUse when billing-exact token counts are required
Related docs