191 lines
7.2 KiB
Python
191 lines
7.2 KiB
Python
# Copyright (c) Microsoft. All rights reserved.
|
|
from enum import Enum
|
|
|
|
from semantic_kernel.contents import AuthorRole, ChatHistory, ImageContent, TextContent
|
|
from semantic_kernel.contents.audio_content import AudioContent
|
|
from semantic_kernel.exceptions import ServiceException, ServiceInvalidRequestError
|
|
|
|
|
|
class ONNXTemplate(str, Enum):
|
|
"""ONNXTemplate is an enumeration that represents different ONNX model templates.
|
|
|
|
Attributes:
|
|
PHI3 (str): Represents the "phi3" ONNX model template.
|
|
PHI3V (str): Represents the "phi3v" ONNX model template.
|
|
GEMMA (str): Represents the "gemma" ONNX model template.
|
|
LLAMA (str): Represents the "llama" ONNX model template.
|
|
NONE (str): Can be chosen if no Template should be used.
|
|
|
|
"""
|
|
|
|
PHI3 = "phi3"
|
|
PHI3V = "phi3v"
|
|
PHI4 = "phi4"
|
|
PHI4MM = "phi4mm"
|
|
GEMMA = "gemma"
|
|
LLAMA = "llama"
|
|
NONE = "none"
|
|
|
|
|
|
def apply_template(history: ChatHistory, template: ONNXTemplate) -> str:
|
|
"""Apply the specified ONNX template to the given chat history.
|
|
|
|
Args:
|
|
history (ChatHistory): The chat history to which the template will be applied.
|
|
template (ONNXTemplate): The ONNX template to apply.
|
|
|
|
Returns:
|
|
str: The result of applying the template to the chat history.
|
|
|
|
Raises:
|
|
ServiceException: If an error occurs while applying the template.
|
|
"""
|
|
template_functions = {
|
|
ONNXTemplate.PHI3: phi3_template,
|
|
ONNXTemplate.PHI4: phi4_template,
|
|
ONNXTemplate.GEMMA: gemma_template,
|
|
ONNXTemplate.LLAMA: llama_template,
|
|
ONNXTemplate.PHI3V: phi3v_template,
|
|
ONNXTemplate.PHI4MM: phi4mm_template,
|
|
ONNXTemplate.NONE: lambda text: text,
|
|
}
|
|
|
|
try:
|
|
return template_functions[template](history)
|
|
except Exception as e:
|
|
raise ServiceException(f"An error occurred while applying the template: {template.value}") from e
|
|
|
|
|
|
def phi3_template(history: ChatHistory) -> str:
|
|
"""Generates a formatted string from the chat history for use with the phi3 model.
|
|
|
|
Args:
|
|
history (ChatHistory): An object containing the chat history with a list of messages.
|
|
|
|
Returns:
|
|
str: A formatted string where each message is prefixed with the role and suffixed with an end marker.
|
|
"""
|
|
phi3_input = ""
|
|
for message in history.messages:
|
|
phi3_input += f"<|{message.role.value}|>\n{message.content}<|end|>\n"
|
|
phi3_input += "<|assistant|>\n"
|
|
return phi3_input
|
|
|
|
|
|
def phi4_template(history: ChatHistory) -> str:
|
|
"""Generates a formatted string from the chat history for use with the phi4 model.
|
|
|
|
Args:
|
|
history (ChatHistory): An object containing the chat history with a list of messages.
|
|
|
|
Returns:
|
|
str: A formatted string where each message is prefixed with the role and suffixed with an end marker.
|
|
"""
|
|
phi4_input = ""
|
|
for message in history.messages:
|
|
phi4_input += f"<|{message.role.value}|>\n{message.content}<|end|>\n"
|
|
phi4_input += "<|assistant|>\n"
|
|
return phi4_input
|
|
|
|
|
|
def phi3v_template(history: ChatHistory) -> str:
|
|
"""Generates a formatted string from a given chat history for use with the phi3v model.
|
|
|
|
Args:
|
|
history (ChatHistory): An object containing the chat history with messages.
|
|
|
|
Returns:
|
|
str: A formatted string representing the chat history, with special tokens indicating
|
|
the role of each message (system, user, assistant) and the type of content (text, image).
|
|
"""
|
|
phi3v_input = ""
|
|
image_count = 0
|
|
for message in history.messages:
|
|
if message.role == AuthorRole.SYSTEM:
|
|
phi3v_input += f"<|system|>\n{message.content}<|end|>\n"
|
|
if message.role == AuthorRole.USER:
|
|
for item in message.items:
|
|
if isinstance(item, TextContent):
|
|
phi3v_input += f"<|user|>\n{item.text}<|end|>\n"
|
|
if isinstance(item, ImageContent):
|
|
phi3v_input += f"<|image_{image_count + 1}|>\n"
|
|
image_count += 1
|
|
if message.role == AuthorRole.ASSISTANT:
|
|
phi3v_input += f"<|assistant|>\n{message.content}<|end|>\n"
|
|
phi3v_input += "<|assistant|>\n"
|
|
return phi3v_input
|
|
|
|
|
|
def phi4mm_template(history: ChatHistory) -> str:
|
|
"""Generates a formatted string from a given chat history for use with the phi4mm model.
|
|
|
|
Args:
|
|
history (ChatHistory): An object containing the chat history with messages.
|
|
|
|
Returns:
|
|
str: A formatted string representing the chat history, with special tokens indicating
|
|
the role of each message (system, user, assistant) and the type of content (text, image).
|
|
"""
|
|
phi4mm_input = ""
|
|
image_count = 0
|
|
audio_count = 0
|
|
for message in history.messages:
|
|
if message.role == AuthorRole.SYSTEM:
|
|
phi4mm_input += f"<|system|>\n{message.content}<|end|>\n"
|
|
if message.role == AuthorRole.USER:
|
|
for item in message.items:
|
|
if isinstance(item, TextContent):
|
|
phi4mm_input += f"<|user|>\n{item.text}<|end|>\n"
|
|
# Currently only one image is supported in Onnx
|
|
if isinstance(item, ImageContent):
|
|
phi4mm_input += f"<|image_{image_count + 1}|>\n"
|
|
image_count += 1
|
|
if isinstance(item, AudioContent):
|
|
phi4mm_input += f"<|audio_{audio_count + 1}|>\n"
|
|
audio_count += 1
|
|
if message.role == AuthorRole.ASSISTANT:
|
|
phi4mm_input += f"<|assistant|>\n{message.content}<|end|>\n"
|
|
phi4mm_input += "<|assistant|>\n"
|
|
return phi4mm_input
|
|
|
|
|
|
def gemma_template(history: ChatHistory) -> str:
|
|
"""Generates a formatted string for the Gemma model based on the provided chat history.
|
|
|
|
Args:
|
|
history (ChatHistory): An object containing the chat history with messages.
|
|
|
|
Returns:
|
|
str: A formatted string representing the chat history for the Gemma model.
|
|
|
|
Raises:
|
|
ServiceInvalidRequestError: If a system message is encountered in the chat history.
|
|
"""
|
|
gemma_input = "<bos>"
|
|
for message in history.messages:
|
|
if message.role == AuthorRole.SYSTEM:
|
|
raise ServiceInvalidRequestError("System messages are not supported in Gemma")
|
|
if message.role == AuthorRole.USER:
|
|
gemma_input += f"<start_of_turn>user\n{message.content}<end_of_turn>\n"
|
|
if message.role == AuthorRole.ASSISTANT:
|
|
gemma_input += f"<start_of_turn>model\n{message.content}<end_of_turn>\n"
|
|
gemma_input += "<start_of_turn>model\n"
|
|
return gemma_input
|
|
|
|
|
|
def llama_template(history: ChatHistory) -> str:
|
|
"""Generates a formatted string from a given chat history for use with the LLaMA model.
|
|
|
|
Args:
|
|
history (ChatHistory): An object containing the chat history, which includes a list of messages.
|
|
|
|
Returns:
|
|
str: A formatted string where each message is wrapped with specific header and end tags,
|
|
and the final string ends with an assistant header tag.
|
|
"""
|
|
llama_input = ""
|
|
for message in history.messages:
|
|
llama_input += f"<|start_header_id|>{message.role.value}<|end_header_id|>\n\n{message.content}<|eot_id|>"
|
|
llama_input += "<|start_header_id|>assistant<|end_header_id|>"
|
|
return llama_input
|