Nous.Messages (nous v0.16.4)
View SourceUtilities for working with conversations and message lists.
This module provides functions to:
- Work with lists of messages (conversations)
- Convert between internal format and provider-specific formats
- Extract data from conversations
- Parse provider responses into internal format
Message Format
We use Nous.Message structs with standard roles:
%Message{role: :system}- System instructions%Message{role: :user}- User input (text or multi-modal)%Message{role: :assistant}- AI responses (with optional tool calls)%Message{role: :tool}- Tool execution results
Example
# Build conversation
conversation = [
Message.system("You are a helpful assistant"),
Message.user("What is 2+2?"),
Message.assistant("2+2 equals 4")
]
# Convert to provider format
openai_messages = Messages.to_openai_format(conversation)
anthropic_messages = Messages.to_anthropic_format(conversation)
# Parse provider response
response = Messages.from_openai_response(openai_response)
# => %Message{role: :assistant, content: "4"}
Summary
Functions
Count messages by role.
Extract text content from messages in a conversation.
Extract tool calls from a conversation.
Find messages by role in a conversation.
Parse Anthropic response into a Message.
Parse Gemini response into a Message.
Parse OpenAI response into a Message.
Parse provider response into a Message.
Get the last message from a conversation.
Normalize any message format to internal Message representation.
Convert messages to Anthropic format.
Convert messages to Gemini format.
Convert messages to OpenAI format.
Convert messages to provider-specific format.
Functions
@spec count_by_role([Nous.Message.t()]) :: map()
Count messages by role.
Examples
iex> conversation = [Message.system("Hi"), Message.user("Hello"), Message.user("World")]
iex> Messages.count_by_role(conversation)
%{system: 1, user: 2, assistant: 0, tool: 0}
@spec extract_text([Nous.Message.t()] | Nous.Message.t()) :: [String.t()] | String.t()
Extract text content from messages in a conversation.
Examples
iex> conversation = [Message.system("Be helpful"), Message.user("Hello")]
iex> Messages.extract_text(conversation)
["Be helpful", "Hello"]
iex> message = Message.user("Hi there")
iex> Messages.extract_text(message)
"Hi there"
@spec extract_tool_calls([Nous.Message.t()]) :: [map()]
Extract tool calls from a conversation.
Returns all tool calls found in assistant messages.
Examples
iex> conversation = [
...> Message.assistant("Let me search", tool_calls: [%{id: "call_1", name: "search", arguments: %{}}])
...> ]
iex> Messages.extract_tool_calls(conversation)
[%{id: "call_1", name: "search", arguments: %{}}]
@spec find_by_role([Nous.Message.t()], atom()) :: [Nous.Message.t()]
Find messages by role in a conversation.
Examples
iex> conversation = [Message.system("Be helpful"), Message.user("Hello")]
iex> Messages.find_by_role(conversation, :system)
[%Message{role: :system, content: "Be helpful"}]
@spec from_anthropic_response(map()) :: Nous.Message.t()
Parse Anthropic response into a Message.
Examples
iex> anthropic_response = %{
...> "content" => [%{"type" => "text", "text" => "Hello"}],
...> "model" => "claude-3-sonnet"
...> }
iex> Messages.from_anthropic_response(anthropic_response)
%Message{role: :assistant, content: "Hello"}
@spec from_gemini_response(map()) :: Nous.Message.t()
Parse Gemini response into a Message.
Examples
iex> gemini_response = %{
...> "candidates" => [%{"content" => %{"parts" => [%{"text" => "Hello"}]}}]
...> }
iex> Messages.from_gemini_response(gemini_response)
%Message{role: :assistant, content: "Hello"}
@spec from_openai_response(map()) :: Nous.Message.t()
Parse OpenAI response into a Message.
Examples
iex> openai_response = %{
...> "choices" => [%{"message" => %{"role" => "assistant", "content" => "Hello"}}],
...> "usage" => %{"total_tokens" => 10}
...> }
iex> Messages.from_openai_response(openai_response)
%Message{role: :assistant, content: "Hello"}
@spec from_provider_response(map(), atom()) :: Nous.Message.t()
Parse provider response into a Message.
Dispatches to appropriate provider-specific parser.
Examples
iex> Messages.from_provider_response(openai_response, :openai)
%Message{role: :assistant, content: "Hello"}
@spec last_message([Nous.Message.t()]) :: Nous.Message.t() | nil
Get the last message from a conversation.
Examples
iex> conversation = [Message.user("Hi"), Message.assistant("Hello")]
iex> Messages.last_message(conversation)
%Message{role: :assistant, content: "Hello"}
@spec normalize_format(any()) :: [Nous.Message.t()]
Normalize any message format to internal Message representation.
Attempts to detect format and convert to Message structs.
Examples
iex> Messages.normalize_format([%{"role" => "user", "content" => "Hi"}])
[%Message{role: :user, content: "Hi"}]
@spec to_anthropic_format([Nous.Message.t()]) :: {String.t() | nil, [map()]}
Convert messages to Anthropic format.
Returns {system_prompt, messages} where system prompt is extracted
and combined, and messages are converted to Anthropic format.
Examples
iex> conversation = [Message.system("Be helpful"), Message.user("Hello")]
iex> Messages.to_anthropic_format(conversation)
{"Be helpful", [%{"role" => "user", "content" => "Hello"}]}
@spec to_gemini_format([Nous.Message.t()]) :: {String.t() | nil, [map()]}
Convert messages to Gemini format.
Returns {system_prompt, contents} where system prompt is extracted
and messages are converted to Gemini contents format.
Examples
iex> conversation = [Message.system("Be helpful"), Message.user("Hello")]
iex> Messages.to_gemini_format(conversation)
{"Be helpful", [%{"role" => "user", "parts" => [%{"text" => "Hello"}]}]}
@spec to_openai_format([Nous.Message.t()]) :: [map()]
Convert messages to OpenAI format.
Examples
iex> conversation = [Message.system("Be helpful"), Message.user("Hello")]
iex> Messages.to_openai_format(conversation)
[
%{"role" => "system", "content" => "Be helpful"},
%{"role" => "user", "content" => "Hello"}
]
@spec to_provider_format([Nous.Message.t()], atom()) :: any()
Convert messages to provider-specific format.
Dispatches to the appropriate provider-specific conversion function.
Examples
iex> conversation = [Message.system("Be helpful"), Message.user("Hello")]
iex> Messages.to_provider_format(conversation, :openai)
[%{"role" => "system", "content" => "Be helpful"}, %{"role" => "user", "content" => "Hello"}]
iex> Messages.to_provider_format(conversation, :anthropic)
{"Be helpful", [%{"role" => "user", "content" => "Hello"}]}