feat: Phase 2 — chat templates, reasoning parser, collapsible TUI, mouse support
- internal/llama/template.go: ChatML/Llama3 template engine with stop tokens - internal/agent/reasoning.go: parse <think>/<reasoning> tags from LLM output - companion/promptbuilder.go: output structured BuildResult, add date/time context - agent/agent.go: wire templates + reasoning split into message loop - storage: add reasoning TEXT column to messages table + migration - channel/tui.go: collapsible reasoning (tab toggle), mouse scroll, polished dimmed style - config: CHAT_TEMPLATE env var (chatml|llama3|none) - plan.md: mark Phase 2 complete, add themes TODO
This commit is contained in:
@@ -15,12 +15,13 @@ type Client struct {
|
||||
}
|
||||
|
||||
type CompletionRequest struct {
|
||||
Prompt string `json:"prompt"`
|
||||
Temperature float64 `json:"temperature"`
|
||||
TopP float64 `json:"top_p"`
|
||||
MaxTokens int `json:"n_predict"`
|
||||
Stream bool `json:"stream"`
|
||||
CachePrompt bool `json:"cache_prompt"`
|
||||
Prompt string `json:"prompt"`
|
||||
Temperature float64 `json:"temperature"`
|
||||
TopP float64 `json:"top_p"`
|
||||
MaxTokens int `json:"n_predict"`
|
||||
Stop []string `json:"stop,omitempty"`
|
||||
Stream bool `json:"stream"`
|
||||
CachePrompt bool `json:"cache_prompt"`
|
||||
}
|
||||
|
||||
type CompletionResponse struct {
|
||||
|
||||
71
internal/llama/template.go
Normal file
71
internal/llama/template.go
Normal file
@@ -0,0 +1,71 @@
|
||||
package llama
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"git.db123.ir/db123/divacode/pkg/types"
|
||||
)
|
||||
|
||||
type TemplateEngine struct {
|
||||
format string
|
||||
}
|
||||
|
||||
func NewTemplateEngine(format string) *TemplateEngine {
|
||||
return &TemplateEngine{format: format}
|
||||
}
|
||||
|
||||
func (te *TemplateEngine) Build(segments []types.PromptSegment) string {
|
||||
switch te.format {
|
||||
case "chatml":
|
||||
return te.buildChatML(segments)
|
||||
case "llama3":
|
||||
return te.buildLlama3(segments)
|
||||
default:
|
||||
return te.buildRaw(segments)
|
||||
}
|
||||
}
|
||||
|
||||
func (te *TemplateEngine) StopTokens() []string {
|
||||
switch te.format {
|
||||
case "chatml":
|
||||
return []string{"<|im_end|>"}
|
||||
case "llama3":
|
||||
return []string{"<|eot_id|>"}
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (te *TemplateEngine) buildChatML(segments []types.PromptSegment) string {
|
||||
var b strings.Builder
|
||||
for _, seg := range segments {
|
||||
b.WriteString(fmt.Sprintf("<|im_start|>%s\n%s<|im_end|>\n", seg.Type, seg.Content))
|
||||
}
|
||||
b.WriteString("<|im_start|>assistant\n")
|
||||
return b.String()
|
||||
}
|
||||
|
||||
func (te *TemplateEngine) buildLlama3(segments []types.PromptSegment) string {
|
||||
var b strings.Builder
|
||||
b.WriteString("<|begin_of_text|>")
|
||||
for _, seg := range segments {
|
||||
b.WriteString(fmt.Sprintf("<|start_header_id|>%s<|end_header_id|>\n\n%s<|eot_id|>", seg.Type, seg.Content))
|
||||
}
|
||||
b.WriteString("<|start_header_id|>assistant<|end_header_id|>\n\n")
|
||||
return b.String()
|
||||
}
|
||||
|
||||
func (te *TemplateEngine) buildRaw(segments []types.PromptSegment) string {
|
||||
var b strings.Builder
|
||||
for _, seg := range segments {
|
||||
switch seg.Type {
|
||||
case types.SegSystem:
|
||||
b.WriteString("[System]\n" + seg.Content + "\n\n")
|
||||
case types.SegUser:
|
||||
b.WriteString("User: " + seg.Content + "\n")
|
||||
}
|
||||
}
|
||||
b.WriteString("You:")
|
||||
return b.String()
|
||||
}
|
||||
Reference in New Issue
Block a user