gemini.go 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. package controller
  2. import (
  3. "github.com/bytedance/sonic"
  4. "github.com/gin-gonic/gin"
  5. "github.com/labring/aiproxy/core/common"
  6. "github.com/labring/aiproxy/core/model"
  7. relaymodel "github.com/labring/aiproxy/core/relay/model"
  8. )
  9. func GetGeminiRequestUsage(c *gin.Context, mc model.ModelConfig) (model.Usage, error) {
  10. var geminiReq relaymodel.GeminiChatRequest
  11. err := common.UnmarshalRequestReusable(c.Request, &geminiReq)
  12. if err != nil {
  13. return model.Usage{}, err
  14. }
  15. // Count tokens from all content parts
  16. totalTokens := int64(0)
  17. // Count system instruction tokens
  18. if geminiReq.SystemInstruction != nil {
  19. for _, part := range geminiReq.SystemInstruction.Parts {
  20. if part.Text != "" {
  21. totalTokens += countTokensForText(part.Text, mc.Model)
  22. }
  23. }
  24. }
  25. // Count tokens from all messages
  26. for _, content := range geminiReq.Contents {
  27. for _, part := range content.Parts {
  28. if part.Text != "" {
  29. totalTokens += countTokensForText(part.Text, mc.Model)
  30. }
  31. // Function calls and responses also consume tokens
  32. if part.FunctionCall != nil {
  33. // Approximate token count for function call
  34. if data, err := sonic.Marshal(part.FunctionCall); err == nil {
  35. totalTokens += countTokensForText(string(data), mc.Model)
  36. }
  37. }
  38. if part.FunctionResponse != nil {
  39. // Approximate token count for function response
  40. if data, err := sonic.Marshal(part.FunctionResponse); err == nil {
  41. totalTokens += countTokensForText(string(data), mc.Model)
  42. }
  43. }
  44. }
  45. }
  46. return model.Usage{
  47. InputTokens: model.ZeroNullInt64(totalTokens),
  48. }, nil
  49. }
  50. // countTokensForText provides a rough estimate of token count
  51. // This is a simplified version - in production you might want to use a proper tokenizer
  52. func countTokensForText(text, _ string) int64 {
  53. // Rough approximation: 1 token ≈ 4 characters for English
  54. // This is a simplified estimate and should be replaced with proper tokenization
  55. // for production use
  56. // Note: modelName parameter is reserved for future use with model-specific tokenizers
  57. return int64(len(text) / 4)
  58. }