go-chatgpt
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

107 lines
2.7 KiB

  1. package gogpt
  2. import (
  3. "context"
  4. "encoding/json"
  5. "fmt"
  6. "net/http"
  7. )
  8. // Client is OpenAI GPT-3 API client.
  9. type Client struct {
  10. config ClientConfig
  11. requestBuilder requestBuilder
  12. }
  13. // NewClient creates new OpenAI API client.
  14. func NewClient(authToken string) *Client {
  15. config := DefaultConfig(authToken)
  16. return NewClientWithConfig(config)
  17. }
  18. // NewClientWithConfig creates new OpenAI API client for specified config.
  19. func NewClientWithConfig(config ClientConfig) *Client {
  20. return &Client{
  21. config: config,
  22. requestBuilder: newRequestBuilder(),
  23. }
  24. }
  25. // NewOrgClient creates new OpenAI API client for specified Organization ID.
  26. //
  27. // Deprecated: Please use NewClientWithConfig.
  28. func NewOrgClient(authToken, org string) *Client {
  29. config := DefaultConfig(authToken)
  30. config.OrgID = org
  31. return NewClientWithConfig(config)
  32. }
  33. func (c *Client) sendRequest(req *http.Request, v interface{}) error {
  34. req.Header.Set("Accept", "application/json; charset=utf-8")
  35. req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", c.config.authToken))
  36. // Check whether Content-Type is already set, Upload Files API requires
  37. // Content-Type == multipart/form-data
  38. contentType := req.Header.Get("Content-Type")
  39. if contentType == "" {
  40. req.Header.Set("Content-Type", "application/json; charset=utf-8")
  41. }
  42. if len(c.config.OrgID) > 0 {
  43. req.Header.Set("OpenAI-Organization", c.config.OrgID)
  44. }
  45. res, err := c.config.HTTPClient.Do(req)
  46. if err != nil {
  47. return err
  48. }
  49. defer res.Body.Close()
  50. if res.StatusCode < http.StatusOK || res.StatusCode >= http.StatusBadRequest {
  51. var errRes ErrorResponse
  52. err = json.NewDecoder(res.Body).Decode(&errRes)
  53. if err != nil || errRes.Error == nil {
  54. reqErr := RequestError{
  55. StatusCode: res.StatusCode,
  56. Err: err,
  57. }
  58. return fmt.Errorf("error, %w", &reqErr)
  59. }
  60. errRes.Error.StatusCode = res.StatusCode
  61. return fmt.Errorf("error, status code: %d, message: %w", res.StatusCode, errRes.Error)
  62. }
  63. if v != nil {
  64. if err = json.NewDecoder(res.Body).Decode(v); err != nil {
  65. return err
  66. }
  67. }
  68. return nil
  69. }
  70. func (c *Client) fullURL(suffix string) string {
  71. return fmt.Sprintf("%s%s", c.config.BaseURL, suffix)
  72. }
  73. func (c *Client) newStreamRequest(
  74. ctx context.Context,
  75. method string,
  76. urlSuffix string,
  77. body any) (*http.Request, error) {
  78. req, err := c.requestBuilder.build(ctx, method, c.fullURL(urlSuffix), body)
  79. if err != nil {
  80. return nil, err
  81. }
  82. req.Header.Set("Content-Type", "application/json")
  83. req.Header.Set("Accept", "text/event-stream")
  84. req.Header.Set("Cache-Control", "no-cache")
  85. req.Header.Set("Connection", "keep-alive")
  86. req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", c.config.authToken))
  87. return req, nil
  88. }