gemini.go 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. package dto
  2. import (
  3. "encoding/json"
  4. "one-api/common"
  5. "strings"
  6. )
  7. type GeminiChatRequest struct {
  8. Contents []GeminiChatContent `json:"contents"`
  9. SafetySettings []GeminiChatSafetySettings `json:"safetySettings,omitempty"`
  10. GenerationConfig GeminiChatGenerationConfig `json:"generationConfig,omitempty"`
  11. Tools json.RawMessage `json:"tools,omitempty"`
  12. SystemInstructions *GeminiChatContent `json:"systemInstruction,omitempty"`
  13. }
  14. func (r *GeminiChatRequest) GetTools() []GeminiChatTool {
  15. var tools []GeminiChatTool
  16. if strings.HasSuffix(string(r.Tools), "[") {
  17. // is array
  18. if err := common.Unmarshal(r.Tools, &tools); err != nil {
  19. common.LogError(nil, "error_unmarshalling_tools: "+err.Error())
  20. return nil
  21. }
  22. } else if strings.HasPrefix(string(r.Tools), "{") {
  23. // is object
  24. singleTool := GeminiChatTool{}
  25. if err := common.Unmarshal(r.Tools, &singleTool); err != nil {
  26. common.LogError(nil, "error_unmarshalling_single_tool: "+err.Error())
  27. return nil
  28. }
  29. tools = []GeminiChatTool{singleTool}
  30. }
  31. return tools
  32. }
  33. func (r *GeminiChatRequest) SetTools(tools []GeminiChatTool) {
  34. if len(tools) == 0 {
  35. r.Tools = json.RawMessage("[]")
  36. return
  37. }
  38. // Marshal the tools to JSON
  39. data, err := common.Marshal(tools)
  40. if err != nil {
  41. common.LogError(nil, "error_marshalling_tools: "+err.Error())
  42. return
  43. }
  44. r.Tools = data
  45. }
  46. type GeminiThinkingConfig struct {
  47. IncludeThoughts bool `json:"includeThoughts,omitempty"`
  48. ThinkingBudget *int `json:"thinkingBudget,omitempty"`
  49. }
  50. func (c *GeminiThinkingConfig) SetThinkingBudget(budget int) {
  51. c.ThinkingBudget = &budget
  52. }
  53. type GeminiInlineData struct {
  54. MimeType string `json:"mimeType"`
  55. Data string `json:"data"`
  56. }
  57. // UnmarshalJSON custom unmarshaler for GeminiInlineData to support snake_case and camelCase for MimeType
  58. func (g *GeminiInlineData) UnmarshalJSON(data []byte) error {
  59. type Alias GeminiInlineData // Use type alias to avoid recursion
  60. var aux struct {
  61. Alias
  62. MimeTypeSnake string `json:"mime_type"`
  63. }
  64. if err := common.Unmarshal(data, &aux); err != nil {
  65. return err
  66. }
  67. *g = GeminiInlineData(aux.Alias) // Copy other fields if any in future
  68. // Prioritize snake_case if present
  69. if aux.MimeTypeSnake != "" {
  70. g.MimeType = aux.MimeTypeSnake
  71. } else if aux.MimeType != "" { // Fallback to camelCase from Alias
  72. g.MimeType = aux.MimeType
  73. }
  74. // g.Data would be populated by aux.Alias.Data
  75. return nil
  76. }
  77. type FunctionCall struct {
  78. FunctionName string `json:"name"`
  79. Arguments any `json:"args"`
  80. }
  81. type GeminiFunctionResponse struct {
  82. Name string `json:"name"`
  83. Response map[string]interface{} `json:"response"`
  84. }
  85. type GeminiPartExecutableCode struct {
  86. Language string `json:"language,omitempty"`
  87. Code string `json:"code,omitempty"`
  88. }
  89. type GeminiPartCodeExecutionResult struct {
  90. Outcome string `json:"outcome,omitempty"`
  91. Output string `json:"output,omitempty"`
  92. }
  93. type GeminiFileData struct {
  94. MimeType string `json:"mimeType,omitempty"`
  95. FileUri string `json:"fileUri,omitempty"`
  96. }
  97. type GeminiPart struct {
  98. Text string `json:"text,omitempty"`
  99. Thought bool `json:"thought,omitempty"`
  100. InlineData *GeminiInlineData `json:"inlineData,omitempty"`
  101. FunctionCall *FunctionCall `json:"functionCall,omitempty"`
  102. FunctionResponse *GeminiFunctionResponse `json:"functionResponse,omitempty"`
  103. FileData *GeminiFileData `json:"fileData,omitempty"`
  104. ExecutableCode *GeminiPartExecutableCode `json:"executableCode,omitempty"`
  105. CodeExecutionResult *GeminiPartCodeExecutionResult `json:"codeExecutionResult,omitempty"`
  106. }
  107. // UnmarshalJSON custom unmarshaler for GeminiPart to support snake_case and camelCase for InlineData
  108. func (p *GeminiPart) UnmarshalJSON(data []byte) error {
  109. // Alias to avoid recursion during unmarshalling
  110. type Alias GeminiPart
  111. var aux struct {
  112. Alias
  113. InlineDataSnake *GeminiInlineData `json:"inline_data,omitempty"` // snake_case variant
  114. }
  115. if err := common.Unmarshal(data, &aux); err != nil {
  116. return err
  117. }
  118. // Assign fields from alias
  119. *p = GeminiPart(aux.Alias)
  120. // Prioritize snake_case for InlineData if present
  121. if aux.InlineDataSnake != nil {
  122. p.InlineData = aux.InlineDataSnake
  123. } else if aux.InlineData != nil { // Fallback to camelCase from Alias
  124. p.InlineData = aux.InlineData
  125. }
  126. // Other fields like Text, FunctionCall etc. are already populated via aux.Alias
  127. return nil
  128. }
  129. type GeminiChatContent struct {
  130. Role string `json:"role,omitempty"`
  131. Parts []GeminiPart `json:"parts"`
  132. }
  133. type GeminiChatSafetySettings struct {
  134. Category string `json:"category"`
  135. Threshold string `json:"threshold"`
  136. }
  137. type GeminiChatTool struct {
  138. GoogleSearch any `json:"googleSearch,omitempty"`
  139. GoogleSearchRetrieval any `json:"googleSearchRetrieval,omitempty"`
  140. CodeExecution any `json:"codeExecution,omitempty"`
  141. FunctionDeclarations any `json:"functionDeclarations,omitempty"`
  142. }
  143. type GeminiChatGenerationConfig struct {
  144. Temperature *float64 `json:"temperature,omitempty"`
  145. TopP float64 `json:"topP,omitempty"`
  146. TopK float64 `json:"topK,omitempty"`
  147. MaxOutputTokens uint `json:"maxOutputTokens,omitempty"`
  148. CandidateCount int `json:"candidateCount,omitempty"`
  149. StopSequences []string `json:"stopSequences,omitempty"`
  150. ResponseMimeType string `json:"responseMimeType,omitempty"`
  151. ResponseSchema any `json:"responseSchema,omitempty"`
  152. Seed int64 `json:"seed,omitempty"`
  153. ResponseModalities []string `json:"responseModalities,omitempty"`
  154. ThinkingConfig *GeminiThinkingConfig `json:"thinkingConfig,omitempty"`
  155. SpeechConfig json.RawMessage `json:"speechConfig,omitempty"` // RawMessage to allow flexible speech config
  156. }
  157. type GeminiChatCandidate struct {
  158. Content GeminiChatContent `json:"content"`
  159. FinishReason *string `json:"finishReason"`
  160. Index int64 `json:"index"`
  161. SafetyRatings []GeminiChatSafetyRating `json:"safetyRatings"`
  162. }
  163. type GeminiChatSafetyRating struct {
  164. Category string `json:"category"`
  165. Probability string `json:"probability"`
  166. }
  167. type GeminiChatPromptFeedback struct {
  168. SafetyRatings []GeminiChatSafetyRating `json:"safetyRatings"`
  169. }
  170. type GeminiChatResponse struct {
  171. Candidates []GeminiChatCandidate `json:"candidates"`
  172. PromptFeedback GeminiChatPromptFeedback `json:"promptFeedback"`
  173. UsageMetadata GeminiUsageMetadata `json:"usageMetadata"`
  174. }
  175. type GeminiUsageMetadata struct {
  176. PromptTokenCount int `json:"promptTokenCount"`
  177. CandidatesTokenCount int `json:"candidatesTokenCount"`
  178. TotalTokenCount int `json:"totalTokenCount"`
  179. ThoughtsTokenCount int `json:"thoughtsTokenCount"`
  180. PromptTokensDetails []GeminiPromptTokensDetails `json:"promptTokensDetails"`
  181. }
  182. type GeminiPromptTokensDetails struct {
  183. Modality string `json:"modality"`
  184. TokenCount int `json:"tokenCount"`
  185. }
  186. // Imagen related structs
  187. type GeminiImageRequest struct {
  188. Instances []GeminiImageInstance `json:"instances"`
  189. Parameters GeminiImageParameters `json:"parameters"`
  190. }
  191. type GeminiImageInstance struct {
  192. Prompt string `json:"prompt"`
  193. }
  194. type GeminiImageParameters struct {
  195. SampleCount int `json:"sampleCount,omitempty"`
  196. AspectRatio string `json:"aspectRatio,omitempty"`
  197. PersonGeneration string `json:"personGeneration,omitempty"`
  198. }
  199. type GeminiImageResponse struct {
  200. Predictions []GeminiImagePrediction `json:"predictions"`
  201. }
  202. type GeminiImagePrediction struct {
  203. MimeType string `json:"mimeType"`
  204. BytesBase64Encoded string `json:"bytesBase64Encoded"`
  205. RaiFilteredReason string `json:"raiFilteredReason,omitempty"`
  206. SafetyAttributes any `json:"safetyAttributes,omitempty"`
  207. }
  208. // Embedding related structs
  209. type GeminiEmbeddingRequest struct {
  210. Model string `json:"model,omitempty"`
  211. Content GeminiChatContent `json:"content"`
  212. TaskType string `json:"taskType,omitempty"`
  213. Title string `json:"title,omitempty"`
  214. OutputDimensionality int `json:"outputDimensionality,omitempty"`
  215. }
  216. type GeminiBatchEmbeddingRequest struct {
  217. Requests []*GeminiEmbeddingRequest `json:"requests"`
  218. }
  219. type GeminiEmbeddingResponse struct {
  220. Embedding ContentEmbedding `json:"embedding"`
  221. }
  222. type GeminiBatchEmbeddingResponse struct {
  223. Embeddings []*ContentEmbedding `json:"embeddings"`
  224. }
  225. type ContentEmbedding struct {
  226. Values []float64 `json:"values"`
  227. }