Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Update completion API Message type #146

Open
1 task done
cvauclair opened this issue Dec 9, 2024 · 1 comment
Open
1 task done

feat: Update completion API Message type #146

cvauclair opened this issue Dec 9, 2024 · 1 comment
Assignees
Milestone

Comments

@cvauclair
Copy link
Contributor

cvauclair commented Dec 9, 2024

  • I have looked for existing issues (including closed) about this

Feature Request

Update the completion::Message type to reflect new features in popular model providers.

Note: this would solve #121 and offer limited multimodal support in the case where text completion models accept images as input.

Motivation

Many popular completion model providers have expanded their APIs to support different types of message. For instance, OpenAI now supports the tool message type and has added the ability to upload images using the user message type. Anthropic also supports uploading images using the user message type.

Supporting these advanced features would make Rig a lot more flexible.

Here is a (non-exhaustive) list of providers and the message types we currently do not support:

  • OpenAI: tool messages, tool_calls in assistant messages and images in user messages
  • Anthropic: images in user messages and ToolResult as a message content type
  • Cohere: tool message and tool_calls in assistant messages

Proposal

  1. Refactor the completion::Message type such that is more complete, e.g. using an enum:

    pub enum Message {
        UserMessage(...),
        AssistantMessage(...),
        SystemMessage(...),
        ToolMessage(...),
    }

    Note: Make sure that the new Message type covers all possible types across all providers.

  2. Update the provider client implementations to covert the new Message type to their own completion model.

    Important: It is important to handle the case where the provider does not support a given message type (e.g.: Anthropic does not support the tool message type). There are two options to handle those cases: 1) return an error; 2) convert them to another type that makes sense (e.g.: converting the ToolMessage to a user type message for Anthropic). Not all types can be converted though. For instance, if a provider does not support an image user message, then the client should return an error.

Alternatives

An alternative could be to add an additional_params field to the existing Message type allowing users to provide additional parameters on a per-provider basis, similar to how additional_params is available on CompletionRequest.

@alkeryn
Copy link

alkeryn commented Dec 14, 2024

i'm not using rig as i'm using my own llm library because i need something custom built.
i was curious about it though.

however, i think it's better to have the message content with a Role enum that has a Custom(String) field in case you want a custom role.

this way you can also impl Display for role to pretty print it, but you could add your own function to it ie as_openai where it'd format it to chat completion role etc...

my message struct looks something like that

#[derive(Debug, Clone)]
pub struct Message {
    pub role: Role,
    pub message: String
}

role code looks this way

#[derive(Clone, Debug)]
pub enum Role {
    User,
    Assistant,
    System,
    Root
}

impl std::fmt::Display for Role {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            Role::User => write!(f, "User"),
            Role::Assistant => write!(f, "LLM"),
            Role::System => write!(f, "SYSTEM:"),
            Role::Root => write!(f, "Root:")
        }
    }
}

impl Role {
    pub fn as_openai(&self) -> String {
        match self {
            Role::User => "user".into(),
            Role::Assistant => "assistant".into(),
            Role::System => "system".into(),
            Role::Root => "root".into()
        }
    }
}

i didn't need the Custom field, but i may add one later and one for context too !

this way you can also implement display and as_openai for Message or Vec.

@cvauclair cvauclair modified the milestones: v0.6, v0.7 Dec 19, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

When branches are created from issues, their pull requests are automatically linked.

3 participants