Skip to content

Commit 4b771a6

Browse files
committed
Updated
1 parent 4f4f6d6 commit 4b771a6

File tree

4 files changed

+105
-80
lines changed

4 files changed

+105
-80
lines changed

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ require (
1414

1515
require (
1616
github.com/davecgh/go-spew v1.1.1 // indirect
17+
github.com/go-telegram-bot-api/telegram-bot-api/v5 v5.5.1 // indirect
1718
github.com/mattn/go-colorable v0.1.4 // indirect
1819
github.com/mattn/go-isatty v0.0.11 // indirect
1920
github.com/mattn/go-runewidth v0.0.15 // indirect

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ github.com/djthorpe/go-errors v1.0.3 h1:GZeMPkC1mx2vteXLI/gvxZS0Ee9zxzwD1mcYyKU5
1313
github.com/djthorpe/go-errors v1.0.3/go.mod h1:HtfrZnMd6HsX75Mtbv9Qcnn0BqOrrFArvCaj3RMnZhY=
1414
github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s=
1515
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
16+
github.com/go-telegram-bot-api/telegram-bot-api/v5 v5.5.1 h1:wG8n/XJQ07TmjbITcGiUaOtXxdrINDz1b0J1w0SzqDc=
17+
github.com/go-telegram-bot-api/telegram-bot-api/v5 v5.5.1/go.mod h1:A2S0CWkNylc2phvKXWBBdD3K0iGnDBGbzRpISP2zBl8=
1618
github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM=
1719
github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg=
1820
github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA=

pkg/ollama/completion.go

Lines changed: 41 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ type Response struct {
2020
CreatedAt time.Time `json:"created_at"`
2121
Done bool `json:"done"`
2222
Reason string `json:"done_reason,omitempty"`
23-
Response *string `json:"response"` // For completion
23+
Response *string `json:"response,omitempty"` // For completion
2424
Message `json:"message"` // For chat
2525
Metrics
2626
}
@@ -90,6 +90,7 @@ type reqCompletion struct {
9090
Options map[string]any `json:"options,omitempty"`
9191
}
9292

93+
// Create a completion from a prompt
9394
func (model *model) Completion(ctx context.Context, prompt string, opts ...llm.Opt) (llm.Completion, error) {
9495
// Apply options - including prompt options
9596
opt, err := llm.ApplyPromptOpts(opts...)
@@ -125,126 +126,86 @@ func (model *model) Completion(ctx context.Context, prompt string, opts ...llm.O
125126
return model.request(ctx, req, opt.StreamFn(), client.OptPath("generate"))
126127
}
127128

128-
func (model *model) request(ctx context.Context, req client.Payload, streamfn func(llm.Completion), opts ...client.RequestOpt) (*Response, error) {
129-
var delta, response Response
130-
if streamfn != nil {
131-
opts = append(opts, client.OptJsonStreamCallback(func(v any) error {
132-
if v, ok := v.(*Response); !ok || v == nil {
133-
return llm.ErrConflict.Withf("Invalid stream response: %v", delta)
134-
} else if err := streamEvent(&response, v); err != nil {
135-
return err
136-
}
137-
if fn := streamfn; fn != nil {
138-
fn(&response)
139-
}
140-
return nil
141-
}))
142-
}
143-
144-
// Response
145-
if err := model.DoWithContext(ctx, req, &delta, opts...); err != nil {
146-
return nil, err
147-
}
148-
149-
// Return success
150-
if streamfn != nil {
151-
return &response, nil
152-
} else if delta.Response != nil {
153-
delta.Message = Message{
154-
RoleContent: RoleContent{
155-
Role: "user",
156-
Content: *delta.Response,
157-
},
158-
}
159-
return &delta, nil
160-
} else {
161-
return nil, llm.ErrInternalServerError.Withf("No response")
162-
}
163-
}
164-
165-
// Create a completion from a chat session
166-
func (model *model) Chat(context.Context, []llm.Completion, ...llm.Opt) (llm.Completion, error) {
167-
return nil, llm.ErrNotImplemented
168-
}
169-
170-
/*
171129
type reqChat struct {
172-
Model string `json:"model"`
173-
Messages []*Message `json:"messages"`
174-
Tools []llm.Tool `json:"tools,omitempty"`
175-
Format string `json:"format,omitempty"`
176-
Options map[string]interface{} `json:"options,omitempty"`
177-
Stream bool `json:"stream"`
178-
KeepAlive *time.Duration `json:"keep_alive,omitempty"`
130+
Model string `json:"model"`
131+
Messages []llm.Completion `json:"messages"`
132+
Tools []llm.Tool `json:"tools,omitempty"`
133+
Format string `json:"format,omitempty"`
134+
Options map[string]any `json:"options,omitempty"`
135+
Stream *bool `json:"stream"`
136+
KeepAlive *time.Duration `json:"keep_alive,omitempty"`
179137
}
180138

181-
func (ollama *Client) Chat(ctx context.Context, context llm.Context, opts ...llm.Opt) (*Response, error) {
139+
// Create a completion from a chat session
140+
func (model *model) Chat(ctx context.Context, completions []llm.Completion, opts ...llm.Opt) (llm.Completion, error) {
182141
// Apply options
183142
opt, err := llm.ApplyOpts(opts...)
184143
if err != nil {
185144
return nil, err
186145
}
187146

188-
// Append the system prompt at the beginning
189-
messages := make([]*Message, 0, len(context.(*session).seq)+1)
147+
// Create the completions including the system prompt
148+
messages := make([]llm.Completion, 0, len(completions)+1)
190149
if system := opt.SystemPrompt(); system != "" {
191-
messages = append(messages, systemPrompt(system))
192-
}
193-
194-
// Always append the first message of each completion
195-
for _, message := range context.(*session).seq {
196-
messages = append(messages, message)
150+
messages = append(messages, messagefactory{}.SystemPrompt(system))
197151
}
152+
messages = append(messages, completions...)
198153

199154
// Request
200155
req, err := client.NewJSONRequest(reqChat{
201-
Model: context.(*session).model.Name(),
156+
Model: model.Name(),
202157
Messages: messages,
203-
Tools: optTools(ollama, opt),
158+
Tools: optTools(model.Client, opt),
204159
Format: optFormat(opt),
205160
Options: optOptions(opt),
206-
Stream: optStream(ollama, opt),
161+
Stream: optStream(model.Client, opt),
207162
KeepAlive: optKeepAlive(opt),
208163
})
209164
if err != nil {
210165
return nil, err
211166
}
212167

213-
// Response
214-
var response, delta Response
215-
reqopts := []client.RequestOpt{
216-
client.OptPath("chat"),
217-
}
218-
if optStream(ollama, opt) {
219-
reqopts = append(reqopts, client.OptJsonStreamCallback(func(v any) error {
168+
// Make the request
169+
return model.request(ctx, req, opt.StreamFn(), client.OptPath("chat"))
170+
}
171+
172+
///////////////////////////////////////////////////////////////////////////////
173+
// PRIVATE METHODS
174+
175+
func (model *model) request(ctx context.Context, req client.Payload, streamfn func(llm.Completion), opts ...client.RequestOpt) (*Response, error) {
176+
var delta, response Response
177+
if streamfn != nil {
178+
opts = append(opts, client.OptJsonStreamCallback(func(v any) error {
220179
if v, ok := v.(*Response); !ok || v == nil {
221-
return llm.ErrConflict.Withf("Invalid stream response: %v", v)
180+
return llm.ErrConflict.Withf("Invalid stream response: %v", delta)
222181
} else if err := streamEvent(&response, v); err != nil {
223182
return err
224183
}
225-
if fn := opt.StreamFn(); fn != nil {
184+
if fn := streamfn; fn != nil {
226185
fn(&response)
227186
}
228187
return nil
229188
}))
230189
}
231190

232191
// Response
233-
if err := ollama.DoWithContext(ctx, req, &delta, reqopts...); err != nil {
192+
if err := model.DoWithContext(ctx, req, &delta, opts...); err != nil {
234193
return nil, err
235194
}
236195

237196
// Return success
238-
if optStream(ollama, opt) {
197+
if streamfn != nil {
239198
return &response, nil
240-
} else {
241-
return &delta, nil
199+
} else if delta.Response != nil {
200+
delta.Message = Message{
201+
RoleContent: RoleContent{
202+
Role: "user",
203+
Content: *delta.Response,
204+
},
205+
}
242206
}
207+
return &delta, nil
243208
}
244-
*/
245-
246-
///////////////////////////////////////////////////////////////////////////////
247-
// PRIVATE METHODS
248209

249210
func streamEvent(response, delta *Response) error {
250211
// Completion instead of chat

pkg/telegram/telegram.go

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package telegram
2+
3+
import (
4+
"context"
5+
"fmt"
6+
7+
// Packages
8+
telegram "github.com/go-telegram-bot-api/telegram-bot-api/v5"
9+
)
10+
11+
/////////////////////////////////////////////////////////////////////
12+
// TYPES
13+
14+
type t struct {
15+
*telegram.BotAPI
16+
}
17+
18+
/////////////////////////////////////////////////////////////////////
19+
// LIFECYCLE
20+
21+
func NewTelegram(token string) (*t, error) {
22+
bot, err := telegram.NewBotAPI(token)
23+
if err != nil {
24+
return nil, err
25+
}
26+
27+
// Create a new telegram instance
28+
telegram := &t{bot}
29+
30+
// Return the instance
31+
return telegram, nil
32+
}
33+
34+
/////////////////////////////////////////////////////////////////////
35+
// PUBLIC METHODS
36+
37+
func (t *t) Run(ctx context.Context) error {
38+
updates := t.GetUpdatesChan(telegram.NewUpdate(0))
39+
FOR_LOOP:
40+
for {
41+
select {
42+
case <-ctx.Done():
43+
break FOR_LOOP
44+
case evt := <-updates:
45+
if evt.Message != nil && !evt.Message.IsCommand() {
46+
t.handleMessage(evt.Message)
47+
}
48+
}
49+
}
50+
51+
// Return success
52+
return nil
53+
}
54+
55+
/////////////////////////////////////////////////////////////////////
56+
// PRIVATE METHODS
57+
58+
func (t *t) handleMessage(update *telegram.Message) {
59+
fmt.Println("Received message from", update.From.UserName)
60+
fmt.Println(" => ", update.Text)
61+
}

0 commit comments

Comments
 (0)