Skip to content

Commit 39a969b

Browse files
authored
fix: ai service race (#768)
1 parent 6ed7c5d commit 39a969b

2 files changed

Lines changed: 17 additions & 30 deletions

File tree

pkg/bridge/ai/api_server.go

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import (
77
"fmt"
88
"net"
99
"net/http"
10-
"sync"
1110
"time"
1211

1312
gonanoid "github.com/matoous/go-nanoid/v2"
@@ -127,14 +126,6 @@ func HandleInvoke(w http.ResponseWriter, r *http.Request) {
127126
return
128127
}
129128

130-
ci := &CacheItem{
131-
wg: &sync.WaitGroup{},
132-
ResponseWriter: w,
133-
}
134-
if _, ok := service.cache[reqID]; !ok {
135-
service.cache[reqID] = ci
136-
}
137-
138129
var req ai.InvokeRequest
139130
req.ReqID = reqID
140131

pkg/bridge/ai/service.go

Lines changed: 17 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package ai
22

33
import (
44
"fmt"
5-
"net/http"
65
"sync"
76
"time"
87

@@ -24,27 +23,19 @@ var (
2423
services *expirable.LRU[string, *Service]
2524
)
2625

27-
// CacheItem cache the http.ResponseWriter, which is used for writing response from reducer.
28-
// TODO: http.ResponseWriter is from the SimpleRestfulServer interface, should be decoupled
29-
// from here.
30-
type CacheItem struct {
31-
ResponseWriter http.ResponseWriter
32-
wg *sync.WaitGroup
33-
mu sync.Mutex
34-
}
35-
3626
// Service is used to invoke LLM Provider to get the functions to be executed,
3727
// then, use source to send arguments which returned by llm provider to target
3828
// function. Finally, use reducer to aggregate all the results, and write the
3929
// result by the http.ResponseWriter.
4030
type Service struct {
41-
credential string
42-
zipperAddr string
43-
md metadata.M
44-
source yomo.Source
45-
reducer yomo.StreamFunction
46-
cache map[string]*CacheItem
31+
credential string
32+
zipperAddr string
33+
md metadata.M
34+
source yomo.Source
35+
reducer yomo.StreamFunction
36+
// cache map[string]*CacheItem
4737
sfnCallCache map[string]*sfnAsyncCall
38+
muCallCache sync.Mutex
4839
LLMProvider
4940
}
5041

@@ -72,9 +63,9 @@ func DefaultExchangeMetadataFunc(credential string) (metadata.M, error) {
7263

7364
func newService(credential string, zipperAddr string, aiProvider LLMProvider, exFn ExchangeMetadataFunc) (*Service, error) {
7465
s := &Service{
75-
credential: credential,
76-
zipperAddr: zipperAddr,
77-
cache: make(map[string]*CacheItem),
66+
credential: credential,
67+
zipperAddr: zipperAddr,
68+
// cache: make(map[string]*CacheItem),
7869
LLMProvider: aiProvider,
7970
sfnCallCache: make(map[string]*sfnAsyncCall),
8071
}
@@ -116,7 +107,6 @@ func (s *Service) Release() {
116107
if s.reducer != nil {
117108
s.reducer.Close()
118109
}
119-
clear(s.cache)
120110
}
121111

122112
func (s *Service) createSource() (yomo.Source, error) {
@@ -156,7 +146,9 @@ func (s *Service) createReducer() (yomo.StreamFunction, error) {
156146
reqID := invoke.ReqID
157147

158148
// write parallel function calling results to cache, after all the results are written, the reducer will be done
149+
s.muCallCache.Lock()
159150
c, ok := s.sfnCallCache[reqID]
151+
s.muCallCache.Unlock()
160152
if !ok {
161153
ylog.Error("[sfn-reducer] req_id not found", "req_id", reqID)
162154
return
@@ -242,7 +234,9 @@ func (s *Service) runFunctionCalls(fns map[uint32][]*ai.ToolCall, reqID string)
242234
wg: &sync.WaitGroup{},
243235
val: make(map[string]ai.ToolMessage),
244236
}
237+
s.muCallCache.Lock()
245238
s.sfnCallCache[reqID] = asyncCall
239+
s.muCallCache.Unlock()
246240

247241
for tag, tcs := range fns {
248242
ylog.Debug("+++invoke toolCalls", "tag", tag, "len(toolCalls)", len(tcs), "reqID", reqID)
@@ -262,11 +256,13 @@ func (s *Service) runFunctionCalls(fns map[uint32][]*ai.ToolCall, reqID string)
262256

263257
arr := make([]ai.ToolMessage, 0)
264258

259+
asyncCall.mu.RLock()
265260
for _, call := range asyncCall.val {
266261
ylog.Debug("---invoke done", "id", call.ToolCallId, "content", call.Content)
267262
call.Role = "tool"
268263
arr = append(arr, call)
269264
}
265+
asyncCall.mu.RUnlock()
270266

271267
return arr, nil
272268
}
@@ -307,6 +303,6 @@ func init() {
307303

308304
type sfnAsyncCall struct {
309305
wg *sync.WaitGroup
310-
mu sync.Mutex
306+
mu sync.RWMutex
311307
val map[string]ai.ToolMessage
312308
}

0 commit comments

Comments
 (0)