Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
OpenDAS
ollama
Commits
1c4e85b4
Unverified
Commit
1c4e85b4
authored
Dec 11, 2025
by
EasonLin
Committed by
GitHub
Dec 10, 2025
Browse files
routes: add logprobs in tool calls (#13238)
parent
dac4f17f
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
99 additions
and
2 deletions
+99
-2
server/routes.go
server/routes.go
+10
-2
server/routes_generate_test.go
server/routes_generate_test.go
+89
-0
No files found.
server/routes.go
View file @
1c4e85b4
...
@@ -2195,7 +2195,7 @@ func (s *Server) ChatHandler(c *gin.Context) {
...
@@ -2195,7 +2195,7 @@ func (s *Server) ChatHandler(c *gin.Context) {
return
return
}
}
if
res
.
Message
.
Content
!=
""
||
res
.
Message
.
Thinking
!=
""
||
len
(
res
.
Message
.
ToolCalls
)
>
0
||
r
.
Done
{
if
res
.
Message
.
Content
!=
""
||
res
.
Message
.
Thinking
!=
""
||
len
(
res
.
Message
.
ToolCalls
)
>
0
||
r
.
Done
||
len
(
res
.
Logprobs
)
>
0
{
slog
.
Log
(
context
.
TODO
(),
logutil
.
LevelTrace
,
"builtin parser output"
,
"parser"
,
m
.
Config
.
Parser
,
"content"
,
content
,
"thinking"
,
thinking
,
"toolCalls"
,
toolCalls
,
"done"
,
r
.
Done
)
slog
.
Log
(
context
.
TODO
(),
logutil
.
LevelTrace
,
"builtin parser output"
,
"parser"
,
m
.
Config
.
Parser
,
"content"
,
content
,
"thinking"
,
thinking
,
"toolCalls"
,
toolCalls
,
"done"
,
r
.
Done
)
ch
<-
res
ch
<-
res
}
else
{
}
else
{
...
@@ -2235,8 +2235,16 @@ func (s *Server) ChatHandler(c *gin.Context) {
...
@@ -2235,8 +2235,16 @@ func (s *Server) ChatHandler(c *gin.Context) {
res
.
Message
.
ToolCalls
=
toolCalls
res
.
Message
.
ToolCalls
=
toolCalls
res
.
Message
.
Content
=
""
res
.
Message
.
Content
=
""
}
else
if
res
.
Message
.
Thinking
!=
""
{
}
else
if
res
.
Message
.
Thinking
!=
""
{
// don't return
// don't return
, fall through to send
}
else
{
}
else
{
// Send logprobs while content is being buffered by the parser for tool calls
if
len
(
res
.
Logprobs
)
>
0
&&
!
r
.
Done
{
logprobRes
:=
res
logprobRes
.
Message
.
Content
=
""
logprobRes
.
Message
.
ToolCalls
=
nil
ch
<-
logprobRes
}
if
r
.
Done
{
if
r
.
Done
{
res
.
Message
.
Content
=
toolParser
.
Content
()
res
.
Message
.
Content
=
toolParser
.
Content
()
ch
<-
res
ch
<-
res
...
...
server/routes_generate_test.go
View file @
1c4e85b4
...
@@ -708,6 +708,95 @@ func TestGenerateChat(t *testing.T) {
...
@@ -708,6 +708,95 @@ func TestGenerateChat(t *testing.T) {
}
}
})
})
t
.
Run
(
"messages with tools and logprobs (streaming)"
,
func
(
t
*
testing
.
T
)
{
tools
:=
[]
api
.
Tool
{
{
Type
:
"function"
,
Function
:
api
.
ToolFunction
{
Name
:
"get_weather"
,
Parameters
:
api
.
ToolFunctionParameters
{
Type
:
"object"
,
Properties
:
map
[
string
]
api
.
ToolProperty
{
"location"
:
{
Type
:
api
.
PropertyType
{
"string"
}},
},
},
},
},
}
var
wg
sync
.
WaitGroup
wg
.
Add
(
1
)
mock
.
CompletionFn
=
func
(
ctx
context
.
Context
,
r
llm
.
CompletionRequest
,
fn
func
(
r
llm
.
CompletionResponse
))
error
{
defer
wg
.
Done
()
// Simulate a response where logprobs are sent while the tool call is being buffered
responses
:=
[]
llm
.
CompletionResponse
{
{
Content
:
`{ "name": "get_weather"`
,
Done
:
false
,
Logprobs
:
[]
llm
.
Logprob
{{}},
},
{
Content
:
`,"arguments":{"location":"Seattle, WA","unit":"celsius"}}`
,
Done
:
false
,
Logprobs
:
[]
llm
.
Logprob
{{}},
},
{
Content
:
``
,
Done
:
true
,
DoneReason
:
llm
.
DoneReasonStop
,
Logprobs
:
nil
,
},
}
for
_
,
resp
:=
range
responses
{
select
{
case
<-
ctx
.
Done
()
:
return
ctx
.
Err
()
default
:
fn
(
resp
)
time
.
Sleep
(
10
*
time
.
Millisecond
)
}
}
return
nil
}
w
:=
createRequest
(
t
,
s
.
ChatHandler
,
api
.
ChatRequest
{
Model
:
"test-system"
,
Messages
:
[]
api
.
Message
{
{
Role
:
"user"
,
Content
:
"Weather?"
},
},
Tools
:
tools
,
Stream
:
&
stream
,
})
wg
.
Wait
()
if
w
.
Code
!=
http
.
StatusOK
{
t
.
Errorf
(
"expected status 200, got %d"
,
w
.
Code
)
}
decoder
:=
json
.
NewDecoder
(
w
.
Body
)
var
totalLogprobs
int
for
{
var
resp
api
.
ChatResponse
if
err
:=
decoder
.
Decode
(
&
resp
);
err
==
io
.
EOF
{
break
}
else
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
totalLogprobs
+=
len
(
resp
.
Logprobs
)
}
expectedLogprobs
:=
2
if
totalLogprobs
!=
expectedLogprobs
{
t
.
Errorf
(
"expected %d logprobs, got %d"
,
expectedLogprobs
,
totalLogprobs
)
}
})
t
.
Run
(
"status error non-streaming"
,
func
(
t
*
testing
.
T
)
{
t
.
Run
(
"status error non-streaming"
,
func
(
t
*
testing
.
T
)
{
mock
.
CompletionFn
=
func
(
ctx
context
.
Context
,
r
llm
.
CompletionRequest
,
fn
func
(
r
llm
.
CompletionResponse
))
error
{
mock
.
CompletionFn
=
func
(
ctx
context
.
Context
,
r
llm
.
CompletionRequest
,
fn
func
(
r
llm
.
CompletionResponse
))
error
{
return
api
.
StatusError
{
return
api
.
StatusError
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment