-
Notifications
You must be signed in to change notification settings - Fork 159
Expand file tree
/
Copy pathentry_tutor_question_entries.py
More file actions
121 lines (118 loc) · 4.26 KB
/
entry_tutor_question_entries.py
File metadata and controls
121 lines (118 loc) · 4.26 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
from __future__ import annotations
from .entry_common import (
Err,
Ok,
SdkError,
_entry_exception_error,
_validate_optional_vision_image_payload,
plugin_entry,
tr,
LLM_OPERATION_QUESTION_GENERATE,
)
class _TutorQuestionEntriesMixin:
@plugin_entry(
id="study_generate_question",
name=tr("entries.generate_question.name", default="Generate Study Question"),
description=tr(
"entries.generate_question.description",
default="Generate one study question from supplied text or the latest OCR text.",
),
input_schema={
"type": "object",
"properties": {
"text": {"type": "string", "default": ""},
"topic": {"type": "string", "default": ""},
"vision_image_base64": {"type": "string", "default": ""},
},
},
timeout=60.0,
llm_result_fields=[
"summary",
"question",
"answer",
"hint",
"difficulty",
"topic",
],
)
async def study_generate_question(
self,
text: str = "",
topic: str = "",
vision_image_base64: str = "",
**_,
):
if self._agent is None:
return Err(SdkError("study tutor agent is not initialized"))
source_text = str(text or "").strip()
vision_image_payload = str(vision_image_base64 or "").strip()
used_ocr_fallback = False
if not source_text:
async with self._lock:
source_text = self._state.last_ocr_text
used_ocr_fallback = bool(source_text.strip())
source_text = source_text.strip()
if not source_text and not vision_image_payload:
return Err(
SdkError(
"study tutor requires text, an image, or a non-empty OCR snapshot",
code="MISSING_TEXT",
)
)
validated_vision_image = _validate_optional_vision_image_payload(
self, vision_image_payload, operation="study_generate_question"
)
if isinstance(validated_vision_image, Err):
return validated_vision_image
vision_image_payload = validated_vision_image
try:
async with self._lock:
active_mode = self._state.active_mode
tutor_context = await self._build_learning_context(
LLM_OPERATION_QUESTION_GENERATE,
input_text=source_text,
extra={
"source": "ocr_snapshot"
if used_ocr_fallback
else (
"vision_image"
if vision_image_payload and not source_text
else "manual"
),
"source_text": source_text,
"topic_hint": str(topic or "").strip(),
"mode": active_mode,
**(
{
"vision_enabled": True,
"vision_image_base64": vision_image_payload,
}
if vision_image_payload
else {}
),
},
)
reply = await self._agent.question_generate(
source_text, mode=active_mode, context=tutor_context
)
payload = await self._finalize_tutor_call(
LLM_OPERATION_QUESTION_GENERATE,
reply,
history_kind=LLM_OPERATION_QUESTION_GENERATE,
metadata={
"degraded": reply.degraded,
"diagnostic": reply.diagnostic,
"payload": reply.payload,
"screen_classification": tutor_context.get("screen_classification")
or {},
},
extra_context=tutor_context,
)
payload["screen_classification"] = (
tutor_context.get("screen_classification") or {}
)
return Ok(payload)
except Exception as exc:
return _entry_exception_error(
self, exc, operation="study_generate_question"
)