AlixJabda commited on
Commit
2c66281
·
1 Parent(s): a153436

Aktualisierung der AM-RL-Module und Retrieval-Logik

Browse files
src/__pycache__/norm_anchors.cpython-311.pyc ADDED
Binary file (90.7 kB). View file
 
src/norm_anchors.py CHANGED
@@ -196,11 +196,19 @@ class Fehlgriff:
196
  stört auch neben der richtigen Norm. § 40c AM-RL betrifft ausschließlich
197
  biotechnologisch hergestellte Arzneimittel; in einer allgemeinen Frage nach
198
  Darreichungsformen verengt er die Antwort auf einen Sonderfall.
 
 
 
 
 
 
 
199
  """
200
 
201
  muster: str
202
  warum: str
203
  nur_ohne_tragende: bool = True
 
204
  wenn: Bedingung = Bedingung()
205
 
206
 
@@ -659,6 +667,41 @@ ANKER: Tuple[Anker, ...] = (
659
  "auf die Antwort; die Ausschlussentscheidung trifft § 34."
660
  ),
661
  ),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
662
  ),
663
  hinweise=(
664
  Hinweis(
@@ -1106,7 +1149,10 @@ ANKER: Tuple[Anker, ...] = (
1106
  corpus_id="rv129",
1107
  container_id="Vertrag",
1108
  section_id="§ 13",
1109
- tragend=False,
 
 
 
1110
  warum="Führt die Abgabe preisgünstiger Importe nach § 9 im Einzelnen aus.",
1111
  ),
1112
  Norm(
@@ -1114,7 +1160,10 @@ ANKER: Tuple[Anker, ...] = (
1114
  corpus_id="rv129",
1115
  container_id="Vertrag",
1116
  section_id="§ 14",
1117
- tragend=False,
 
 
 
1118
  warum=(
1119
  "Regelt abschließend, wann von der Abgaberangfolge abgewichen werden "
1120
  "darf. Eine Antwort, die nur sagt, die vorrangige Abgabe sei „nicht "
@@ -1122,6 +1171,35 @@ ANKER: Tuple[Anker, ...] = (
1122
  ),
1123
  ),
1124
  ),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1125
  hinweise=(
1126
  Hinweis(
1127
  # Ohne Fallbezug ist das ein Sonderfall und gehört nicht in die Kette.
@@ -1909,6 +1987,20 @@ def normabschnitt(answer: str) -> str:
1909
  return answer or ""
1910
 
1911
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1912
  # „§ 34 Abs. 1 SGB V“ soll auch auf „§ 34 SGB V“ und „§ 34 Absatz 1“ passen: das
1913
  # Modell schreibt die Norm selten genau so, wie das Register sie führt. Geprüft
1914
  # wird deshalb nur der Paragraf — der Absatz ist eine Genauigkeit, die eine
@@ -1976,13 +2068,14 @@ def pruefe(question: str = "", answer: str = "") -> Befund:
1976
  # Ein Fehlgriff der Sorte „gehört dazu, nur nicht als die entscheidende Norm"
1977
  # zählt nur, wenn keine tragende Norm neben ihm steht. § 31 SGB V gehört in
1978
  # eine OTC-Antwort — nur eben nicht als die Norm, die den Ausschluss trifft.
 
1979
  tragend_im_abschnitt = any(_genannt_in(n.zitat, abschnitt) for n in tragende)
1980
  fehlgriffe = [
1981
  f
1982
  for a in anker
1983
  for f in a.fehlgriffe
1984
  if f.wenn.gilt(haystack)
1985
- and re.search(f.muster, abschnitt)
1986
  and not (f.nur_ohne_tragende and tragend_im_abschnitt)
1987
  ]
1988
 
@@ -2084,7 +2177,12 @@ def _ohne_verworfene_bloecke(text: str, fehlgriffe: List[Fehlgriff]) -> str:
2084
  Eine Abschnittsüberschrift schützt ihren Absatz: Text unter einer eigenen
2085
  Überschrift zu löschen hieße, den Abschnitt zu entscheiden, und dafür ist
2086
  das Register nicht zuständig.
 
 
 
 
2087
  """
 
