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
ca498dfa
Commit
ca498dfa
authored
Jun 19, 2026
by
Kantz
Browse files
reworking the context architecture
parent
6cf9eb8c
Changes
14
Hide whitespace changes
Inline
Side-by-side
math-tutor/backend/app/api/chat.py
View file @
ca498dfa
...
@@ -7,7 +7,11 @@ from typing import List, Optional
...
@@ -7,7 +7,11 @@ from typing import List, Optional
import
app.config
as
config
import
app.config
as
config
from
app.deterministic_services
import
session_store
from
app.deterministic_services
import
session_store
from
app.deterministic_services
import
context_store
,
retrieval_store
,
task_catalog
from
app.deterministic_services
import
retrieval_store
,
task_catalog
from
app.deterministic_services.context_stores
import
(
context_store_base
,
context_store_task
,
)
from
app.deterministic_services
import
socratic_oranisator
from
app.deterministic_services
import
socratic_oranisator
from
app.deterministic_services.orchestrators
import
(
from
app.deterministic_services.orchestrators
import
(
orchestrator_qa
,
orchestrator_qa
,
...
@@ -129,10 +133,10 @@ def chat(request: ChatRequest) -> ChatResponse:
...
@@ -129,10 +133,10 @@ def chat(request: ChatRequest) -> ChatResponse:
@
router
.
post
(
"/api/chat/bootstrap-socratic"
,
response_model
=
SocraticBootstrapResponse
)
@
router
.
post
(
"/api/chat/bootstrap-socratic"
,
response_model
=
SocraticBootstrapResponse
)
def
bootstrap_socratic
(
request
:
SocraticBootstrapRequest
)
->
SocraticBootstrapResponse
:
def
bootstrap_socratic
(
request
:
SocraticBootstrapRequest
)
->
SocraticBootstrapResponse
:
chat_id
=
context_store
.
get_chat_id
([],
draft
=
request
.
draft
)
chat_id
=
context_store
_base
.
get_chat_id
([],
draft
=
request
.
draft
)
sheet
=
context_store
.
load_sheet
(
chat_id
)
sheet
=
context_store
_base
.
load_sheet
(
chat_id
)
if
not
sheet
:
if
not
sheet
:
sheet
=
context_store
.
context_store_task
.
init_sheet
(
chat_id
,
[])
sheet
=
context_store_task
.
init_sheet
(
chat_id
,
[])
try
:
try
:
topic_entry
=
socratic_oranisator
.
get_topic_entry
(
request
.
topic_key
)
topic_entry
=
socratic_oranisator
.
get_topic_entry
(
request
.
topic_key
)
...
@@ -145,9 +149,9 @@ def bootstrap_socratic(request: SocraticBootstrapRequest) -> SocraticBootstrapRe
...
@@ -145,9 +149,9 @@ def bootstrap_socratic(request: SocraticBootstrapRequest) -> SocraticBootstrapRe
pg_url
=
config
.
get_postgres_url
(),
pg_url
=
config
.
get_postgres_url
(),
parent_refs
=
refs
,
parent_refs
=
refs
,
)
)
context_store
.
set_sources
(
sheet
,
sources
)
context_store
_base
.
set_sources
(
sheet
,
sources
)
context_store
.
set_initialized
(
sheet
,
True
)
context_store
_base
.
set_initialized
(
sheet
,
True
)
context_store
.
save_sheet
(
sheet
)
context_store
_base
.
save_sheet
(
sheet
)
try
:
try
:
reply
=
socratic_oranisator
.
get_initial_message
(
request
.
topic_key
)
reply
=
socratic_oranisator
.
get_initial_message
(
request
.
topic_key
)
...
@@ -155,8 +159,8 @@ def bootstrap_socratic(request: SocraticBootstrapRequest) -> SocraticBootstrapRe
...
@@ -155,8 +159,8 @@ def bootstrap_socratic(request: SocraticBootstrapRequest) -> SocraticBootstrapRe
logger
.
exception
(
"Socratic bootstrap prompt lookup failed"
)
logger
.
exception
(
"Socratic bootstrap prompt lookup failed"
)
raise
HTTPException
(
status_code
=
500
,
detail
=
str
(
exc
))
from
exc
raise
HTTPException
(
status_code
=
500
,
detail
=
str
(
exc
))
from
exc
context_store
.
append_history_message
(
sheet
,
"assistant"
,
reply
)
context_store
_base
.
append_history_message
(
sheet
,
"assistant"
,
reply
)
context_store
.
save_sheet
(
sheet
)
context_store
_base
.
save_sheet
(
sheet
)
return
SocraticBootstrapResponse
(
return
SocraticBootstrapResponse
(
reply
=
reply
,
reply
=
reply
,
...
...
math-tutor/backend/app/api/context.py
View file @
ca498dfa
...
@@ -7,7 +7,10 @@ from typing import List, Optional
...
@@ -7,7 +7,10 @@ from typing import List, Optional
from
fastapi
import
APIRouter
,
HTTPException
from
fastapi
import
APIRouter
,
HTTPException
from
pydantic
import
BaseModel
,
Field
from
pydantic
import
BaseModel
,
Field
from
app.deterministic_services
import
context_store
from
app.deterministic_services.context_stores
import
(
context_store_base
,
context_store_task
,
)
router
=
APIRouter
()
router
=
APIRouter
()
...
@@ -33,12 +36,12 @@ def get_retrieval_context(request: ContextRequest) -> List[dict]:
...
@@ -33,12 +36,12 @@ def get_retrieval_context(request: ContextRequest) -> List[dict]:
raise
HTTPException
(
status_code
=
400
,
detail
=
"messages required"
)
raise
HTTPException
(
status_code
=
400
,
detail
=
"messages required"
)
messages
=
[{
"role"
:
m
.
role
,
"content"
:
m
.
text
}
for
m
in
request
.
messages
]
messages
=
[{
"role"
:
m
.
role
,
"content"
:
m
.
text
}
for
m
in
request
.
messages
]
chat_id
=
context_store
.
get_chat_id
(
messages
,
draft
=
request
.
draft
)
chat_id
=
context_store
_base
.
get_chat_id
(
messages
,
draft
=
request
.
draft
)
sheet
=
context_store
.
load_sheet
(
chat_id
)
sheet
=
context_store
_base
.
load_sheet
(
chat_id
)
if
not
sheet
:
if
not
sheet
:
raise
HTTPException
(
status_code
=
404
,
detail
=
"context sheet not found"
)
raise
HTTPException
(
status_code
=
404
,
detail
=
"context sheet not found"
)
sources
=
context_store
.
get_retrieval
(
sheet
)
sources
=
context_store
_base
.
get_retrieval
(
sheet
)
if
not
sources
:
if
not
sources
:
return
[]
return
[]
return
[
source
.
model_dump
()
for
source
in
sources
]
return
[
source
.
model_dump
()
for
source
in
sources
]
...
@@ -48,10 +51,10 @@ def get_retrieval_context(request: ContextRequest) -> List[dict]:
...
@@ -48,10 +51,10 @@ def get_retrieval_context(request: ContextRequest) -> List[dict]:
@
router
.
post
(
"/api/context/solution"
)
@
router
.
post
(
"/api/context/solution"
)
def
get_context_solution
(
request
:
DraftRequest
)
->
dict
[
str
,
str
]:
def
get_context_solution
(
request
:
DraftRequest
)
->
dict
[
str
,
str
]:
sheet
=
context_store
.
load_sheet
(
request
.
draft
)
sheet
=
context_store
_base
.
load_sheet
(
request
.
draft
)
if
not
sheet
:
if
not
sheet
:
raise
HTTPException
(
status_code
=
404
,
detail
=
"context sheet not found"
)
raise
HTTPException
(
status_code
=
404
,
detail
=
"context sheet not found"
)
return
{
return
{
"solution"
:
context_store
.
context_store_task
.
get_solution
(
sheet
),
"solution"
:
context_store_task
.
get_solution
(
sheet
),
}
}
math-tutor/backend/app/api/tasks.py
View file @
ca498dfa
...
@@ -10,7 +10,11 @@ from fastapi import APIRouter, HTTPException
...
@@ -10,7 +10,11 @@ from fastapi import APIRouter, HTTPException
from
fastapi.responses
import
FileResponse
from
fastapi.responses
import
FileResponse
from
pydantic
import
BaseModel
,
Field
from
pydantic
import
BaseModel
,
Field
from
app.deterministic_services
import
context_store
,
task_catalog
,
socratic_oranisator
from
app.deterministic_services
import
task_catalog
,
socratic_oranisator
from
app.deterministic_services.context_stores
import
(
context_store_base
,
context_store_task
,
)
router
=
APIRouter
()
router
=
APIRouter
()
...
@@ -128,10 +132,10 @@ def list_socratic_topics() -> SocraticResponse:
...
@@ -128,10 +132,10 @@ def list_socratic_topics() -> SocraticResponse:
@
router
.
post
(
"/api/tasks/select"
,
response_model
=
SelectTaskResponse
)
@
router
.
post
(
"/api/tasks/select"
,
response_model
=
SelectTaskResponse
)
def
select_task
(
request
:
SelectTaskRequest
)
->
SelectTaskResponse
:
def
select_task
(
request
:
SelectTaskRequest
)
->
SelectTaskResponse
:
chat_id
=
context_store
.
get_chat_id
([],
draft
=
request
.
draft
)
chat_id
=
context_store
_base
.
get_chat_id
([],
draft
=
request
.
draft
)
sheet
=
context_store
.
load_sheet
(
chat_id
)
sheet
=
context_store
_base
.
load_sheet
(
chat_id
)
if
not
sheet
:
if
not
sheet
:
sheet
=
context_store
.
context_store_task
.
init_sheet
(
chat_id
,
[])
sheet
=
context_store_task
.
init_sheet
(
chat_id
,
[])
updated
=
task_catalog
.
select_task_by_ids
(
updated
=
task_catalog
.
select_task_by_ids
(
sheet
,
sheet
,
...
@@ -141,7 +145,7 @@ def select_task(request: SelectTaskRequest) -> SelectTaskResponse:
...
@@ -141,7 +145,7 @@ def select_task(request: SelectTaskRequest) -> SelectTaskResponse:
if
not
updated
:
if
not
updated
:
raise
HTTPException
(
status_code
=
404
,
detail
=
"task not found"
)
raise
HTTPException
(
status_code
=
404
,
detail
=
"task not found"
)
context_store
.
save_sheet
(
sheet
)
context_store
_base
.
save_sheet
(
sheet
)
file_id
,
task_id
=
task_catalog
.
get_selected_task_ids
(
sheet
)
file_id
,
task_id
=
task_catalog
.
get_selected_task_ids
(
sheet
)
return
SelectTaskResponse
(
return
SelectTaskResponse
(
status
=
"ok"
,
status
=
"ok"
,
...
@@ -152,17 +156,17 @@ def select_task(request: SelectTaskRequest) -> SelectTaskResponse:
...
@@ -152,17 +156,17 @@ def select_task(request: SelectTaskRequest) -> SelectTaskResponse:
@
router
.
post
(
"/api/tasks/select-topic"
,
response_model
=
SelectTopicResponse
)
@
router
.
post
(
"/api/tasks/select-topic"
,
response_model
=
SelectTopicResponse
)
def
select_topic
(
request
:
SelectTopicRequest
)
->
SelectTopicResponse
:
def
select_topic
(
request
:
SelectTopicRequest
)
->
SelectTopicResponse
:
chat_id
=
context_store
.
get_chat_id
([],
draft
=
request
.
draft
)
chat_id
=
context_store
_base
.
get_chat_id
([],
draft
=
request
.
draft
)
sheet
=
context_store
.
load_sheet
(
chat_id
)
sheet
=
context_store
_base
.
load_sheet
(
chat_id
)
if
not
sheet
:
if
not
sheet
:
sheet
=
context_store
.
context_store_task
.
init_sheet
(
chat_id
,
[])
sheet
=
context_store_task
.
init_sheet
(
chat_id
,
[])
try
:
try
:
topic_key
=
_set_selected_socratic_topic
(
sheet
,
request
.
topic_key
)
topic_key
=
_set_selected_socratic_topic
(
sheet
,
request
.
topic_key
)
except
ValueError
as
exc
:
except
ValueError
as
exc
:
raise
HTTPException
(
status_code
=
404
,
detail
=
"topic not found"
)
from
exc
raise
HTTPException
(
status_code
=
404
,
detail
=
"topic not found"
)
from
exc
context_store
.
save_sheet
(
sheet
)
context_store
_base
.
save_sheet
(
sheet
)
return
SelectTopicResponse
(
return
SelectTopicResponse
(
status
=
"ok"
,
status
=
"ok"
,
topic_key
=
topic_key
,
topic_key
=
topic_key
,
...
...
math-tutor/backend/app/deterministic_services/context_store.py
deleted
100644 → 0
View file @
6cf9eb8c
from
__future__
import
annotations
# Shared/base API
from
app.deterministic_services.context_stores.context_store_base
import
(
add_decision
,
append_history_message
,
format_history
,
get_chat_id
,
get_chat_id_value
,
get_created_at
,
get_decisions
,
get_history
,
get_history_turns
,
get_initialized
,
get_retrieval
,
get_updated_at
,
load_sheet
,
save_sheet
,
set_chat_id
,
set_created_at
,
set_decisions
,
set_history
,
set_initialized
,
set_sources
,
set_updated_at
,
update_history
,
update_retrieval_context
,
)
# Old/open variant is the default for backwards compatibility.
from
app.deterministic_services.context_stores.context_store_open
import
(
add_LLM_solution
,
format_sheet
,
get_llm_solutions
,
get_task
,
init_sheet
,
last_LLM_solution
,
set_llm_solutions
,
)
# Expose variant modules so callers can opt in explicitly.
from
app.deterministic_services.context_stores
import
context_store_task
,
context_store_open
__all__
=
[
# shared/base
"get_chat_id"
,
"load_sheet"
,
"save_sheet"
,
"format_history"
,
"update_history"
,
"append_history_message"
,
"get_history"
,
"get_history_turns"
,
"update_retrieval_context"
,
"get_retrieval"
,
"add_decision"
,
"set_chat_id"
,
"get_chat_id_value"
,
"set_created_at"
,
"get_created_at"
,
"set_updated_at"
,
"get_updated_at"
,
"set_history"
,
"set_decisions"
,
"get_decisions"
,
"set_initialized"
,
"get_initialized"
,
"set_sources"
,
# default/open variant
"init_sheet"
,
"format_sheet"
,
"set_llm_solutions"
,
"get_llm_solutions"
,
"add_LLM_solution"
,
"last_LLM_solution"
,
"get_task"
,
# explicit variants
"context_store_open"
,
"context_store_task"
,
]
math-tutor/backend/app/deterministic_services/orchestrators/orchestrator_base.py
View file @
ca498dfa
...
@@ -6,13 +6,16 @@ from typing import Any, Callable, List, TypeVar
...
@@ -6,13 +6,16 @@ from typing import Any, Callable, List, TypeVar
import
app.config
as
config
import
app.config
as
config
from
app.deterministic_services
import
(
from
app.deterministic_services
import
(
context_store
,
embedding_provider
,
embedding_provider
,
referenz_decoder
,
referenz_decoder
,
retrieval_store
,
retrieval_store
,
tool_log_context
,
tool_log_context
,
tool_logging
,
tool_logging
,
)
)
from
app.deterministic_services.context_stores
import
(
context_store_base
,
context_store_open
,
)
from
app.deterministic_services.context_stores.context_store_base
import
berlin_now_iso
from
app.deterministic_services.context_stores.context_store_base
import
berlin_now_iso
from
app.deterministic_services.retrieval_store
import
Source
from
app.deterministic_services.retrieval_store
import
Source
...
@@ -167,7 +170,7 @@ def bootstrap_retrieval(sheet: dict, query_text: str, tool_log: list[dict]) -> N
...
@@ -167,7 +170,7 @@ def bootstrap_retrieval(sheet: dict, query_text: str, tool_log: list[dict]) -> N
finished_at
=
finished_at
,
finished_at
=
finished_at
,
duration_ms
=
duration_ms
,
duration_ms
=
duration_ms
,
)
)
context_store
.
update_retrieval_context
(
sheet
,
sources
)
context_store
_base
.
update_retrieval_context
(
sheet
,
sources
)
# --
# --
# Chat Status
# Chat Status
...
@@ -186,14 +189,14 @@ def init_chat_state(
...
@@ -186,14 +189,14 @@ def init_chat_state(
raise
ValueError
(
"last user message required"
)
raise
ValueError
(
"last user message required"
)
last_user
=
user_messages
[
-
1
]
last_user
=
user_messages
[
-
1
]
chat_id
=
context_store
.
get_chat_id
(
messages
,
draft
=
draft
)
chat_id
=
context_store
_base
.
get_chat_id
(
messages
,
draft
=
draft
)
new_chat
=
is_new_chat
(
messages
)
new_chat
=
is_new_chat
(
messages
)
sheet
=
context_store
.
load_sheet
(
chat_id
)
sheet
=
context_store
_base
.
load_sheet
(
chat_id
)
if
not
sheet
:
if
not
sheet
:
create_sheet
=
init_sheet_fn
or
context_store
.
init_sheet
create_sheet
=
init_sheet_fn
or
context_store
_open
.
init_sheet
sheet
=
create_sheet
(
chat_id
,
messages
)
sheet
=
create_sheet
(
chat_id
,
messages
)
context_store
.
update_history
(
sheet
,
messages
)
context_store
_base
.
update_history
(
sheet
,
messages
)
return
ChatState
(
return
ChatState
(
messages
=
messages
,
messages
=
messages
,
draft
=
draft
,
draft
=
draft
,
...
@@ -214,12 +217,12 @@ def finalize_response(state: ChatState, reply: str | None) -> dict:
...
@@ -214,12 +217,12 @@ def finalize_response(state: ChatState, reply: str | None) -> dict:
reply
=
"Dazu steht nichts im Material"
reply
=
"Dazu steht nichts im Material"
else
:
else
:
decoded
,
_
=
referenz_decoder
.
decode_references
(
decoded
,
_
=
referenz_decoder
.
decode_references
(
reply
,
context_store
.
get_retrieval
(
state
.
sheet
)
reply
,
context_store
_base
.
get_retrieval
(
state
.
sheet
)
)
)
reply
=
decoded
reply
=
decoded
context_store
.
append_history_message
(
state
.
sheet
,
"assistant"
,
reply
)
context_store
_base
.
append_history_message
(
state
.
sheet
,
"assistant"
,
reply
)
context_store
.
save_sheet
(
state
.
sheet
)
context_store
_base
.
save_sheet
(
state
.
sheet
)
tool_logging
.
write_tool_log
(
tool_logging
.
write_tool_log
(
state
.
tool_log
,
state
.
tool_log
,
created_at
=
state
.
sheet
.
get
(
"created_at"
),
created_at
=
state
.
sheet
.
get
(
"created_at"
),
...
...
math-tutor/backend/app/deterministic_services/orchestrators/orchestrator_qa.py
View file @
ca498dfa
from
__future__
import
annotations
from
__future__
import
annotations
from
app.LLM_services
import
qa_LLM
from
app.LLM_services
import
qa_LLM
from
app.deterministic_services
import
context_store
from
app.deterministic_services.context_stores
import
(
context_store_base
,
context_store_open
,
)
from
app.deterministic_services.orchestrators
import
orchestrator_base
as
base
from
app.deterministic_services.orchestrators
import
orchestrator_base
as
base
# beim ersten Aufruf
# beim ersten Aufruf
...
@@ -18,9 +21,11 @@ def _on_turn_logic(state: base.ChatState) -> None:
...
@@ -18,9 +21,11 @@ def _on_turn_logic(state: base.ChatState) -> None:
def
_on_build_reply
(
state
:
base
.
ChatState
)
->
str
|
None
:
def
_on_build_reply
(
state
:
base
.
ChatState
)
->
str
|
None
:
args
=
{
args
=
{
"question"
:
context_store
.
get_task
(
state
.
sheet
),
"question"
:
context_store_open
.
get_task
(
state
.
sheet
),
"history"
:
context_store
.
format_history
(
state
.
messages
),
"history"
:
context_store_base
.
format_history
(
state
.
messages
),
"sources"
:
"
\n
"
.
join
([
source
.
to_string
()
for
source
in
context_store
.
get_retrieval
(
state
.
sheet
)]),
"sources"
:
"
\n
"
.
join
(
[
source
.
to_string
()
for
source
in
context_store_base
.
get_retrieval
(
state
.
sheet
)]
),
}
}
return
base
.
log_timed_call
(
return
base
.
log_timed_call
(
state
.
tool_log
,
state
.
tool_log
,
...
...
math-tutor/backend/app/deterministic_services/orchestrators/orchestrator_socratic.py
View file @
ca498dfa
...
@@ -2,7 +2,11 @@ from __future__ import annotations
...
@@ -2,7 +2,11 @@ from __future__ import annotations
from
app.LLM_services
import
socratic_LLM
from
app.LLM_services
import
socratic_LLM
import
app.config
as
config
import
app.config
as
config
from
app.deterministic_services
import
context_store
,
retrieval_store
,
task_catalog
from
app.deterministic_services
import
retrieval_store
,
task_catalog
from
app.deterministic_services.context_stores
import
(
context_store_base
,
context_store_task
,
)
from
app.deterministic_services.orchestrators
import
orchestrator_base
as
base
from
app.deterministic_services.orchestrators
import
orchestrator_base
as
base
...
@@ -30,7 +34,7 @@ def _retrieve_context_for_topic(state: base.ChatState, query_text: str) -> int:
...
@@ -30,7 +34,7 @@ def _retrieve_context_for_topic(state: base.ChatState, query_text: str) -> int:
pg_url
=
config
.
get_postgres_url
(),
pg_url
=
config
.
get_postgres_url
(),
parent_refs
=
refs
,
parent_refs
=
refs
,
)
)
context_store
.
update_retrieval_context
(
state
.
sheet
,
sources
)
context_store
_base
.
update_retrieval_context
(
state
.
sheet
,
sources
)
return
{
return
{
"parent_refs"
:
refs
,
"parent_refs"
:
refs
,
"source_count"
:
len
(
sources
),
"source_count"
:
len
(
sources
),
...
@@ -58,13 +62,15 @@ def _on_turn_logic(state: base.ChatState) -> None:
...
@@ -58,13 +62,15 @@ def _on_turn_logic(state: base.ChatState) -> None:
def
_on_build_reply
(
state
:
base
.
ChatState
)
->
str
|
None
:
def
_on_build_reply
(
state
:
base
.
ChatState
)
->
str
|
None
:
history_turns
=
context_store
.
get_history_turns
(
state
.
sheet
)
history_turns
=
context_store
_base
.
get_history_turns
(
state
.
sheet
)
parent_refs
=
task_catalog
.
get_selected_topic_parent_refs
(
state
.
sheet
)
parent_refs
=
task_catalog
.
get_selected_topic_parent_refs
(
state
.
sheet
)
args
=
{
args
=
{
"query"
:
state
.
last_user
,
"query"
:
state
.
last_user
,
"parent_refs"
:
parent_refs
,
"parent_refs"
:
parent_refs
,
"history"
:
history_turns
,
"history"
:
history_turns
,
"sources"
:
"
\n
"
.
join
([
source
.
to_string
()
for
source
in
context_store
.
get_retrieval
(
state
.
sheet
)]),
"sources"
:
"
\n
"
.
join
(
[
source
.
to_string
()
for
source
in
context_store_base
.
get_retrieval
(
state
.
sheet
)]
),
}
}
return
base
.
log_timed_call
(
return
base
.
log_timed_call
(
state
.
tool_log
,
state
.
tool_log
,
...
@@ -97,5 +103,5 @@ def run_chat(
...
@@ -97,5 +103,5 @@ def run_chat(
on_bootstrap
=
on_bootstrap
,
on_bootstrap
=
on_bootstrap
,
on_turn_logic
=
on_turn_logic
,
on_turn_logic
=
on_turn_logic
,
on_build_reply
=
_on_build_reply
,
on_build_reply
=
_on_build_reply
,
init_sheet_fn
=
context_store
.
context_store
_task
.
init_sheet
,
init_sheet_fn
=
context_store_task
.
init_sheet
,
)
)
math-tutor/backend/app/deterministic_services/orchestrators/orchestrator_task.py
View file @
ca498dfa
...
@@ -2,16 +2,16 @@ from __future__ import annotations
...
@@ -2,16 +2,16 @@ from __future__ import annotations
from
app.LLM_services
import
task_hint_LLM
from
app.LLM_services
import
task_hint_LLM
import
app.config
as
config
import
app.config
as
config
from
app.deterministic_services
import
(
from
app.deterministic_services
import
retrieval_store
,
task_catalog
context_store
,
from
app.deterministic_services.
context_store
s
import
(
retrieval_stor
e
,
context_store_bas
e
,
task_catalog
,
context_store_task
,
)
)
from
app.deterministic_services.orchestrators
import
orchestrator_base
as
base
from
app.deterministic_services.orchestrators
import
orchestrator_base
as
base
def
_ensure_context_task_fields
(
state
:
base
.
ChatState
,
query_text
:
str
)
->
tuple
[
str
,
str
]
|
None
:
def
_ensure_context_task_fields
(
state
:
base
.
ChatState
,
query_text
:
str
)
->
tuple
[
str
,
str
]
|
None
:
store_new
=
context_store
.
context_store_task
store_new
=
context_store_task
has_task
=
bool
(
store_new
.
get_task
(
state
.
sheet
))
has_task
=
bool
(
store_new
.
get_task
(
state
.
sheet
))
has_hints
=
bool
(
store_new
.
get_hints
(
state
.
sheet
))
has_hints
=
bool
(
store_new
.
get_hints
(
state
.
sheet
))
has_solution
=
bool
(
store_new
.
get_solution
(
state
.
sheet
))
has_solution
=
bool
(
store_new
.
get_solution
(
state
.
sheet
))
...
@@ -26,12 +26,14 @@ def _ensure_context_task_fields(state: base.ChatState, query_text: str) -> tuple
...
@@ -26,12 +26,14 @@ def _ensure_context_task_fields(state: base.ChatState, query_text: str) -> tuple
if
was_selected
:
if
was_selected
:
return
selected
[
0
],
selected
[
1
]
return
selected
[
0
],
selected
[
1
]
sources_text
=
"
\n
"
.
join
([
source
.
to_string
()
for
source
in
context_store
.
get_retrieval
(
state
.
sheet
)])
sources_text
=
"
\n
"
.
join
(
[
source
.
to_string
()
for
source
in
context_store_base
.
get_retrieval
(
state
.
sheet
)]
)
selection
=
task_catalog
.
select_task_for_context
(
selection
=
task_catalog
.
select_task_for_context
(
state
.
sheet
,
state
.
sheet
,
query_text
=
query_text
,
query_text
=
query_text
,
sources_text
=
sources_text
,
sources_text
=
sources_text
,
history
=
context_store
.
get_history_turns
(
state
.
sheet
),
history
=
context_store
_base
.
get_history_turns
(
state
.
sheet
),
)
)
if
not
selection
:
if
not
selection
:
return
None
return
None
...
@@ -64,7 +66,7 @@ def _retrieve_context_for_task(state: base.ChatState, query_text: str) -> int:
...
@@ -64,7 +66,7 @@ def _retrieve_context_for_task(state: base.ChatState, query_text: str) -> int:
pg_url
=
config
.
get_postgres_url
(),
pg_url
=
config
.
get_postgres_url
(),
parent_refs
=
refs
,
parent_refs
=
refs
,
)
)
context_store
.
update_retrieval_context
(
state
.
sheet
,
sources
)
context_store
_base
.
update_retrieval_context
(
state
.
sheet
,
sources
)
return
{
return
{
"parent_refs"
:
refs
,
"parent_refs"
:
refs
,
"source_count"
:
len
(
sources
),
"source_count"
:
len
(
sources
),
...
@@ -87,7 +89,7 @@ def _on_bootstrap(state: base.ChatState, query_text: str) -> None:
...
@@ -87,7 +89,7 @@ def _on_bootstrap(state: base.ChatState, query_text: str) -> None:
source_count
=
_retrieve_context_for_task
(
state
,
query_text
)
source_count
=
_retrieve_context_for_task
(
state
,
query_text
)
if
source_count
>
0
:
if
source_count
>
0
:
_ensure_context_task_fields
(
state
,
query_text
)
_ensure_context_task_fields
(
state
,
query_text
)
task_text
=
context_store
.
context_store_task
.
get_task
(
state
.
sheet
).
strip
()
task_text
=
context_store_task
.
get_task
(
state
.
sheet
).
strip
()
retrieval_query
=
query_text
retrieval_query
=
query_text
if
task_text
:
if
task_text
:
retrieval_query
=
f
"Aufgabe:
\n
{
task_text
}
\n\n
{
query_text
}
"
retrieval_query
=
f
"Aufgabe:
\n
{
task_text
}
\n\n
{
query_text
}
"
...
@@ -101,15 +103,17 @@ def _on_turn_logic(state: base.ChatState) -> None:
...
@@ -101,15 +103,17 @@ def _on_turn_logic(state: base.ChatState) -> None:
# Antwort generieren
# Antwort generieren
def
_on_build_reply
(
state
:
base
.
ChatState
)
->
str
|
None
:
def
_on_build_reply
(
state
:
base
.
ChatState
)
->
str
|
None
:
store_new
=
context_store
.
context_store_task
store_new
=
context_store_task
history_turns
=
context_store
.
get_history_turns
(
state
.
sheet
)
history_turns
=
context_store
_base
.
get_history_turns
(
state
.
sheet
)
args
=
{
args
=
{
"query"
:
state
.
last_user
if
not
state
.
new_chat
else
None
,
"query"
:
state
.
last_user
if
not
state
.
new_chat
else
None
,
"task"
:
store_new
.
get_task
(
state
.
sheet
),
"task"
:
store_new
.
get_task
(
state
.
sheet
),
"hints"
:
store_new
.
get_hints
(
state
.
sheet
),
"hints"
:
store_new
.
get_hints
(
state
.
sheet
),
"solution"
:
store_new
.
get_solution
(
state
.
sheet
),
"solution"
:
store_new
.
get_solution
(
state
.
sheet
),
"history"
:
history_turns
,
"history"
:
history_turns
,
"sources"
:
"
\n
"
.
join
([
source
.
to_string
()
for
source
in
context_store
.
get_retrieval
(
state
.
sheet
)]),
"sources"
:
"
\n
"
.
join
(
[
source
.
to_string
()
for
source
in
context_store_base
.
get_retrieval
(
state
.
sheet
)]
),
}
}
return
base
.
log_timed_call
(
return
base
.
log_timed_call
(
state
.
tool_log
,
state
.
tool_log
,
...
@@ -151,5 +155,5 @@ def run_chat(
...
@@ -151,5 +155,5 @@ def run_chat(
on_bootstrap
=
on_bootstrap
,
on_bootstrap
=
on_bootstrap
,
on_turn_logic
=
on_turn_logic
,
on_turn_logic
=
on_turn_logic
,
on_build_reply
=
_on_build_reply
,
on_build_reply
=
_on_build_reply
,
init_sheet_fn
=
context_store
.
context_store
_task
.
init_sheet
,
init_sheet_fn
=
context_store_task
.
init_sheet
,
)
)
math-tutor/backend/app/deterministic_services/orchestrators/orchestrator_tutor.py
View file @
ca498dfa
from
__future__
import
annotations
from
__future__
import
annotations
from
app.LLM_services
import
open_hint_LLM
,
solver_LLM
from
app.LLM_services
import
open_hint_LLM
,
solver_LLM
from
app.deterministic_services
import
context_store
from
app.deterministic_services.context_stores
import
(
context_store_base
,
context_store_open
,
)
from
app.deterministic_services.orchestrators
import
orchestrator_base
as
base
from
app.deterministic_services.orchestrators
import
orchestrator_base
as
base
# beim ersten Aufruf
# beim ersten Aufruf
...
@@ -13,25 +16,27 @@ def _on_bootstrap(state: base.ChatState, query_text: str) -> None:
...
@@ -13,25 +16,27 @@ def _on_bootstrap(state: base.ChatState, query_text: str) -> None:
def
_on_turn_logic
(
state
:
base
.
ChatState
)
->
None
:
def
_on_turn_logic
(
state
:
base
.
ChatState
)
->
None
:
if
state
.
new_chat
:
if
state
.
new_chat
:
sheet_text
=
context_store
.
format_sheet
(
state
.
sheet
)
sheet_text
=
context_store
_open
.
format_sheet
(
state
.
sheet
)
llm_solution
=
base
.
log_timed_call
(
llm_solution
=
base
.
log_timed_call
(
state
.
tool_log
,
state
.
tool_log
,
"LLM_Solution"
,
"LLM_Solution"
,
{
"question"
:
state
.
last_user
,
"sheet"
:
sheet_text
},
{
"question"
:
state
.
last_user
,
"sheet"
:
sheet_text
},
lambda
:
solver_LLM
.
solve_question
(
state
.
last_user
,
sheet_text
),
lambda
:
solver_LLM
.
solve_question
(
state
.
last_user
,
sheet_text
),
)
)
context_store
.
add_LLM_solution
(
state
.
sheet
,
llm_solution
)
context_store
_open
.
add_LLM_solution
(
state
.
sheet
,
llm_solution
)
# Antwort generieren
# Antwort generieren
def
_on_build_reply
(
state
:
base
.
ChatState
)
->
str
|
None
:
def
_on_build_reply
(
state
:
base
.
ChatState
)
->
str
|
None
:
history_turns
=
context_store
.
get_history_turns
(
state
.
sheet
)
history_turns
=
context_store
_base
.
get_history_turns
(
state
.
sheet
)
args
=
{
args
=
{
"query"
:
state
.
last_user
if
not
state
.
new_chat
else
None
,
"query"
:
state
.
last_user
if
not
state
.
new_chat
else
None
,
"task"
:
context_store
.
get_task
(
state
.
sheet
),
"task"
:
context_store
_open
.
get_task
(
state
.
sheet
),
"LLM_solution"
:
context_store
.
last_LLM_solution
(
state
.
sheet
),
"LLM_solution"
:
context_store
_open
.
last_LLM_solution
(
state
.
sheet
),
"history"
:
history_turns
,
"history"
:
history_turns
,
"sources"
:
"
\n
"
.
join
([
source
.
to_string
()
for
source
in
context_store
.
get_retrieval
(
state
.
sheet
)]),
"sources"
:
"
\n
"
.
join
(
[
source
.
to_string
()
for
source
in
context_store_base
.
get_retrieval
(
state
.
sheet
)]
),
}
}
return
base
.
log_timed_call
(
return
base
.
log_timed_call
(
state
.
tool_log
,
state
.
tool_log
,
...
...
math-tutor/backend/app/deterministic_services/session_store.py
View file @
ca498dfa
...
@@ -8,7 +8,10 @@ from collections import deque
...
@@ -8,7 +8,10 @@ from collections import deque
from
threading
import
Lock
from
threading
import
Lock
from
typing
import
Any
from
typing
import
Any
from
app.deterministic_services
import
context_store
from
app.deterministic_services.context_stores
import
(
context_store_base
,
context_store_open
,
)
from
app.deterministic_services.context_stores.context_store_base
import
berlin_now_iso
from
app.deterministic_services.context_stores.context_store_base
import
berlin_now_iso
_LOCK
=
Lock
()
_LOCK
=
Lock
()
...
@@ -36,20 +39,20 @@ def archive_chat(
...
@@ -36,20 +39,20 @@ def archive_chat(
draft
:
str
|
None
=
None
,
draft
:
str
|
None
=
None
,
orchestrator
:
str
|
None
=
None
,
orchestrator
:
str
|
None
=
None
,
)
->
str
:
)
->
str
:
chat_id
=
context_store
.
get_chat_id
(
messages
,
draft
=
draft
)
chat_id
=
context_store
_base
.
get_chat_id
(
messages
,
draft
=
draft
)
sheet
=
context_store
.
load_sheet
(
chat_id
)
sheet
=
context_store
_base
.
load_sheet
(
chat_id
)
if
not
sheet
:
if
not
sheet
:
sheet
=
context_store
.
init_sheet
(
chat_id
,
messages
)
sheet
=
context_store
_open
.
init_sheet
(
chat_id
,
messages
)
context_store
.
update_history
(
sheet
,
messages
)
context_store
_base
.
update_history
(
sheet
,
messages
)
context_store
.
save_sheet
(
sheet
)
context_store
_base
.
save_sheet
(
sheet
)
record
=
{
record
=
{
"chat_id"
:
chat_id
,
"chat_id"
:
chat_id
,
"saved_at"
:
berlin_now_iso
(),
"saved_at"
:
berlin_now_iso
(),
"orchestrator"
:
str
(
orchestrator
or
""
).
strip
().
lower
()
or
None
,
"orchestrator"
:
str
(
orchestrator
or
""
).
strip
().
lower
()
or
None
,
"history"
:
sheet
.
get
(
"history"
,
[]),
"history"
:
sheet
.
get
(
"history"
,
[]),
"context_sheet"
:
context_store
.
format_sheet
(
sheet
),
"context_sheet"
:
context_store
_open
.
format_sheet
(
sheet
),
"retrieval_contexts"
:
sheet
.
get
(
"retrieval_contexts"
,
[]),
"retrieval_contexts"
:
sheet
.
get
(
"retrieval_contexts"
,
[]),
"sources"
:
sheet
.
get
(
"sources"
,
[]),
"sources"
:
sheet
.
get
(
"sources"
,
[]),
"selected_task"
:
_extract_selected_task
(
sheet
),
"selected_task"
:
_extract_selected_task
(
sheet
),
...
...
math-tutor/backend/app/deterministic_services/task_catalog.py
View file @
ca498dfa
...
@@ -11,7 +11,7 @@ from urllib.parse import quote
...
@@ -11,7 +11,7 @@ from urllib.parse import quote
import
yaml
import
yaml
from
app
import
config
from
app
import
config
from
app.deterministic_services
import
context_store
from
app.deterministic_services
.context_stores
import
context_store
_task
from
app.deterministic_services.vector_store
import
parse_markdown_with_frontmatter
from
app.deterministic_services.vector_store
import
parse_markdown_with_frontmatter
TASKS_DIR
=
config
.
get_task_folder
()
TASKS_DIR
=
config
.
get_task_folder
()
...
@@ -571,7 +571,7 @@ def set_selected_task(
...
@@ -571,7 +571,7 @@ def set_selected_task(
task_entry
:
dict
[
str
,
Any
],
task_entry
:
dict
[
str
,
Any
],
)
->
None
:
)
->
None
:
task_text
,
hints
,
solution
,
_
=
_build_task_payload
(
task_file
,
task_entry
)
task_text
,
hints
,
solution
,
_
=
_build_task_payload
(
task_file
,
task_entry
)
store_new
=
context_store
.
context_store_task
store_new
=
context_store_task
store_new
.
set_task
(
sheet
,
task_text
)
store_new
.
set_task
(
sheet
,
task_text
)
store_new
.
set_hints
(
sheet
,
hints
)
store_new
.
set_hints
(
sheet
,
hints
)
store_new
.
set_solution
(
sheet
,
solution
)
store_new
.
set_solution
(
sheet
,
solution
)
...
...
math-tutor/backend/test/context_sheet_history_test.py
View file @
ca498dfa
...
@@ -37,7 +37,7 @@ class FinalizeResponseHistoryTest(unittest.TestCase):
...
@@ -37,7 +37,7 @@ class FinalizeResponseHistoryTest(unittest.TestCase):
"app.deterministic_services.orchestrators.orchestrator_base.referenz_decoder.decode_references"
,
"app.deterministic_services.orchestrators.orchestrator_base.referenz_decoder.decode_references"
,
return_value
=
(
"Dekodierte Antwort"
,
[]),
return_value
=
(
"Dekodierte Antwort"
,
[]),
),
patch
(
),
patch
(
"app.deterministic_services.orchestrators.orchestrator_base.context_store.save_sheet"
"app.deterministic_services.orchestrators.orchestrator_base.context_store
_base
.save_sheet"
)
as
save_sheet
,
patch
(
)
as
save_sheet
,
patch
(
"app.deterministic_services.orchestrators.orchestrator_base.tool_logging.write_tool_log"
"app.deterministic_services.orchestrators.orchestrator_base.tool_logging.write_tool_log"
):
):
...
@@ -57,7 +57,7 @@ class FinalizeResponseHistoryTest(unittest.TestCase):
...
@@ -57,7 +57,7 @@ class FinalizeResponseHistoryTest(unittest.TestCase):
state
=
_build_state
()
state
=
_build_state
()
with
patch
(
with
patch
(
"app.deterministic_services.orchestrators.orchestrator_base.context_store.save_sheet"
"app.deterministic_services.orchestrators.orchestrator_base.context_store
_base
.save_sheet"
)
as
save_sheet
,
patch
(
)
as
save_sheet
,
patch
(
"app.deterministic_services.orchestrators.orchestrator_base.tool_logging.write_tool_log"
"app.deterministic_services.orchestrators.orchestrator_base.tool_logging.write_tool_log"
):
):
...
...
math-tutor/backend/test/hint_test.py
View file @
ca498dfa
...
@@ -7,7 +7,10 @@ os.environ.setdefault("EMBEDDING_PROVIDER", "sentence-transformer")
...
@@ -7,7 +7,10 @@ os.environ.setdefault("EMBEDDING_PROVIDER", "sentence-transformer")
os
.
environ
.
setdefault
(
"EMBEDDING_TYPE"
,
"sentence-transformer"
)
os
.
environ
.
setdefault
(
"EMBEDDING_TYPE"
,
"sentence-transformer"
)
from
app.LLM_services
import
open_hint_LLM
as
hint_LLM
from
app.LLM_services
import
open_hint_LLM
as
hint_LLM
from
app.deterministic_services
import
context_store
from
app.deterministic_services.context_stores
import
(
context_store_base
,
context_store_open
,
)
def
_load_sheet_from_path
(
path
:
str
)
->
dict
[
str
,
Any
]:
def
_load_sheet_from_path
(
path
:
str
)
->
dict
[
str
,
Any
]:
...
@@ -19,7 +22,7 @@ def _resolve_sheet(args: argparse.Namespace) -> dict[str, Any]:
...
@@ -19,7 +22,7 @@ def _resolve_sheet(args: argparse.Namespace) -> dict[str, Any]:
if
args
.
sheet
:
if
args
.
sheet
:
return
_load_sheet_from_path
(
args
.
sheet
)
return
_load_sheet_from_path
(
args
.
sheet
)
if
args
.
chat_id
:
if
args
.
chat_id
:
sheet
=
context_store
.
load_sheet
(
args
.
chat_id
)
sheet
=
context_store
_base
.
load_sheet
(
args
.
chat_id
)
if
sheet
is
None
:
if
sheet
is
None
:
raise
FileNotFoundError
(
raise
FileNotFoundError
(
f
"Kein Context-Sheet gefunden fuer chat_id=
{
args
.
chat_id
}
"
)
f
"Kein Context-Sheet gefunden fuer chat_id=
{
args
.
chat_id
}
"
)
...
@@ -38,13 +41,15 @@ def main() -> None:
...
@@ -38,13 +41,15 @@ def main() -> None:
sheet
=
_resolve_sheet
(
args
)
sheet
=
_resolve_sheet
(
args
)
history_turns
=
context_store
.
get_history_turns
(
sheet
)
history_turns
=
context_store
_base
.
get_history_turns
(
sheet
)
args
=
{
args
=
{
"query"
:
history_turns
[
-
1
][
"content"
]
if
history_turns
else
""
,
"query"
:
history_turns
[
-
1
][
"content"
]
if
history_turns
else
""
,
"task"
:
context_store
.
get_task
(
sheet
),
"task"
:
context_store
_open
.
get_task
(
sheet
),
"LLM_solution"
:
context_store
.
last_LLM_solution
(
sheet
),
"LLM_solution"
:
context_store
_open
.
last_LLM_solution
(
sheet
),
"history"
:
history_turns
,
"history"
:
history_turns
,
"sources"
:
"
\n
"
.
join
([
source
.
to_string
()
for
source
in
context_store
.
get_retrieval
(
sheet
)]),
"sources"
:
"
\n
"
.
join
(
[
source
.
to_string
()
for
source
in
context_store_base
.
get_retrieval
(
sheet
)]
),
}
}
reply
=
hint_LLM
.
generate_hint
(
**
args
)
reply
=
hint_LLM
.
generate_hint
(
**
args
)
...
...
math-tutor/backend/test/task_catalog_socratic_test.py
View file @
ca498dfa
...
@@ -517,17 +517,22 @@ class TaskApiSocraticTest(unittest.TestCase):
...
@@ -517,17 +517,22 @@ class TaskApiSocraticTest(unittest.TestCase):
def
test_select_topic_endpoint_returns_selected_key
(
self
)
->
None
:
def
test_select_topic_endpoint_returns_selected_key
(
self
)
->
None
:
sheet
:
dict
[
str
,
object
]
=
{}
sheet
:
dict
[
str
,
object
]
=
{}
with
patch
(
"app.api.tasks.context_store.get_chat_id"
,
return_value
=
"chat-1"
),
patch
(
with
patch
(
"app.api.tasks.context_store
_base
.get_chat_id"
,
return_value
=
"chat-1"
),
patch
(
"app.api.tasks.context_store.load_sheet"
,
"app.api.tasks.context_store
_base
.load_sheet"
,
return_value
=
sheet
,
return_value
=
sheet
,
),
patch
(
),
patch
(
"app.api.tasks.context_store
.context_store
_task.init_sheet"
,
"app.api.tasks.context_store_task.init_sheet"
,
return_value
=
sheet
,
return_value
=
sheet
,
),
patch
(
),
patch
(
"app.api.tasks.task_catalog.select_topic_by_key"
,
"app.api.tasks.socratic_oranisator.get_topic_entry"
,
return_value
=
True
,
return_value
=
{
)
as
select_mock
,
patch
(
"topic_key"
:
"quadratische gleichungen"
,
"app.api.tasks.context_store.save_sheet"
"label"
:
"Quadratische Gleichungen"
,
"level"
:
"subsubsection"
,
"refs"
:
[[
1
,
3
,
3
,
1
]],
},
),
patch
(
"app.api.tasks.context_store_base.save_sheet"
),
patch
(
),
patch
(
"app.api.tasks.task_catalog.get_selected_topic_ids"
,
"app.api.tasks.task_catalog.get_selected_topic_ids"
,
return_value
=
(
None
,
"quadratische gleichungen"
),
return_value
=
(
None
,
"quadratische gleichungen"
),
...
@@ -542,7 +547,8 @@ class TaskApiSocraticTest(unittest.TestCase):
...
@@ -542,7 +547,8 @@ class TaskApiSocraticTest(unittest.TestCase):
self
.
assertEqual
(
response
.
status_code
,
200
)
self
.
assertEqual
(
response
.
status_code
,
200
)
self
.
assertEqual
(
response
.
json
()[
"topic_key"
],
"quadratische gleichungen"
)
self
.
assertEqual
(
response
.
json
()[
"topic_key"
],
"quadratische gleichungen"
)
select_mock
.
assert_called_once_with
(
sheet
,
topic_key
=
"quadratische_gleichungen"
)
self
.
assertEqual
(
sheet
[
"selected_topic_key"
],
"quadratische gleichungen"
)
self
.
assertEqual
(
sheet
[
"selected_topic_parent_refs"
],
[[
1
,
3
,
3
,
1
]])
class
ChatBootstrapSocraticTest
(
unittest
.
TestCase
):
class
ChatBootstrapSocraticTest
(
unittest
.
TestCase
):
...
@@ -554,21 +560,29 @@ class ChatBootstrapSocraticTest(unittest.TestCase):
...
@@ -554,21 +560,29 @@ class ChatBootstrapSocraticTest(unittest.TestCase):
def
test_bootstrap_socratic_loads_sources_and_writes_only_assistant_history
(
self
)
->
None
:
def
test_bootstrap_socratic_loads_sources_and_writes_only_assistant_history
(
self
)
->
None
:
sheet
:
dict
[
str
,
object
]
=
{}
sheet
:
dict
[
str
,
object
]
=
{}
with
patch
(
"app.api.chat.context_store.get_chat_id"
,
return_value
=
"chat-1"
),
patch
(
with
patch
(
"app.api.chat.context_store
_base
.get_chat_id"
,
return_value
=
"chat-1"
),
patch
(
"app.api.chat.context_store.load_sheet"
,
"app.api.chat.context_store
_base
.load_sheet"
,
return_value
=
sheet
,
return_value
=
sheet
,
),
patch
(
),
patch
(
"app.api.chat.context_store
.context_store
_task.init_sheet"
,
"app.api.chat.context_store_task.init_sheet"
,
return_value
=
sheet
,
return_value
=
sheet
,
),
patch
(
),
patch
(
"app.api.chat.context_store.save_sheet"
"app.api.chat.context_store
_base
.save_sheet"
),
patch
(
),
patch
(
"app.api.chat.context_store.set_sources"
"app.api.chat.context_store
_base
.set_sources"
),
patch
(
),
patch
(
"app.api.chat.context_store.set_initialized"
"app.api.chat.context_store
_base
.set_initialized"
),
patch
(
),
patch
(
"app.api.chat.task_catalog.load_topic_map"
,
"app.api.chat.socratic_oranisator.get_topic_entry"
,
return_value
=
{
"quadratische gleichungen"
:
(
1
,
3
,
3
,
1
)},
return_value
=
{
"topic_key"
:
"quadratische gleichungen"
,
"label"
:
"Quadratische Gleichungen"
,
"level"
:
"subsubsection"
,
"refs"
:
[[
1
,
3
,
3
,
1
]],
},
),
patch
(
"app.api.chat.config.get_postgres_url"
,
return_value
=
"postgresql://localhost/test"
,
),
patch
(
),
patch
(
"app.api.chat.retrieval_store.retrieve_for_parent_refs"
,
"app.api.chat.retrieval_store.retrieve_for_parent_refs"
,
return_value
=
[],
return_value
=
[],
...
...
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