iop/apps/edge/internal/openai/responses_completion.go
toki 04879f2b43 feat(openai): 실제 provider별 사용량 귀속을 기록한다
요청 종료 계수와 실제 provider 시도 사용량을 분리하고, 직접·pool·retry 경로의 attribution을 보존한다. 관련 계약·스펙과 완료된 task archive 정리도 함께 반영한다.
2026-07-31 20:22:23 +09:00

45 lines
1.5 KiB
Go

package openai
import (
"go.uber.org/zap"
edgeservice "iop/apps/edge/internal/service"
"net/http"
"time"
)
func (s *Server) completeResponse(w http.ResponseWriter, dc *responsesDispatchContext, handle edgeservice.RunResult) {
text, reasoning, _, toolCalls, usage, _, err := collectRunResult(dc.r.Context(), handle.Stream(), handle.WaitTimeout())
if err != nil {
s.cancelRunOnHTTPGiveUp(handle.Dispatch(), err)
dc.finishUsageRequest(usageStatusForError(err), responseModeNormalized)
writeError(w, httpStatusForRunError(err), "run_error", err.Error())
return
}
text, reasoning, normalized := normalizeCompletionOutput(dc.outputPolicy, text, reasoning, false)
s.logger.Info("openai responses output",
zap.String("run_id", handle.Dispatch().RunID),
zap.Bool("strict_output", dc.outputPolicy.Strict),
zap.String("xml_completion_tool", dc.outputPolicy.XMLCompletionTool),
zap.Bool("normalized", normalized),
zap.Int("content_len", len(text)),
zap.Int("reasoning_len", len(reasoning)),
)
var u openAIUsage
if usage != nil {
u = *usage
}
dc.recordUsageAttempt(handle.Dispatch(), responseModeNormalized, usageObservationFromOpenAIUsage(usage, len(reasoning)))
dc.finishUsageRequest(usageStatusSuccess, responseModeNormalized)
writeJSON(w, http.StatusOK, responsesResponse{
ID: "resp-" + handle.Dispatch().RunID,
Object: "response",
CreatedAt: time.Now().Unix(),
Model: responseModel(dc.req.Model, handle.Dispatch().Target),
OutputText: text,
Output: responsesOutputItems(text, toolCalls),
Usage: u,
})
}