2088
  if not fehlgriffe or not (text or "").strip():
2089
  return text
2090
 
@@ -2115,6 +2213,7 @@ def _nimmt_noch_bezug(text: str, fehlgriffe: List[Fehlgriff]) -> bool:
2115
  Ein Hinweis auf einen „Restbezug" wäre dort eine Warnung vor dem richtigen
2116
  Zitat.
2117
  """
 
2118
  if not fehlgriffe:
2119
  return False
2120
  ersetzt = (_KURZ_UEBERSCHRIFT, _NORM_UEBERSCHRIFT, "Wortlaut")
@@ -2153,11 +2252,18 @@ def befund_block(befund: Befund, *, restverweis: bool = False) -> str:
2153
  if befund.status == "abweichung":
2154
  zeilen.append(f"{_KORREKTUR_EINLEITUNG} ({themen}):")
2155
  if befund.fehlgriffe:
2156
- zeilen.append(
2157
- "Kurzantwort und maßgebliche Norm oben stammen aus dem kuratierten "
2158
- "Normregister; die zunächst herangezogene Vorschrift entscheidet diese "
2159
- "Frage nicht."
2160
- )
 
 
 
 
 
 
 
2161
  for fehlgriff in befund.fehlgriffe:
2162
  zeilen.append(f" {fehlgriff.warum}")
2163
  else:
 
196
  stört auch neben der richtigen Norm. § 40c AM-RL betrifft ausschließlich
197
  biotechnologisch hergestellte Arzneimittel; in einer allgemeinen Frage nach
198
  Darreichungsformen verengt er die Antwort auf einen Sonderfall.
199
+
200
+ `im_kurzabschnitt=True` — das Muster wird gegen die **Kurzantwort** geprüft,
201
+ nicht gegen den Normabschnitt. Manche Fehler stehen nicht in der Wahl der
202
+ Vorschrift, sondern in ihrer Zusammenfassung: die OTC-Kurzantwort nennt die
203
+ richtige Norm (§ 34) und fasst ihre Absätze trotzdem falsch zusammen. Ein
204
+ solcher Fehlgriff treibt keine Blockentfernung (`_ohne_verworfene_bloecke`);
205
+ er löst allein die Neusetzung der Kurzantwort aus der `kernaussage` aus.
206
  """
207
 
208
  muster: str
209
  warum: str
210
  nur_ohne_tragende: bool = True
211
+ im_kurzabschnitt: bool = False
212
  wenn: Bedingung = Bedingung()
213
 
214
 
 
667
  "auf die Antwort; die Ausschlussentscheidung trifft § 34."
668
  ),
669
  ),
670
+ Fehlgriff(
671
+ # Gemessen am realen Lauf: die Kurzantwort nannte die richtige Norm
672
+ # (§ 34), machte aber die in § 34 Abs. 1 Satz 5 ff. genannten Gruppen
673
+ # zum Negativmaßstab der OTC-Ausnahme („… nicht zu den ausgeschlossenen
674
+ # Gruppen wie Abführmittel … gehört“). Das vermischt zwei Regelungs-
675
+ # komplexe. Der Fehlgriff sucht deshalb die Kurzantwort, nicht den
676
+ # Normabschnitt, und feuert nicht, wenn die Frage selbst eine der
677
+ # Gruppen benennt (dann ist ihre Nennung sachgerecht).
678
+ muster=(
679
+ r"(?is)nicht zu (?:den|einer)\b.{0,80}ausgeschlossen"
680
+ r".{0,120}(abführmittel|abfuehrmittel|reisekrankheit|erkältung"
681
+ r"|erkaeltung|rachentherapeutika|grippal)"
682
+ ),
683
+ warum=(
684
+ "Die in § 34 Abs. 1 Satz 5 ff. SGB V genannten Gruppen (Erkältungs- "
685
+ "und Grippemittel, Mund- und Rachentherapeutika, Abführmittel, Mittel "
686
+ "gegen Reisekrankheit) sind ein eigener Ausschluss bestimmter "
687
+ "verschreibungspflichtiger Arzneimittel für Erwachsene — nicht der "
688
+ "Negativmaßstab der OTC-Ausnahme. Ob ein nicht verschreibungspflichtiges "
689
+ "Arzneimittel ausnahmsweise verordnungsfähig ist, entscheidet allein "
690
+ "§ 12 in Verbindung mit Anlage I der AM-RL; ein nicht "
691
+ "verschreibungspflichtiges Abführmittel etwa kann für eine dort "
692
+ "gelistete schwerwiegende Erkrankung verordnungsfähig sein."
693
+ ),
694
+ nur_ohne_tragende=False,
695
+ im_kurzabschnitt=True,
696
+ wenn=Bedingung(
697
+ nicht_bei=(
698
+ "abführmittel",
699
+ "abfuehrmittel",
700
+ "reisekrankheit",
701
+ "rachentherapeutika",
702
+ )
703
+ ),
704
+ ),
705
  ),
