gemini.go 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613
  1. package dto
  2. import (
  3. "encoding/json"
  4. "strings"
  5. "github.com/QuantumNous/new-api/common"
  6. "github.com/QuantumNous/new-api/logger"
  7. "github.com/QuantumNous/new-api/types"
  8. "github.com/gin-gonic/gin"
  9. )
  10. type GeminiChatRequest struct {
  11. Requests []GeminiChatRequest `json:"requests,omitempty"` // For batch requests
  12. Contents []GeminiChatContent `json:"contents"`
  13. SafetySettings []GeminiChatSafetySettings `json:"safetySettings,omitempty"`
  14. GenerationConfig GeminiChatGenerationConfig `json:"generationConfig,omitempty"`
  15. Tools json.RawMessage `json:"tools,omitempty"`
  16. ToolConfig *ToolConfig `json:"toolConfig,omitempty"`
  17. SystemInstructions *GeminiChatContent `json:"systemInstruction,omitempty"`
  18. CachedContent string `json:"cachedContent,omitempty"`
  19. }
  20. // UnmarshalJSON allows GeminiChatRequest to accept both snake_case and camelCase fields.
  21. func (r *GeminiChatRequest) UnmarshalJSON(data []byte) error {
  22. type Alias GeminiChatRequest
  23. var aux struct {
  24. Alias
  25. SystemInstructionSnake *GeminiChatContent `json:"system_instruction,omitempty"`
  26. }
  27. if err := common.Unmarshal(data, &aux); err != nil {
  28. return err
  29. }
  30. *r = GeminiChatRequest(aux.Alias)
  31. if aux.SystemInstructionSnake != nil {
  32. r.SystemInstructions = aux.SystemInstructionSnake
  33. }
  34. return nil
  35. }
  36. type ToolConfig struct {
  37. FunctionCallingConfig *FunctionCallingConfig `json:"functionCallingConfig,omitempty"`
  38. RetrievalConfig *RetrievalConfig `json:"retrievalConfig,omitempty"`
  39. }
  40. type FunctionCallingConfig struct {
  41. Mode FunctionCallingConfigMode `json:"mode,omitempty"`
  42. AllowedFunctionNames []string `json:"allowedFunctionNames,omitempty"`
  43. }
  44. type FunctionCallingConfigMode string
  45. type RetrievalConfig struct {
  46. LatLng *LatLng `json:"latLng,omitempty"`
  47. LanguageCode string `json:"languageCode,omitempty"`
  48. }
  49. type LatLng struct {
  50. Latitude *float64 `json:"latitude,omitempty"`
  51. Longitude *float64 `json:"longitude,omitempty"`
  52. }
  53. // createGeminiFileSource 根据数据内容创建正确类型的 FileSource
  54. func createGeminiFileSource(data string, mimeType string) *types.FileSource {
  55. if strings.HasPrefix(data, "http://") || strings.HasPrefix(data, "https://") {
  56. return types.NewURLFileSource(data)
  57. }
  58. return types.NewBase64FileSource(data, mimeType)
  59. }
  60. func (r *GeminiChatRequest) GetTokenCountMeta() *types.TokenCountMeta {
  61. var files []*types.FileMeta = make([]*types.FileMeta, 0)
  62. var maxTokens int
  63. if r.GenerationConfig.MaxOutputTokens != nil && *r.GenerationConfig.MaxOutputTokens > 0 {
  64. maxTokens = int(*r.GenerationConfig.MaxOutputTokens)
  65. }
  66. var inputTexts []string
  67. for _, content := range r.Contents {
  68. for _, part := range content.Parts {
  69. if part.Text != "" {
  70. inputTexts = append(inputTexts, part.Text)
  71. }
  72. if part.InlineData != nil && part.InlineData.Data != "" {
  73. mimeType := part.InlineData.MimeType
  74. source := createGeminiFileSource(part.InlineData.Data, mimeType)
  75. var fileType types.FileType
  76. if strings.HasPrefix(mimeType, "image/") {
  77. fileType = types.FileTypeImage
  78. } else if strings.HasPrefix(mimeType, "audio/") {
  79. fileType = types.FileTypeAudio
  80. } else if strings.HasPrefix(mimeType, "video/") {
  81. fileType = types.FileTypeVideo
  82. } else {
  83. fileType = types.FileTypeFile
  84. }
  85. files = append(files, &types.FileMeta{
  86. FileType: fileType,
  87. Source: source,
  88. MimeType: mimeType,
  89. })
  90. }
  91. }
  92. }
  93. inputText := strings.Join(inputTexts, "\n")
  94. return &types.TokenCountMeta{
  95. CombineText: inputText,
  96. Files: files,
  97. MaxTokens: maxTokens,
  98. }
  99. }
  100. func (r *GeminiChatRequest) IsStream(c *gin.Context) bool {
  101. if c.Query("alt") == "sse" {
  102. return true
  103. }
  104. return false
  105. }
  106. func (r *GeminiChatRequest) SetModelName(modelName string) {
  107. // GeminiChatRequest does not have a model field, so this method does nothing.
  108. }
  109. func (r *GeminiChatRequest) GetTools() []GeminiChatTool {
  110. var tools []GeminiChatTool
  111. if strings.HasPrefix(string(r.Tools), "[") {
  112. // is array
  113. if err := common.Unmarshal(r.Tools, &tools); err != nil {
  114. logger.LogError(nil, "error_unmarshalling_tools: "+err.Error())
  115. return nil
  116. }
  117. } else if strings.HasPrefix(string(r.Tools), "{") {
  118. // is object
  119. singleTool := GeminiChatTool{}
  120. if err := common.Unmarshal(r.Tools, &singleTool); err != nil {
  121. logger.LogError(nil, "error_unmarshalling_single_tool: "+err.Error())
  122. return nil
  123. }
  124. tools = []GeminiChatTool{singleTool}
  125. }
  126. return tools
  127. }
  128. func (r *GeminiChatRequest) SetTools(tools []GeminiChatTool) {
  129. if len(tools) == 0 {
  130. r.Tools = json.RawMessage("[]")
  131. return
  132. }
  133. // Marshal the tools to JSON
  134. data, err := common.Marshal(tools)
  135. if err != nil {
  136. logger.LogError(nil, "error_marshalling_tools: "+err.Error())
  137. return
  138. }
  139. r.Tools = data
  140. }
  141. type GeminiThinkingConfig struct {
  142. IncludeThoughts bool `json:"includeThoughts,omitempty"`
  143. ThinkingBudget *int `json:"thinkingBudget,omitempty"`
  144. // TODO Conflict with thinkingbudget.
  145. ThinkingLevel string `json:"thinkingLevel,omitempty"`
  146. }
  147. // UnmarshalJSON allows GeminiThinkingConfig to accept both snake_case and camelCase fields.
  148. func (c *GeminiThinkingConfig) UnmarshalJSON(data []byte) error {
  149. type Alias GeminiThinkingConfig
  150. var aux struct {
  151. Alias
  152. IncludeThoughtsSnake *bool `json:"include_thoughts,omitempty"`
  153. ThinkingBudgetSnake *int `json:"thinking_budget,omitempty"`
  154. ThinkingLevelSnake string `json:"thinking_level,omitempty"`
  155. }
  156. if err := common.Unmarshal(data, &aux); err != nil {
  157. return err
  158. }
  159. *c = GeminiThinkingConfig(aux.Alias)
  160. if aux.IncludeThoughtsSnake != nil {
  161. c.IncludeThoughts = *aux.IncludeThoughtsSnake
  162. }
  163. if aux.ThinkingBudgetSnake != nil {
  164. c.ThinkingBudget = aux.ThinkingBudgetSnake
  165. }
  166. if aux.ThinkingLevelSnake != "" {
  167. c.ThinkingLevel = aux.ThinkingLevelSnake
  168. }
  169. return nil
  170. }
  171. func (c *GeminiThinkingConfig) SetThinkingBudget(budget int) {
  172. c.ThinkingBudget = &budget
  173. }
  174. type GeminiInlineData struct {
  175. MimeType string `json:"mimeType"`
  176. Data string `json:"data"`
  177. }
  178. // UnmarshalJSON custom unmarshaler for GeminiInlineData to support snake_case and camelCase for MimeType
  179. func (g *GeminiInlineData) UnmarshalJSON(data []byte) error {
  180. type Alias GeminiInlineData // Use type alias to avoid recursion
  181. var aux struct {
  182. Alias
  183. MimeTypeSnake string `json:"mime_type"`
  184. }
  185. if err := common.Unmarshal(data, &aux); err != nil {
  186. return err
  187. }
  188. *g = GeminiInlineData(aux.Alias) // Copy other fields if any in future
  189. // Prioritize snake_case if present
  190. if aux.MimeTypeSnake != "" {
  191. g.MimeType = aux.MimeTypeSnake
  192. } else if aux.MimeType != "" { // Fallback to camelCase from Alias
  193. g.MimeType = aux.MimeType
  194. }
  195. // g.Data would be populated by aux.Alias.Data
  196. return nil
  197. }
  198. type FunctionCall struct {
  199. FunctionName string `json:"name"`
  200. Arguments any `json:"args"`
  201. }
  202. type GeminiFunctionResponse struct {
  203. Name string `json:"name"`
  204. Response map[string]interface{} `json:"response"`
  205. WillContinue json.RawMessage `json:"willContinue,omitempty"`
  206. Scheduling json.RawMessage `json:"scheduling,omitempty"`
  207. Parts json.RawMessage `json:"parts,omitempty"`
  208. ID json.RawMessage `json:"id,omitempty"`
  209. }
  210. type GeminiPartExecutableCode struct {
  211. Language string `json:"language,omitempty"`
  212. Code string `json:"code,omitempty"`
  213. }
  214. type GeminiPartCodeExecutionResult struct {
  215. Outcome string `json:"outcome,omitempty"`
  216. Output string `json:"output,omitempty"`
  217. }
  218. type GeminiFileData struct {
  219. MimeType string `json:"mimeType,omitempty"`
  220. FileUri string `json:"fileUri,omitempty"`
  221. }
  222. type GeminiPart struct {
  223. Text string `json:"text,omitempty"`
  224. Thought bool `json:"thought,omitempty"`
  225. InlineData *GeminiInlineData `json:"inlineData,omitempty"`
  226. FunctionCall *FunctionCall `json:"functionCall,omitempty"`
  227. ThoughtSignature json.RawMessage `json:"thoughtSignature,omitempty"`
  228. FunctionResponse *GeminiFunctionResponse `json:"functionResponse,omitempty"`
  229. // Optional. Media resolution for the input media.
  230. MediaResolution json.RawMessage `json:"mediaResolution,omitempty"`
  231. VideoMetadata json.RawMessage `json:"videoMetadata,omitempty"`
  232. FileData *GeminiFileData `json:"fileData,omitempty"`
  233. ExecutableCode *GeminiPartExecutableCode `json:"executableCode,omitempty"`
  234. CodeExecutionResult *GeminiPartCodeExecutionResult `json:"codeExecutionResult,omitempty"`
  235. }
  236. // UnmarshalJSON custom unmarshaler for GeminiPart to support snake_case and camelCase for InlineData
  237. func (p *GeminiPart) UnmarshalJSON(data []byte) error {
  238. // Alias to avoid recursion during unmarshalling
  239. type Alias GeminiPart
  240. var aux struct {
  241. Alias
  242. InlineDataSnake *GeminiInlineData `json:"inline_data,omitempty"` // snake_case variant
  243. }
  244. if err := common.Unmarshal(data, &aux); err != nil {
  245. return err
  246. }
  247. // Assign fields from alias
  248. *p = GeminiPart(aux.Alias)
  249. // Prioritize snake_case for InlineData if present
  250. if aux.InlineDataSnake != nil {
  251. p.InlineData = aux.InlineDataSnake
  252. } else if aux.InlineData != nil { // Fallback to camelCase from Alias
  253. p.InlineData = aux.InlineData
  254. }
  255. // Other fields like Text, FunctionCall etc. are already populated via aux.Alias
  256. return nil
  257. }
  258. type GeminiChatContent struct {
  259. Role string `json:"role,omitempty"`
  260. Parts []GeminiPart `json:"parts"`
  261. }
  262. type GeminiChatSafetySettings struct {
  263. Category string `json:"category"`
  264. Threshold string `json:"threshold"`
  265. }
  266. type GeminiChatTool struct {
  267. GoogleSearch any `json:"googleSearch,omitempty"`
  268. GoogleSearchRetrieval any `json:"googleSearchRetrieval,omitempty"`
  269. CodeExecution any `json:"codeExecution,omitempty"`
  270. FunctionDeclarations any `json:"functionDeclarations,omitempty"`
  271. URLContext any `json:"urlContext,omitempty"`
  272. }
  273. type GeminiChatGenerationConfig struct {
  274. Temperature *float64 `json:"temperature,omitempty"`
  275. TopP *float64 `json:"topP,omitempty"`
  276. TopK *float64 `json:"topK,omitempty"`
  277. MaxOutputTokens *uint `json:"maxOutputTokens,omitempty"`
  278. CandidateCount *int `json:"candidateCount,omitempty"`
  279. StopSequences []string `json:"stopSequences,omitempty"`
  280. ResponseMimeType string `json:"responseMimeType,omitempty"`
  281. ResponseSchema any `json:"responseSchema,omitempty"`
  282. ResponseJsonSchema json.RawMessage `json:"responseJsonSchema,omitempty"`
  283. PresencePenalty *float32 `json:"presencePenalty,omitempty"`
  284. FrequencyPenalty *float32 `json:"frequencyPenalty,omitempty"`
  285. ResponseLogprobs *bool `json:"responseLogprobs,omitempty"`
  286. Logprobs *int32 `json:"logprobs,omitempty"`
  287. EnableEnhancedCivicAnswers *bool `json:"enableEnhancedCivicAnswers,omitempty"`
  288. MediaResolution MediaResolution `json:"mediaResolution,omitempty"`
  289. Seed *int64 `json:"seed,omitempty"`
  290. ResponseModalities []string `json:"responseModalities,omitempty"`
  291. ThinkingConfig *GeminiThinkingConfig `json:"thinkingConfig,omitempty"`
  292. SpeechConfig json.RawMessage `json:"speechConfig,omitempty"` // RawMessage to allow flexible speech config
  293. ImageConfig json.RawMessage `json:"imageConfig,omitempty"` // RawMessage to allow flexible image config
  294. }
  295. // UnmarshalJSON allows GeminiChatGenerationConfig to accept both snake_case and camelCase fields.
  296. func (c *GeminiChatGenerationConfig) UnmarshalJSON(data []byte) error {
  297. type Alias GeminiChatGenerationConfig
  298. var aux struct {
  299. Alias
  300. TopPSnake *float64 `json:"top_p,omitempty"`
  301. TopKSnake *float64 `json:"top_k,omitempty"`
  302. MaxOutputTokensSnake *uint `json:"max_output_tokens,omitempty"`
  303. CandidateCountSnake *int `json:"candidate_count,omitempty"`
  304. StopSequencesSnake []string `json:"stop_sequences,omitempty"`
  305. ResponseMimeTypeSnake string `json:"response_mime_type,omitempty"`
  306. ResponseSchemaSnake any `json:"response_schema,omitempty"`
  307. ResponseJsonSchemaSnake json.RawMessage `json:"response_json_schema,omitempty"`
  308. PresencePenaltySnake *float32 `json:"presence_penalty,omitempty"`
  309. FrequencyPenaltySnake *float32 `json:"frequency_penalty,omitempty"`
  310. ResponseLogprobsSnake *bool `json:"response_logprobs,omitempty"`
  311. EnableEnhancedCivicAnswersSnake *bool `json:"enable_enhanced_civic_answers,omitempty"`
  312. MediaResolutionSnake MediaResolution `json:"media_resolution,omitempty"`
  313. ResponseModalitiesSnake []string `json:"response_modalities,omitempty"`
  314. ThinkingConfigSnake *GeminiThinkingConfig `json:"thinking_config,omitempty"`
  315. SpeechConfigSnake json.RawMessage `json:"speech_config,omitempty"`
  316. ImageConfigSnake json.RawMessage `json:"image_config,omitempty"`
  317. }
  318. if err := common.Unmarshal(data, &aux); err != nil {
  319. return err
  320. }
  321. *c = GeminiChatGenerationConfig(aux.Alias)
  322. // Prioritize snake_case if present
  323. if aux.TopPSnake != nil {
  324. c.TopP = aux.TopPSnake
  325. }
  326. if aux.TopKSnake != nil {
  327. c.TopK = aux.TopKSnake
  328. }
  329. if aux.MaxOutputTokensSnake != nil {
  330. c.MaxOutputTokens = aux.MaxOutputTokensSnake
  331. }
  332. if aux.CandidateCountSnake != nil {
  333. c.CandidateCount = aux.CandidateCountSnake
  334. }
  335. if len(aux.StopSequencesSnake) > 0 {
  336. c.StopSequences = aux.StopSequencesSnake
  337. }
  338. if aux.ResponseMimeTypeSnake != "" {
  339. c.ResponseMimeType = aux.ResponseMimeTypeSnake
  340. }
  341. if aux.ResponseSchemaSnake != nil {
  342. c.ResponseSchema = aux.ResponseSchemaSnake
  343. }
  344. if len(aux.ResponseJsonSchemaSnake) > 0 {
  345. c.ResponseJsonSchema = aux.ResponseJsonSchemaSnake
  346. }
  347. if aux.PresencePenaltySnake != nil {
  348. c.PresencePenalty = aux.PresencePenaltySnake
  349. }
  350. if aux.FrequencyPenaltySnake != nil {
  351. c.FrequencyPenalty = aux.FrequencyPenaltySnake
  352. }
  353. if aux.ResponseLogprobsSnake != nil {
  354. c.ResponseLogprobs = aux.ResponseLogprobsSnake
  355. }
  356. if aux.EnableEnhancedCivicAnswersSnake != nil {
  357. c.EnableEnhancedCivicAnswers = aux.EnableEnhancedCivicAnswersSnake
  358. }
  359. if aux.MediaResolutionSnake != "" {
  360. c.MediaResolution = aux.MediaResolutionSnake
  361. }
  362. if len(aux.ResponseModalitiesSnake) > 0 {
  363. c.ResponseModalities = aux.ResponseModalitiesSnake
  364. }
  365. if aux.ThinkingConfigSnake != nil {
  366. c.ThinkingConfig = aux.ThinkingConfigSnake
  367. }
  368. if len(aux.SpeechConfigSnake) > 0 {
  369. c.SpeechConfig = aux.SpeechConfigSnake
  370. }
  371. if len(aux.ImageConfigSnake) > 0 {
  372. c.ImageConfig = aux.ImageConfigSnake
  373. }
  374. return nil
  375. }
  376. type MediaResolution string
  377. type GeminiChatCandidate struct {
  378. Content GeminiChatContent `json:"content"`
  379. FinishReason *string `json:"finishReason"`
  380. Index int64 `json:"index"`
  381. SafetyRatings []GeminiChatSafetyRating `json:"safetyRatings"`
  382. }
  383. type GeminiChatSafetyRating struct {
  384. Category string `json:"category"`
  385. Probability string `json:"probability"`
  386. }
  387. type GeminiChatPromptFeedback struct {
  388. SafetyRatings []GeminiChatSafetyRating `json:"safetyRatings"`
  389. BlockReason *string `json:"blockReason,omitempty"`
  390. }
  391. type GeminiChatResponse struct {
  392. Candidates []GeminiChatCandidate `json:"candidates"`
  393. PromptFeedback *GeminiChatPromptFeedback `json:"promptFeedback,omitempty"`
  394. UsageMetadata GeminiUsageMetadata `json:"usageMetadata"`
  395. }
  396. type GeminiUsageMetadata struct {
  397. PromptTokenCount int `json:"promptTokenCount"`
  398. ToolUsePromptTokenCount int `json:"toolUsePromptTokenCount"`
  399. CandidatesTokenCount int `json:"candidatesTokenCount"`
  400. TotalTokenCount int `json:"totalTokenCount"`
  401. ThoughtsTokenCount int `json:"thoughtsTokenCount"`
  402. CachedContentTokenCount int `json:"cachedContentTokenCount"`
  403. PromptTokensDetails []GeminiPromptTokensDetails `json:"promptTokensDetails"`
  404. ToolUsePromptTokensDetails []GeminiPromptTokensDetails `json:"toolUsePromptTokensDetails"`
  405. }
  406. type GeminiPromptTokensDetails struct {
  407. Modality string `json:"modality"`
  408. TokenCount int `json:"tokenCount"`
  409. }
  410. // Imagen related structs
  411. type GeminiImageRequest struct {
  412. Instances []GeminiImageInstance `json:"instances"`
  413. Parameters GeminiImageParameters `json:"parameters"`
  414. }
  415. type GeminiImageInstance struct {
  416. Prompt string `json:"prompt"`
  417. }
  418. type GeminiImageParameters struct {
  419. SampleCount int `json:"sampleCount,omitempty"`
  420. AspectRatio string `json:"aspectRatio,omitempty"`
  421. PersonGeneration string `json:"personGeneration,omitempty"`
  422. ImageSize string `json:"imageSize,omitempty"`
  423. }
  424. type GeminiImageResponse struct {
  425. Predictions []GeminiImagePrediction `json:"predictions"`
  426. }
  427. type GeminiImagePrediction struct {
  428. MimeType string `json:"mimeType"`
  429. BytesBase64Encoded string `json:"bytesBase64Encoded"`
  430. RaiFilteredReason string `json:"raiFilteredReason,omitempty"`
  431. SafetyAttributes any `json:"safetyAttributes,omitempty"`
  432. }
  433. // Embedding related structs
  434. type GeminiEmbeddingRequest struct {
  435. Model string `json:"model,omitempty"`
  436. Content GeminiChatContent `json:"content"`
  437. TaskType string `json:"taskType,omitempty"`
  438. Title string `json:"title,omitempty"`
  439. OutputDimensionality int `json:"outputDimensionality,omitempty"`
  440. }
  441. func (r *GeminiEmbeddingRequest) IsStream(c *gin.Context) bool {
  442. // Gemini embedding requests are not streamed
  443. return false
  444. }
  445. func (r *GeminiEmbeddingRequest) GetTokenCountMeta() *types.TokenCountMeta {
  446. var inputTexts []string
  447. for _, part := range r.Content.Parts {
  448. if part.Text != "" {
  449. inputTexts = append(inputTexts, part.Text)
  450. }
  451. }
  452. inputText := strings.Join(inputTexts, "\n")
  453. return &types.TokenCountMeta{
  454. CombineText: inputText,
  455. }
  456. }
  457. func (r *GeminiEmbeddingRequest) SetModelName(modelName string) {
  458. if modelName != "" {
  459. r.Model = modelName
  460. }
  461. }
  462. type GeminiBatchEmbeddingRequest struct {
  463. Requests []*GeminiEmbeddingRequest `json:"requests"`
  464. }
  465. func (r *GeminiBatchEmbeddingRequest) IsStream(c *gin.Context) bool {
  466. // Gemini batch embedding requests are not streamed
  467. return false
  468. }
  469. func (r *GeminiBatchEmbeddingRequest) GetTokenCountMeta() *types.TokenCountMeta {
  470. var inputTexts []string
  471. for _, request := range r.Requests {
  472. meta := request.GetTokenCountMeta()
  473. if meta != nil && meta.CombineText != "" {
  474. inputTexts = append(inputTexts, meta.CombineText)
  475. }
  476. }
  477. inputText := strings.Join(inputTexts, "\n")
  478. return &types.TokenCountMeta{
  479. CombineText: inputText,
  480. }
  481. }
  482. func (r *GeminiBatchEmbeddingRequest) SetModelName(modelName string) {
  483. if modelName != "" {
  484. for _, req := range r.Requests {
  485. req.SetModelName(modelName)
  486. }
  487. }
  488. }
  489. type GeminiEmbeddingResponse struct {
  490. Embedding ContentEmbedding `json:"embedding"`
  491. }
  492. type GeminiBatchEmbeddingResponse struct {
  493. Embeddings []*ContentEmbedding `json:"embeddings"`
  494. }
  495. type ContentEmbedding struct {
  496. Values []float64 `json:"values"`
  497. }
  498. // File API related structs
  499. type GeminiFileUploadResponse struct {
  500. File GeminiFile `json:"file"`
  501. }
  502. type GeminiFile struct {
  503. Name string `json:"name"`
  504. DisplayName string `json:"displayName,omitempty"`
  505. MimeType string `json:"mimeType"`
  506. SizeBytes string `json:"sizeBytes"`
  507. CreateTime string `json:"createTime"`
  508. UpdateTime string `json:"updateTime"`
  509. ExpirationTime string `json:"expirationTime,omitempty"`
  510. Sha256Hash string `json:"sha256Hash,omitempty"`
  511. Uri string `json:"uri"`
  512. State string `json:"state"`
  513. Error *GeminiFileError `json:"error,omitempty"`
  514. VideoMetadata *GeminiVideoMeta `json:"videoMetadata,omitempty"`
  515. }
  516. type GeminiVideoMeta struct {
  517. VideoDuration string `json:"videoDuration,omitempty"`
  518. }
  519. type GeminiFileListResponse struct {
  520. Files []GeminiFile `json:"files"`
  521. NextPageToken string `json:"nextPageToken,omitempty"`
  522. }
  523. type GeminiFileError struct {
  524. Code int `json:"code"`
  525. Message string `json:"message"`
  526. Status string `json:"status"`
  527. }