feat(file): unify file handling with a new FileSource abstraction for URL and base64 data

This commit is contained in:
CaIon
2026-02-04 17:15:24 +08:00
parent 36d3ae1c94
commit 9ef9e78821
28 changed files with 1119 additions and 357 deletions
+16 -2
View File
@@ -214,6 +214,14 @@ type ClaudeRequest struct {
ServiceTier string `json:"service_tier,omitempty"`
}
// createClaudeFileSource 根据数据内容创建正确类型的 FileSource
func createClaudeFileSource(data string) *types.FileSource {
if strings.HasPrefix(data, "http://") || strings.HasPrefix(data, "https://") {
return types.NewURLFileSource(data)
}
return types.NewBase64FileSource(data, "")
}
func (c *ClaudeRequest) GetTokenCountMeta() *types.TokenCountMeta {
var tokenCountMeta = types.TokenCountMeta{
TokenType: types.TokenTypeTokenizer,
@@ -243,7 +251,10 @@ func (c *ClaudeRequest) GetTokenCountMeta() *types.TokenCountMeta {
data = common.Interface2String(media.Source.Data)
}
if data != "" {
fileMeta = append(fileMeta, &types.FileMeta{FileType: types.FileTypeImage, OriginData: data})
fileMeta = append(fileMeta, &types.FileMeta{
FileType: types.FileTypeImage,
Source: createClaudeFileSource(data),
})
}
}
}
@@ -275,7 +286,10 @@ func (c *ClaudeRequest) GetTokenCountMeta() *types.TokenCountMeta {
data = common.Interface2String(media.Source.Data)
}
if data != "" {
fileMeta = append(fileMeta, &types.FileMeta{FileType: types.FileTypeImage, OriginData: data})
fileMeta = append(fileMeta, &types.FileMeta{
FileType: types.FileTypeImage,
Source: createClaudeFileSource(data),
})
}
}
case "tool_use":
+23 -19
View File
@@ -64,6 +64,14 @@ type LatLng struct {
Longitude *float64 `json:"longitude,omitempty"`
}
// createGeminiFileSource 根据数据内容创建正确类型的 FileSource
func createGeminiFileSource(data string, mimeType string) *types.FileSource {
if strings.HasPrefix(data, "http://") || strings.HasPrefix(data, "https://") {
return types.NewURLFileSource(data)
}
return types.NewBase64FileSource(data, mimeType)
}
func (r *GeminiChatRequest) GetTokenCountMeta() *types.TokenCountMeta {
var files []*types.FileMeta = make([]*types.FileMeta, 0)
@@ -80,27 +88,23 @@ func (r *GeminiChatRequest) GetTokenCountMeta() *types.TokenCountMeta {
inputTexts = append(inputTexts, part.Text)
}
if part.InlineData != nil && part.InlineData.Data != "" {
if strings.HasPrefix(part.InlineData.MimeType, "image/") {
files = append(files, &types.FileMeta{
FileType: types.FileTypeImage,
OriginData: part.InlineData.Data,
})
} else if strings.HasPrefix(part.InlineData.MimeType, "audio/") {
files = append(files, &types.FileMeta{
FileType: types.FileTypeAudio,
OriginData: part.InlineData.Data,
})
} else if strings.HasPrefix(part.InlineData.MimeType, "video/") {
files = append(files, &types.FileMeta{
FileType: types.FileTypeVideo,
OriginData: part.InlineData.Data,
})
mimeType := part.InlineData.MimeType
source := createGeminiFileSource(part.InlineData.Data, mimeType)
var fileType types.FileType
if strings.HasPrefix(mimeType, "image/") {
fileType = types.FileTypeImage
} else if strings.HasPrefix(mimeType, "audio/") {
fileType = types.FileTypeAudio
} else if strings.HasPrefix(mimeType, "video/") {
fileType = types.FileTypeVideo
} else {
files = append(files, &types.FileMeta{
FileType: types.FileTypeFile,
OriginData: part.InlineData.Data,
})
fileType = types.FileTypeFile
}
files = append(files, &types.FileMeta{
FileType: fileType,
Source: source,
MimeType: mimeType,
})
}
}
}
+34 -28
View File
@@ -101,6 +101,14 @@ type GeneralOpenAIRequest struct {
SearchMode string `json:"search_mode,omitempty"`
}
// createFileSource 根据数据内容创建正确类型的 FileSource
func createFileSource(data string) *types.FileSource {
if strings.HasPrefix(data, "http://") || strings.HasPrefix(data, "https://") {
return types.NewURLFileSource(data)
}
return types.NewBase64FileSource(data, "")
}
func (r *GeneralOpenAIRequest) GetTokenCountMeta() *types.TokenCountMeta {
var tokenCountMeta types.TokenCountMeta
var texts = make([]string, 0)
@@ -144,42 +152,40 @@ func (r *GeneralOpenAIRequest) GetTokenCountMeta() *types.TokenCountMeta {
for _, m := range arrayContent {
if m.Type == ContentTypeImageURL {
imageUrl := m.GetImageMedia()
if imageUrl != nil {
if imageUrl.Url != "" {
meta := &types.FileMeta{
FileType: types.FileTypeImage,
}
meta.OriginData = imageUrl.Url
meta.Detail = imageUrl.Detail
fileMeta = append(fileMeta, meta)
}
if imageUrl != nil && imageUrl.Url != "" {
source := createFileSource(imageUrl.Url)
fileMeta = append(fileMeta, &types.FileMeta{
FileType: types.FileTypeImage,
Source: source,
Detail: imageUrl.Detail,
})
}
} else if m.Type == ContentTypeInputAudio {
inputAudio := m.GetInputAudio()
if inputAudio != nil {
meta := &types.FileMeta{
if inputAudio != nil && inputAudio.Data != "" {
source := createFileSource(inputAudio.Data)
fileMeta = append(fileMeta, &types.FileMeta{
FileType: types.FileTypeAudio,
}
meta.OriginData = inputAudio.Data
fileMeta = append(fileMeta, meta)
Source: source,
})
}
} else if m.Type == ContentTypeFile {
file := m.GetFile()
if file != nil {
meta := &types.FileMeta{
if file != nil && file.FileData != "" {
source := createFileSource(file.FileData)
fileMeta = append(fileMeta, &types.FileMeta{
FileType: types.FileTypeFile,
}
meta.OriginData = file.FileData
fileMeta = append(fileMeta, meta)
Source: source,
})
}
} else if m.Type == ContentTypeVideoUrl {
videoUrl := m.GetVideoUrl()
if videoUrl != nil && videoUrl.Url != "" {
meta := &types.FileMeta{
source := createFileSource(videoUrl.Url)
fileMeta = append(fileMeta, &types.FileMeta{
FileType: types.FileTypeVideo,
}
meta.OriginData = videoUrl.Url
fileMeta = append(fileMeta, meta)
Source: source,
})
}
} else {
texts = append(texts, m.Text)
@@ -833,16 +839,16 @@ func (r *OpenAIResponsesRequest) GetTokenCountMeta() *types.TokenCountMeta {
if input.Type == "input_image" {
if input.ImageUrl != "" {
fileMeta = append(fileMeta, &types.FileMeta{
FileType: types.FileTypeImage,
OriginData: input.ImageUrl,
Detail: input.Detail,
FileType: types.FileTypeImage,
Source: createFileSource(input.ImageUrl),
Detail: input.Detail,
})
}
} else if input.Type == "input_file" {
if input.FileUrl != "" {
fileMeta = append(fileMeta, &types.FileMeta{
FileType: types.FileTypeFile,
OriginData: input.FileUrl,
FileType: types.FileTypeFile,
Source: createFileSource(input.FileUrl),
})
}
} else {