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,310 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""
|
|
4
|
+
Query Numbered Item Tool - Query definitions, theorems, formulas, figures, etc.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import json
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
import sys
|
|
10
|
+
|
|
11
|
+
# Add parent directory to path (insert at front to prioritize project modules)
|
|
12
|
+
project_root = Path(__file__).parent.parent.parent
|
|
13
|
+
sys.path.insert(0, str(project_root))
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def query_numbered_item(
|
|
17
|
+
identifier: str,
|
|
18
|
+
kb_name: str | None = None,
|
|
19
|
+
kb_base_dir: str | None = None,
|
|
20
|
+
max_results: int | None = None,
|
|
21
|
+
) -> dict:
|
|
22
|
+
"""
|
|
23
|
+
Query numbered item - Supports returning multiple matching results
|
|
24
|
+
|
|
25
|
+
Args:
|
|
26
|
+
identifier: Identifier of the numbered item
|
|
27
|
+
- Definition/Theorem: e.g., "Definition 1.1", "Theorem 2.3"
|
|
28
|
+
- Formula: e.g., "(1.2.1)", "(2.3.5)"
|
|
29
|
+
- Figure: e.g., "Figure 1.1", "Figure 2.5"
|
|
30
|
+
- Example: e.g., "Example 1.1", "Remark 2.1"
|
|
31
|
+
kb_name: Knowledge base name (optional, defaults to default knowledge base)
|
|
32
|
+
kb_base_dir: Knowledge base base directory (optional, defaults to knowledge_bases under project root)
|
|
33
|
+
max_results: Maximum number of items to return (optional, defaults to config value or 5)
|
|
34
|
+
|
|
35
|
+
Returns:
|
|
36
|
+
dict: Dictionary containing query results
|
|
37
|
+
{
|
|
38
|
+
"identifier": str, # Original query identifier
|
|
39
|
+
"type": str, # formula/definition/theorem/lemma/figure/example/remark
|
|
40
|
+
"status": str, # success/failed
|
|
41
|
+
"count": int, # Number of matched items
|
|
42
|
+
"items": [ # List of all matched items (sorted by priority)
|
|
43
|
+
{
|
|
44
|
+
"identifier": str, # Actual matched identifier
|
|
45
|
+
"type": str,
|
|
46
|
+
"content": str
|
|
47
|
+
},
|
|
48
|
+
...
|
|
49
|
+
],
|
|
50
|
+
"content": str, # Backward compatible: single item content or merged content for multiple items
|
|
51
|
+
"error": str (only when failed)
|
|
52
|
+
}
|
|
53
|
+
"""
|
|
54
|
+
# Load configuration for max_results if not specified
|
|
55
|
+
if max_results is None:
|
|
56
|
+
try:
|
|
57
|
+
from src.services.config import load_config_with_main
|
|
58
|
+
|
|
59
|
+
project_root = Path(__file__).parent.parent.parent
|
|
60
|
+
config = load_config_with_main("main.yaml", project_root)
|
|
61
|
+
max_results = config.get("tools", {}).get("query_item", {}).get("max_results", 5)
|
|
62
|
+
except Exception:
|
|
63
|
+
max_results = 5 # Default value
|
|
64
|
+
|
|
65
|
+
# If path not specified, use absolute path relative to this file
|
|
66
|
+
if kb_base_dir is None:
|
|
67
|
+
# __file__ = DeepTutor/tools/query_item_tool.py
|
|
68
|
+
# .parent = DeepTutor/tools
|
|
69
|
+
# .parent = DeepTutor
|
|
70
|
+
kb_base_dir = Path(__file__).parent.parent.parent / "data/knowledge_bases"
|
|
71
|
+
else:
|
|
72
|
+
kb_base_dir = Path(kb_base_dir)
|
|
73
|
+
|
|
74
|
+
base_dir = kb_base_dir
|
|
75
|
+
|
|
76
|
+
# Get knowledge base
|
|
77
|
+
if not kb_name:
|
|
78
|
+
config_file = base_dir / "kb_config.json"
|
|
79
|
+
if config_file.exists():
|
|
80
|
+
try:
|
|
81
|
+
with open(config_file, encoding="utf-8") as f:
|
|
82
|
+
config = json.load(f)
|
|
83
|
+
kb_name = config.get("default")
|
|
84
|
+
except Exception:
|
|
85
|
+
pass
|
|
86
|
+
|
|
87
|
+
if not kb_name:
|
|
88
|
+
return {
|
|
89
|
+
"identifier": identifier,
|
|
90
|
+
"type": "unknown",
|
|
91
|
+
"content": "",
|
|
92
|
+
"status": "failed",
|
|
93
|
+
"error": "Error: Knowledge base not specified and no default knowledge base",
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
# Load items
|
|
97
|
+
kb_dir = base_dir / kb_name
|
|
98
|
+
if not kb_dir.exists():
|
|
99
|
+
return {
|
|
100
|
+
"identifier": identifier,
|
|
101
|
+
"type": "unknown",
|
|
102
|
+
"content": "",
|
|
103
|
+
"status": "failed",
|
|
104
|
+
"error": f"Error: Knowledge base '{kb_name}' does not exist",
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
items_file = kb_dir / "numbered_items.json"
|
|
108
|
+
if not items_file.exists():
|
|
109
|
+
return {
|
|
110
|
+
"identifier": identifier,
|
|
111
|
+
"type": "unknown",
|
|
112
|
+
"content": "",
|
|
113
|
+
"status": "failed",
|
|
114
|
+
"error": f"Error: numbered_items.json not found in knowledge base '{kb_name}'",
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
try:
|
|
118
|
+
with open(items_file, encoding="utf-8") as f:
|
|
119
|
+
raw_items = json.load(f)
|
|
120
|
+
except Exception as e:
|
|
121
|
+
return {
|
|
122
|
+
"identifier": identifier,
|
|
123
|
+
"type": "unknown",
|
|
124
|
+
"content": "",
|
|
125
|
+
"status": "failed",
|
|
126
|
+
"error": f"Error: Unable to read file - {e}",
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
# Extract text content
|
|
130
|
+
items = {}
|
|
131
|
+
for key, value in raw_items.items():
|
|
132
|
+
if isinstance(value, dict):
|
|
133
|
+
items[key] = value.get("text", str(value))
|
|
134
|
+
else:
|
|
135
|
+
items[key] = value
|
|
136
|
+
|
|
137
|
+
# Validate identifier parameter
|
|
138
|
+
if not identifier:
|
|
139
|
+
return {
|
|
140
|
+
"identifier": identifier or "",
|
|
141
|
+
"type": "unknown",
|
|
142
|
+
"content": "",
|
|
143
|
+
"status": "failed",
|
|
144
|
+
"error": "Error: identifier parameter is empty or None",
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
# Ensure identifier is a string
|
|
148
|
+
if not isinstance(identifier, str):
|
|
149
|
+
identifier = str(identifier)
|
|
150
|
+
|
|
151
|
+
# Determine type
|
|
152
|
+
item_type = "unknown"
|
|
153
|
+
identifier_lower = identifier.lower()
|
|
154
|
+
if "figure" in identifier_lower:
|
|
155
|
+
item_type = "figure"
|
|
156
|
+
elif "definition" in identifier_lower:
|
|
157
|
+
item_type = "definition"
|
|
158
|
+
elif "theorem" in identifier_lower:
|
|
159
|
+
item_type = "theorem"
|
|
160
|
+
elif "lemma" in identifier_lower:
|
|
161
|
+
item_type = "lemma"
|
|
162
|
+
elif "example" in identifier_lower:
|
|
163
|
+
item_type = "example"
|
|
164
|
+
elif "remark" in identifier_lower:
|
|
165
|
+
item_type = "remark"
|
|
166
|
+
elif identifier.strip().startswith("(") and identifier.strip().endswith(")"):
|
|
167
|
+
item_type = "formula"
|
|
168
|
+
|
|
169
|
+
# 1. Exact match (highest priority)
|
|
170
|
+
if identifier in items:
|
|
171
|
+
matched_item = {"identifier": identifier, "type": item_type, "content": items[identifier]}
|
|
172
|
+
return {
|
|
173
|
+
"identifier": identifier,
|
|
174
|
+
"type": item_type,
|
|
175
|
+
"status": "success",
|
|
176
|
+
"count": 1,
|
|
177
|
+
"items": [matched_item],
|
|
178
|
+
"content": items[identifier], # Backward compatible
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
# 2. Case-insensitive exact match
|
|
182
|
+
exact_matches = []
|
|
183
|
+
for key, value in items.items():
|
|
184
|
+
if key.lower() == identifier_lower:
|
|
185
|
+
exact_matches.append({"identifier": key, "type": item_type, "content": value})
|
|
186
|
+
|
|
187
|
+
if exact_matches:
|
|
188
|
+
# Limit results
|
|
189
|
+
if max_results and len(exact_matches) > max_results:
|
|
190
|
+
exact_matches = exact_matches[:max_results]
|
|
191
|
+
|
|
192
|
+
# Build content (backward compatible)
|
|
193
|
+
content = (
|
|
194
|
+
exact_matches[0]["content"]
|
|
195
|
+
if len(exact_matches) == 1
|
|
196
|
+
else "\n\n".join(
|
|
197
|
+
[f"[{item['identifier']}]\n{item['content']}" for item in exact_matches]
|
|
198
|
+
)
|
|
199
|
+
)
|
|
200
|
+
|
|
201
|
+
return {
|
|
202
|
+
"identifier": identifier,
|
|
203
|
+
"type": item_type,
|
|
204
|
+
"status": "success",
|
|
205
|
+
"count": len(exact_matches),
|
|
206
|
+
"items": exact_matches,
|
|
207
|
+
"content": content,
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
# 3. Prefix match (e.g., "2.1" matches "(2.1.1)", "(2.1.2)", etc.)
|
|
211
|
+
prefix_matches = []
|
|
212
|
+
identifier_clean = identifier.strip().strip("()") # Remove parentheses, extract pure numbers
|
|
213
|
+
|
|
214
|
+
for key, value in items.items():
|
|
215
|
+
key_clean = key.strip().strip("()")
|
|
216
|
+
# Prefix match: key starts with identifier (after removing parentheses)
|
|
217
|
+
if (
|
|
218
|
+
key_clean.startswith(identifier_clean + ".")
|
|
219
|
+
or key_clean == identifier_clean
|
|
220
|
+
or key.lower().startswith(identifier_lower)
|
|
221
|
+
):
|
|
222
|
+
prefix_matches.append({"identifier": key, "type": item_type, "content": value})
|
|
223
|
+
|
|
224
|
+
# Limit results
|
|
225
|
+
if max_results and len(prefix_matches) > max_results:
|
|
226
|
+
prefix_matches = prefix_matches[:max_results]
|
|
227
|
+
|
|
228
|
+
if prefix_matches:
|
|
229
|
+
# Build content
|
|
230
|
+
content = (
|
|
231
|
+
prefix_matches[0]["content"]
|
|
232
|
+
if len(prefix_matches) == 1
|
|
233
|
+
else "\n\n".join(
|
|
234
|
+
[f"[{item['identifier']}]\n{item['content']}" for item in prefix_matches]
|
|
235
|
+
)
|
|
236
|
+
)
|
|
237
|
+
|
|
238
|
+
return {
|
|
239
|
+
"identifier": identifier,
|
|
240
|
+
"type": item_type,
|
|
241
|
+
"status": "success",
|
|
242
|
+
"count": len(prefix_matches),
|
|
243
|
+
"items": prefix_matches,
|
|
244
|
+
"content": content,
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
# 4. Partial match (contains query string)
|
|
248
|
+
partial_matches = []
|
|
249
|
+
for key, value in items.items():
|
|
250
|
+
if identifier_lower in key.lower():
|
|
251
|
+
partial_matches.append({"identifier": key, "type": item_type, "content": value})
|
|
252
|
+
|
|
253
|
+
# Limit results
|
|
254
|
+
if max_results and len(partial_matches) > max_results:
|
|
255
|
+
partial_matches = partial_matches[:max_results]
|
|
256
|
+
|
|
257
|
+
if partial_matches:
|
|
258
|
+
content = (
|
|
259
|
+
partial_matches[0]["content"]
|
|
260
|
+
if len(partial_matches) == 1
|
|
261
|
+
else "\n\n".join(
|
|
262
|
+
[f"[{item['identifier']}]\n{item['content']}" for item in partial_matches]
|
|
263
|
+
)
|
|
264
|
+
)
|
|
265
|
+
|
|
266
|
+
return {
|
|
267
|
+
"identifier": identifier,
|
|
268
|
+
"type": item_type,
|
|
269
|
+
"status": "success",
|
|
270
|
+
"count": len(partial_matches),
|
|
271
|
+
"items": partial_matches,
|
|
272
|
+
"content": content,
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
# 5. Not found - provide suggestions
|
|
276
|
+
suggestions = [k for k in items if identifier_lower in k.lower()][:5]
|
|
277
|
+
error_msg = f"Numbered item '{identifier}' not found"
|
|
278
|
+
if suggestions:
|
|
279
|
+
error_msg += "\n\nSimilar items:\n" + "\n".join(f" • {s}" for s in suggestions)
|
|
280
|
+
|
|
281
|
+
return {
|
|
282
|
+
"identifier": identifier,
|
|
283
|
+
"type": item_type,
|
|
284
|
+
"status": "failed",
|
|
285
|
+
"count": 0,
|
|
286
|
+
"items": [],
|
|
287
|
+
"content": "",
|
|
288
|
+
"error": error_msg,
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
|
|
292
|
+
if __name__ == "__main__":
|
|
293
|
+
import sys
|
|
294
|
+
|
|
295
|
+
if sys.platform == "win32":
|
|
296
|
+
import io
|
|
297
|
+
|
|
298
|
+
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding="utf-8")
|
|
299
|
+
|
|
300
|
+
# Test
|
|
301
|
+
print("Testing query_numbered_item\n" + "=" * 60)
|
|
302
|
+
|
|
303
|
+
# Test 1
|
|
304
|
+
print("\n[Test 1] Query formula (1.2.1):")
|
|
305
|
+
result = query_numbered_item("(1.2.1)", kb_name="ai_textbook")
|
|
306
|
+
print(f"Status: {result['status']}")
|
|
307
|
+
print(f"Type: {result['type']}")
|
|
308
|
+
print(f"Content: {result.get('content', result.get('error'))[:200]}...")
|
|
309
|
+
|
|
310
|
+
print("\n" + "=" * 60)
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Question Tools - Question generation system toolset
|
|
3
|
+
|
|
4
|
+
Tools for PDF parsing, question extraction, and exam mimicking.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from .exam_mimic import mimic_exam_questions
|
|
8
|
+
from .pdf_parser import parse_pdf_with_mineru
|
|
9
|
+
from .question_extractor import extract_questions_from_paper
|
|
10
|
+
|
|
11
|
+
__all__ = [
|
|
12
|
+
"parse_pdf_with_mineru",
|
|
13
|
+
"extract_questions_from_paper",
|
|
14
|
+
"mimic_exam_questions",
|
|
15
|
+
]
|