add generation params: top_p, top_k, min_p, top_a, repetition_penalty, max_completion_tokens, response_format, reasoning_effort, include_reasoning, stop, verbosity
This commit is contained in:
parent
6dfae368d0
commit
3867d52689
|
|
@ -78,10 +78,22 @@ func BuildAgentEnv(cfg *config.Config, d tools.Dispatcher, cwd string) AgentEnv
|
|||
preamble = resolved
|
||||
}
|
||||
genParams = backend.GenerationParams{
|
||||
MaxTokens: cfg.MaxTokens,
|
||||
Temperature: cfg.Temperature,
|
||||
FrequencyPenalty: cfg.FrequencyPenalty,
|
||||
PresencePenalty: cfg.PresencePenalty,
|
||||
MaxTokens: cfg.MaxTokens,
|
||||
MaxCompletionTokens: cfg.MaxCompletionTokens,
|
||||
Temperature: cfg.Temperature,
|
||||
TopP: cfg.TopP,
|
||||
TopK: cfg.TopK,
|
||||
MinP: cfg.MinP,
|
||||
TopA: cfg.TopA,
|
||||
FrequencyPenalty: cfg.FrequencyPenalty,
|
||||
PresencePenalty: cfg.PresencePenalty,
|
||||
RepetitionPenalty: cfg.RepetitionPenalty,
|
||||
ThinkingBudget: cfg.Reasoning,
|
||||
ReasoningEffort: cfg.ReasoningEffort,
|
||||
IncludeReasoning: cfg.IncludeReasoning,
|
||||
ResponseFormat: cfg.ResponseFormat,
|
||||
Stop: cfg.Stop,
|
||||
Verbosity: cfg.Verbosity,
|
||||
}
|
||||
maxSteps = cfg.MaxSteps
|
||||
if len(cfg.TrustedTools) > 0 {
|
||||
|
|
|
|||
|
|
@ -54,6 +54,9 @@ type anthropicRequest struct {
|
|||
Tools []anthropicTool `json:"tools,omitempty"`
|
||||
Stream bool `json:"stream"`
|
||||
Temperature *float64 `json:"temperature,omitempty"`
|
||||
TopP *float64 `json:"top_p,omitempty"`
|
||||
TopK *int `json:"top_k,omitempty"`
|
||||
StopSeqs []string `json:"stop_sequences,omitempty"`
|
||||
Thinking *anthropicThinking `json:"thinking,omitempty"`
|
||||
}
|
||||
|
||||
|
|
@ -113,6 +116,9 @@ func (b *AnthropicBackend) ChatStream(ctx context.Context, messages []Message, t
|
|||
Messages: wireMessages,
|
||||
Stream: true,
|
||||
Temperature: params.Temperature,
|
||||
TopP: params.TopP,
|
||||
TopK: params.TopK,
|
||||
StopSeqs: params.Stop,
|
||||
}
|
||||
if params.ThinkingBudget > 0 {
|
||||
areq.Thinking = &anthropicThinking{Type: "enabled", BudgetTokens: params.ThinkingBudget}
|
||||
|
|
|
|||
|
|
@ -105,11 +105,22 @@ func (e *ToolUnsupportedError) Error() string { return e.Message }
|
|||
// GenerationParams controls sampling behaviour for a single ChatStream call.
|
||||
// Zero values mean "use the API default".
|
||||
type GenerationParams struct {
|
||||
MaxTokens int // 0 = no limit
|
||||
Temperature *float64 // nil = API default
|
||||
FrequencyPenalty *float64 // nil = API default
|
||||
PresencePenalty *float64 // nil = API default
|
||||
ThinkingBudget int // Anthropic extended thinking token budget; 0 = disabled
|
||||
MaxTokens int // 0 = no limit
|
||||
MaxCompletionTokens int // OpenAI o-series; 0 = use MaxTokens
|
||||
Temperature *float64 // nil = API default
|
||||
TopP *float64 // nil = API default
|
||||
TopK *int // nil = API default (Anthropic, Ollama)
|
||||
MinP *float64 // nil = API default (Ollama)
|
||||
TopA *float64 // nil = API default (Ollama)
|
||||
FrequencyPenalty *float64 // nil = API default
|
||||
PresencePenalty *float64 // nil = API default
|
||||
RepetitionPenalty *float64 // nil = API default (Ollama)
|
||||
ThinkingBudget int // Anthropic extended thinking token budget; 0 = disabled
|
||||
ReasoningEffort string // OpenAI o-series: "low", "medium", "high"
|
||||
IncludeReasoning *bool // include reasoning in response (OpenRouter)
|
||||
ResponseFormat string // "json_object", "text", etc.
|
||||
Stop []string // stop sequences
|
||||
Verbosity string // internal: controls output detail level
|
||||
}
|
||||
|
||||
// Backend is the interface all LLM providers must implement.
|
||||
|
|
|
|||
|
|
@ -134,10 +134,12 @@ type ollamaToolFunction struct {
|
|||
}
|
||||
|
||||
type ollamaChatRequest struct {
|
||||
Model string `json:"model"`
|
||||
Messages []ollamaMessage `json:"messages"`
|
||||
Tools []ollamaTool `json:"tools,omitempty"`
|
||||
Stream bool `json:"stream"`
|
||||
Model string `json:"model"`
|
||||
Messages []ollamaMessage `json:"messages"`
|
||||
Tools []ollamaTool `json:"tools,omitempty"`
|
||||
Stream bool `json:"stream"`
|
||||
Options map[string]interface{} `json:"options,omitempty"`
|
||||
Stop []string `json:"stop,omitempty"`
|
||||
}
|
||||
|
||||
type ollamaChatResponse struct {
|
||||
|
|
@ -150,7 +152,7 @@ type ollamaChatResponse struct {
|
|||
|
||||
// -- implementation --
|
||||
|
||||
func (b *OllamaBackend) ChatStream(ctx context.Context, messages []Message, tools []Tool, _ GenerationParams) (<-chan StreamEvent, error) {
|
||||
func (b *OllamaBackend) ChatStream(ctx context.Context, messages []Message, tools []Tool, params GenerationParams) (<-chan StreamEvent, error) {
|
||||
model := b.model
|
||||
wireMessages := make([]ollamaMessage, len(messages))
|
||||
for i, m := range messages {
|
||||
|
|
@ -174,11 +176,45 @@ func (b *OllamaBackend) ChatStream(ctx context.Context, messages []Message, tool
|
|||
})
|
||||
}
|
||||
|
||||
opts := make(map[string]interface{})
|
||||
if params.Temperature != nil {
|
||||
opts["temperature"] = *params.Temperature
|
||||
}
|
||||
if params.TopP != nil {
|
||||
opts["top_p"] = *params.TopP
|
||||
}
|
||||
if params.TopK != nil {
|
||||
opts["top_k"] = *params.TopK
|
||||
}
|
||||
if params.MinP != nil {
|
||||
opts["min_p"] = *params.MinP
|
||||
}
|
||||
if params.TopA != nil {
|
||||
opts["top_a"] = *params.TopA
|
||||
}
|
||||
if params.RepetitionPenalty != nil {
|
||||
opts["repeat_penalty"] = *params.RepetitionPenalty
|
||||
}
|
||||
if params.FrequencyPenalty != nil {
|
||||
opts["frequency_penalty"] = *params.FrequencyPenalty
|
||||
}
|
||||
if params.PresencePenalty != nil {
|
||||
opts["presence_penalty"] = *params.PresencePenalty
|
||||
}
|
||||
if params.MaxTokens > 0 {
|
||||
opts["num_predict"] = params.MaxTokens
|
||||
}
|
||||
if len(opts) == 0 {
|
||||
opts = nil
|
||||
}
|
||||
|
||||
data, _ := json.Marshal(ollamaChatRequest{
|
||||
Model: model,
|
||||
Messages: wireMessages,
|
||||
Tools: wireTools,
|
||||
Stream: true,
|
||||
Options: opts,
|
||||
Stop: params.Stop,
|
||||
})
|
||||
|
||||
httpReq, _ := http.NewRequestWithContext(ctx, http.MethodPost, b.baseURL.JoinPath("/api/chat").String(), bytes.NewReader(data))
|
||||
|
|
|
|||
|
|
@ -170,15 +170,25 @@ type openAIStreamOptions struct {
|
|||
}
|
||||
|
||||
type openAIChatRequest struct {
|
||||
Model string `json:"model"`
|
||||
Messages []openAIMessage `json:"messages"`
|
||||
Tools []openAITool `json:"tools,omitempty"`
|
||||
Stream bool `json:"stream"`
|
||||
StreamOptions *openAIStreamOptions `json:"stream_options,omitempty"`
|
||||
MaxTokens int `json:"max_tokens,omitempty"`
|
||||
Temperature *float64 `json:"temperature,omitempty"`
|
||||
FrequencyPenalty *float64 `json:"frequency_penalty,omitempty"`
|
||||
PresencePenalty *float64 `json:"presence_penalty,omitempty"`
|
||||
Model string `json:"model"`
|
||||
Messages []openAIMessage `json:"messages"`
|
||||
Tools []openAITool `json:"tools,omitempty"`
|
||||
Stream bool `json:"stream"`
|
||||
StreamOptions *openAIStreamOptions `json:"stream_options,omitempty"`
|
||||
MaxTokens int `json:"max_tokens,omitempty"`
|
||||
MaxCompletionTokens int `json:"max_completion_tokens,omitempty"`
|
||||
Temperature *float64 `json:"temperature,omitempty"`
|
||||
TopP *float64 `json:"top_p,omitempty"`
|
||||
FrequencyPenalty *float64 `json:"frequency_penalty,omitempty"`
|
||||
PresencePenalty *float64 `json:"presence_penalty,omitempty"`
|
||||
Stop []string `json:"stop,omitempty"`
|
||||
ResponseFormat *openAIResponseFmt `json:"response_format,omitempty"`
|
||||
ReasoningEffort string `json:"reasoning_effort,omitempty"`
|
||||
IncludeReasoning *bool `json:"include_reasoning,omitempty"`
|
||||
}
|
||||
|
||||
type openAIResponseFmt struct {
|
||||
Type string `json:"type"`
|
||||
}
|
||||
|
||||
type openAIUsage struct {
|
||||
|
|
@ -462,15 +472,23 @@ func (b *OpenAIBackend) ChatStream(ctx context.Context, messages []Message, tool
|
|||
}
|
||||
}
|
||||
req := openAIChatRequest{
|
||||
Model: b.model,
|
||||
Messages: wireMessages,
|
||||
Tools: wireTools,
|
||||
Stream: true,
|
||||
StreamOptions: &openAIStreamOptions{IncludeUsage: true},
|
||||
MaxTokens: params.MaxTokens,
|
||||
Temperature: params.Temperature,
|
||||
FrequencyPenalty: params.FrequencyPenalty,
|
||||
PresencePenalty: params.PresencePenalty,
|
||||
Model: b.model,
|
||||
Messages: wireMessages,
|
||||
Tools: wireTools,
|
||||
Stream: true,
|
||||
StreamOptions: &openAIStreamOptions{IncludeUsage: true},
|
||||
MaxTokens: params.MaxTokens,
|
||||
MaxCompletionTokens: params.MaxCompletionTokens,
|
||||
Temperature: params.Temperature,
|
||||
TopP: params.TopP,
|
||||
FrequencyPenalty: params.FrequencyPenalty,
|
||||
PresencePenalty: params.PresencePenalty,
|
||||
Stop: params.Stop,
|
||||
ReasoningEffort: params.ReasoningEffort,
|
||||
IncludeReasoning: params.IncludeReasoning,
|
||||
}
|
||||
if params.ResponseFormat != "" {
|
||||
req.ResponseFormat = &openAIResponseFmt{Type: params.ResponseFormat}
|
||||
}
|
||||
|
||||
data, _ := json.Marshal(req)
|
||||
|
|
|
|||
|
|
@ -59,16 +59,28 @@ func (p Prompt) MarshalJSON() ([]byte, error) {
|
|||
}
|
||||
|
||||
type Config struct {
|
||||
Hooks map[string]HookCmds `json:"hooks,omitempty"`
|
||||
Prompt Prompt `json:"prompt,omitempty"`
|
||||
Tools *bool `json:"tools,omitempty"`
|
||||
TrustedTools []string `json:"trustedTools,omitempty"`
|
||||
MaxTokens int `json:"maxTokens,omitempty"`
|
||||
Hooks map[string]HookCmds `json:"hooks,omitempty"`
|
||||
Prompt Prompt `json:"prompt,omitempty"`
|
||||
Tools *bool `json:"tools,omitempty"`
|
||||
TrustedTools []string `json:"trustedTools,omitempty"`
|
||||
MaxTokens int `json:"maxTokens,omitempty"`
|
||||
MaxCompletionTokens int `json:"maxCompletionTokens,omitempty"`
|
||||
// MaxSteps caps the number of tool-call rounds per turn. 0 means unlimited.
|
||||
MaxSteps int `json:"maxSteps,omitempty"`
|
||||
Temperature *float64 `json:"temperature,omitempty"`
|
||||
FrequencyPenalty *float64 `json:"frequencyPenalty,omitempty"`
|
||||
PresencePenalty *float64 `json:"presencePenalty,omitempty"`
|
||||
MaxSteps int `json:"maxSteps,omitempty"`
|
||||
Temperature *float64 `json:"temperature,omitempty"`
|
||||
TopP *float64 `json:"topP,omitempty"`
|
||||
TopK *int `json:"topK,omitempty"`
|
||||
MinP *float64 `json:"minP,omitempty"`
|
||||
TopA *float64 `json:"topA,omitempty"`
|
||||
FrequencyPenalty *float64 `json:"frequencyPenalty,omitempty"`
|
||||
PresencePenalty *float64 `json:"presencePenalty,omitempty"`
|
||||
RepetitionPenalty *float64 `json:"repetitionPenalty,omitempty"`
|
||||
Reasoning int `json:"reasoning,omitempty"`
|
||||
ReasoningEffort string `json:"reasoningEffort,omitempty"`
|
||||
IncludeReasoning *bool `json:"includeReasoning,omitempty"`
|
||||
ResponseFormat string `json:"responseFormat,omitempty"`
|
||||
Stop []string `json:"stop,omitempty"`
|
||||
Verbosity string `json:"verbosity,omitempty"`
|
||||
}
|
||||
|
||||
// Load parses a Config from r.
|
||||
|
|
|
|||
Reference in New Issue