in gollm/openai.go [209:272]
func (cs *openAIChatSession) Send(ctx context.Context, contents ...any) (ChatResponse, error) {
klog.V(1).InfoS("openAIChatSession.Send called", "model", cs.model, "history_len", len(cs.history))
// 1. Append user message(s) to history
for _, content := range contents {
switch c := content.(type) {
case string:
klog.V(2).Infof("Adding user message to history: %s", c)
cs.history = append(cs.history, openai.UserMessage(c))
case FunctionCallResult:
klog.V(2).Infof("Adding tool call result to history: Name=%s, ID=%s", c.Name, c.ID)
// Marshal the result map into a JSON string for the message content
resultJSON, err := json.Marshal(c.Result)
if err != nil {
klog.Errorf("Failed to marshal function call result: %v", err)
return nil, fmt.Errorf("failed to marshal function call result %q: %w", c.Name, err)
}
cs.history = append(cs.history, openai.ToolMessage(string(resultJSON), c.ID))
default:
// TODO: Handle other content types if necessary?
klog.Warningf("Unhandled content type in Send: %T", content)
return nil, fmt.Errorf("unhandled content type: %T", content)
}
}
// 2. Prepare the API request
chatReq := openai.ChatCompletionNewParams{
Model: openai.ChatModel(cs.model),
Messages: cs.history,
}
if len(cs.tools) > 0 {
chatReq.Tools = cs.tools
// chatReq.ToolChoice = openai.ToolChoiceAuto // Or specify if needed
}
// 3. Call the OpenAI API
klog.V(1).InfoS("Sending request to OpenAI Chat API", "model", cs.model, "messages", len(chatReq.Messages), "tools", len(chatReq.Tools))
completion, err := cs.client.Chat.Completions.New(ctx, chatReq)
if err != nil {
// TODO: Check if error is retryable using cs.IsRetryableError
klog.Errorf("OpenAI ChatCompletion API error: %v", err)
return nil, fmt.Errorf("OpenAI chat completion failed: %w", err)
}
klog.V(1).InfoS("Received response from OpenAI Chat API", "id", completion.ID, "choices", len(completion.Choices))
// 4. Process the response
if len(completion.Choices) == 0 {
klog.Warning("Received response with no choices from OpenAI")
return nil, errors.New("received empty response from OpenAI (no choices)")
}
// Add assistant's response (first choice) to history
assistantMsg := completion.Choices[0].Message
// Convert to param type before appending to history
cs.history = append(cs.history, assistantMsg.ToParam())
klog.V(2).InfoS("Added assistant message to history", "content_present", assistantMsg.Content != "", "tool_calls", len(assistantMsg.ToolCalls))
// Wrap the response
resp := &openAIChatResponse{
openaiCompletion: completion,
}
return resp, nil
}