added -model
This commit is contained in:
@@ -10,7 +10,7 @@ Hygate is a standalone, single-binary gateway that exposes Tencent's Hunyuan 3 (
|
||||
- Reasoning content passthrough (`reasoning_content`)
|
||||
- Tool/function calling, including incremental streaming of tool-call arguments
|
||||
- Fibonacci backoff retry on upstream calls
|
||||
- Configurable endpoint and User-Agent
|
||||
- Configurable endpoint, model name, and User-Agent
|
||||
- No external dependencies (standard library only)
|
||||
|
||||
## Installation
|
||||
@@ -38,13 +38,14 @@ Alternatively, you can directly build from source by running `make`. This produc
|
||||
Run the gateway:
|
||||
|
||||
```
|
||||
hygate [-port 8080] [-endpoint https://tencent-hy3.hf.space]
|
||||
hygate [-port 8080] [-endpoint https://tencent-hy3.hf.space] [-model hy3]
|
||||
```
|
||||
|
||||
Available flags:
|
||||
|
||||
- `-port` — TCP port to listen on (default `8080`)
|
||||
- `-endpoint` — root URL of the Hunyuan Gradio space (default `https://tencent-hy3.hf.space`)
|
||||
- `-model` — exposed model name (default `hy3`)
|
||||
- `-user-agent` / `-ua` — custom User-Agent sent to the upstream
|
||||
|
||||
Endpoints served:
|
||||
@@ -72,7 +73,7 @@ Even through the Gradio API, Tencent Hy3 is a very fast and performant model whe
|
||||
|
||||
### Which models are reported?
|
||||
|
||||
A single model, `hy3`, is advertised via `/v1/models`.
|
||||
By default, a single model, `hy3` (configurable via the `-model` flag), is advertised via `/v1/models`.
|
||||
|
||||
### Are token usage counts returned?
|
||||
|
||||
|
||||
+16
-4
@@ -10,7 +10,7 @@ import (
|
||||
)
|
||||
|
||||
func TestHunyuanServiceEndpoint(t *testing.T) {
|
||||
svc := NewHunyuanService("https://example.com/gradio/")
|
||||
svc := NewHunyuanService("https://example.com/gradio/", "")
|
||||
if svc.endpoint != "https://example.com/gradio" {
|
||||
t.Errorf("expected trailing slash stripped, got %q", svc.endpoint)
|
||||
}
|
||||
@@ -21,6 +21,18 @@ func TestHunyuanServiceEndpoint(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestCustomModelNameConfiguration(t *testing.T) {
|
||||
svc := NewHunyuanService("https://example.com/gradio", "hunyuan-custom-v1")
|
||||
if svc.modelName != "hunyuan-custom-v1" {
|
||||
t.Errorf("expected modelName 'hunyuan-custom-v1', got %q", svc.modelName)
|
||||
}
|
||||
|
||||
models := svc.ListModels()
|
||||
if len(models) != 1 || models[0].ID != "hunyuan-custom-v1" {
|
||||
t.Fatalf("expected model ID 'hunyuan-custom-v1', got %v", models)
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseGradioStreamData(t *testing.T) {
|
||||
sampleJSON := `[["Hello world", "Thinking process...", null]]`
|
||||
c, r, tc, ok := parseGradioStreamData(sampleJSON)
|
||||
@@ -60,7 +72,7 @@ func TestHunyuanMockedCompletion(t *testing.T) {
|
||||
server := httptest.NewServer(handler)
|
||||
defer server.Close()
|
||||
|
||||
svc := NewHunyuanService(server.URL)
|
||||
svc := NewHunyuanService(server.URL, "hy3")
|
||||
|
||||
rec := httptest.NewRecorder()
|
||||
req, _ := http.NewRequest("POST", "/v1/chat/completions", nil)
|
||||
@@ -146,7 +158,7 @@ func TestHunyuanToolCallingNonStreaming(t *testing.T) {
|
||||
server := httptest.NewServer(handler)
|
||||
defer server.Close()
|
||||
|
||||
svc := NewHunyuanService(server.URL)
|
||||
svc := NewHunyuanService(server.URL, "hy3")
|
||||
rec := httptest.NewRecorder()
|
||||
req, _ := http.NewRequest("POST", "/v1/chat/completions", nil)
|
||||
|
||||
@@ -230,7 +242,7 @@ func TestHunyuanReasoningAndToolCallingStreaming(t *testing.T) {
|
||||
server := httptest.NewServer(handler)
|
||||
defer server.Close()
|
||||
|
||||
svc := NewHunyuanService(server.URL)
|
||||
svc := NewHunyuanService(server.URL, "hy3")
|
||||
rec := httptest.NewRecorder()
|
||||
req, _ := http.NewRequest("POST", "/v1/chat/completions", nil)
|
||||
|
||||
|
||||
@@ -375,29 +375,34 @@ func parseGradioStreamData(dataJSON string) (string, string, []ToolCall, bool) {
|
||||
}
|
||||
|
||||
type HunyuanService struct {
|
||||
endpoint string
|
||||
client *http.Client
|
||||
endpoint string
|
||||
modelName string
|
||||
client *http.Client
|
||||
}
|
||||
|
||||
func NewHunyuanService(endpoint string) *HunyuanService {
|
||||
func NewHunyuanService(endpoint string, modelName string) *HunyuanService {
|
||||
cleanEndpoint := strings.TrimRight(endpoint, "/")
|
||||
if modelName == "" {
|
||||
modelName = "hy3"
|
||||
}
|
||||
return &HunyuanService{
|
||||
endpoint: cleanEndpoint,
|
||||
client: &http.Client{Timeout: 300 * time.Second},
|
||||
endpoint: cleanEndpoint,
|
||||
modelName: modelName,
|
||||
client: &http.Client{Timeout: 300 * time.Second},
|
||||
}
|
||||
}
|
||||
|
||||
func (s *HunyuanService) ListModels() []ModelItem {
|
||||
now := time.Now().Unix()
|
||||
return []ModelItem{
|
||||
{ID: "hy3", Object: "model", Created: now, OwnedBy: "hunyuan"},
|
||||
{ID: s.modelName, Object: "model", Created: now, OwnedBy: "hunyuan"},
|
||||
}
|
||||
}
|
||||
|
||||
func (s *HunyuanService) Chat(w http.ResponseWriter, r *http.Request, req ChatCompletionRequest) error {
|
||||
modelName := req.Model
|
||||
if modelName == "" {
|
||||
modelName = "hy3"
|
||||
modelName = s.modelName
|
||||
}
|
||||
maxTokens := ResolveMaxTokens(req)
|
||||
|
||||
@@ -722,6 +727,7 @@ func NewMux(service *HunyuanService) *http.ServeMux {
|
||||
func main() {
|
||||
portFlag := flag.String("port", "8080", "Port to listen on")
|
||||
endpointFlag := flag.String("endpoint", "https://tencent-hy3.hf.space", "Root URL of the Hunyuan Gradio space")
|
||||
modelFlag := flag.String("model", "hy3", "Exposed model name")
|
||||
uaFlag := flag.String("user-agent", DefaultUserAgent, "Custom User-Agent header")
|
||||
uaShortFlag := flag.String("ua", "", "Alias for -user-agent")
|
||||
flag.Parse()
|
||||
@@ -731,11 +737,12 @@ func main() {
|
||||
ConfiguredUserAgent = *uaShortFlag
|
||||
}
|
||||
|
||||
service := NewHunyuanService(*endpointFlag)
|
||||
service := NewHunyuanService(*endpointFlag, *modelFlag)
|
||||
mux := NewMux(service)
|
||||
|
||||
fmt.Printf("hygate starting on port %s...\n", *portFlag)
|
||||
fmt.Printf("Target Endpoint: %s\n", service.endpoint)
|
||||
fmt.Printf("Model Name: %s\n", service.modelName)
|
||||
fmt.Printf("User-Agent: %s\n", ConfiguredUserAgent)
|
||||
fmt.Printf("Endpoints:\n")
|
||||
fmt.Printf(" GET http://localhost:%s/v1/models\n", *portFlag)
|
||||
|
||||
Reference in New Issue
Block a user