entari-plugin-hyw 4.0.0rc7__py3-none-any.whl → 4.0.0rc8__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.
Potentially problematic release.
This version of entari-plugin-hyw might be problematic. Click here for more details.
- entari_plugin_hyw/Untitled-1 +1865 -0
- entari_plugin_hyw/__init__.py +726 -394
- entari_plugin_hyw/history.py +26 -13
- entari_plugin_hyw/misc.py +3 -0
- entari_plugin_hyw/search_cache.py +154 -0
- {entari_plugin_hyw-4.0.0rc7.dist-info → entari_plugin_hyw-4.0.0rc8.dist-info}/METADATA +3 -1
- entari_plugin_hyw-4.0.0rc8.dist-info/RECORD +68 -0
- {entari_plugin_hyw-4.0.0rc7.dist-info → entari_plugin_hyw-4.0.0rc8.dist-info}/WHEEL +1 -1
- {entari_plugin_hyw-4.0.0rc7.dist-info → entari_plugin_hyw-4.0.0rc8.dist-info}/top_level.txt +1 -0
- hyw_core/__init__.py +94 -0
- hyw_core/browser_control/__init__.py +65 -0
- hyw_core/browser_control/assets/card-dist/index.html +409 -0
- hyw_core/browser_control/assets/index.html +5691 -0
- hyw_core/browser_control/engines/__init__.py +17 -0
- {entari_plugin_hyw/browser → hyw_core/browser_control}/engines/duckduckgo.py +42 -8
- {entari_plugin_hyw/browser → hyw_core/browser_control}/engines/google.py +1 -1
- {entari_plugin_hyw/browser → hyw_core/browser_control}/manager.py +15 -8
- entari_plugin_hyw/render_vue.py → hyw_core/browser_control/renderer.py +29 -14
- {entari_plugin_hyw/browser → hyw_core/browser_control}/service.py +287 -112
- hyw_core/config.py +154 -0
- hyw_core/core.py +322 -0
- hyw_core/definitions.py +83 -0
- entari_plugin_hyw/modular_pipeline.py → hyw_core/pipeline.py +121 -97
- {entari_plugin_hyw → hyw_core}/search.py +19 -14
- hyw_core/stages/__init__.py +21 -0
- entari_plugin_hyw/stage_base.py → hyw_core/stages/base.py +2 -2
- entari_plugin_hyw/stage_summary.py → hyw_core/stages/summary.py +34 -11
- entari_plugin_hyw/assets/card-dist/index.html +0 -387
- entari_plugin_hyw/browser/__init__.py +0 -10
- entari_plugin_hyw/browser/engines/bing.py +0 -95
- entari_plugin_hyw/card-ui/.gitignore +0 -24
- entari_plugin_hyw/card-ui/README.md +0 -5
- entari_plugin_hyw/card-ui/index.html +0 -16
- entari_plugin_hyw/card-ui/package-lock.json +0 -2342
- entari_plugin_hyw/card-ui/package.json +0 -31
- entari_plugin_hyw/card-ui/public/logos/anthropic.svg +0 -1
- entari_plugin_hyw/card-ui/public/logos/cerebras.svg +0 -9
- entari_plugin_hyw/card-ui/public/logos/deepseek.png +0 -0
- entari_plugin_hyw/card-ui/public/logos/gemini.svg +0 -1
- entari_plugin_hyw/card-ui/public/logos/google.svg +0 -1
- entari_plugin_hyw/card-ui/public/logos/grok.png +0 -0
- entari_plugin_hyw/card-ui/public/logos/huggingface.png +0 -0
- entari_plugin_hyw/card-ui/public/logos/microsoft.svg +0 -15
- entari_plugin_hyw/card-ui/public/logos/minimax.png +0 -0
- entari_plugin_hyw/card-ui/public/logos/mistral.png +0 -0
- entari_plugin_hyw/card-ui/public/logos/nvida.png +0 -0
- entari_plugin_hyw/card-ui/public/logos/openai.svg +0 -1
- entari_plugin_hyw/card-ui/public/logos/openrouter.png +0 -0
- entari_plugin_hyw/card-ui/public/logos/perplexity.svg +0 -24
- entari_plugin_hyw/card-ui/public/logos/qwen.png +0 -0
- entari_plugin_hyw/card-ui/public/logos/xai.png +0 -0
- entari_plugin_hyw/card-ui/public/logos/xiaomi.png +0 -0
- entari_plugin_hyw/card-ui/public/logos/zai.png +0 -0
- entari_plugin_hyw/card-ui/public/vite.svg +0 -1
- entari_plugin_hyw/card-ui/src/App.vue +0 -787
- entari_plugin_hyw/card-ui/src/assets/vue.svg +0 -1
- entari_plugin_hyw/card-ui/src/components/HelloWorld.vue +0 -41
- entari_plugin_hyw/card-ui/src/components/MarkdownContent.vue +0 -382
- entari_plugin_hyw/card-ui/src/components/SectionCard.vue +0 -41
- entari_plugin_hyw/card-ui/src/components/StageCard.vue +0 -240
- entari_plugin_hyw/card-ui/src/main.ts +0 -5
- entari_plugin_hyw/card-ui/src/style.css +0 -29
- entari_plugin_hyw/card-ui/src/test_regex.js +0 -103
- entari_plugin_hyw/card-ui/src/types.ts +0 -61
- entari_plugin_hyw/card-ui/tsconfig.app.json +0 -16
- entari_plugin_hyw/card-ui/tsconfig.json +0 -7
- entari_plugin_hyw/card-ui/tsconfig.node.json +0 -26
- entari_plugin_hyw/card-ui/vite.config.ts +0 -16
- entari_plugin_hyw/definitions.py +0 -174
- entari_plugin_hyw/stage_instruct.py +0 -355
- entari_plugin_hyw/stage_instruct_deepsearch.py +0 -104
- entari_plugin_hyw/stage_vision.py +0 -113
- entari_plugin_hyw-4.0.0rc7.dist-info/RECORD +0 -102
- {entari_plugin_hyw → hyw_core/browser_control}/assets/card-dist/logos/anthropic.svg +0 -0
- {entari_plugin_hyw → hyw_core/browser_control}/assets/card-dist/logos/cerebras.svg +0 -0
- {entari_plugin_hyw → hyw_core/browser_control}/assets/card-dist/logos/deepseek.png +0 -0
- {entari_plugin_hyw → hyw_core/browser_control}/assets/card-dist/logos/gemini.svg +0 -0
- {entari_plugin_hyw → hyw_core/browser_control}/assets/card-dist/logos/google.svg +0 -0
- {entari_plugin_hyw → hyw_core/browser_control}/assets/card-dist/logos/grok.png +0 -0
- {entari_plugin_hyw → hyw_core/browser_control}/assets/card-dist/logos/huggingface.png +0 -0
- {entari_plugin_hyw → hyw_core/browser_control}/assets/card-dist/logos/microsoft.svg +0 -0
- {entari_plugin_hyw → hyw_core/browser_control}/assets/card-dist/logos/minimax.png +0 -0
- {entari_plugin_hyw → hyw_core/browser_control}/assets/card-dist/logos/mistral.png +0 -0
- {entari_plugin_hyw → hyw_core/browser_control}/assets/card-dist/logos/nvida.png +0 -0
- {entari_plugin_hyw → hyw_core/browser_control}/assets/card-dist/logos/openai.svg +0 -0
- {entari_plugin_hyw → hyw_core/browser_control}/assets/card-dist/logos/openrouter.png +0 -0
- {entari_plugin_hyw → hyw_core/browser_control}/assets/card-dist/logos/perplexity.svg +0 -0
- {entari_plugin_hyw → hyw_core/browser_control}/assets/card-dist/logos/qwen.png +0 -0
- {entari_plugin_hyw → hyw_core/browser_control}/assets/card-dist/logos/xai.png +0 -0
- {entari_plugin_hyw → hyw_core/browser_control}/assets/card-dist/logos/xiaomi.png +0 -0
- {entari_plugin_hyw → hyw_core/browser_control}/assets/card-dist/logos/zai.png +0 -0
- {entari_plugin_hyw → hyw_core/browser_control}/assets/card-dist/vite.svg +0 -0
- {entari_plugin_hyw/assets/icon → hyw_core/browser_control/assets/logos}/anthropic.svg +0 -0
- {entari_plugin_hyw/assets/icon → hyw_core/browser_control/assets/logos}/cerebras.svg +0 -0
- {entari_plugin_hyw/assets/icon → hyw_core/browser_control/assets/logos}/deepseek.png +0 -0
- {entari_plugin_hyw/assets/icon → hyw_core/browser_control/assets/logos}/gemini.svg +0 -0
- {entari_plugin_hyw/assets/icon → hyw_core/browser_control/assets/logos}/google.svg +0 -0
- {entari_plugin_hyw/assets/icon → hyw_core/browser_control/assets/logos}/grok.png +0 -0
- {entari_plugin_hyw/assets/icon → hyw_core/browser_control/assets/logos}/huggingface.png +0 -0
- {entari_plugin_hyw/assets/icon → hyw_core/browser_control/assets/logos}/microsoft.svg +0 -0
- {entari_plugin_hyw/assets/icon → hyw_core/browser_control/assets/logos}/minimax.png +0 -0
- {entari_plugin_hyw/assets/icon → hyw_core/browser_control/assets/logos}/mistral.png +0 -0
- {entari_plugin_hyw/assets/icon → hyw_core/browser_control/assets/logos}/nvida.png +0 -0
- {entari_plugin_hyw/assets/icon → hyw_core/browser_control/assets/logos}/openai.svg +0 -0
- {entari_plugin_hyw/assets/icon → hyw_core/browser_control/assets/logos}/openrouter.png +0 -0
- {entari_plugin_hyw/assets/icon → hyw_core/browser_control/assets/logos}/perplexity.svg +0 -0
- {entari_plugin_hyw/assets/icon → hyw_core/browser_control/assets/logos}/qwen.png +0 -0
- {entari_plugin_hyw/assets/icon → hyw_core/browser_control/assets/logos}/xai.png +0 -0
- {entari_plugin_hyw/assets/icon → hyw_core/browser_control/assets/logos}/xiaomi.png +0 -0
- {entari_plugin_hyw/assets/icon → hyw_core/browser_control/assets/logos}/zai.png +0 -0
- {entari_plugin_hyw/browser → hyw_core/browser_control}/engines/base.py +0 -0
- {entari_plugin_hyw/browser → hyw_core/browser_control}/engines/default.py +0 -0
- {entari_plugin_hyw/browser → hyw_core/browser_control}/landing.html +0 -0
- {entari_plugin_hyw → hyw_core}/image_cache.py +0 -0
hyw_core/core.py
ADDED
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
"""
|
|
2
|
+
hyw_core.core - Main HywCore Class
|
|
3
|
+
|
|
4
|
+
Provides the unified LLM query interface and search capabilities.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import asyncio
|
|
8
|
+
import time
|
|
9
|
+
from dataclasses import dataclass, field
|
|
10
|
+
from typing import Dict, List, Any, Optional, Callable, Awaitable
|
|
11
|
+
|
|
12
|
+
from loguru import logger
|
|
13
|
+
from openai import AsyncOpenAI
|
|
14
|
+
|
|
15
|
+
from .config import HywCoreConfig, ModelConfig
|
|
16
|
+
from .pipeline import ModularPipeline
|
|
17
|
+
from .search import SearchService
|
|
18
|
+
from .stages.base import StageContext
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@dataclass
|
|
22
|
+
class QueryRequest:
|
|
23
|
+
"""Request for the query interface."""
|
|
24
|
+
user_input: str
|
|
25
|
+
images: List[str] = field(default_factory=list) # base64 encoded images
|
|
26
|
+
conversation_history: List[Dict] = field(default_factory=list)
|
|
27
|
+
model_name: Optional[str] = None # Override model
|
|
28
|
+
|
|
29
|
+
# Optional callbacks
|
|
30
|
+
send_notification: Optional[Callable[[str], Awaitable[None]]] = None
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
@dataclass
|
|
34
|
+
class QueryResponse:
|
|
35
|
+
"""Response from the query interface."""
|
|
36
|
+
success: bool
|
|
37
|
+
content: str # Markdown response
|
|
38
|
+
image_path: Optional[str] = None # Path to rendered image
|
|
39
|
+
|
|
40
|
+
# Statistics
|
|
41
|
+
usage: Dict[str, int] = field(default_factory=dict)
|
|
42
|
+
cost: float = 0.0
|
|
43
|
+
total_time: float = 0.0
|
|
44
|
+
|
|
45
|
+
# References
|
|
46
|
+
references: List[Dict[str, Any]] = field(default_factory=list)
|
|
47
|
+
page_references: List[Dict[str, Any]] = field(default_factory=list)
|
|
48
|
+
image_references: List[Dict[str, Any]] = field(default_factory=list)
|
|
49
|
+
|
|
50
|
+
# Trace information
|
|
51
|
+
stages_trace: Dict[str, Any] = field(default_factory=dict)
|
|
52
|
+
|
|
53
|
+
# Error handling
|
|
54
|
+
error: Optional[str] = None
|
|
55
|
+
should_refuse: bool = False
|
|
56
|
+
refuse_reason: str = ""
|
|
57
|
+
|
|
58
|
+
# Debug/Save
|
|
59
|
+
web_results: List[Dict[str, Any]] = field(default_factory=list)
|
|
60
|
+
stages_used: List[Dict[str, Any]] = field(default_factory=list)
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
class HywCore:
|
|
65
|
+
"""
|
|
66
|
+
HYW Core Service.
|
|
67
|
+
|
|
68
|
+
Provides the unified LLM query interface (/q command) and search capabilities.
|
|
69
|
+
|
|
70
|
+
Usage:
|
|
71
|
+
from hyw_core import HywCore, HywCoreConfig, QueryRequest
|
|
72
|
+
|
|
73
|
+
config = HywCoreConfig.from_yaml("config.yaml")
|
|
74
|
+
core = HywCore(config)
|
|
75
|
+
|
|
76
|
+
response = await core.query(QueryRequest(
|
|
77
|
+
user_input="What is Python?",
|
|
78
|
+
images=[],
|
|
79
|
+
conversation_history=[]
|
|
80
|
+
))
|
|
81
|
+
"""
|
|
82
|
+
|
|
83
|
+
def __init__(
|
|
84
|
+
self,
|
|
85
|
+
config: HywCoreConfig,
|
|
86
|
+
send_func: Optional[Callable[[str], Awaitable[None]]] = None
|
|
87
|
+
):
|
|
88
|
+
"""
|
|
89
|
+
Initialize HywCore.
|
|
90
|
+
|
|
91
|
+
Args:
|
|
92
|
+
config: HywCoreConfig instance
|
|
93
|
+
send_func: Optional callback for sending notifications
|
|
94
|
+
"""
|
|
95
|
+
self.config = config
|
|
96
|
+
self._send_func = send_func
|
|
97
|
+
|
|
98
|
+
# Create OpenAI client
|
|
99
|
+
self._client = AsyncOpenAI(
|
|
100
|
+
api_key=config.api_key,
|
|
101
|
+
base_url=config.base_url if config.base_url else None
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
# Create search service
|
|
105
|
+
self._search_service = SearchService(config)
|
|
106
|
+
|
|
107
|
+
# Create pipeline
|
|
108
|
+
self._pipeline = ModularPipeline(
|
|
109
|
+
config=config,
|
|
110
|
+
search_service=self._search_service,
|
|
111
|
+
send_func=send_func
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
# Create renderer (lazy init)
|
|
115
|
+
self._renderer = None
|
|
116
|
+
|
|
117
|
+
logger.info("HywCore initialized")
|
|
118
|
+
|
|
119
|
+
async def _ensure_renderer(self):
|
|
120
|
+
"""Lazy initialize renderer."""
|
|
121
|
+
if self._renderer is None:
|
|
122
|
+
from .browser_control import ContentRenderer
|
|
123
|
+
self._renderer = ContentRenderer(headless=self.config.headless)
|
|
124
|
+
await self._renderer.start()
|
|
125
|
+
|
|
126
|
+
async def query(
|
|
127
|
+
self,
|
|
128
|
+
request: QueryRequest,
|
|
129
|
+
output_path: Optional[str] = None
|
|
130
|
+
) -> QueryResponse:
|
|
131
|
+
"""
|
|
132
|
+
Unified query interface.
|
|
133
|
+
|
|
134
|
+
This is the main entry point for /q commands.
|
|
135
|
+
|
|
136
|
+
Args:
|
|
137
|
+
request: QueryRequest with user input, images, history
|
|
138
|
+
output_path: Optional path to save rendered image
|
|
139
|
+
|
|
140
|
+
Returns:
|
|
141
|
+
QueryResponse with content, rendered image path, and metadata
|
|
142
|
+
"""
|
|
143
|
+
start_time = time.time()
|
|
144
|
+
|
|
145
|
+
try:
|
|
146
|
+
# Override model if specified
|
|
147
|
+
model_name = request.model_name or self.config.model_name
|
|
148
|
+
|
|
149
|
+
# Use notification callback from request if provided
|
|
150
|
+
send_func = request.send_notification or self._send_func
|
|
151
|
+
if send_func and self._pipeline._send_func != send_func:
|
|
152
|
+
self._pipeline._send_func = send_func
|
|
153
|
+
|
|
154
|
+
# Execute pipeline
|
|
155
|
+
result = await self._pipeline.execute(
|
|
156
|
+
user_input=request.user_input,
|
|
157
|
+
conversation_history=request.conversation_history,
|
|
158
|
+
model_name=model_name,
|
|
159
|
+
images=request.images if request.images else None
|
|
160
|
+
)
|
|
161
|
+
|
|
162
|
+
total_time = time.time() - start_time
|
|
163
|
+
|
|
164
|
+
# Check for refusal
|
|
165
|
+
if result.get("should_refuse"):
|
|
166
|
+
return QueryResponse(
|
|
167
|
+
success=True,
|
|
168
|
+
content="",
|
|
169
|
+
should_refuse=True,
|
|
170
|
+
refuse_reason=result.get("refuse_reason", ""),
|
|
171
|
+
total_time=total_time
|
|
172
|
+
)
|
|
173
|
+
|
|
174
|
+
# Extract response data
|
|
175
|
+
content = result.get("llm_response", "")
|
|
176
|
+
structured = result.get("structured_response", {})
|
|
177
|
+
billing = result.get("billing_info", {})
|
|
178
|
+
|
|
179
|
+
usage = {
|
|
180
|
+
"input_tokens": billing.get("input_tokens", 0),
|
|
181
|
+
"output_tokens": billing.get("output_tokens", 0)
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
# Calculate cost
|
|
185
|
+
model_cfg = self.config.get_model_config("main")
|
|
186
|
+
cost = (
|
|
187
|
+
usage["input_tokens"] * (model_cfg.input_price or 0) / 1_000_000 +
|
|
188
|
+
usage["output_tokens"] * (model_cfg.output_price or 0) / 1_000_000
|
|
189
|
+
)
|
|
190
|
+
|
|
191
|
+
# Build response
|
|
192
|
+
response = QueryResponse(
|
|
193
|
+
success=True,
|
|
194
|
+
content=content,
|
|
195
|
+
usage=usage,
|
|
196
|
+
cost=cost,
|
|
197
|
+
total_time=total_time,
|
|
198
|
+
references=structured.get("references", []),
|
|
199
|
+
page_references=structured.get("page_references", []),
|
|
200
|
+
image_references=structured.get("image_references", []),
|
|
201
|
+
stages_trace=result.get("trace", {}),
|
|
202
|
+
web_results=result.get("web_results", []),
|
|
203
|
+
stages_used=result.get("stages_used", [])
|
|
204
|
+
)
|
|
205
|
+
|
|
206
|
+
# Render image if output path provided
|
|
207
|
+
if output_path and content:
|
|
208
|
+
await self._ensure_renderer()
|
|
209
|
+
|
|
210
|
+
render_success = await self._renderer.render(
|
|
211
|
+
markdown_content=content,
|
|
212
|
+
output_path=output_path,
|
|
213
|
+
stats=result.get("stats", {}),
|
|
214
|
+
references=result.get("references", []),
|
|
215
|
+
page_references=result.get("page_references", []),
|
|
216
|
+
image_references=result.get("image_references", []),
|
|
217
|
+
stages_used=result.get("stages_used", []),
|
|
218
|
+
theme_color=self.config.theme_color
|
|
219
|
+
)
|
|
220
|
+
|
|
221
|
+
if render_success:
|
|
222
|
+
response.image_path = output_path
|
|
223
|
+
|
|
224
|
+
return response
|
|
225
|
+
|
|
226
|
+
except Exception as e:
|
|
227
|
+
logger.error(f"HywCore query failed: {e}")
|
|
228
|
+
return QueryResponse(
|
|
229
|
+
success=False,
|
|
230
|
+
content="",
|
|
231
|
+
error=str(e),
|
|
232
|
+
total_time=time.time() - start_time
|
|
233
|
+
)
|
|
234
|
+
|
|
235
|
+
async def search(
|
|
236
|
+
self,
|
|
237
|
+
queries: List[str],
|
|
238
|
+
engine: Optional[str] = None,
|
|
239
|
+
limit: int = 10
|
|
240
|
+
) -> List[List[Dict[str, Any]]]:
|
|
241
|
+
"""
|
|
242
|
+
Independent search interface.
|
|
243
|
+
|
|
244
|
+
For future step-by-step search functionality.
|
|
245
|
+
|
|
246
|
+
Args:
|
|
247
|
+
queries: List of search queries
|
|
248
|
+
engine: Optional search engine override
|
|
249
|
+
limit: Results per query
|
|
250
|
+
|
|
251
|
+
Returns:
|
|
252
|
+
List of search results for each query
|
|
253
|
+
"""
|
|
254
|
+
# TODO: Support engine override per-call
|
|
255
|
+
return await self._search_service.search_batch(queries)
|
|
256
|
+
|
|
257
|
+
async def screenshot(self, url: str) -> Optional[str]:
|
|
258
|
+
"""
|
|
259
|
+
Capture full page screenshot of a URL.
|
|
260
|
+
Returns: base64 string or None
|
|
261
|
+
"""
|
|
262
|
+
# Default to full_page=True as requested for /w command
|
|
263
|
+
return await self._search_service.screenshot_url(url, full_page=True)
|
|
264
|
+
|
|
265
|
+
async def screenshot_batch(self, urls: List[str]) -> List[Optional[str]]:
|
|
266
|
+
"""
|
|
267
|
+
Capture full page screenshots of multiple URLs concurrently.
|
|
268
|
+
Returns: list of base64 strings (None for failed ones)
|
|
269
|
+
"""
|
|
270
|
+
return await self._search_service.screenshot_urls_batch(urls, full_page=True)
|
|
271
|
+
|
|
272
|
+
async def fetch_pages(
|
|
273
|
+
self,
|
|
274
|
+
urls: List[str],
|
|
275
|
+
include_screenshot: bool = False
|
|
276
|
+
) -> List[Dict[str, Any]]:
|
|
277
|
+
"""
|
|
278
|
+
Fetch multiple pages.
|
|
279
|
+
|
|
280
|
+
Args:
|
|
281
|
+
urls: List of URLs to fetch
|
|
282
|
+
include_screenshot: Whether to capture screenshots
|
|
283
|
+
|
|
284
|
+
Returns:
|
|
285
|
+
List of page data dicts
|
|
286
|
+
"""
|
|
287
|
+
return await self._search_service.fetch_pages_batch(
|
|
288
|
+
urls,
|
|
289
|
+
include_screenshot=include_screenshot
|
|
290
|
+
)
|
|
291
|
+
|
|
292
|
+
async def render(
|
|
293
|
+
self,
|
|
294
|
+
markdown_content: str,
|
|
295
|
+
output_path: str,
|
|
296
|
+
**kwargs
|
|
297
|
+
) -> bool:
|
|
298
|
+
"""
|
|
299
|
+
Render markdown to image.
|
|
300
|
+
|
|
301
|
+
Args:
|
|
302
|
+
markdown_content: Markdown to render
|
|
303
|
+
output_path: Path to save image
|
|
304
|
+
**kwargs: Additional render options
|
|
305
|
+
|
|
306
|
+
Returns:
|
|
307
|
+
True if successful
|
|
308
|
+
"""
|
|
309
|
+
await self._ensure_renderer()
|
|
310
|
+
return await self._renderer.render(
|
|
311
|
+
markdown_content=markdown_content,
|
|
312
|
+
output_path=output_path,
|
|
313
|
+
theme_color=kwargs.pop("theme_color", self.config.theme_color),
|
|
314
|
+
**kwargs
|
|
315
|
+
)
|
|
316
|
+
|
|
317
|
+
async def close(self):
|
|
318
|
+
"""Close all resources."""
|
|
319
|
+
if self._renderer:
|
|
320
|
+
await self._renderer.close()
|
|
321
|
+
await self._pipeline.close()
|
|
322
|
+
logger.info("HywCore closed")
|
hyw_core/definitions.py
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Centralized Definitions
|
|
3
|
+
|
|
4
|
+
All global prompts and tool definitions for the pipeline stages.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from typing import Dict, Any
|
|
8
|
+
|
|
9
|
+
# =============================================================================
|
|
10
|
+
# PROMPTS
|
|
11
|
+
# =============================================================================
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
SUMMARY_REPORT_SP = """# 你是一个信息整合专家 (Summary Agent).
|
|
18
|
+
你需要根据用户问题、搜索结果和网页详细内容,生成最终的回答.
|
|
19
|
+
如果用户发送你好或空内容回应你好即可.
|
|
20
|
+
|
|
21
|
+
## 内容审查
|
|
22
|
+
以下情况调用 `refuse_answer`:
|
|
23
|
+
- 内容涉及隐喻政治事件、任务、现役国家领导人
|
|
24
|
+
- r18+、r18g(但不包含正常galgame、科普等)
|
|
25
|
+
|
|
26
|
+
## 过程要求
|
|
27
|
+
- 用户要求的回复语言(包裹在 language 标签内)
|
|
28
|
+
```language
|
|
29
|
+
{language}
|
|
30
|
+
```
|
|
31
|
+
- 字数控制在600字以内, 百科式风格, 语言严谨不啰嗦.
|
|
32
|
+
- 视觉信息: 输入中如果包含自动获取的网页截图,请分析图片中的信息作为参考.
|
|
33
|
+
- 注意分辨搜索内容是否和用户问题有直接关系, 避免盲目相信混为一谈.
|
|
34
|
+
- 正文格式:
|
|
35
|
+
- 先给出一个 `# `大标题约 8-10 个字, 不要有多余废话, 不要直接回答用户的提问.
|
|
36
|
+
- 然后紧接着给出一个 <summary>...</summary>, 除了给出一个约 100 字的纯文本简介, 介绍本次输出的长文的清晰、重点概括.
|
|
37
|
+
- 随后开始详细二级标题 + markdown 正文, 语言描绘格式丰富多样, 简洁准确可信.
|
|
38
|
+
- 请不要给出过长的代码、表格列数等, 只讲重点和准确的数据.
|
|
39
|
+
- 不支持渲染: 链接, 图片链接, mermaid
|
|
40
|
+
- 支持渲染: 公式, 代码高亮, 只在需要的时候给出.
|
|
41
|
+
- 图片链接、链接框架会自动渲染出, 你无需显式给出.
|
|
42
|
+
- 引用:
|
|
43
|
+
> 重要: 所有正文内容必须基于实际信息, 保证百分百真实度
|
|
44
|
+
- 信息来源已按获取顺序编号为 [1], [2], [3]...
|
|
45
|
+
- 优先引用优质 fetch 抓取的页面的资源, 但如果抓取到需要登录、需要验证码、需要跳转到其他网站等无法获取的资源, 则不引用此资源
|
|
46
|
+
- 正文中直接使用 [1] 格式引用, 只引用对回答有帮助的来源, 只使用官方性较强的 wiki、官方网站、资源站等等, 不使用第三方转载新闻网站.
|
|
47
|
+
- 无需给出参考文献列表, 系统会自动生成
|
|
48
|
+
"""
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
# =============================================================================
|
|
52
|
+
# VISION DESCRIPTION PROMPT
|
|
53
|
+
# =============================================================================
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
# =============================================================================
|
|
59
|
+
# TOOL DEFINITIONS
|
|
60
|
+
# =============================================================================
|
|
61
|
+
|
|
62
|
+
def get_refuse_answer_tool() -> Dict[str, Any]:
|
|
63
|
+
"""Tool for refusing to answer inappropriate content."""
|
|
64
|
+
return {
|
|
65
|
+
"type": "function",
|
|
66
|
+
"function": {
|
|
67
|
+
"name": "refuse_answer",
|
|
68
|
+
"description": "违规内容拒绝回答",
|
|
69
|
+
"parameters": {
|
|
70
|
+
"type": "object",
|
|
71
|
+
"properties": {
|
|
72
|
+
"reason": {"type": "string", "description": "拒绝回答的原因(展示给用户)"},
|
|
73
|
+
},
|
|
74
|
+
"required": ["reason"],
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
|