Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
math_tutor_dev
public_math_tutor
Commits
82adf746
Commit
82adf746
authored
Jun 24, 2026
by
Kantz
Browse files
refactoring
parent
faffe19f
Changes
1
Hide whitespace changes
Inline
Side-by-side
math-tutor/backend/test/test_llm_provider.py
View file @
82adf746
...
@@ -81,6 +81,7 @@ if importlib.util.find_spec("mcp") is None:
...
@@ -81,6 +81,7 @@ if importlib.util.find_spec("mcp") is None:
from
app
import
config
from
app
import
config
from
app.deterministic_services
import
llm_client
from
app.deterministic_services
import
llm_client
from
app.deterministic_services
import
llm_tool_client
from
app.deterministic_services
import
tool_log_context
from
app.deterministic_services
import
tool_log_context
from
app.deterministic_services.orchestrators
import
orchestrator_tutor
from
app.deterministic_services.orchestrators
import
orchestrator_tutor
from
app.deterministic_services.orchestrators.orchestrator_base
import
ChatState
from
app.deterministic_services.orchestrators.orchestrator_base
import
ChatState
...
@@ -219,7 +220,7 @@ class LLMClientProviderTest(unittest.TestCase):
...
@@ -219,7 +220,7 @@ class LLMClientProviderTest(unittest.TestCase):
),
patch
.
object
(
),
patch
.
object
(
llm_client
,
"_chat_openai_compatible"
,
return_value
=
expected
llm_client
,
"_chat_openai_compatible"
,
return_value
=
expected
)
as
openai_chat
,
patch
.
object
(
)
as
openai_chat
,
patch
.
object
(
llm_client
,
"
_
run_tool_chat_sync"
llm_client
,
"run_tool_chat_sync"
)
as
tool_chat
,
patch
.
object
(
)
as
tool_chat
,
patch
.
object
(
llm_client
,
"_chat_mistral"
llm_client
,
"_chat_mistral"
)
as
mistral_chat
,
patch
.
object
(
)
as
mistral_chat
,
patch
.
object
(
...
@@ -246,7 +247,7 @@ class LLMClientProviderTest(unittest.TestCase):
...
@@ -246,7 +247,7 @@ class LLMClientProviderTest(unittest.TestCase):
),
patch
.
object
(
),
patch
.
object
(
llm_client
,
"_record_call"
,
side_effect
=
lambda
result
,
tokens
=
None
:
result
llm_client
,
"_record_call"
,
side_effect
=
lambda
result
,
tokens
=
None
:
result
),
patch
.
object
(
),
patch
.
object
(
llm_client
,
"
_
run_tool_chat_sync"
,
return_value
=
expected
llm_client
,
"run_tool_chat_sync"
,
return_value
=
expected
)
as
tool_chat
,
patch
.
object
(
)
as
tool_chat
,
patch
.
object
(
llm_client
,
"_chat_openai_compatible"
llm_client
,
"_chat_openai_compatible"
)
as
openai_chat
:
)
as
openai_chat
:
...
@@ -271,7 +272,7 @@ class LLMClientProviderTest(unittest.TestCase):
...
@@ -271,7 +272,7 @@ class LLMClientProviderTest(unittest.TestCase):
),
patch
.
object
(
),
patch
.
object
(
llm_client
,
"_chat_openai_compatible"
,
return_value
=
expected
llm_client
,
"_chat_openai_compatible"
,
return_value
=
expected
)
as
compatible_chat
,
patch
.
object
(
)
as
compatible_chat
,
patch
.
object
(
llm_client
,
"
_
run_tool_chat_sync"
llm_client
,
"run_tool_chat_sync"
)
as
tool_chat
,
patch
.
object
(
)
as
tool_chat
,
patch
.
object
(
llm_client
,
"_chat_mistral"
llm_client
,
"_chat_mistral"
)
as
mistral_chat
,
patch
.
object
(
)
as
mistral_chat
,
patch
.
object
(
...
@@ -298,7 +299,7 @@ class LLMClientProviderTest(unittest.TestCase):
...
@@ -298,7 +299,7 @@ class LLMClientProviderTest(unittest.TestCase):
),
patch
.
object
(
),
patch
.
object
(
llm_client
,
"_record_call"
,
side_effect
=
lambda
result
,
tokens
=
None
:
result
llm_client
,
"_record_call"
,
side_effect
=
lambda
result
,
tokens
=
None
:
result
),
patch
.
object
(
),
patch
.
object
(
llm_client
,
"
_
run_tool_chat_sync"
,
return_value
=
expected
llm_client
,
"run_tool_chat_sync"
,
return_value
=
expected
)
as
tool_chat
,
patch
.
object
(
)
as
tool_chat
,
patch
.
object
(
llm_client
,
"_chat_openai_compatible"
llm_client
,
"_chat_openai_compatible"
)
as
compatible_chat
:
)
as
compatible_chat
:
...
@@ -323,7 +324,7 @@ class LLMClientProviderTest(unittest.TestCase):
...
@@ -323,7 +324,7 @@ class LLMClientProviderTest(unittest.TestCase):
),
patch
.
object
(
),
patch
.
object
(
llm_client
,
"_chat_openai_compatible"
llm_client
,
"_chat_openai_compatible"
)
as
openai_chat
,
patch
.
object
(
)
as
openai_chat
,
patch
.
object
(
llm_client
,
"
_
run_tool_chat_sync"
llm_client
,
"run_tool_chat_sync"
)
as
tool_chat
,
patch
.
object
(
)
as
tool_chat
,
patch
.
object
(
llm_client
,
"_chat_mistral"
,
return_value
=
expected
llm_client
,
"_chat_mistral"
,
return_value
=
expected
)
as
mistral_chat
,
patch
.
object
(
)
as
mistral_chat
,
patch
.
object
(
...
@@ -350,7 +351,7 @@ class LLMClientProviderTest(unittest.TestCase):
...
@@ -350,7 +351,7 @@ class LLMClientProviderTest(unittest.TestCase):
),
patch
.
object
(
),
patch
.
object
(
llm_client
,
"_record_call"
,
side_effect
=
lambda
result
,
tokens
=
None
:
result
llm_client
,
"_record_call"
,
side_effect
=
lambda
result
,
tokens
=
None
:
result
),
patch
.
object
(
),
patch
.
object
(
llm_client
,
"
_
run_tool_chat_sync"
llm_client
,
"run_tool_chat_sync"
)
as
tool_chat
,
patch
.
object
(
)
as
tool_chat
,
patch
.
object
(
llm_client
,
"_chat_mistral"
,
return_value
=
expected
llm_client
,
"_chat_mistral"
,
return_value
=
expected
)
as
mistral_chat
:
)
as
mistral_chat
:
...
@@ -374,7 +375,7 @@ class LLMClientProviderTest(unittest.TestCase):
...
@@ -374,7 +375,7 @@ class LLMClientProviderTest(unittest.TestCase):
)
as
openai_chat
,
patch
.
object
(
)
as
openai_chat
,
patch
.
object
(
llm_client
,
"_chat_mistral"
llm_client
,
"_chat_mistral"
)
as
mistral_chat
,
patch
.
object
(
)
as
mistral_chat
,
patch
.
object
(
llm_client
,
"
_
run_tool_chat_sync"
llm_client
,
"run_tool_chat_sync"
)
as
tool_chat
,
patch
.
object
(
)
as
tool_chat
,
patch
.
object
(
llm_client
,
"_chat_ollama"
,
return_value
=
expected
llm_client
,
"_chat_ollama"
,
return_value
=
expected
)
as
ollama_chat
:
)
as
ollama_chat
:
...
@@ -396,7 +397,7 @@ class LLMClientProviderTest(unittest.TestCase):
...
@@ -396,7 +397,7 @@ class LLMClientProviderTest(unittest.TestCase):
),
patch
.
object
(
),
patch
.
object
(
llm_client
,
"_record_call"
,
side_effect
=
lambda
result
,
tokens
=
None
:
result
llm_client
,
"_record_call"
,
side_effect
=
lambda
result
,
tokens
=
None
:
result
),
patch
.
object
(
),
patch
.
object
(
llm_client
,
"
_
run_tool_chat_sync"
,
return_value
=
expected
llm_client
,
"run_tool_chat_sync"
,
return_value
=
expected
)
as
tool_chat
,
patch
.
object
(
)
as
tool_chat
,
patch
.
object
(
llm_client
,
"_chat_ollama"
llm_client
,
"_chat_ollama"
)
as
ollama_chat
:
)
as
ollama_chat
:
...
@@ -453,7 +454,7 @@ class LLMClientProviderTest(unittest.TestCase):
...
@@ -453,7 +454,7 @@ class LLMClientProviderTest(unittest.TestCase):
)
as
ensure_quota
,
patch
.
object
(
)
as
ensure_quota
,
patch
.
object
(
llm_client
,
"_record_call"
,
side_effect
=
lambda
result
,
tokens
=
None
:
result
llm_client
,
"_record_call"
,
side_effect
=
lambda
result
,
tokens
=
None
:
result
)
as
record_call
,
patch
.
object
(
)
as
record_call
,
patch
.
object
(
llm_client
,
"
_
run_tool_chat_sync"
,
return_value
=
expected
llm_client
,
"run_tool_chat_sync"
,
return_value
=
expected
):
):
result
=
llm_client
.
chat
(
MESSAGES
)
result
=
llm_client
.
chat
(
MESSAGES
)
...
@@ -470,7 +471,7 @@ class LLMClientProviderTest(unittest.TestCase):
...
@@ -470,7 +471,7 @@ class LLMClientProviderTest(unittest.TestCase):
)
as
ensure_quota
,
patch
.
object
(
)
as
ensure_quota
,
patch
.
object
(
llm_client
,
"_record_call"
,
side_effect
=
lambda
result
,
tokens
=
None
:
result
llm_client
,
"_record_call"
,
side_effect
=
lambda
result
,
tokens
=
None
:
result
)
as
record_call
,
patch
.
object
(
)
as
record_call
,
patch
.
object
(
llm_client
,
"
_
run_tool_chat_sync"
,
side_effect
=
RuntimeError
(
"boom"
)
llm_client
,
"run_tool_chat_sync"
,
side_effect
=
RuntimeError
(
"boom"
)
):
):
with
self
.
assertRaisesRegex
(
RuntimeError
,
"boom"
):
with
self
.
assertRaisesRegex
(
RuntimeError
,
"boom"
):
llm_client
.
chat
(
MESSAGES
)
llm_client
.
chat
(
MESSAGES
)
...
@@ -482,12 +483,12 @@ class LLMClientProviderTest(unittest.TestCase):
...
@@ -482,12 +483,12 @@ class LLMClientProviderTest(unittest.TestCase):
class
LLMClientToolHelpersTest
(
unittest
.
TestCase
):
class
LLMClientToolHelpersTest
(
unittest
.
TestCase
):
def
test_extract_structured_tool_output_prefers_structured_content
(
self
)
->
None
:
def
test_extract_structured_tool_output_prefers_structured_content
(
self
)
->
None
:
result
=
_FakeToolResult
(
structured_content
=
{
"answer"
:
42
})
result
=
_FakeToolResult
(
structured_content
=
{
"answer"
:
42
})
self
.
assertEqual
(
llm_client
.
_extract_structured_tool_output
(
result
),
{
"answer"
:
42
})
self
.
assertEqual
(
llm_
tool_
client
.
_extract_structured_tool_output
(
result
),
{
"answer"
:
42
})
def
test_extract_structured_tool_output_joins_text_blocks
(
self
)
->
None
:
def
test_extract_structured_tool_output_joins_text_blocks
(
self
)
->
None
:
blocks
=
[
types
.
SimpleNamespace
(
text
=
"a"
),
types
.
SimpleNamespace
(
text
=
"b"
)]
blocks
=
[
types
.
SimpleNamespace
(
text
=
"a"
),
types
.
SimpleNamespace
(
text
=
"b"
)]
result
=
_FakeToolResult
(
content
=
blocks
)
result
=
_FakeToolResult
(
content
=
blocks
)
self
.
assertEqual
(
llm_client
.
_extract_structured_tool_output
(
result
),
"a
\n
b"
)
self
.
assertEqual
(
llm_
tool_
client
.
_extract_structured_tool_output
(
result
),
"a
\n
b"
)
def
test_run_provider_chat_appends_tool_trace_to_active_log
(
self
)
->
None
:
def
test_run_provider_chat_appends_tool_trace_to_active_log
(
self
)
->
None
:
active_log
:
list
[
dict
]
=
[]
active_log
:
list
[
dict
]
=
[]
...
@@ -551,8 +552,8 @@ class LLMClientToolHelpersTest(unittest.TestCase):
...
@@ -551,8 +552,8 @@ class LLMClientToolHelpersTest(unittest.TestCase):
async
def
fake_with_mcp_session
(
mcp_settings
,
handler
,
http_client
=
None
):
async
def
fake_with_mcp_session
(
mcp_settings
,
handler
,
http_client
=
None
):
return
await
handler
(
_FakeSession
([]),
[])
return
await
handler
(
_FakeSession
([]),
[])
with
patch
.
object
(
llm_client
,
"
_
with_mcp_session"
,
side_effect
=
fake_with_mcp_session
):
with
patch
.
object
(
llm_
tool_
client
,
"with_mcp_session"
,
side_effect
=
fake_with_mcp_session
):
result
=
await
llm_client
.
_run_openai_compatible_tool_loop
(
result
=
await
llm_
tool_
client
.
_run_openai_compatible_tool_loop
(
MESSAGES
,
MESSAGES
,
settings
,
settings
,
openai_client
=
fake_client
,
openai_client
=
fake_client
,
...
@@ -597,8 +598,8 @@ class LLMClientToolHelpersTest(unittest.TestCase):
...
@@ -597,8 +598,8 @@ class LLMClientToolHelpersTest(unittest.TestCase):
async
def
fake_with_mcp_session
(
mcp_settings
,
handler
,
http_client
=
None
):
async
def
fake_with_mcp_session
(
mcp_settings
,
handler
,
http_client
=
None
):
return
await
handler
(
session
,
[
fake_tool
])
return
await
handler
(
session
,
[
fake_tool
])
with
patch
.
object
(
llm_client
,
"
_
with_mcp_session"
,
side_effect
=
fake_with_mcp_session
):
with
patch
.
object
(
llm_
tool_
client
,
"with_mcp_session"
,
side_effect
=
fake_with_mcp_session
):
result
=
await
llm_client
.
_run_openai_compatible_tool_loop
(
result
=
await
llm_
tool_
client
.
_run_openai_compatible_tool_loop
(
MESSAGES
,
MESSAGES
,
settings
,
settings
,
openai_client
=
fake_client
,
openai_client
=
fake_client
,
...
@@ -653,8 +654,8 @@ class LLMClientToolHelpersTest(unittest.TestCase):
...
@@ -653,8 +654,8 @@ class LLMClientToolHelpersTest(unittest.TestCase):
async
def
fake_with_mcp_session
(
mcp_settings
,
handler
,
http_client
=
None
):
async
def
fake_with_mcp_session
(
mcp_settings
,
handler
,
http_client
=
None
):
return
await
handler
(
session
,
fake_tools
)
return
await
handler
(
session
,
fake_tools
)
with
patch
.
object
(
llm_client
,
"
_
with_mcp_session"
,
side_effect
=
fake_with_mcp_session
):
with
patch
.
object
(
llm_
tool_
client
,
"with_mcp_session"
,
side_effect
=
fake_with_mcp_session
):
result
=
await
llm_client
.
_run_openai_compatible_tool_loop
(
result
=
await
llm_
tool_
client
.
_run_openai_compatible_tool_loop
(
MESSAGES
,
MESSAGES
,
settings
,
settings
,
openai_client
=
fake_client
,
openai_client
=
fake_client
,
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new 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