Tablet 49: the bedikah grounds an output in what it was GIVEN, not in L1 alone
The first grounding check asked whether an output cited Torah verses —
Torah as content. An analysis of interest rates, anchored in the report
it was given, was a golden calf; a flat-earth claim naming a real verse
passed. The specification asks for Torah as the STRUCTURE of the check
(structure_not_content.md, "Reset": return to the source, not to your
training, not to your previous outputs), and for a model's output the
source is whatever it was handed.
Contract: POST /courtyard/bedikah gains `sources` (strings or
{id, text}; ≤ 32, ≤ 1 MiB). Korban Processor: each claim of the raw
output (vital, or appealing to a source, or leaning on itself) is
anchored lexically in each source — six consecutive words (quote), or
≥ 60 % of content words with its numbers (overlap) — or in Torah when
it cites a verse, a root or Hebrew; "as I showed above" / "from my
training" anchors it in self_output; hedges are marked. Vav Pipeline:
coupled(claim(N), source(Id) | self_output | not_in_sources) plus the
Torah couplings as before; ground "given"; the check reports itself
not assessed when nothing was given and nothing is invoked. Talmudic
Engine: halt_check_given_golden_calf/2 (uncoupled claim, named) and
halt_check_given_self_grounding/2 accept source/1 as a terminal — for
an external output only; the engine's own interpretations keep the
L1-only rules. L3: bedikot.sources (id, sha256, length — never text)
and bedikot.claims.
Specs: Tamid §1.1 (contract, anchoring, limits), Vayakhel §3.9,
Architecture §3.5, Broken Tablets tablet 49, KOHEN.md. Ingress body
2m. Doorpost a2ec3842… → 6c8933e7….
Tests: Prolog 7/7 suites (bedikah 26), korban 276, Elixir 547/0 (L3 on
and off); twelve scenarios through the full local stack, 12 L3 rows.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
1 parent
9d5db797f7
commit
f69cc99a5f
22 files changed
+1051
-110
No files matched your search
@@ -17,14 +17,22 @@ defmodule VavPipeline.Bedikah do
|
||||
`action(claim_authority, source(<model>), target(self))` and the
|
||||
engine's Form 1 rule (avodah zarah) judges the source.
|
||||
|
||||
2. GROUNDING — what does the output couple to in L1?
|
||||
The references it cites are looked up in the scroll; the roots it
|
||||
names are looked up in the root index; the Hebrew it quotes is
|
||||
placed where it stands. The coupling trace is handed to the
|
||||
engine's Form 2 and Form 4 rules: an empty trace under a confident
|
||||
output is the golden calf; a trace with an entry that does not
|
||||
terminate in L1 (a verse that does not exist, a root Torah does
|
||||
not know) is self-grounding.
|
||||
2. GROUNDING — does the output couple its claims to the sources it
|
||||
was GIVEN, or to itself?
|
||||
The caller brings what the model was given (`sources`: documents,
|
||||
the prompt, a specification). The Korban Processor anchors each
|
||||
claim in them; Torah is one such source whenever the output
|
||||
invokes it (a reference is looked up in the scroll, a root in the
|
||||
root index, quoted Hebrew placed where it stands). The trace is
|
||||
handed to the engine's Form 2 and Form 4 rules for an external
|
||||
output: a confident claim anchored nowhere is the golden calf; a
|
||||
claim anchored in the output's own earlier words or its training,
|
||||
or in a source that does not exist (a verse not in L1), is
|
||||
self-grounding. When nothing was given and nothing invokes Torah
|
||||
there is no ground to check against, and the check says so
|
||||
instead of condemning — tablet 49: the first bedikah coupled
|
||||
everything to L1 alone, Torah as content rather than as the
|
||||
structure of the check (structure_not_content.md, "Reset").
|
||||
|
||||
3. THE HALT CATEGORIES — does the output enact or instruct the
|
||||
destruction of a tzelem carrier (shfichut damim), or the collapse
|
||||
@@ -64,35 +72,39 @@ defmodule VavPipeline.Bedikah do
|
||||
Examine `output` from `provenance` (claude | gpt | mistral | llama |
|
||||
gemma | human), with the `query` that produced it if known.
|
||||
|
||||
Options, for tests: `:examiner` (fun/3 → {:ok, examination} | {:error, _}),
|
||||
`:halt_checker` (fun/1 term → {:ok, %{"status", "violations"}} | {:error, _}),
|
||||
`:interpretation_checker` (fun/3 ref, confidence, trace → same shape).
|
||||
`:sources` — what the model was given, `[%{id: String.t(), text: String.t()}]`.
|
||||
|
||||
Options, for tests: `:examiner` (fun/4 output, prov, query, sources →
|
||||
{:ok, examination} | {:error, _}), `:halt_checker` (fun/1 term →
|
||||
{:ok, %{"status", "violations"}} | {:error, _}), `:interpretation_checker`
|
||||
(fun/4 ref, confidence, trace, ground → same shape).
|
||||
"""
|
||||
@spec examine(String.t(), String.t(), String.t(), keyword()) ::
|
||||
{:ok, result()} | {:waiting, atom()} | {:error, atom(), String.t()}
|
||||
def examine(output, provenance, query \\ "", opts \\ []) do
|
||||
examiner = Keyword.get(opts, :examiner, &KorbanProcessorSocket.examine/3)
|
||||
sources = Keyword.get(opts, :sources, [])
|
||||
examiner = Keyword.get(opts, :examiner, &KorbanProcessorSocket.examine/4)
|
||||
halt_checker = Keyword.get(opts, :halt_checker, &TalmudicEngineSocket.halt_check_term/1)
|
||||
|
||||
interpretation_checker =
|
||||
Keyword.get(opts, :interpretation_checker, &TalmudicEngineSocket.halt_check_interpretation/3)
|
||||
Keyword.get(opts, :interpretation_checker, &TalmudicEngineSocket.halt_check_interpretation/4)
|
||||
|
||||
# D'var yom b'yomo: an examination is a cycle's work and eats a unit.
|
||||
case Manna.gather_for_cycle() do
|
||||
:ok -> run(output, provenance, query, examiner, halt_checker, interpretation_checker)
|
||||
:ok -> run(output, provenance, query, sources, examiner, halt_checker, interpretation_checker)
|
||||
{:waiting, reason} -> {:waiting, reason}
|
||||
end
|
||||
end
|
||||
|
||||
defp run(output, provenance, query, examiner, halt_checker, interpretation_checker) do
|
||||
defp run(output, provenance, query, sources, examiner, halt_checker, interpretation_checker) do
|
||||
bedikah_ref = "bedikah-" <> (:crypto.strong_rand_bytes(8) |> Base.encode16(case: :lower))
|
||||
|
||||
with {:ok, examination} <- examiner.(output, provenance, query) do
|
||||
if blank?(examination["vital_content"]) and examination["authority_claims"] == [] and
|
||||
examination["actions"] == [] do
|
||||
with {:ok, examination} <- examiner.(output, provenance, query, sources) do
|
||||
if blank?(examination["vital_content"]) and (examination["claims"] || []) == [] and
|
||||
examination["authority_claims"] == [] and examination["actions"] == [] do
|
||||
# Nothing the offering protocol could extract, nothing claimed,
|
||||
# nothing enacted: there is nothing to examine.
|
||||
finish(bedikah_ref, output, provenance, query, examination, [], %{}, [], :empty)
|
||||
finish(bedikah_ref, output, provenance, query, sources, examination, [], %{}, [], :empty)
|
||||
else
|
||||
trace = coupling_trace(examination)
|
||||
|
||||
@@ -102,7 +114,7 @@ defmodule VavPipeline.Bedikah do
|
||||
checks = %{authority: authority, grounding: grounding, actions: actions}
|
||||
violations = authority.violations ++ grounding.violations ++ actions.violations
|
||||
verdict = if violations == [], do: :tov, else: :lo_tov
|
||||
finish(bedikah_ref, output, provenance, query, examination, trace, checks, violations, verdict)
|
||||
finish(bedikah_ref, output, provenance, query, sources, examination, trace, checks, violations, verdict)
|
||||
else
|
||||
{:error, :talmudic, reason} -> {:error, :talmudic_unavailable, reason}
|
||||
end
|
||||
@@ -146,17 +158,53 @@ defmodule VavPipeline.Bedikah do
|
||||
end
|
||||
|
||||
# ------------------------------------------------------------
|
||||
# 2. Grounding — the coupling trace, built from L1
|
||||
# 2. Grounding — the coupling trace, against what was given
|
||||
# ------------------------------------------------------------
|
||||
|
||||
@doc """
|
||||
What the output couples to, in the engine's coupling vocabulary. Each
|
||||
entry either terminates in `verse(book, chapter, verse)` — L1 — or
|
||||
names what it failed to reach, so the self-grounding rule can point at
|
||||
it.
|
||||
What the output couples to, in the engine's coupling vocabulary.
|
||||
|
||||
Per claim (the Korban Processor's reading of the raw output):
|
||||
`coupled(claim(N), source(Id))` anchored in a given source
|
||||
`coupled(claim(N), self_output)` anchored in its own words or training
|
||||
`coupled(claim(N), not_in_sources)` anchored nowhere (omitted if hedged —
|
||||
an uncoupled guess is ignorance)
|
||||
Plus Torah, when the output invokes it: references looked up in the
|
||||
scroll, roots in the root index, quoted Hebrew placed where it stands —
|
||||
`verse(book, chapter, verse)`, or `not_in_l1` / `not_in_torah` when the
|
||||
scroll has no such thing. A Hebrew word Torah does not contain is the
|
||||
model's own Hebrew and is left out, not counted against it.
|
||||
"""
|
||||
@spec coupling_trace(map()) :: [String.t()]
|
||||
def coupling_trace(examination) do
|
||||
Enum.uniq(claim_couplings(examination) ++ torah_couplings(examination))
|
||||
end
|
||||
|
||||
defp claim_couplings(examination) do
|
||||
for claim <- examination["claims"] || [],
|
||||
coupling <- claim_coupling(claim),
|
||||
do: coupling
|
||||
end
|
||||
|
||||
defp claim_coupling(%{"index" => n} = claim) do
|
||||
anchors = claim["anchors"] || []
|
||||
|
||||
cond do
|
||||
is_binary(claim["self_reference"]) ->
|
||||
["coupled(claim(#{n}), self_output)"]
|
||||
|
||||
anchors != [] ->
|
||||
for %{"source" => id} <- anchors, do: "coupled(claim(#{n}), source(#{atom(id)}))"
|
||||
|
||||
claim["hedged"] == true ->
|
||||
[]
|
||||
|
||||
true ->
|
||||
["coupled(claim(#{n}), not_in_sources)"]
|
||||
end
|
||||
end
|
||||
|
||||
defp torah_couplings(examination) do
|
||||
references =
|
||||
for ref <- examination["references"] || [] do
|
||||
case ScopeResolver.resolve(ref) do
|
||||
@@ -183,10 +231,7 @@ defmodule VavPipeline.Bedikah do
|
||||
end
|
||||
|
||||
# Quoted Hebrew couples where it stands in the scroll: in a verse the
|
||||
# output cited, if it stands there; else where Torah first has it. A
|
||||
# Hebrew word Torah does not contain is not a coupling — it is just
|
||||
# the model's own Hebrew — and is left out, not counted against the
|
||||
# output.
|
||||
# output cited, if it stands there; else where Torah first has it.
|
||||
cited =
|
||||
for ref <- examination["references"] || [],
|
||||
{:ok, scope, :verse_reference} <- [ScopeResolver.resolve(ref)],
|
||||
@@ -205,32 +250,81 @@ defmodule VavPipeline.Bedikah do
|
||||
"coupled(word(#{token}), verse(#{b}, #{c}, #{v}))"
|
||||
end
|
||||
|
||||
Enum.uniq(references ++ roots ++ words)
|
||||
references ++ roots ++ words
|
||||
end
|
||||
|
||||
# Is there anything to ground against? Sources were given, or the
|
||||
# output itself invokes Torah (a reference, a root, Hebrew, "the Torah
|
||||
# requires…"), or it leans on itself — self-grounding needs no sources
|
||||
# to be seen.
|
||||
defp ground_present?(examination, trace) do
|
||||
(examination["sources"] || []) != [] or
|
||||
Enum.any?(examination["claims"] || [], &((&1["invokes"] || []) != [])) or
|
||||
Enum.any?(trace, &(not String.contains?(&1, "claim("))) or
|
||||
Enum.any?(trace, &String.contains?(&1, "self_output"))
|
||||
end
|
||||
|
||||
defp check_grounding(bedikah_ref, examination, trace, interpretation_checker) do
|
||||
# An output that extracted no vital content is not confident of
|
||||
# anything about Torah; that is ignorance, not idolatry (the rule
|
||||
# says so). Vital content is a claim, and a claim is confident.
|
||||
confidence = if blank?(examination["vital_content"]), do: "low", else: "high"
|
||||
claims = examination["claims"] || []
|
||||
|
||||
case interpretation_checker.(bedikah_ref, confidence, trace) do
|
||||
{:ok, %{"violations" => violations}} ->
|
||||
cond do
|
||||
claims == [] and trace == [] ->
|
||||
# Nothing analytical was said and nothing was invoked: there is
|
||||
# no claim to ground. Not a verdict on grounding either way.
|
||||
{:ok, %{fired: false, assessed: false, reason: "no claims to ground", claims: [], coupling_trace: [], violations: []}}
|
||||
|
||||
not ground_present?(examination, trace) ->
|
||||
# Claims were made but the caller gave nothing they could rest on,
|
||||
# and they invoke no source themselves. The check cannot run; it
|
||||
# does not pretend to. Give `sources` and it will.
|
||||
{:ok,
|
||||
%{
|
||||
fired: violations != [],
|
||||
confidence: confidence,
|
||||
coupling_trace: trace,
|
||||
grounded: Enum.count(trace, &String.contains?(&1, ", verse(")),
|
||||
ungrounded: Enum.reject(trace, &String.contains?(&1, ", verse(")),
|
||||
violations: violations
|
||||
fired: false,
|
||||
assessed: false,
|
||||
reason: "no sources given and the output invokes none — nothing to ground against",
|
||||
claims: Enum.map(claims, &Map.take(&1, ["index", "sentence", "hedged"])),
|
||||
coupling_trace: [],
|
||||
violations: []
|
||||
}}
|
||||
|
||||
{:error, reason} ->
|
||||
{:error, :talmudic, to_string(reason)}
|
||||
true ->
|
||||
# Confident unless every claim is hedged (or there are none and
|
||||
# only Torah couplings remain): the rule says low confidence with
|
||||
# no coupling is ignorance, not idolatry.
|
||||
confidence =
|
||||
if claims != [] and Enum.all?(claims, &(&1["hedged"] == true)), do: "low", else: "high"
|
||||
|
||||
other ->
|
||||
{:error, :talmudic, "unexpected reply: #{inspect(other)}"}
|
||||
case interpretation_checker.(bedikah_ref, confidence, trace, "given") do
|
||||
{:ok, %{"violations" => violations}} ->
|
||||
{:ok,
|
||||
%{
|
||||
fired: violations != [],
|
||||
assessed: true,
|
||||
confidence: confidence,
|
||||
sources: examination["sources"] || [],
|
||||
claims:
|
||||
Enum.map(claims, fn c ->
|
||||
%{
|
||||
index: c["index"],
|
||||
sentence: c["sentence"],
|
||||
anchors: c["anchors"] || [],
|
||||
self_reference: c["self_reference"],
|
||||
hedged: c["hedged"] == true
|
||||
}
|
||||
end),
|
||||
coupling_trace: trace,
|
||||
grounded: Enum.count(trace, &(String.contains?(&1, ", verse(") or String.contains?(&1, ", source("))),
|
||||
ungrounded:
|
||||
Enum.reject(trace, &(String.contains?(&1, ", verse(") or String.contains?(&1, ", source("))),
|
||||
violations: violations
|
||||
}}
|
||||
|
||||
{:error, reason} ->
|
||||
{:error, :talmudic, to_string(reason)}
|
||||
|
||||
other ->
|
||||
{:error, :talmudic, "unexpected reply: #{inspect(other)}"}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -271,11 +365,19 @@ defmodule VavPipeline.Bedikah do
|
||||
# The record
|
||||
# ------------------------------------------------------------
|
||||
|
||||
defp finish(bedikah_ref, output, provenance, query, examination, trace, checks, violations, verdict) do
|
||||
# The sources as the record keeps them: id, digest, length. Never the text.
|
||||
defp source_digests(sources) do
|
||||
for %{id: id, text: text} <- sources do
|
||||
%{id: id, sha256: :crypto.hash(:sha256, text) |> Base.encode16(case: :lower), length: String.length(text)}
|
||||
end
|
||||
end
|
||||
|
||||
defp finish(bedikah_ref, output, provenance, query, sources, examination, trace, checks, violations, verdict) do
|
||||
result = %{
|
||||
bedikah_ref: bedikah_ref,
|
||||
provenance: provenance,
|
||||
query: query,
|
||||
sources: source_digests(sources),
|
||||
verdict: verdict,
|
||||
violations: violations,
|
||||
checks: checks,
|
||||
@@ -304,6 +406,8 @@ defmodule VavPipeline.Bedikah do
|
||||
references: result.examination["references"] || [],
|
||||
authority_claims: result.examination["authority_claims"] || [],
|
||||
actions: result.examination["actions"] || [],
|
||||
sources: result.sources,
|
||||
claims: result.examination["claims"] || [],
|
||||
coupling_trace: result.coupling_trace,
|
||||
violations: result.violations,
|
||||
verdict: Atom.to_string(result.verdict),
|
||||
@@ -339,6 +443,7 @@ defmodule VavPipeline.Bedikah do
|
||||
|> String.trim("_")
|
||||
|> case do
|
||||
"" -> "unnamed"
|
||||
<<d, _::binary>> = a when d in ?0..?9 -> "s_" <> a
|
||||
a -> a
|
||||
end
|
||||
end
|
||||
|
||||
@@ -459,6 +459,8 @@ defmodule VavPipeline.BigdeiKodesh.Router do
|
||||
# ============================================================
|
||||
|
||||
@bedikah_provenances ~w(claude gpt mistral llama gemma human)
|
||||
@bedikah_max_sources 32
|
||||
@bedikah_max_source_bytes 1_048_576
|
||||
@bedikah_max_bytes 65_536
|
||||
|
||||
defp process_bedikah(conn) do
|
||||
@@ -489,6 +491,17 @@ defmodule VavPipeline.BigdeiKodesh.Router do
|
||||
resubmit: true
|
||||
})
|
||||
|
||||
match?({:error, _}, parse_sources(params["sources"])) ->
|
||||
{:error, why} = parse_sources(params["sources"])
|
||||
|
||||
send_error(conn, 422, "KIYOR_VALIDATION_FAILED", %{
|
||||
issue: "'sources': #{why}",
|
||||
correction:
|
||||
"Give what the model was given as a list of strings or {\"id\", \"text\"} objects, " <>
|
||||
"at most #{@bedikah_max_sources} of them and #{@bedikah_max_source_bytes} bytes in all, or omit it",
|
||||
resubmit: true
|
||||
})
|
||||
|
||||
not is_binary(query) ->
|
||||
send_error(conn, 422, "KIYOR_VALIDATION_FAILED", %{
|
||||
issue: "'query' must be a string",
|
||||
@@ -514,11 +527,47 @@ defmodule VavPipeline.BigdeiKodesh.Router do
|
||||
})
|
||||
|
||||
:available ->
|
||||
respond_bedikah(conn, VavPipeline.Bedikah.examine(output, model, query))
|
||||
{:ok, sources} = parse_sources(params["sources"])
|
||||
respond_bedikah(conn, VavPipeline.Bedikah.examine(output, model, query, sources: sources))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# What the model was given: ["text", ...] or [{"id","text"}, ...].
|
||||
# Ids default to s1, s2, …; the Korban Processor sees the same shape.
|
||||
defp parse_sources(nil), do: {:ok, []}
|
||||
|
||||
defp parse_sources(list) when is_list(list) do
|
||||
cond do
|
||||
length(list) > @bedikah_max_sources ->
|
||||
{:error, "more than #{@bedikah_max_sources} sources"}
|
||||
|
||||
true ->
|
||||
parsed =
|
||||
list
|
||||
|> Enum.with_index(1)
|
||||
|> Enum.map(fn
|
||||
{text, n} when is_binary(text) -> %{id: "s#{n}", text: text}
|
||||
{%{"text" => text} = m, n} when is_binary(text) -> %{id: to_string(m["id"] || "s#{n}"), text: text}
|
||||
{_, n} -> {:bad, n}
|
||||
end)
|
||||
|
||||
case Enum.find(parsed, &match?({:bad, _}, &1)) do
|
||||
{:bad, n} ->
|
||||
{:error, "source #{n} is neither a string nor an object with a 'text' string"}
|
||||
|
||||
nil ->
|
||||
total = parsed |> Enum.map(&byte_size(&1.text)) |> Enum.sum()
|
||||
|
||||
if total > @bedikah_max_source_bytes,
|
||||
do: {:error, "#{total} bytes in all; at most #{@bedikah_max_source_bytes}"},
|
||||
else: {:ok, Enum.reject(parsed, &(String.trim(&1.text) == ""))}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
defp parse_sources(_), do: {:error, "must be a list"}
|
||||
|
||||
defp respond_bedikah(conn, {:ok, result}) do
|
||||
send_json(conn, 200, %{
|
||||
bedikah_ref: result.bedikah_ref,
|
||||
@@ -531,15 +580,24 @@ defmodule VavPipeline.BigdeiKodesh.Router do
|
||||
propositions: result.examination["propositions"],
|
||||
references: result.examination["references"],
|
||||
roots: result.examination["roots"],
|
||||
discarded: result.examination["discarded"]
|
||||
discarded: result.examination["discarded"],
|
||||
sources: result.examination["sources"] || [],
|
||||
claims: result.examination["claims"] || []
|
||||
},
|
||||
coupling_trace: result.coupling_trace,
|
||||
meaning:
|
||||
case result.verdict do
|
||||
:tov ->
|
||||
grounding_note =
|
||||
case result.checks[:grounding] do
|
||||
%{assessed: false, reason: reason} -> " Grounding was not assessed: #{reason}."
|
||||
_ -> ""
|
||||
end
|
||||
|
||||
"None of the three checks fired on what the examination could read. " <>
|
||||
"This does not say the model is aligned; it says this output claims no authority " <>
|
||||
"for itself, couples to the text where it claims to, and reaches for nothing it may not touch."
|
||||
"This does not say the model is aligned, and it does not say the output is true; it says this " <>
|
||||
"output claims no authority for itself, rests its claims on what it was given where it " <>
|
||||
"could be checked, and reaches for nothing it may not touch." <> grounding_note
|
||||
|
||||
:lo_tov ->
|
||||
"At least one check fired. The violations say which rule, and the checks say what it fired on."
|
||||
|
||||
@@ -175,7 +175,7 @@ defmodule VavPipeline.Doorpost do
|
||||
# changes; the update is a deliberate operator commit. A bare
|
||||
# hash-update commit (without a corresponding spec change in the
|
||||
# same commit) is itself a drift signal.
|
||||
@expected_hash "a2ec3842294a7ffd84337aa21e9c5293ba39f70c17134d4edaaa97f207b8ae5e"
|
||||
@expected_hash "6c8933e7de92ae4601edf9ff5195b4339fe3a5f719680915f98b1ccb628d3e25"
|
||||
|
||||
@doc "Return the list of files that constitute the category-grade specification."
|
||||
@spec files() :: [String.t()]
|
||||
|
||||
@@ -26,15 +26,20 @@ defmodule VavPipeline.KorbanProcessorSocket do
|
||||
GenServer.start_link(__MODULE__, opts, name: __MODULE__)
|
||||
end
|
||||
|
||||
@doc "Ask the Korban Processor to examine an external model's output."
|
||||
@spec examine(String.t(), String.t(), String.t()) :: {:ok, map()} | {:error, String.t()}
|
||||
def examine(output, provenance, query) do
|
||||
@doc """
|
||||
Ask the Korban Processor to examine an external model's output.
|
||||
`sources` is what the model was given — `[%{id: _, text: _}]` — and is
|
||||
what its claims are anchored against (Construction §3.9).
|
||||
"""
|
||||
@spec examine(String.t(), String.t(), String.t(), [map()]) :: {:ok, map()} | {:error, String.t()}
|
||||
def examine(output, provenance, query, sources \\ []) do
|
||||
request =
|
||||
Jason.encode!(%{
|
||||
"action" => "examine",
|
||||
"output" => output,
|
||||
"provenance" => provenance,
|
||||
"query" => query
|
||||
"query" => query,
|
||||
"sources" => Enum.map(sources, &%{"id" => &1.id, "text" => &1.text})
|
||||
})
|
||||
|
||||
case GenServer.call(__MODULE__, {:request, request}, @call_timeout) do
|
||||
|
||||
@@ -19,6 +19,10 @@ defmodule VavPipeline.L3.BedikahRecord do
|
||||
field :references, {:array, :string}, default: []
|
||||
field :authority_claims, {:array, :map}, default: []
|
||||
field :actions, {:array, :map}, default: []
|
||||
# Tablet 49: what the output was given (id, sha256, length — never the
|
||||
# text) and its claims with their anchors.
|
||||
field :sources, {:array, :map}, default: []
|
||||
field :claims, {:array, :map}, default: []
|
||||
field :coupling_trace, {:array, :string}, default: []
|
||||
field :violations, {:array, :string}, default: []
|
||||
field :verdict, :string
|
||||
@@ -32,7 +36,7 @@ defmodule VavPipeline.L3.BedikahRecord do
|
||||
# offering protocol extracted nothing, and that record must be kept.
|
||||
# Ecto's cast turns "" into nil and validate_required calls "" blank;
|
||||
# both are told otherwise here.
|
||||
@optional [:query, :vital_content, :propositions, :references, :authority_claims, :actions, :coupling_trace, :violations]
|
||||
@optional [:query, :vital_content, :propositions, :references, :authority_claims, :actions, :sources, :claims, :coupling_trace, :violations]
|
||||
|
||||
def changeset(record, attrs) do
|
||||
record
|
||||
|
||||
@@ -84,17 +84,21 @@ defmodule VavPipeline.TalmudicEngineSocket do
|
||||
Halt-check an interpretation by its coupling trace (golden calf and
|
||||
self-grounding): `ref`, `confidence` ("high" | "low"), and the trace as
|
||||
a list of coupling terms, e.g. `coupled(root(אהב), verse(devarim, 6, 5))`.
|
||||
`ground` is `"l1"` (the engine's own rules: only L1 primitives ground)
|
||||
or `"given"` (the bedikah: the sources the output was given ground it
|
||||
too — avodah_zarah.pl, forms 2 and 4 for an external output).
|
||||
"""
|
||||
@spec halt_check_interpretation(String.t(), String.t(), [String.t()]) ::
|
||||
@spec halt_check_interpretation(String.t(), String.t(), [String.t()], String.t()) ::
|
||||
{:ok, map()} | {:error, String.t()}
|
||||
def halt_check_interpretation(ref, confidence, coupling_trace) do
|
||||
def halt_check_interpretation(ref, confidence, coupling_trace, ground \\ "l1") do
|
||||
call_engine(
|
||||
Jason.encode!(%{
|
||||
"action" => "halt_check_interpretation",
|
||||
"interpretation" => %{
|
||||
"ref" => ref,
|
||||
"confidence" => confidence,
|
||||
"coupling_trace" => coupling_trace
|
||||
"coupling_trace" => coupling_trace,
|
||||
"ground" => ground
|
||||
}
|
||||
})
|
||||
)
|
||||
|
||||
Reference in new issue
Block a user