Skip to content

Commit 680d983

Browse files
committed
Add allganize feature: history, break, GPTSCRIPT_PROGRESS_TIME_STEP_MS
1 parent eaaf0cd commit 680d983

File tree

8 files changed

+131
-7
lines changed

8 files changed

+131
-7
lines changed

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,5 @@
99
/binaries
1010
/checksums.txt
1111
/.env*
12+
ui/
13+
gptscript.code-workspace

Makefile

+12
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@ all: build
55
build-exe:
66
GOOS=windows go build -o bin/gptscript.exe -tags "${GO_TAGS}" .
77

8+
build-linux-amd64:
9+
GOOS=linux GOARCH=amd64 go build -o bin/gptscript_linux_amd64 -tags "${GO_TAGS}" .
10+
11+
build-linux-arm64:
12+
GOOS=linux GOARCH=arm64 go build -o bin/gptscript_linux_arm64 -tags "${GO_TAGS}" .
13+
814
build:
915
CGO_ENABLED=0 go build -o bin/gptscript -tags "${GO_TAGS}" -ldflags "-s -w" .
1016

@@ -23,6 +29,12 @@ smoke:
2329
go test -v -tags='smoke' ./pkg/tests/smoke/...
2430

2531
GOLANGCI_LINT_VERSION ?= v1.60.1
32+
33+
cp: build-linux-amd64 build-linux-arm64
34+
cp bin/gptscript_linux_amd64 ~/Workspace/streamlit-gptscript/gptscript/bin/gptscript
35+
cp bin/gptscript_linux_amd64 ~/Workspace/streamlit-gptscript/gptscript/bin/gptscript_linux_amd64
36+
cp bin/gptscript_linux_arm64 ~/Workspace/streamlit-gptscript/gptscript/bin/gptscript_linux_arm64
37+
2638
lint:
2739
if ! command -v golangci-lint &> /dev/null; then \
2840
echo "Could not find golangci-lint, installing version $(GOLANGCI_LINT_VERSION)."; \

examples/sh.gpt

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
name: main
2+
tools: answer, extract_hashtag
3+
Chat: True
4+
5+
당신은 주어진 툴을 이용해서 사용자의 질문에 대답하는 agent입니다.
6+
처음에는 "안녕"이라 말해주세요.
7+
8+
---
9+
name: answer
10+
description: 사용자의 질문에 대해서 답해줍니다.
11+
args: question : 사용자의 질문
12+
args: hashtags : example) ["postgres", "mysql"]. 이 인자를 얻기위해서는 반드시 extract_hashtag tool을 사용한 결과로 해야합니다.
13+
tools: extract_hashtag
14+
15+
#!/usr/bin/env python
16+
17+
print("melong")
18+
19+
---
20+
name: extract_hashtag
21+
description: 사용자의 질문에서 해시태그를 추출합니다.
22+
args: question : 사용자의 질문
23+
24+
#!/usr/bin/env python
25+
26+
print("hash1, hash2")

go.mod