706
  hinweise=(
707
  Hinweis(
 
1149
  corpus_id="rv129",
1150
  container_id="Vertrag",
1151
  section_id="§ 13",
1152
+ # Die Frage nennt den Import ausdrücklich; ohne § 13 als maßgebliche
1153
+ # Norm fehlt die Vorschrift, die seine Abgabe regelt. Ein Chunk genügt:
1154
+ # der Anker soll ihn benennen und knapp belegen, nicht ausbreiten.
1155
+ chunks=1,
1156
  warum="Führt die Abgabe preisgünstiger Importe nach § 9 im Einzelnen aus.",
1157
  ),
1158
  Norm(
 
1160
  corpus_id="rv129",
1161
  container_id="Vertrag",
1162
  section_id="§ 14",
1163
+ # Die Frage fragt ausdrücklich nach der Abweichung von der Rangfolge;
1164
+ # § 14 ist die Vorschrift, die sie regelt, und gehört damit in die
1165
+ # maßgeblichen Normen. Ein Chunk hält das Abrufbudget schmal.
1166
+ chunks=1,
1167
  warum=(
1168
  "Regelt abschließend, wann von der Abgaberangfolge abgewichen werden "
1169
  "darf. Eine Antwort, die nur sagt, die vorrangige Abgabe sei „nicht "
 
1171
  ),
1172
  ),
1173
  ),
