// Package llm 抽象 LLM Pool(vLLM / Ollama 集群)的负载均衡与流式推理。 package llm import ( "context" "strings" "time" ) // Pool 维护后端 LLM 实例列表与路由策略。 type Pool struct{ /* backends []Backend */ } func NewPool() *Pool { return &Pool{} } // 占位参数:模拟真实后端的 TTFT(首 token 延迟) 与逐 token 间隔。 const ( timeToFirstToken = 700 * time.Millisecond interTokenDelay = 60 * time.Millisecond ) // Stream 选择一个后端进行流式推理,逐 Token 回调 onToken。 // 当前为占位实现:把对 prompt 的确定性回复按 token 流式返回, // 真实接入 vLLM/Ollama 时替换为后端 streaming API 即可(回调签名不变)。 func (p *Pool) Stream(ctx context.Context, prompt string, onToken func([]byte)) error { // TODO: 选路 (least-load / 模型亲和) → 调 vLLM/Ollama streaming API reply := buildReply(prompt) select { case <-ctx.Done(): return ctx.Err() case <-time.After(timeToFirstToken): // 模拟 TTFT } for _, tok := range tokenize(reply) { select { case <-ctx.Done(): return ctx.Err() default: } onToken([]byte(tok)) time.Sleep(interTokenDelay) } return nil } // buildReply 占位:真实实现应由 DSL 编排出的对话上下文驱动后端生成。 func buildReply(prompt string) string { p := strings.TrimSpace(prompt) if len(p) > 40 { p = p[:40] + "…" } return "已编排执行该 Agent 图,输入摘要: " + p } // tokenize 占位分词:按 rune 切,保证多字节中文也能逐字流式。 func tokenize(s string) []string { out := make([]string, 0, len(s)) for _, r := range s { out = append(out, string(r)) } return out }