Načítanie nástrojov

This commit is contained in:
Ján Pták 2026-11-07 16:16:05 +01:00
parent 6d0654db47
commit 3d0dfa154b
10 changed files with 48 additions and 5 deletions

View File

@ -3,12 +3,12 @@
{
"archive": "zpwiki-rag.zip",
"name": "rag",
"sha256": "3eb3a59827b3eda400c7a5cd5dc3909831d5343903b159a71d843fb712970b52"
"sha256": "c710593a12c030c716ad4ba620e13182c35a86ded339e6180c235941398e2911"
},
{
"archive": "zpwiki-graphrag.zip",
"name": "graphrag",
"sha256": "99cf35d9050b5942b1d33744c49ade436e8c4b811d536257a2d0b090700dd3e0"
"sha256": "160f58d665aa5b156589731427eeb4113a4eb0020291d338a2ec35a0c81b7696"
}
],
"schema_version": 1

Binary file not shown.

Binary file not shown.

View File

@ -39,7 +39,13 @@ that subject is unambiguous in the immediately preceding exchange. Preserve the
and every remaining condition. Otherwise ask for the name. Document authorship does not
establish supervision.
1. With a ZP Wiki MCP connector, call `zpwiki_graphrag` with the complete question.
1. With a ZP Wiki MCP connector, load its current tool definition before calling it.
When tools are deferred, use the host's tool search (for example `tool_search`) to find
`zpwiki_graphrag`. Use the exact loaded identifier and schema; never guess a tool name or arguments.
Pass the complete question as `query`, for example `{"query":"the complete question"}`.
The optional `limit` is an integer. Do not send an argument named `question`.
If the host reports that the tool has not been loaded, discover it first and retry the same
question with the loaded schema. This is a tool-discovery error, not evidence of a DNS failure.
2. Otherwise, with securely configured backend access in a Python execution environment,
run `python scripts/query.py "the complete question"` relative to this directory.
Keep every condition in the same query (maximum 500 characters): names, work type,

View File

