realtimex-deeptutor 0.5.0.post1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- realtimex_deeptutor/__init__.py +67 -0
- realtimex_deeptutor-0.5.0.post1.dist-info/METADATA +1612 -0
- realtimex_deeptutor-0.5.0.post1.dist-info/RECORD +276 -0
- realtimex_deeptutor-0.5.0.post1.dist-info/WHEEL +5 -0
- realtimex_deeptutor-0.5.0.post1.dist-info/entry_points.txt +2 -0
- realtimex_deeptutor-0.5.0.post1.dist-info/licenses/LICENSE +661 -0
- realtimex_deeptutor-0.5.0.post1.dist-info/top_level.txt +2 -0
- src/__init__.py +40 -0
- src/agents/__init__.py +24 -0
- src/agents/base_agent.py +657 -0
- src/agents/chat/__init__.py +24 -0
- src/agents/chat/chat_agent.py +435 -0
- src/agents/chat/prompts/en/chat_agent.yaml +35 -0
- src/agents/chat/prompts/zh/chat_agent.yaml +35 -0
- src/agents/chat/session_manager.py +311 -0
- src/agents/co_writer/__init__.py +0 -0
- src/agents/co_writer/edit_agent.py +260 -0
- src/agents/co_writer/narrator_agent.py +423 -0
- src/agents/co_writer/prompts/en/edit_agent.yaml +113 -0
- src/agents/co_writer/prompts/en/narrator_agent.yaml +88 -0
- src/agents/co_writer/prompts/zh/edit_agent.yaml +113 -0
- src/agents/co_writer/prompts/zh/narrator_agent.yaml +88 -0
- src/agents/guide/__init__.py +16 -0
- src/agents/guide/agents/__init__.py +11 -0
- src/agents/guide/agents/chat_agent.py +104 -0
- src/agents/guide/agents/interactive_agent.py +223 -0
- src/agents/guide/agents/locate_agent.py +149 -0
- src/agents/guide/agents/summary_agent.py +150 -0
- src/agents/guide/guide_manager.py +500 -0
- src/agents/guide/prompts/en/chat_agent.yaml +41 -0
- src/agents/guide/prompts/en/interactive_agent.yaml +202 -0
- src/agents/guide/prompts/en/locate_agent.yaml +68 -0
- src/agents/guide/prompts/en/summary_agent.yaml +157 -0
- src/agents/guide/prompts/zh/chat_agent.yaml +41 -0
- src/agents/guide/prompts/zh/interactive_agent.yaml +626 -0
- src/agents/guide/prompts/zh/locate_agent.yaml +68 -0
- src/agents/guide/prompts/zh/summary_agent.yaml +157 -0
- src/agents/ideagen/__init__.py +12 -0
- src/agents/ideagen/idea_generation_workflow.py +426 -0
- src/agents/ideagen/material_organizer_agent.py +173 -0
- src/agents/ideagen/prompts/en/idea_generation.yaml +187 -0
- src/agents/ideagen/prompts/en/material_organizer.yaml +69 -0
- src/agents/ideagen/prompts/zh/idea_generation.yaml +187 -0
- src/agents/ideagen/prompts/zh/material_organizer.yaml +69 -0
- src/agents/question/__init__.py +24 -0
- src/agents/question/agents/__init__.py +18 -0
- src/agents/question/agents/generate_agent.py +381 -0
- src/agents/question/agents/relevance_analyzer.py +207 -0
- src/agents/question/agents/retrieve_agent.py +239 -0
- src/agents/question/coordinator.py +718 -0
- src/agents/question/example.py +109 -0
- src/agents/question/prompts/en/coordinator.yaml +75 -0
- src/agents/question/prompts/en/generate_agent.yaml +77 -0
- src/agents/question/prompts/en/relevance_analyzer.yaml +41 -0
- src/agents/question/prompts/en/retrieve_agent.yaml +32 -0
- src/agents/question/prompts/zh/coordinator.yaml +75 -0
- src/agents/question/prompts/zh/generate_agent.yaml +77 -0
- src/agents/question/prompts/zh/relevance_analyzer.yaml +39 -0
- src/agents/question/prompts/zh/retrieve_agent.yaml +30 -0
- src/agents/research/agents/__init__.py +23 -0
- src/agents/research/agents/decompose_agent.py +507 -0
- src/agents/research/agents/manager_agent.py +228 -0
- src/agents/research/agents/note_agent.py +180 -0
- src/agents/research/agents/rephrase_agent.py +263 -0
- src/agents/research/agents/reporting_agent.py +1333 -0
- src/agents/research/agents/research_agent.py +714 -0
- src/agents/research/data_structures.py +451 -0
- src/agents/research/main.py +188 -0
- src/agents/research/prompts/en/decompose_agent.yaml +89 -0
- src/agents/research/prompts/en/manager_agent.yaml +24 -0
- src/agents/research/prompts/en/note_agent.yaml +121 -0
- src/agents/research/prompts/en/rephrase_agent.yaml +58 -0
- src/agents/research/prompts/en/reporting_agent.yaml +380 -0
- src/agents/research/prompts/en/research_agent.yaml +173 -0
- src/agents/research/prompts/zh/decompose_agent.yaml +89 -0
- src/agents/research/prompts/zh/manager_agent.yaml +24 -0
- src/agents/research/prompts/zh/note_agent.yaml +121 -0
- src/agents/research/prompts/zh/rephrase_agent.yaml +58 -0
- src/agents/research/prompts/zh/reporting_agent.yaml +380 -0
- src/agents/research/prompts/zh/research_agent.yaml +173 -0
- src/agents/research/research_pipeline.py +1309 -0
- src/agents/research/utils/__init__.py +60 -0
- src/agents/research/utils/citation_manager.py +799 -0
- src/agents/research/utils/json_utils.py +98 -0
- src/agents/research/utils/token_tracker.py +297 -0
- src/agents/solve/__init__.py +80 -0
- src/agents/solve/analysis_loop/__init__.py +14 -0
- src/agents/solve/analysis_loop/investigate_agent.py +414 -0
- src/agents/solve/analysis_loop/note_agent.py +190 -0
- src/agents/solve/main_solver.py +862 -0
- src/agents/solve/memory/__init__.py +34 -0
- src/agents/solve/memory/citation_memory.py +353 -0
- src/agents/solve/memory/investigate_memory.py +226 -0
- src/agents/solve/memory/solve_memory.py +340 -0
- src/agents/solve/prompts/en/analysis_loop/investigate_agent.yaml +55 -0
- src/agents/solve/prompts/en/analysis_loop/note_agent.yaml +54 -0
- src/agents/solve/prompts/en/solve_loop/manager_agent.yaml +67 -0
- src/agents/solve/prompts/en/solve_loop/precision_answer_agent.yaml +62 -0
- src/agents/solve/prompts/en/solve_loop/response_agent.yaml +90 -0
- src/agents/solve/prompts/en/solve_loop/solve_agent.yaml +75 -0
- src/agents/solve/prompts/en/solve_loop/tool_agent.yaml +38 -0
- src/agents/solve/prompts/zh/analysis_loop/investigate_agent.yaml +53 -0
- src/agents/solve/prompts/zh/analysis_loop/note_agent.yaml +54 -0
- src/agents/solve/prompts/zh/solve_loop/manager_agent.yaml +66 -0
- src/agents/solve/prompts/zh/solve_loop/precision_answer_agent.yaml +62 -0
- src/agents/solve/prompts/zh/solve_loop/response_agent.yaml +90 -0
- src/agents/solve/prompts/zh/solve_loop/solve_agent.yaml +76 -0
- src/agents/solve/prompts/zh/solve_loop/tool_agent.yaml +41 -0
- src/agents/solve/solve_loop/__init__.py +22 -0
- src/agents/solve/solve_loop/citation_manager.py +74 -0
- src/agents/solve/solve_loop/manager_agent.py +274 -0
- src/agents/solve/solve_loop/precision_answer_agent.py +96 -0
- src/agents/solve/solve_loop/response_agent.py +301 -0
- src/agents/solve/solve_loop/solve_agent.py +325 -0
- src/agents/solve/solve_loop/tool_agent.py +470 -0
- src/agents/solve/utils/__init__.py +64 -0
- src/agents/solve/utils/config_validator.py +313 -0
- src/agents/solve/utils/display_manager.py +223 -0
- src/agents/solve/utils/error_handler.py +363 -0
- src/agents/solve/utils/json_utils.py +98 -0
- src/agents/solve/utils/performance_monitor.py +407 -0
- src/agents/solve/utils/token_tracker.py +541 -0
- src/api/__init__.py +0 -0
- src/api/main.py +240 -0
- src/api/routers/__init__.py +1 -0
- src/api/routers/agent_config.py +69 -0
- src/api/routers/chat.py +296 -0
- src/api/routers/co_writer.py +337 -0
- src/api/routers/config.py +627 -0
- src/api/routers/dashboard.py +18 -0
- src/api/routers/guide.py +337 -0
- src/api/routers/ideagen.py +436 -0
- src/api/routers/knowledge.py +821 -0
- src/api/routers/notebook.py +247 -0
- src/api/routers/question.py +537 -0
- src/api/routers/research.py +394 -0
- src/api/routers/settings.py +164 -0
- src/api/routers/solve.py +305 -0
- src/api/routers/system.py +252 -0
- src/api/run_server.py +61 -0
- src/api/utils/history.py +172 -0
- src/api/utils/log_interceptor.py +21 -0
- src/api/utils/notebook_manager.py +415 -0
- src/api/utils/progress_broadcaster.py +72 -0
- src/api/utils/task_id_manager.py +100 -0
- src/config/__init__.py +0 -0
- src/config/accessors.py +18 -0
- src/config/constants.py +34 -0
- src/config/defaults.py +18 -0
- src/config/schema.py +38 -0
- src/config/settings.py +50 -0
- src/core/errors.py +62 -0
- src/knowledge/__init__.py +23 -0
- src/knowledge/add_documents.py +606 -0
- src/knowledge/config.py +65 -0
- src/knowledge/example_add_documents.py +236 -0
- src/knowledge/extract_numbered_items.py +1039 -0
- src/knowledge/initializer.py +621 -0
- src/knowledge/kb.py +22 -0
- src/knowledge/manager.py +782 -0
- src/knowledge/progress_tracker.py +182 -0
- src/knowledge/start_kb.py +535 -0
- src/logging/__init__.py +103 -0
- src/logging/adapters/__init__.py +17 -0
- src/logging/adapters/lightrag.py +184 -0
- src/logging/adapters/llamaindex.py +141 -0
- src/logging/config.py +80 -0
- src/logging/handlers/__init__.py +20 -0
- src/logging/handlers/console.py +75 -0
- src/logging/handlers/file.py +201 -0
- src/logging/handlers/websocket.py +127 -0
- src/logging/logger.py +709 -0
- src/logging/stats/__init__.py +16 -0
- src/logging/stats/llm_stats.py +179 -0
- src/services/__init__.py +56 -0
- src/services/config/__init__.py +61 -0
- src/services/config/knowledge_base_config.py +210 -0
- src/services/config/loader.py +260 -0
- src/services/config/unified_config.py +603 -0
- src/services/embedding/__init__.py +45 -0
- src/services/embedding/adapters/__init__.py +22 -0
- src/services/embedding/adapters/base.py +106 -0
- src/services/embedding/adapters/cohere.py +127 -0
- src/services/embedding/adapters/jina.py +99 -0
- src/services/embedding/adapters/ollama.py +116 -0
- src/services/embedding/adapters/openai_compatible.py +96 -0
- src/services/embedding/client.py +159 -0
- src/services/embedding/config.py +156 -0
- src/services/embedding/provider.py +119 -0
- src/services/llm/__init__.py +152 -0
- src/services/llm/capabilities.py +313 -0
- src/services/llm/client.py +302 -0
- src/services/llm/cloud_provider.py +530 -0
- src/services/llm/config.py +200 -0
- src/services/llm/error_mapping.py +103 -0
- src/services/llm/exceptions.py +152 -0
- src/services/llm/factory.py +450 -0
- src/services/llm/local_provider.py +347 -0
- src/services/llm/providers/anthropic.py +95 -0
- src/services/llm/providers/base_provider.py +93 -0
- src/services/llm/providers/open_ai.py +83 -0
- src/services/llm/registry.py +71 -0
- src/services/llm/telemetry.py +40 -0
- src/services/llm/types.py +27 -0
- src/services/llm/utils.py +333 -0
- src/services/prompt/__init__.py +25 -0
- src/services/prompt/manager.py +206 -0
- src/services/rag/__init__.py +64 -0
- src/services/rag/components/__init__.py +29 -0
- src/services/rag/components/base.py +59 -0
- src/services/rag/components/chunkers/__init__.py +18 -0
- src/services/rag/components/chunkers/base.py +34 -0
- src/services/rag/components/chunkers/fixed.py +71 -0
- src/services/rag/components/chunkers/numbered_item.py +94 -0
- src/services/rag/components/chunkers/semantic.py +97 -0
- src/services/rag/components/embedders/__init__.py +14 -0
- src/services/rag/components/embedders/base.py +32 -0
- src/services/rag/components/embedders/openai.py +63 -0
- src/services/rag/components/indexers/__init__.py +18 -0
- src/services/rag/components/indexers/base.py +35 -0
- src/services/rag/components/indexers/graph.py +172 -0
- src/services/rag/components/indexers/lightrag.py +156 -0
- src/services/rag/components/indexers/vector.py +146 -0
- src/services/rag/components/parsers/__init__.py +18 -0
- src/services/rag/components/parsers/base.py +35 -0
- src/services/rag/components/parsers/markdown.py +52 -0
- src/services/rag/components/parsers/pdf.py +115 -0
- src/services/rag/components/parsers/text.py +86 -0
- src/services/rag/components/retrievers/__init__.py +18 -0
- src/services/rag/components/retrievers/base.py +34 -0
- src/services/rag/components/retrievers/dense.py +200 -0
- src/services/rag/components/retrievers/hybrid.py +164 -0
- src/services/rag/components/retrievers/lightrag.py +169 -0
- src/services/rag/components/routing.py +286 -0
- src/services/rag/factory.py +234 -0
- src/services/rag/pipeline.py +215 -0
- src/services/rag/pipelines/__init__.py +32 -0
- src/services/rag/pipelines/academic.py +44 -0
- src/services/rag/pipelines/lightrag.py +43 -0
- src/services/rag/pipelines/llamaindex.py +313 -0
- src/services/rag/pipelines/raganything.py +384 -0
- src/services/rag/service.py +244 -0
- src/services/rag/types.py +73 -0
- src/services/search/__init__.py +284 -0
- src/services/search/base.py +87 -0
- src/services/search/consolidation.py +398 -0
- src/services/search/providers/__init__.py +128 -0
- src/services/search/providers/baidu.py +188 -0
- src/services/search/providers/exa.py +194 -0
- src/services/search/providers/jina.py +161 -0
- src/services/search/providers/perplexity.py +153 -0
- src/services/search/providers/serper.py +209 -0
- src/services/search/providers/tavily.py +161 -0
- src/services/search/types.py +114 -0
- src/services/setup/__init__.py +34 -0
- src/services/setup/init.py +285 -0
- src/services/tts/__init__.py +16 -0
- src/services/tts/config.py +99 -0
- src/tools/__init__.py +91 -0
- src/tools/code_executor.py +536 -0
- src/tools/paper_search_tool.py +171 -0
- src/tools/query_item_tool.py +310 -0
- src/tools/question/__init__.py +15 -0
- src/tools/question/exam_mimic.py +616 -0
- src/tools/question/pdf_parser.py +211 -0
- src/tools/question/question_extractor.py +397 -0
- src/tools/rag_tool.py +173 -0
- src/tools/tex_chunker.py +339 -0
- src/tools/tex_downloader.py +253 -0
- src/tools/web_search.py +71 -0
- src/utils/config_manager.py +206 -0
- src/utils/document_validator.py +168 -0
- src/utils/error_rate_tracker.py +111 -0
- src/utils/error_utils.py +82 -0
- src/utils/json_parser.py +110 -0
- src/utils/network/circuit_breaker.py +79 -0
|
@@ -0,0 +1,500 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""
|
|
4
|
+
GuideManager - Guided Learning Session Manager
|
|
5
|
+
Manages the complete lifecycle of learning sessions
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from dataclasses import asdict, dataclass, field
|
|
9
|
+
import json
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
import time
|
|
12
|
+
from typing import Any
|
|
13
|
+
import uuid
|
|
14
|
+
|
|
15
|
+
import yaml
|
|
16
|
+
|
|
17
|
+
from src.logging import get_logger
|
|
18
|
+
from src.services.config import load_config_with_main, parse_language
|
|
19
|
+
|
|
20
|
+
from .agents import ChatAgent, InteractiveAgent, LocateAgent, SummaryAgent
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
@dataclass
|
|
24
|
+
class GuidedSession:
|
|
25
|
+
"""Guided learning session"""
|
|
26
|
+
|
|
27
|
+
session_id: str
|
|
28
|
+
notebook_id: str
|
|
29
|
+
notebook_name: str
|
|
30
|
+
created_at: float
|
|
31
|
+
knowledge_points: list[dict[str, Any]] = field(default_factory=list)
|
|
32
|
+
current_index: int = 0
|
|
33
|
+
chat_history: list[dict[str, Any]] = field(default_factory=list)
|
|
34
|
+
status: str = "initialized" # initialized, learning, completed
|
|
35
|
+
current_html: str = ""
|
|
36
|
+
summary: str = ""
|
|
37
|
+
|
|
38
|
+
def to_dict(self) -> dict[str, Any]:
|
|
39
|
+
return asdict(self)
|
|
40
|
+
|
|
41
|
+
@classmethod
|
|
42
|
+
def from_dict(cls, data: dict[str, Any]) -> "GuidedSession":
|
|
43
|
+
return cls(**data)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class GuideManager:
|
|
47
|
+
"""Guided learning manager"""
|
|
48
|
+
|
|
49
|
+
def __init__(
|
|
50
|
+
self,
|
|
51
|
+
api_key: str,
|
|
52
|
+
base_url: str,
|
|
53
|
+
api_version: str | None = None,
|
|
54
|
+
language: str | None = None,
|
|
55
|
+
output_dir: str | None = None,
|
|
56
|
+
config_path: str | None = None,
|
|
57
|
+
binding: str = "openai",
|
|
58
|
+
):
|
|
59
|
+
"""
|
|
60
|
+
Initialize manager
|
|
61
|
+
|
|
62
|
+
Args:
|
|
63
|
+
api_key: API key
|
|
64
|
+
base_url: API endpoint
|
|
65
|
+
api_version: API version (for Azure OpenAI)
|
|
66
|
+
language: Language setting (if None, read from config file)
|
|
67
|
+
output_dir: Output directory
|
|
68
|
+
config_path: Configuration file path (if None, use default path)
|
|
69
|
+
binding: LLM provider binding
|
|
70
|
+
"""
|
|
71
|
+
self.api_key = api_key
|
|
72
|
+
self.base_url = base_url
|
|
73
|
+
self.api_version = api_version
|
|
74
|
+
self.binding = binding
|
|
75
|
+
|
|
76
|
+
if config_path is None:
|
|
77
|
+
project_root = Path(__file__).parent.parent.parent.parent
|
|
78
|
+
config = load_config_with_main("guide_config.yaml", project_root)
|
|
79
|
+
else:
|
|
80
|
+
config_path = Path(config_path)
|
|
81
|
+
if config_path.exists():
|
|
82
|
+
try:
|
|
83
|
+
with open(config_path, encoding="utf-8") as f:
|
|
84
|
+
config = yaml.safe_load(f) or {}
|
|
85
|
+
except Exception:
|
|
86
|
+
config = {}
|
|
87
|
+
else:
|
|
88
|
+
config = {}
|
|
89
|
+
|
|
90
|
+
# Initialize logger (from config)
|
|
91
|
+
log_dir = config.get("paths", {}).get("user_log_dir") or config.get("logging", {}).get(
|
|
92
|
+
"log_dir"
|
|
93
|
+
)
|
|
94
|
+
self.logger = get_logger("Guide", log_dir=log_dir)
|
|
95
|
+
|
|
96
|
+
if language is None:
|
|
97
|
+
# Get language config (unified in config/main.yaml system.language)
|
|
98
|
+
lang_config = config.get("system", {}).get("language", "zh")
|
|
99
|
+
self.language = parse_language(lang_config)
|
|
100
|
+
self.logger.info(f"Language setting loaded from config: {self.language}")
|
|
101
|
+
else:
|
|
102
|
+
# If explicitly specified, also parse it to ensure consistency
|
|
103
|
+
self.language = parse_language(language)
|
|
104
|
+
self.logger.info(f"Using explicitly specified language setting: {self.language}")
|
|
105
|
+
|
|
106
|
+
if output_dir:
|
|
107
|
+
self.output_dir = Path(output_dir)
|
|
108
|
+
else:
|
|
109
|
+
# Get output_dir from config (already loaded above)
|
|
110
|
+
output_dir_from_config = config.get("system", {}).get("output_dir")
|
|
111
|
+
if output_dir_from_config:
|
|
112
|
+
self.output_dir = Path(output_dir_from_config)
|
|
113
|
+
else:
|
|
114
|
+
# Fallback to default path
|
|
115
|
+
project_root = Path(__file__).parent.parent.parent.parent
|
|
116
|
+
self.output_dir = project_root / "data" / "user" / "guide"
|
|
117
|
+
self.output_dir.mkdir(parents=True, exist_ok=True)
|
|
118
|
+
|
|
119
|
+
self.locate_agent = LocateAgent(
|
|
120
|
+
api_key,
|
|
121
|
+
base_url,
|
|
122
|
+
language=self.language,
|
|
123
|
+
api_version=self.api_version,
|
|
124
|
+
binding=self.binding,
|
|
125
|
+
)
|
|
126
|
+
self.interactive_agent = InteractiveAgent(
|
|
127
|
+
api_key,
|
|
128
|
+
base_url,
|
|
129
|
+
language=self.language,
|
|
130
|
+
api_version=self.api_version,
|
|
131
|
+
binding=self.binding,
|
|
132
|
+
)
|
|
133
|
+
self.chat_agent = ChatAgent(
|
|
134
|
+
api_key,
|
|
135
|
+
base_url,
|
|
136
|
+
language=self.language,
|
|
137
|
+
api_version=self.api_version,
|
|
138
|
+
binding=self.binding,
|
|
139
|
+
)
|
|
140
|
+
self.summary_agent = SummaryAgent(
|
|
141
|
+
api_key,
|
|
142
|
+
base_url,
|
|
143
|
+
language=self.language,
|
|
144
|
+
api_version=self.api_version,
|
|
145
|
+
binding=self.binding,
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
self._sessions: dict[str, GuidedSession] = {}
|
|
149
|
+
|
|
150
|
+
def _get_session_file(self, session_id: str) -> Path:
|
|
151
|
+
"""Get session file path"""
|
|
152
|
+
return self.output_dir / f"session_{session_id}.json"
|
|
153
|
+
|
|
154
|
+
def _save_session(self, session: GuidedSession):
|
|
155
|
+
"""Save session to file"""
|
|
156
|
+
filepath = self._get_session_file(session.session_id)
|
|
157
|
+
with open(filepath, "w", encoding="utf-8") as f:
|
|
158
|
+
json.dump(session.to_dict(), f, indent=2, ensure_ascii=False)
|
|
159
|
+
self._sessions[session.session_id] = session
|
|
160
|
+
|
|
161
|
+
def _load_session(self, session_id: str) -> GuidedSession | None:
|
|
162
|
+
"""Load session from file"""
|
|
163
|
+
if session_id in self._sessions:
|
|
164
|
+
return self._sessions[session_id]
|
|
165
|
+
|
|
166
|
+
filepath = self._get_session_file(session_id)
|
|
167
|
+
if filepath.exists():
|
|
168
|
+
with open(filepath, encoding="utf-8") as f:
|
|
169
|
+
data = json.load(f)
|
|
170
|
+
session = GuidedSession.from_dict(data)
|
|
171
|
+
self._sessions[session_id] = session
|
|
172
|
+
return session
|
|
173
|
+
return None
|
|
174
|
+
|
|
175
|
+
async def create_session(
|
|
176
|
+
self, notebook_id: str, notebook_name: str, records: list[dict[str, Any]]
|
|
177
|
+
) -> dict[str, Any]:
|
|
178
|
+
"""
|
|
179
|
+
Create new learning session
|
|
180
|
+
|
|
181
|
+
Args:
|
|
182
|
+
notebook_id: Notebook ID
|
|
183
|
+
notebook_name: Notebook name
|
|
184
|
+
records: Notebook records
|
|
185
|
+
|
|
186
|
+
Returns:
|
|
187
|
+
Session creation result
|
|
188
|
+
"""
|
|
189
|
+
session_id = str(uuid.uuid4())[:8]
|
|
190
|
+
|
|
191
|
+
locate_result = await self.locate_agent.process(
|
|
192
|
+
notebook_id=notebook_id, notebook_name=notebook_name, records=records
|
|
193
|
+
)
|
|
194
|
+
|
|
195
|
+
if not locate_result.get("success"):
|
|
196
|
+
return {
|
|
197
|
+
"success": False,
|
|
198
|
+
"error": locate_result.get("error", "Failed to analyze knowledge points"),
|
|
199
|
+
"session_id": None,
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
knowledge_points = locate_result.get("knowledge_points", [])
|
|
203
|
+
|
|
204
|
+
if not knowledge_points:
|
|
205
|
+
return {
|
|
206
|
+
"success": False,
|
|
207
|
+
"error": "No knowledge points identified from notebook",
|
|
208
|
+
"session_id": None,
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
session = GuidedSession(
|
|
212
|
+
session_id=session_id,
|
|
213
|
+
notebook_id=notebook_id,
|
|
214
|
+
notebook_name=notebook_name,
|
|
215
|
+
created_at=time.time(),
|
|
216
|
+
knowledge_points=knowledge_points,
|
|
217
|
+
current_index=0,
|
|
218
|
+
status="initialized",
|
|
219
|
+
)
|
|
220
|
+
|
|
221
|
+
self._save_session(session)
|
|
222
|
+
|
|
223
|
+
return {
|
|
224
|
+
"success": True,
|
|
225
|
+
"session_id": session_id,
|
|
226
|
+
"knowledge_points": knowledge_points,
|
|
227
|
+
"total_points": len(knowledge_points),
|
|
228
|
+
"message": f"Learning plan created with {len(knowledge_points)} knowledge points",
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
def _get_learning_state(
|
|
232
|
+
self, knowledge_points: list[dict[str, Any]], current_index: int
|
|
233
|
+
) -> dict[str, Any]:
|
|
234
|
+
"""
|
|
235
|
+
Get learning state information (internal helper method)
|
|
236
|
+
|
|
237
|
+
Args:
|
|
238
|
+
knowledge_points: Knowledge point list
|
|
239
|
+
current_index: Current knowledge point index
|
|
240
|
+
|
|
241
|
+
Returns:
|
|
242
|
+
Learning state information
|
|
243
|
+
"""
|
|
244
|
+
total_points = len(knowledge_points)
|
|
245
|
+
|
|
246
|
+
if total_points == 0:
|
|
247
|
+
return {"success": False, "error": "No knowledge points to learn", "status": "empty"}
|
|
248
|
+
|
|
249
|
+
if current_index >= total_points:
|
|
250
|
+
return {
|
|
251
|
+
"success": True,
|
|
252
|
+
"current_index": current_index,
|
|
253
|
+
"current_knowledge": None,
|
|
254
|
+
"status": "completed",
|
|
255
|
+
"progress_percentage": 100,
|
|
256
|
+
"total_points": total_points,
|
|
257
|
+
"message": "🎉 Congratulations! You have completed learning all knowledge points!",
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
current_knowledge = knowledge_points[current_index]
|
|
261
|
+
progress = int((current_index / total_points) * 100)
|
|
262
|
+
|
|
263
|
+
message = f"📚 Starting to learn knowledge point {current_index + 1}: {current_knowledge.get('knowledge_title', '')}"
|
|
264
|
+
|
|
265
|
+
return {
|
|
266
|
+
"success": True,
|
|
267
|
+
"current_index": current_index,
|
|
268
|
+
"current_knowledge": current_knowledge,
|
|
269
|
+
"status": "learning",
|
|
270
|
+
"progress_percentage": progress,
|
|
271
|
+
"total_points": total_points,
|
|
272
|
+
"remaining_points": total_points - current_index - 1,
|
|
273
|
+
"message": message,
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
async def start_learning(self, session_id: str) -> dict[str, Any]:
|
|
277
|
+
"""
|
|
278
|
+
Start learning the first knowledge point
|
|
279
|
+
|
|
280
|
+
Args:
|
|
281
|
+
session_id: Session ID
|
|
282
|
+
|
|
283
|
+
Returns:
|
|
284
|
+
First knowledge point information and interactive page
|
|
285
|
+
"""
|
|
286
|
+
session = self._load_session(session_id)
|
|
287
|
+
if not session:
|
|
288
|
+
return {"success": False, "error": "Session does not exist"}
|
|
289
|
+
|
|
290
|
+
state = self._get_learning_state(session.knowledge_points, 0)
|
|
291
|
+
|
|
292
|
+
if not state.get("success"):
|
|
293
|
+
return state
|
|
294
|
+
|
|
295
|
+
current_knowledge = state.get("current_knowledge")
|
|
296
|
+
|
|
297
|
+
interactive_result = await self.interactive_agent.process(knowledge=current_knowledge)
|
|
298
|
+
|
|
299
|
+
session.current_index = 0
|
|
300
|
+
session.status = "learning"
|
|
301
|
+
session.current_html = interactive_result.get("html", "")
|
|
302
|
+
|
|
303
|
+
session.chat_history.append(
|
|
304
|
+
{
|
|
305
|
+
"role": "system",
|
|
306
|
+
"content": state.get("message", ""),
|
|
307
|
+
"knowledge_index": 0,
|
|
308
|
+
"timestamp": time.time(),
|
|
309
|
+
}
|
|
310
|
+
)
|
|
311
|
+
|
|
312
|
+
self._save_session(session)
|
|
313
|
+
|
|
314
|
+
return {
|
|
315
|
+
"success": True,
|
|
316
|
+
"current_index": 0,
|
|
317
|
+
"current_knowledge": current_knowledge,
|
|
318
|
+
"html": interactive_result.get("html", ""),
|
|
319
|
+
"progress": state.get("progress_percentage", 0),
|
|
320
|
+
"total_points": len(session.knowledge_points),
|
|
321
|
+
"message": state.get("message", ""),
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
async def next_knowledge(self, session_id: str) -> dict[str, Any]:
|
|
325
|
+
"""
|
|
326
|
+
Move to next knowledge point
|
|
327
|
+
|
|
328
|
+
Args:
|
|
329
|
+
session_id: Session ID
|
|
330
|
+
|
|
331
|
+
Returns:
|
|
332
|
+
Next knowledge point information and interactive page, or completion summary
|
|
333
|
+
"""
|
|
334
|
+
session = self._load_session(session_id)
|
|
335
|
+
if not session:
|
|
336
|
+
return {"success": False, "error": "Session does not exist"}
|
|
337
|
+
|
|
338
|
+
new_index = session.current_index + 1
|
|
339
|
+
|
|
340
|
+
state = self._get_learning_state(session.knowledge_points, new_index)
|
|
341
|
+
|
|
342
|
+
if not state.get("success"):
|
|
343
|
+
return state
|
|
344
|
+
|
|
345
|
+
if state.get("status") == "completed":
|
|
346
|
+
summary_result = await self.summary_agent.process(
|
|
347
|
+
notebook_name=session.notebook_name,
|
|
348
|
+
knowledge_points=session.knowledge_points,
|
|
349
|
+
chat_history=session.chat_history,
|
|
350
|
+
)
|
|
351
|
+
|
|
352
|
+
session.status = "completed"
|
|
353
|
+
session.summary = summary_result.get("summary", "")
|
|
354
|
+
session.current_index = new_index
|
|
355
|
+
|
|
356
|
+
session.chat_history.append(
|
|
357
|
+
{
|
|
358
|
+
"role": "system",
|
|
359
|
+
"content": state.get(
|
|
360
|
+
"message", "Congratulations on completing all knowledge points!"
|
|
361
|
+
),
|
|
362
|
+
"timestamp": time.time(),
|
|
363
|
+
}
|
|
364
|
+
)
|
|
365
|
+
|
|
366
|
+
self._save_session(session)
|
|
367
|
+
|
|
368
|
+
return {
|
|
369
|
+
"success": True,
|
|
370
|
+
"status": "completed",
|
|
371
|
+
"summary": session.summary,
|
|
372
|
+
"progress": 100,
|
|
373
|
+
"message": state.get("message", ""),
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
current_knowledge = state.get("current_knowledge")
|
|
377
|
+
|
|
378
|
+
interactive_result = await self.interactive_agent.process(knowledge=current_knowledge)
|
|
379
|
+
|
|
380
|
+
session.current_index = new_index
|
|
381
|
+
session.current_html = interactive_result.get("html", "")
|
|
382
|
+
|
|
383
|
+
message = f"→ Entering knowledge point {new_index + 1}: {current_knowledge.get('knowledge_title', '')}"
|
|
384
|
+
|
|
385
|
+
session.chat_history.append(
|
|
386
|
+
{
|
|
387
|
+
"role": "system",
|
|
388
|
+
"content": message,
|
|
389
|
+
"knowledge_index": new_index,
|
|
390
|
+
"timestamp": time.time(),
|
|
391
|
+
}
|
|
392
|
+
)
|
|
393
|
+
|
|
394
|
+
self._save_session(session)
|
|
395
|
+
|
|
396
|
+
return {
|
|
397
|
+
"success": True,
|
|
398
|
+
"current_index": new_index,
|
|
399
|
+
"current_knowledge": current_knowledge,
|
|
400
|
+
"html": interactive_result.get("html", ""),
|
|
401
|
+
"progress": state.get("progress_percentage", 0),
|
|
402
|
+
"total_points": len(session.knowledge_points),
|
|
403
|
+
"remaining_points": state.get("remaining_points", 0),
|
|
404
|
+
"message": message,
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
async def chat(self, session_id: str, user_message: str) -> dict[str, Any]:
|
|
408
|
+
"""
|
|
409
|
+
Process user chat message
|
|
410
|
+
|
|
411
|
+
Args:
|
|
412
|
+
session_id: Session ID
|
|
413
|
+
user_message: User message
|
|
414
|
+
|
|
415
|
+
Returns:
|
|
416
|
+
Assistant's answer
|
|
417
|
+
"""
|
|
418
|
+
session = self._load_session(session_id)
|
|
419
|
+
if not session:
|
|
420
|
+
return {"success": False, "error": "Session does not exist"}
|
|
421
|
+
|
|
422
|
+
if session.status != "learning":
|
|
423
|
+
return {"success": False, "error": "Not currently in learning state"}
|
|
424
|
+
|
|
425
|
+
current_knowledge = session.knowledge_points[session.current_index]
|
|
426
|
+
|
|
427
|
+
current_history = [
|
|
428
|
+
msg
|
|
429
|
+
for msg in session.chat_history
|
|
430
|
+
if msg.get("knowledge_index") == session.current_index
|
|
431
|
+
]
|
|
432
|
+
|
|
433
|
+
user_msg = {
|
|
434
|
+
"role": "user",
|
|
435
|
+
"content": user_message,
|
|
436
|
+
"knowledge_index": session.current_index,
|
|
437
|
+
"timestamp": time.time(),
|
|
438
|
+
}
|
|
439
|
+
session.chat_history.append(user_msg)
|
|
440
|
+
|
|
441
|
+
chat_result = await self.chat_agent.process(
|
|
442
|
+
knowledge=current_knowledge, chat_history=current_history, user_question=user_message
|
|
443
|
+
)
|
|
444
|
+
|
|
445
|
+
assistant_msg = {
|
|
446
|
+
"role": "assistant",
|
|
447
|
+
"content": chat_result.get("answer", ""),
|
|
448
|
+
"knowledge_index": session.current_index,
|
|
449
|
+
"timestamp": time.time(),
|
|
450
|
+
}
|
|
451
|
+
session.chat_history.append(assistant_msg)
|
|
452
|
+
|
|
453
|
+
self._save_session(session)
|
|
454
|
+
|
|
455
|
+
return {
|
|
456
|
+
"success": True,
|
|
457
|
+
"answer": chat_result.get("answer", ""),
|
|
458
|
+
"knowledge_index": session.current_index,
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
async def fix_html(self, session_id: str, bug_description: str) -> dict[str, Any]:
|
|
462
|
+
"""
|
|
463
|
+
Fix HTML page bug
|
|
464
|
+
|
|
465
|
+
Args:
|
|
466
|
+
session_id: Session ID
|
|
467
|
+
bug_description: Bug description
|
|
468
|
+
|
|
469
|
+
Returns:
|
|
470
|
+
Fixed HTML
|
|
471
|
+
"""
|
|
472
|
+
session = self._load_session(session_id)
|
|
473
|
+
if not session:
|
|
474
|
+
return {"success": False, "error": "Session does not exist"}
|
|
475
|
+
|
|
476
|
+
current_knowledge = session.knowledge_points[session.current_index]
|
|
477
|
+
|
|
478
|
+
result = await self.interactive_agent.process(
|
|
479
|
+
knowledge=current_knowledge, retry_with_bug=bug_description
|
|
480
|
+
)
|
|
481
|
+
|
|
482
|
+
if result.get("success"):
|
|
483
|
+
session.current_html = result.get("html", "")
|
|
484
|
+
self._save_session(session)
|
|
485
|
+
|
|
486
|
+
return result
|
|
487
|
+
|
|
488
|
+
def get_session(self, session_id: str) -> dict[str, Any] | None:
|
|
489
|
+
"""Get session information"""
|
|
490
|
+
session = self._load_session(session_id)
|
|
491
|
+
if session:
|
|
492
|
+
return session.to_dict()
|
|
493
|
+
return None
|
|
494
|
+
|
|
495
|
+
def get_current_html(self, session_id: str) -> str | None:
|
|
496
|
+
"""Get current HTML page"""
|
|
497
|
+
session = self._load_session(session_id)
|
|
498
|
+
if session:
|
|
499
|
+
return session.current_html
|
|
500
|
+
return None
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
system: |
|
|
2
|
+
# Role Positioning
|
|
3
|
+
You are an **Intelligent Learning Assistant**. Your responsibility is to answer users' questions, resolve their doubts, and provide additional explanations and examples while they are learning specific knowledge points.
|
|
4
|
+
|
|
5
|
+
# Core Principles
|
|
6
|
+
1. **Focus on Current Knowledge Point**: Answers should revolve around the knowledge point the user is currently learning
|
|
7
|
+
2. **Progressive**: Provide explanations at an appropriate level based on the depth of the user's questions
|
|
8
|
+
3. **Encourage Thinking**: While directly providing answers, guide users to think
|
|
9
|
+
4. **Address Difficulties**: Consider potential difficulties users may have and proactively provide relevant clarifications
|
|
10
|
+
|
|
11
|
+
# Answer Style
|
|
12
|
+
- Use clear, easy-to-understand language
|
|
13
|
+
- Use examples and analogies appropriately
|
|
14
|
+
- For complex concepts, explain step by step
|
|
15
|
+
- Use Markdown format to enhance readability
|
|
16
|
+
- Maintain a friendly, encouraging tone
|
|
17
|
+
|
|
18
|
+
# Output Format
|
|
19
|
+
Directly output answers in Markdown format, with clear structure and highlighted key points.
|
|
20
|
+
|
|
21
|
+
user_template: |
|
|
22
|
+
## Currently Learning Knowledge Point
|
|
23
|
+
**Title**: {knowledge_title}
|
|
24
|
+
|
|
25
|
+
**Content Summary**:
|
|
26
|
+
{knowledge_summary}
|
|
27
|
+
|
|
28
|
+
**User's Potential Difficulties**:
|
|
29
|
+
{user_difficulty}
|
|
30
|
+
|
|
31
|
+
## Conversation History
|
|
32
|
+
{chat_history}
|
|
33
|
+
|
|
34
|
+
## User's Current Question
|
|
35
|
+
{user_question}
|
|
36
|
+
|
|
37
|
+
## Task
|
|
38
|
+
Please answer the user's question based on the content of the current knowledge point and context.
|
|
39
|
+
- Ensure the answer is relevant to the current knowledge point
|
|
40
|
+
- If the question involves the user's potential difficulties, give special attention
|
|
41
|
+
- The answer should be clear and well-organized
|