Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions flowllm/core/enumeration/__init__.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
"""Core enumeration module."""

from .chunk_enum import ChunkEnum
from .content_block_type import ContentBlockType
from .http_enum import HttpEnum
from .registry_enum import RegistryEnum
from .role import Role

__all__ = [
"ChunkEnum",
"ContentBlockType",
"HttpEnum",
"RegistryEnum",
"Role",
Expand Down
12 changes: 12 additions & 0 deletions flowllm/core/enumeration/content_block_type.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
"""Content block type enumeration for multimodal content."""

from enum import Enum


class ContentBlockType(str, Enum):
"""Enumeration of content block types in multimodal responses."""

TEXT = "text"
IMAGE_URL = "image_url"
AUDIO = "audio"
VIDEO = "video"
6 changes: 4 additions & 2 deletions flowllm/core/llm/lite_llm.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,8 @@ def stream_chat(
**self.kwargs,
**kwargs,
}
logger.info(f"LiteLLM.stream_chat: {chat_kwargs}")
log_kwargs = {k: v for k, v in chat_kwargs.items() if k != "messages"}
logger.info(f"LiteLLM.stream_chat: {log_kwargs}")

for i in range(self.max_retries):
try:
Expand Down Expand Up @@ -216,7 +217,8 @@ async def astream_chat(
**self.kwargs,
**kwargs,
}
logger.info(f"LiteLLM.astream_chat: {chat_kwargs}")
log_kwargs = {k: v for k, v in chat_kwargs.items() if k != "messages"}
logger.info(f"LiteLLM.astream_chat: {log_kwargs}")

for i in range(self.max_retries):
try:
Expand Down
6 changes: 4 additions & 2 deletions flowllm/core/llm/openai_compatible_llm.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,8 @@ def stream_chat(
**self.kwargs,
**kwargs,
}
logger.info(f"OpenAICompatibleLLM.stream_chat: {chat_kwargs}")
log_kwargs = {k: v for k, v in chat_kwargs.items() if k != "messages"}
logger.info(f"OpenAICompatibleLLM.stream_chat: {log_kwargs}")

for i in range(self.max_retries):
try:
Expand Down Expand Up @@ -207,7 +208,8 @@ async def astream_chat(
**self.kwargs,
**kwargs,
}
logger.info(f"OpenAICompatibleLLM.astream_chat: {chat_kwargs}")
log_kwargs = {k: v for k, v in chat_kwargs.items() if k != "messages"}
logger.info(f"OpenAICompatibleLLM.astream_chat: {log_kwargs}")

for i in range(self.max_retries):
try:
Expand Down
11 changes: 6 additions & 5 deletions flowllm/core/schema/message.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from pydantic import BaseModel, ConfigDict, Field, model_validator

from .tool_call import ToolCall
from ..enumeration import Role
from ..enumeration import Role, ContentBlockType


class ContentBlock(BaseModel):
Expand Down Expand Up @@ -35,7 +35,7 @@ class ContentBlock(BaseModel):

model_config = ConfigDict(extra="allow")

type: str = Field(default="")
type: ContentBlockType = Field(default="")
content: str | dict | list = Field(default="")

@model_validator(mode="before")
Expand All @@ -44,14 +44,15 @@ def init_block(cls, data: dict):
"""Initialize content block by extracting content based on type field."""
result = data.copy()
content_type = data.get("type", "")
result["content"] = data[content_type]
if content_type and content_type in data:
result["content"] = data[content_type]
return result

def simple_dump(self) -> dict:
"""Convert ContentBlock to a simple dictionary format."""
result = {
"type": self.type,
self.type: self.content,
"type": self.type.value,
self.type.value: self.content,
**self.model_extra,
}

Expand Down
4 changes: 2 additions & 2 deletions tests/test_vision_audio.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ def encode_image(image_path):
return base64.b64encode(image_file.read()).decode("utf-8")

# 将xxxx/eagle.png替换为你本地图像的绝对路径
base64_image = encode_image("/Users/yuli/workspace/ReMe/20251128144329.jpg")
base64_image = encode_image("/Users/yuli/Documents/20251128144329.jpg")

llm = OpenAICompatibleLLM(model_name="qwen3-vl-plus")
messages = [
Expand Down Expand Up @@ -50,7 +50,7 @@ def encode_audio(audio_path):
return base64.b64encode(audio_file.read()).decode("utf-8")

# 请将 ABSOLUTE_PATH/welcome.mp3 替换为本地音频的绝对路径
audio_file_path = "/Users/yuli/workspace/ReMe/recordings/111.wav"
audio_file_path = "/Users/yuli/Documents/111.wav"
base64_audio = encode_audio(audio_file_path)

messages = [
Expand Down