@ -20,6 +20,10 @@ from starlette.responses import JSONResponse
# Host-model rules belong to MCP initialization and Skills, not tool-result data.
QUESTION_POLICY = (
'Load each tool definition using the host tool search when required before calling it. '
'Use the exact loaded tool identifier and schema. For zpwiki_rag and zpwiki_graphrag, '
'the question belongs in the query argument, never an argument named question. '
'A tool-not-loaded or invalid-argument error is a host invocation error, not a DNS failure. '
'For a follow-up omitting a person or supervisor, inherit the subject only from an unambiguous '
'immediately preceding exchange and reconstruct one full question with the new year and all constraints. '
'Otherwise ask for the name. Never infer supervision from document authorship. '
@ -75,6 +79,7 @@ def tool_result(result):
async def zpwiki_rag(query: str, limit: int = 5) -> CallToolResult:
"""Verified ZP Wiki text answer. Keep the full question, names, work type and year.
Pass the full question in query, not question. Optional limit is an integer.
Present the accepted answer with its citations; add no guesses or history commentary.
"""
return tool_result(answer_for_presentation(await asyncio.to_thread(query_backend, query, 'rag', limit=limit)))
@ -83,6 +88,7 @@ async def zpwiki_rag(query: str, limit: int = 5) -> CallToolResult:
async def zpwiki_graphrag(query: str, limit: int = 5) -> CallToolResult:
"""Verified graph answer: relationships, related topics, progress, dated outcomes, years and counts in ZP Wiki.
Pass the full question in query, not question. Optional limit is an integer.
Present the accepted answer with its citations; no_answer means no supporting evidence.
"""
return tool_result(answer_for_presentation(await asyncio.to_thread(query_backend, query, 'graphrag', limit=limit)))

View File

@ -37,7 +37,13 @@ is unclear, ask for the name; never send a subjectless search or infer supervisi
For multiple explicit commands in one message, handle each question separately in order;
keep all conditions belonging to each question together.
1. If a ZP Wiki MCP connector is available, call `zpwiki_rag` with the complete question.
1. If a ZP Wiki MCP connector is available, load its current tool definition before calling it.
When tools are deferred, use the host's tool search (for example `tool_search`) to find
`zpwiki_rag`. Use the exact loaded identifier and schema; never guess a tool name or arguments.
Pass the complete question as `query`, for example `{"query":"the complete question"}`.
The optional `limit` is an integer. Do not send an argument named `question`.
If the host reports that the tool has not been loaded, discover it first and retry the same
question with the loaded schema. This is a tool-discovery error, not evidence of a DNS failure.
2. Otherwise, in a Python execution environment with securely configured backend access, run
`python scripts/query.py "the complete question"` relative to this skill's directory.
The question limit is 500 characters. Preserve names, work type, year and all constraints.

View File

@ -164,3 +164,11 @@ def test_academic_intents_use_the_shared_backend(question,mode):
def test_completed_subtasks_are_not_routed_to_degree_completion():
assert academic_intent('Aké experimenty dokončil Ján Holp?') is None
assert academic_intent('Ktoré úlohy dokončil Ján Holp?') is None
def test_colloquial_thesis_name_keeps_the_work_type_instead_of_listing_all_works(engine):
data=index(('Ján Holp','# Diplomová práca 2021\nVedúci: Daniel Hládek\n'
'# Bakalárska práca 2019\nVedúci: Ján Staš\n'))
r=answer_academic('Kto vedie diplomovku Jána Holpa?',data,engine=engine)
assert r['status']=='ok' and 'Vedúci práce: Daniel Hládek' in r['answer']
assert 'Bakalárska práca' not in r['answer'] and 'Ján Staš' not in r['answer']

View File

@ -336,6 +336,12 @@ def test_mcp_stdio_initialization_discovery_call_and_rejection(backend):
assert ANSWER_PRESENTATION_POLICY in initialized.instructions
listed = await session.list_tools()
assert {row.name for row in listed.tools} == {'zpwiki_rag', 'zpwiki_graphrag', 'zpwiki_health'}
for tool in listed.tools:
if tool.name in {'zpwiki_rag','zpwiki_graphrag'}:
assert tool.inputSchema['required']==['query']
assert 'question' not in tool.inputSchema['properties']
wrong=await session.call_tool(tool.name,{'question':'Práca Evy Novej?'})
assert wrong.isError
for engine in ['rag', 'graphrag']:
result = await session.call_tool('zpwiki_' + engine, {'query': 'Práca Evy Novej?'})
assert not result.isError

View File

@ -11,7 +11,7 @@ import zipfile
ROOT = Path(__file__).resolve().parents[2]
BASE = ROOT / 'packages/claude'
ENGINES = ('rag', 'graphrag')
PACKAGE_VERSION = '1.8.0'
PACKAGE_VERSION = '1.8.1'
def json_bytes(value):

View File

@ -144,11 +144,22 @@ def answer_academic(question, index, *, engine, limit=5, units=None, mode=None):
status='ambiguous',reason='ambiguous_advisor_filter')
from tools.answer_evaluation.rag_evidence import requested_types
types=requested_types(resolved,[m['name'] for m in students])
# Ordinary wording of the same work-type constraint must not silently
# broaden "diplomovku" to every bachelor thesis and project on a profile.
informal={kind for pattern,kind in [(r'\bdiplomovk\w*\b','diploma_thesis'),
(r'\bbakalark\w*\b','bachelor_thesis')]
if re.search(pattern,text)}
if len(informal)>1 or informal and types and not set(types.values())<=informal:
return respond('Upresni, či sa pýtaš na bakalársku alebo diplomovú prácu.',
status='ambiguous',reason='ambiguous_work_type')
if informal:
types={m['name']:next(iter(informal)) for m in students}
global_types=set(types.values())
if not students:
from tools.answer_evaluation.rag_evidence import work_type
kind=work_type(resolved)
if kind:global_types={kind}
elif informal:global_types=informal
# Completion-year filters apply to the EVENT, not the work heading.
from tools.knowledge.query import _period
try:period=_period(resolved)