-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.go
150 lines (130 loc) · 4.48 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
// Package main provides an example of using the TabbyAPI client for streaming chat completions.
package main
import (
"context"
"fmt"
"io"
"log"
"os"
"time"
"github.com/pixelsquared/go-tabbyapi/tabby"
)
func main() {
// Get API endpoint and key from environment variables
endpoint := getEnvOrDefault("TABBY_API_ENDPOINT", "http://localhost:8080")
apiKey := os.Getenv("TABBY_API_KEY")
// Create a new TabbyAPI client
client := tabby.NewClient(
tabby.WithBaseURL(endpoint),
tabby.WithAPIKey(apiKey),
tabby.WithTimeout(60*time.Second), // Longer timeout for streaming
)
// Ensure the client is closed properly
defer client.Close()
// Create a context with timeout
ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
defer cancel()
// Create a chat completion request with stream option enabled
req := &tabby.ChatCompletionRequest{
Messages: []tabby.ChatMessage{
{
Role: tabby.ChatMessageRoleSystem,
Content: "You are a creative writing assistant that specializes in crafting stories.",
},
{
Role: tabby.ChatMessageRoleUser,
Content: "Write a short story about a future where AI and humans collaborate to solve climate change.",
},
},
MaxTokens: 300,
Temperature: 0.8,
TopP: 0.95,
TopK: 50,
Stream: true, // Enable streaming response
}
fmt.Println("Starting streaming chat completion...")
// Call the streaming API
stream, err := client.Chat().CreateStream(ctx, req)
if err != nil {
log.Fatalf("Error creating chat completion stream: %v", err)
}
// Ensure the stream is closed properly
defer stream.Close()
// Process the streaming response
var fullContent string
fmt.Println("Assistant: ")
// Track the current role for rendering purposes (as ChatMessageRole)
var currentRole tabby.ChatMessageRole
for {
// Receive the next chunk from the stream
response, err := stream.Recv()
// Check for end of stream or errors
if err != nil {
if err == io.EOF {
// End of stream
break
}
// Check if it's a stream closed error from the client
if err == tabby.ErrStreamClosed {
fmt.Println("\nStream was closed")
break
}
// Handle other errors
log.Fatalf("Error receiving from stream: %v", err)
}
// Process the response chunk
if len(response.Choices) > 0 {
delta := response.Choices[0].Delta
// Print role change if it happens (usually only on first chunk)
if delta.Role != "" && delta.Role != currentRole {
currentRole = delta.Role
}
// Add content to our running total if present
if delta.Content != "" {
fullContent += delta.Content
fmt.Print(delta.Content) // Print without newline for continuous output
}
// If we received a finish reason, we're done
if response.Choices[0].FinishReason != "" {
fmt.Printf("\n\nFinish reason: %s\n", response.Choices[0].FinishReason)
break
}
}
}
fmt.Println("\n\nStreaming complete!")
fmt.Printf("Total generated content length: %d characters\n", len(fullContent))
// Example of how to use the streamed content in a follow-up request
fmt.Println("\nYou could continue the conversation with a follow-up request like this:")
fmt.Printf("User: Now continue the story with a twist ending.\n")
fmt.Println("Example code for follow-up request:")
// Using multiple Print statements instead of a raw string literal to avoid newline issues
fmt.Print("followUpReq := &tabby.ChatCompletionRequest{\n")
fmt.Print(" Messages: []tabby.ChatMessage{\n")
fmt.Print(" {\n")
fmt.Print(" Role: tabby.ChatMessageRoleSystem,\n")
fmt.Print(" Content: \"You are a creative writing assistant that specializes in crafting stories.\",\n")
fmt.Print(" },\n")
fmt.Print(" {\n")
fmt.Print(" Role: tabby.ChatMessageRoleUser,\n")
fmt.Print(" Content: \"Write a short story about a future where AI and humans collaborate to solve climate change.\",\n")
fmt.Print(" },\n")
fmt.Print(" {\n")
fmt.Print(" Role: tabby.ChatMessageRoleAssistant,\n")
fmt.Print(" Content: fullContent,\n")
fmt.Print(" },\n")
fmt.Print(" {\n")
fmt.Print(" Role: tabby.ChatMessageRoleUser,\n")
fmt.Print(" Content: \"Now continue the story with a twist ending.\",\n")
fmt.Print(" },\n")
fmt.Print(" },\n")
fmt.Print(" // Additional parameters would be set here\n")
fmt.Print("}\n")
}
// getEnvOrDefault returns the value of the environment variable or a default value
func getEnvOrDefault(key, defaultValue string) string {
value := os.Getenv(key)
if value == "" {
return defaultValue
}
return value
}