1174
+ fehlgriffe=(
1175
+ Fehlgriff(
1176
+ # Gemessen am realen Lauf: die Antwort stützte die allgemeine Abweichung
1177
+ # auf § 14 Abs. 5 und zitierte „In den Fällen des § 129 Absätze 2a und
1178
+ # 2b SGB V …“, obwohl die Frage keinen dieser Tatbestände nennt. Der
1179
+ # Fehlgriff feuert deshalb nur, wenn die Frage 2a/2b nicht aufwirft.
1180
+ muster=r"§\s*14\s+Abs(?:atz|\.)?\s*5",
1181
+ warum=(
1182
+ "§ 14 Abs. 5 Rahmenvertrag gilt nur in den Fällen des § 129 Abs. 2a "
1183
+ "und 2b SGB V. Ohne einen dieser Tatbestände trägt er die allgemeine "
1184
+ "Abweichung von der Abgaberangfolge nicht; maßgeblich sind dann die "
1185
+ "§§ 10 bis 14 Rahmenvertrag im Übrigen — insbesondere Nichtverfügbarkeit "
1186
+ "und ordnungsgemäß geltend gemachte pharmazeutische Bedenken."
1187
+ ),
1188
+ nur_ohne_tragende=False,
1189
+ wenn=Bedingung(
1190
+ nicht_bei=(
1191
+ "abs. 2a",
1192
+ "absatz 2a",
1193
+ "abs 2a",
1194
+ "absätze 2a",
1195
+ "absaetze 2a",
1196
+ "abs. 2b",
1197
+ "absatz 2b",
1198
+ "2a und 2b",
1199
+ )
1200
+ ),
1201
+ ),
1202
+ ),
1203
  hinweise=(
1204
  Hinweis(
1205
  # Ohne Fallbezug ist das ein Sonderfall und gehört nicht in die Kette.
 
1987
  return answer or ""
1988
 
1989
 
1990
+ def kurzabschnitt(answer: str) -> str:
1991
+ """Der Text unter „Kurzantwort“ — oder leer, wenn es den Abschnitt nicht gibt.
1992
+
1993
+ Anders als `normabschnitt` fällt das **nicht** auf die ganze Antwort zurück:
1994
+ ein Fehlgriff `im_kurzabschnitt` sucht gezielt die Zusammenfassung, und ein
1995
+ Rückfall würde ihn auch im Wortlaut anschlagen lassen, der die Norm richtig
1996
+ zitiert.
1997
+ """
1998
+ for heading, body in _abschnitte(answer):
1999
+ if _ist(heading, _KURZ_UEBERSCHRIFT):
2000
+ return "\n".join(body)
2001
+ return ""
2002
+
2003
+
2004
  # „§ 34 Abs. 1 SGB V“ soll auch auf „§ 34 SGB V“ und „§ 34 Absatz 1“ passen: das
2005
  # Modell schreibt die Norm selten genau so, wie das Register sie führt. Geprüft
2006
  # wird deshalb nur der Paragraf — der Absatz ist eine Genauigkeit, die eine
 
2068
  # Ein Fehlgriff der Sorte „gehört dazu, nur nicht als die entscheidende Norm"
2069
  # zählt nur, wenn keine tragende Norm neben ihm steht. § 31 SGB V gehört in
2070
  # eine OTC-Antwort — nur eben nicht als die Norm, die den Ausschluss trifft.
2071
+ kurz = kurzabschnitt(answer)
2072
  tragend_im_abschnitt = any(_genannt_in(n.zitat, abschnitt) for n in tragende)
2073
  fehlgriffe = [
2074
  f
2075
  for a in anker
2076
  for f in a.fehlgriffe
2077
  if f.wenn.gilt(haystack)
2078
+ and re.search(f.muster, kurz if f.im_kurzabschnitt else abschnitt)
2079
  and not (f.nur_ohne_tragende and tragend_im_abschnitt)
2080
  ]
2081
 
 
2177
  Eine Abschnittsüberschrift schützt ihren Absatz: Text unter einer eigenen
2178
  Überschrift zu löschen hieße, den Abschnitt zu entscheiden, und dafür ist
2179
  das Register nicht zuständig.
2180
+
2181
+ `im_kurzabschnitt`-Fehlgriffe bleiben außen vor: sie beanstanden keine
2182
+ zitierte Vorschrift, sondern die Zusammenfassung, und ihr Muster ist ein
2183
+ Satzmuster, kein Fundstellenmuster — es dürfte hier keinen Absatz löschen.
2184
  """
2185
+ fehlgriffe = [f for f in fehlgriffe if not f.im_kurzabschnitt]
2186
  if not fehlgriffe or not (text or "").strip():
2187
  return text
2188
 
 
2213
  Ein Hinweis auf einen „Restbezug" wäre dort eine Warnung vor dem richtigen
2214
  Zitat.
2215
  """
2216
+ fehlgriffe = [f for f in fehlgriffe if not f.im_kurzabschnitt]
2217
  if not fehlgriffe:
2218
  return False
2219
  ersetzt = (_KURZ_UEBERSCHRIFT, _NORM_UEBERSCHRIFT, "Wortlaut")
 
2252
  if befund.status == "abweichung":
2253
  zeilen.append(f"{_KORREKTUR_EINLEITUNG} ({themen}):")
2254
  if befund.fehlgriffe:
2255
+ if any(not f.im_kurzabschnitt for f in befund.fehlgriffe):
2256
+ zeilen.append(
2257
+ "Kurzantwort und maßgebliche Norm oben stammen aus dem kuratierten "
2258
+ "Normregister; die zunächst herangezogene Vorschrift entscheidet diese "
2259
+ "Frage nicht."
2260
+ )
2261
+ else:
2262
+ zeilen.append(
2263
+ "Kurzantwort und maßgebliche Norm oben stammen aus dem kuratierten "
2264
+ "Normregister; die ursprüngliche Fassung hat die maßgeblichen "
2265
+ "Regelungen unzutreffend zusammengefasst."
2266
+ )
2267
  for fehlgriff in befund.fehlgriffe:
2268
  zeilen.append(f" {fehlgriff.warum}")
2269
  else: