relay-claude.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. package controller
  2. import (
  3. "fmt"
  4. "one-api/common"
  5. "strings"
  6. )
  7. type ClaudeMetadata struct {
  8. UserId string `json:"user_id"`
  9. }
  10. type ClaudeRequest struct {
  11. Model string `json:"model"`
  12. Prompt string `json:"prompt"`
  13. MaxTokensToSample int `json:"max_tokens_to_sample"`
  14. StopSequences []string `json:"stop_sequences,omitempty"`
  15. Temperature float64 `json:"temperature,omitempty"`
  16. TopP float64 `json:"top_p,omitempty"`
  17. TopK int `json:"top_k,omitempty"`
  18. //ClaudeMetadata `json:"metadata,omitempty"`
  19. Stream bool `json:"stream,omitempty"`
  20. }
  21. type ClaudeError struct {
  22. Type string `json:"type"`
  23. Message string `json:"message"`
  24. }
  25. type ClaudeResponse struct {
  26. Completion string `json:"completion"`
  27. StopReason string `json:"stop_reason"`
  28. Model string `json:"model"`
  29. Error ClaudeError `json:"error"`
  30. }
  31. func stopReasonClaude2OpenAI(reason string) string {
  32. switch reason {
  33. case "stop_sequence":
  34. return "stop"
  35. case "max_tokens":
  36. return "length"
  37. default:
  38. return reason
  39. }
  40. }
  41. func requestOpenAI2Claude(textRequest GeneralOpenAIRequest) *ClaudeRequest {
  42. claudeRequest := ClaudeRequest{
  43. Model: textRequest.Model,
  44. Prompt: "",
  45. MaxTokensToSample: textRequest.MaxTokens,
  46. StopSequences: nil,
  47. Temperature: textRequest.Temperature,
  48. TopP: textRequest.TopP,
  49. Stream: textRequest.Stream,
  50. }
  51. if claudeRequest.MaxTokensToSample == 0 {
  52. claudeRequest.MaxTokensToSample = 1000000
  53. }
  54. prompt := ""
  55. for _, message := range textRequest.Messages {
  56. if message.Role == "user" {
  57. prompt += fmt.Sprintf("\n\nHuman: %s", message.Content)
  58. } else if message.Role == "assistant" {
  59. prompt += fmt.Sprintf("\n\nAssistant: %s", message.Content)
  60. } else {
  61. // ignore other roles
  62. }
  63. prompt += "\n\nAssistant:"
  64. }
  65. claudeRequest.Prompt = prompt
  66. return &claudeRequest
  67. }
  68. func streamResponseClaude2OpenAI(claudeResponse *ClaudeResponse) *ChatCompletionsStreamResponse {
  69. var choice ChatCompletionsStreamResponseChoice
  70. choice.Delta.Content = claudeResponse.Completion
  71. choice.FinishReason = stopReasonClaude2OpenAI(claudeResponse.StopReason)
  72. var response ChatCompletionsStreamResponse
  73. response.Object = "chat.completion.chunk"
  74. response.Model = claudeResponse.Model
  75. response.Choices = []ChatCompletionsStreamResponseChoice{choice}
  76. return &response
  77. }
  78. func responseClaude2OpenAI(claudeResponse *ClaudeResponse) *OpenAITextResponse {
  79. choice := OpenAITextResponseChoice{
  80. Index: 0,
  81. Message: Message{
  82. Role: "assistant",
  83. Content: strings.TrimPrefix(claudeResponse.Completion, " "),
  84. Name: nil,
  85. },
  86. FinishReason: stopReasonClaude2OpenAI(claudeResponse.StopReason),
  87. }
  88. fullTextResponse := OpenAITextResponse{
  89. Id: fmt.Sprintf("chatcmpl-%s", common.GetUUID()),
  90. Object: "chat.completion",
  91. Created: common.GetTimestamp(),
  92. Choices: []OpenAITextResponseChoice{choice},
  93. }
  94. return &fullTextResponse
  95. }