88 "io"
99 "net/http"
1010 "strings"
11+
12+ "github.com/cqfn/refrax/internal/log"
1113)
1214
1315// OpenAI represents a client for interacting with the OpenAI API
@@ -19,8 +21,10 @@ type openAI struct {
1921}
2022
2123type openaiReq struct {
22- Model string `json:"model"`
23- Messages []openaiMsg `json:"messages"`
24+ Model string `json:"model"`
25+ Messages []openaiMsg `json:"messages"`
26+ Stream bool `json:"stream"`
27+ Temperature * float64 `json:"temperature,omitempty"`
2428}
2529
2630type openaiResp struct {
@@ -36,14 +40,23 @@ type openaiMsg struct {
3640 Content string `json:"content"`
3741}
3842
39- // NewOpenAI creates a new OpenAI instance
40- func NewOpenAI (apiKey , system string ) Brain {
43+ // NewOpenAIDefault creates a new OpenAI instance with default settings
44+ func NewOpenAIDefault (token , system string ) (Brain , error ) {
45+ return NewOpenAI (token , "https://api.openai.com/v1/chat/completions" , "gpt-3.5-turbo" , system )
46+ }
47+
48+ // NewOpenAI creates a new OpenAI instance with the provided settings
49+ func NewOpenAI (token , url , model , system string ) (Brain , error ) {
50+ err := verifyUrl (url )
51+ if err != nil {
52+ return nil , err
53+ }
4154 return & openAI {
42- token : apiKey ,
43- url : "https://api.openai.com/v1/chat/completions" ,
44- model : "gpt-3.5-turbo" , // Default model
55+ token : token ,
56+ url : url ,
57+ model : model ,
4558 system : system ,
46- }
59+ }, nil
4760}
4861
4962// Ask sends a question to the OpenAI API
@@ -52,12 +65,16 @@ func (o *openAI) Ask(question string) (string, error) {
5265}
5366
5467func (o * openAI ) send (system , user string ) (answer string , err error ) {
68+ log .Debug ("sending request to '%s', model '%s', and prompt: '%s'" , o .url , o .model , user )
69+ temp := float64 (0.0 )
5570 body := openaiReq {
5671 Model : o .model ,
5772 Messages : []openaiMsg {
5873 {Role : "system" , Content : system },
5974 {Role : "user" , Content : strings .TrimSpace (user )},
6075 },
76+ Stream : false ,
77+ Temperature : & temp ,
6178 }
6279 data , err := json .Marshal (body )
6380 if err != nil {
@@ -68,7 +85,7 @@ func (o *openAI) send(system, user string) (answer string, err error) {
6885 return "" , err
6986 }
7087 req .Header .Set ("Content-Type" , "application/json" )
71- req .Header .Set ("Authorization" , "Bearer " + o .token )
88+ req .Header .Set ("Authorization" , fmt . Sprintf ( "Bearer %s" , o .token ) )
7289 resp , err := http .DefaultClient .Do (req )
7390 if err != nil {
7491 return "" , fmt .Errorf ("API request failed: %w" , err )
@@ -80,7 +97,7 @@ func (o *openAI) send(system, user string) (answer string, err error) {
8097 }()
8198 if resp .StatusCode != http .StatusOK {
8299 body , _ := io .ReadAll (resp .Body )
83- return "" , fmt .Errorf ("API error: %s" , body )
100+ return "" , fmt .Errorf ("API error (code : %d): %s" , resp . StatusCode , body )
84101 }
85102 var response openaiResp
86103 if err := json .NewDecoder (resp .Body ).Decode (& response ); err != nil {
@@ -91,3 +108,13 @@ func (o *openAI) send(system, user string) (answer string, err error) {
91108 }
92109 return response .Choices [0 ].Message .Content , nil
93110}
111+
112+ func verifyUrl (url string ) error {
113+ if ! strings .HasPrefix (url , "http://" ) && ! strings .HasPrefix (url , "https://" ) {
114+ return fmt .Errorf ("invalid URL: must start with http:// or https://" )
115+ }
116+ if ! strings .HasSuffix (url , "/v1/chat/completions" ) {
117+ return fmt .Errorf ("invalid URL: must end with /v1/chat/completions" )
118+ }
119+ return nil
120+ }
0 commit comments