+2
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ require (
5353
github.com/bodgit/plumbing v1.2.0 // indirect
5454
github.com/bodgit/sevenzip v1.3.0 // indirect
5555
github.com/bodgit/windows v1.0.0 // indirect
56+
github.com/cespare/xxhash/v2 v2.2.0 // indirect
5657
github.com/charmbracelet/glamour v0.7.0 // indirect
5758
github.com/charmbracelet/lipgloss v0.11.0 // indirect
5859
github.com/charmbracelet/x/ansi v0.1.1 // indirect
@@ -62,6 +63,7 @@ require (
6263
github.com/cpuguy83/go-md2man/v2 v2.0.3 // indirect
6364
github.com/cyphar/filepath-securejoin v0.2.4 // indirect
6465
github.com/davecgh/go-spew v1.1.1 // indirect
66+
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
6567
github.com/dlclark/regexp2 v1.4.0 // indirect
6668
github.com/dsnet/compress v0.0.1 // indirect
6769
github.com/emirpasic/gods v1.18.1 // indirect

pkg/engine/control.go

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package engine
2+
3+
import (
4+
"encoding/json"
5+
"fmt"
6+
7+
"github.com/gptscript-ai/gptscript/pkg/types"
8+
)
9+
10+
func (e *Engine) runBreak(tool types.Tool, input string) (cmdOut *Return, cmdErr error) {
11+
info, err := json.Marshal(tool)
12+
if err != nil {
13+
return nil, err
14+
}
15+
var dict map[string]interface{}
16+
json.Unmarshal(info, &dict)
17+
dict["input"] = input
18+
info, err = json.Marshal(dict)
19+
return nil, fmt.Errorf("TOOL_BREAK: %s", info)
20+
}

pkg/engine/engine.go

+42
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
package engine
22

33
import (
4+
"bufio"
45
"context"
56
"encoding/json"
67
"fmt"
8+
"log/slog"
9+
"os"
710
"strings"
811
"sync"
912

@@ -281,6 +284,39 @@ func populateMessageParams(ctx Context, completion *types.CompletionRequest, too
281284
return nil
282285
}
283286

287+
func putHistory(messages []types.CompletionMessage) []types.CompletionMessage {
288+
prevHistoryFile := strings.TrimSpace(os.Getenv("GPTSCRIPT_PREVIOUS_HISTORY_FILE"))
289+
290+
if prevHistoryFile == "" {
291+
return messages
292+
}
293+
fp, err := os.Open(prevHistoryFile)
294+
if err != nil {
295+
slog.Error("Open Error", err)
296+
return messages
297+
}
298+
defer fp.Close()
299+
300+
scanner := bufio.NewScanner(fp)
301+
302+
prevMessages := []types.CompletionMessage{}
303+
for scanner.Scan() {
304+
var message types.CompletionMessage
305+
line := scanner.Text()
306+
err := json.Unmarshal([]byte(line), &message)
307+
if err != nil {
308+
slog.Error("Unmarshal Error", err)
309+
return messages
310+
}
311+
if message.Role == "system" {
312+
continue
313+
}
314+
prevMessages = append(prevMessages, message)
315+
}
316+
317+
return append(messages, prevMessages...)
318+
}
319+
284320
func (e *Engine) Start(ctx Context, input string) (ret *Return, _ error) {
285321
tool := ctx.Tool
286322

@@ -299,6 +335,8 @@ func (e *Engine) Start(ctx Context, input string) (ret *Return, _ error) {
299335
return e.runOpenAPI(tool, input)
300336
} else if tool.IsEcho() {
301337
return e.runEcho(tool)
338+
} else if tool.IsBreak() {
339+
return e.runBreak(tool, input)
302340
}
303341
s, err := e.runCommand(ctx, tool, input, ctx.ToolCategory)
304342
if err != nil {
@@ -322,6 +360,10 @@ func (e *Engine) Start(ctx Context, input string) (ret *Return, _ error) {
322360
input = ""
323361
}
324362

363+
if ctx.Parent == nil {
364+
completion.Messages = putHistory(completion.Messages)
365+
}
366+
325367
if input != "" {
326368
completion.Messages = append(completion.Messages, types.CompletionMessage{
327369
Role: types.CompletionMessageRoleTypeUser,

pkg/runner/runner.go

+22-7
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@ import (
55
"encoding/json"
66
"errors"
77
"fmt"
8+
"os"
89
"sort"
10+
"strconv"
911
"strings"
1012
"sync"
1113
"time"
@@ -636,17 +638,29 @@ func streamProgress(callCtx *engine.Context, monitor Monitor) (chan<- types.Comp
636638

637639
wg := sync.WaitGroup{}
638640
wg.Add(1)
641+
progressTimeStepMs, err := strconv.Atoi(os.Getenv("GPTSCRIPT_PROGRESS_TIME_STEP_MS"))
642+
if err != nil {
643+
// 기본값 250ms를 사용하거나 오류를 처리합니다.
644+
progressTimeStepMs = 250
645+
}
646+
progressTimeStep := time.Duration(progressTimeStepMs) * time.Millisecond
639647
go func() {
640648
defer wg.Done()
649+
lastSentTimeMap := make(map[string]time.Time)
641650
for status := range progress {
642651
if message := status.PartialResponse; message != nil {
643-
monitor.Event(Event{
644-
Time: time.Now(),
645-
CallContext: callCtx.GetCallContext(),
646-
Type: EventTypeCallProgress,
647-
ChatCompletionID: status.CompletionID,
648-
Content: getEventContent(message.String(), *callCtx),
649-
})
652+
now := time.Now()
653+
lastSentTime, ok := lastSentTimeMap[status.CompletionID]
654+
if !ok || now.Sub(lastSentTime) > progressTimeStep {
655+
lastSentTimeMap[status.CompletionID] = now
656+
monitor.Event(Event{
657+
Time: time.Now(),
658+
CallContext: callCtx.GetCallContext(),
659+
Type: EventTypeCallProgress,
660+
ChatCompletionID: status.CompletionID,
661+
Content: getEventContent(message.String(), *callCtx),
662+
})
663+
}
650664
} else {
651665
monitor.Event(Event{
652666
Time: time.Now(),
@@ -658,6 +672,7 @@ func streamProgress(callCtx *engine.Context, monitor Monitor) (chan<- types.Comp
658672
Usage: status.Usage,
659673
ChatResponseCached: status.Cached,
660674
})
675+
delete(lastSentTimeMap, status.CompletionID)
661676
}
662677
}
663678
}()

pkg/types/tool.go

+5
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ const (
1919
DaemonPrefix = "#!sys.daemon"
2020
OpenAPIPrefix = "#!sys.openapi"
2121
EchoPrefix = "#!sys.echo"
22+
BreakPrefix = "#!sys.break"
2223
CommandPrefix = "#!"
2324
)
2425

@@ -778,6 +779,10 @@ func (t Tool) IsEcho() bool {
778779
return strings.HasPrefix(t.Instructions, EchoPrefix)
779780
}
780781

782+
func (t Tool) IsBreak() bool {
783+
return strings.HasPrefix(t.Instructions, BreakPrefix)
784+
}
785+
781786
func (t Tool) IsHTTP() bool {
782787
return strings.HasPrefix(t.Instructions, "#!http://") ||
783788
strings.HasPrefix(t.Instructions, "#!https://")

0 commit comments

Comments
 (0)