This document (notebook) describes three ways of making mazes (or labyrinths) using graphs. The first two are based on rectangular grids; the third on a hexagonal grid.
All computational graph features discussed here are provided by the Graph functionalities of Wolfram Language.
TL;DR
Just see the maze pictures below. (And try to solve the mazes.)
Procedure outline
The first maze is made by a simple procedure which is actually some sort of cheating:
A regular rectangular grid graph is generated with random weights associated with its edges.
The (minimum) spanning tree for that graph is found.
That tree is plotted with exaggeratedly large vertices and edges, so the graph plot looks like a maze.
This is “the cheat” — the maze walls are not given by the graph.
The second maze is made “properly”:
Two interlacing regular rectangular grid graphs are created.
The second one has one less row and one less column than the first.
The vertex coordinates of the second graph are at the centers of the rectangles of the first graph.
The first graph provides the maze walls; the second graph is used to make paths through the maze.
In other words, to create a solvable maze.
Again, random weights are assigned to edges of the second graph, and a minimum spanning tree is found.
There is a convenient formula that allows using the spanning tree edges to remove edges from the first graph.
In that way, a proper maze is derived.
The third maze is again made “properly” using the procedure above with two modifications:
Two interlacing regular grid graphs are created: one over a hexagonal grid, the other over a triangular grid.
The hexagonal grid graph provides the maze walls; the triangular grid graph provides the maze paths.
Since the formula for wall removal is hard to derive, a more robust and universal method based on nearest neighbors is used.
Simple Maze
In this section, we create a simple, “cheating” maze.
Remark: The steps are easy to follow, given the procedure outlined in the introduction.
The “maze” above looks like a maze because the vertices and edges are rectangular with matching sizes, and they are thicker than the spaces between them. In other words, we are cheating.
To make that cheating construction clearer, let us plot the shortest path from the bottom left to the top right and color the edges in pink (salmon) and the vertices in red:
finder = Nearest[Thread[GraphEmbedding[g1] -> VertexList[g1]]]
Take a maze edge and its vertex points:
e = First@EdgeList[mazePath];
aMazePathCoords = Association@Thread[VertexList[mazePath] -> GraphEmbedding[mazePath]];
points = List @@ (e /. aMazePathCoords)
Find the edge’s midpoint and the nearest wall-graph vertices:
This document (notebook) discusses number theory properties and relationships of the integer 2026.
The integer 2026 is semiprime and a happy number, with 365 as one of its primitive roots. Although 2026 may not be particularly noteworthy in number theory, this provides a great excuse to create various elaborate visualizations that reveal some interesting aspects of the number.
A happy number is a number for which iteratively summing the squares of its digits eventually reaches 1 (e.g., 13 -> 10 -> 1). Here is a check that 2026 is happy:
ResourceFunction["HappyNumberQ"][2026]
Out[]= True
Here is the corresponding trail of digit-square sums:
The decomposition of $2026$ as $2 * 1013$ means the multiplicative group modulo $2026$ has primitive roots. A primitive root exists for an integer $n$ if and only if $n$ is $1$, $2$,$4$, $p^k$ , or $2 p^k$ , where $k$ is an odd prime and $k>0$ .
We can check additional facts about 2026, such as whether it is “square-free” , among other properties. However, let us compare these with the feature-rich 2025 in the next section.
Comparison with 2025
Here is a side-by-side comparison of key number theory properties for 2025 and 2026.
Property
2025
2026
Notes
Prime or Composite
Composite
Composite
Both non-prime.
Prime Factorization
3^4 * 5^2 (81 * 25)
2 * 1013
2025 has repeated small primes; 2026 is a semiprime (product of two distinct primes).
Number of Divisors
15 (highly composite for its size)
4 (1, 2, 1013, 2026)
2025 has many divisors; 2026 has very few.
Perfect Square
Yes (45^2 = 2025)
No
Major highlight for 2025—rare square year.
Sum of Cubes
Yes (1^3 + 2^3 + … + 9^3 = (1 + … + 9)^2 = 2025)
No
Iconic property for 2025 (Nicomachus’s theorem).
Happy Number
No (process leads to cycle including 4)
Yes (repeated squared digit sums reach 1)
Key point for 2026—its main “happy” trait.
Harshad Number
Yes (divisible by 9)
No (not divisible by 10)
2025 qualifies; 2026 does not.
Primitive Roots
No
Yes
This is a relatively rare property to have.
Other Notable Traits
{(20 + 25)^2 = 2025, Sum of first 45 odd numbers, Deficient number, Many pattern-based representations}
{Even number, Deficient number, Few special patterns}
2025 is packed with elegant properties; 2026 is more “plain” beyond being happy.
Overall “Interest” Level
Highly interesting—celebrated in math communities for squares, cubes, and patterns
Relatively uninteresting—basic semiprime with no standout geometric or sum properties
Reinforces blog’s angle.
To summarize:
2025 stands out as a mathematically rich number, often highlighted in puzzles and articles for its perfect square status and connections to sums of cubes and odd numbers.
2026 , in contrast, has fewer flashy properties — it’s a straightforward even semiprime — but it qualifies as a happy number and it has a primitive root.
Here is a computationally generated comparison table of most of the properties found in the table above:
Let us create and plot a graph showing the trails of all happy numbers less than or equal to 2026. Below, we identify these numbers and their corresponding trails:
There is a theorem by Gauss stating that any integer can be represented as a sum of at most three triangular numbers. Here we find an “interesting” solution:
sol = FindInstance[{2026 == PolygonalNumber[i] + PolygonalNumber[j] + PolygonalNumber[k], i > 10, j > 10, k > 10}, {i, j, k}, Integers]
Remark: It is interesting that 365 (the number of days in a common calendar year) is a primitive root of the multiplicative group generated by 2026 . Not many years have this property this century; many do not have primitive roots at all.
Here we find the position of 2026 in that sequence:
Position[seq, 2026]
Out[]= {{18}}
Given the title of the sequence and the extracted position of $2026$ , this means that the number of disconnected 4-regular graphs with 17 vertices is $2026$. ($17$ because the sequence offset is $0$.) Let us create a few graphs from that set by using the 5-vertex complete graph $\left(K_5\right.$) and circulant graphs . Here is an example of such a graph:
Number theory provides many opportunities for visualizations, so I included utilities for some of the popular patterns in “Math::NumberTheory”, [AAp1] and “NumberTheoryUtilities”.
The number of years in this century that have primitive roots and have 365 as a primitive root is less than the number of years that are happy numbers.
I would say I spent too much time finding a good, suitable, Christmas-themed combination of colors for the trails graph.
This document (notebook) discusses different combinations of Grammar-Based Parser-Interpreters (GBPI) and Large Language Models (LLMs) to generate executable code from Natural Language Computational Specifications (NLCM). We have the soft assumption that the NLCS adhere to a certain relatively small Domain Specific Language (DSL) or use terminology from that DSL. Another assumption is that the target software packages are not necessarily well-known by the LLMs, i.e. direct LLM requests for code using them would produce meaningless results.
We want to do such combinations because:
GBPI are fast, precise, but with a narrow DSL scope
LLMs can be unreliable and slow, but with a wide DSL scope
Because of GBPI and LLMs are complementary technologies with similar and overlapping goals the possible combinations are many. We concentrate on two of the most straightforward designs: (1) judged parallel race of methods execution, and (2) using LLMs as a fallback method if grammar parsing fails. We show asynchronous programmingimplementations for both designs using the Wolfram Language function LLMGraph.
The rest of the document is structured as follows:
Initial grammar-LLM combinations
Assumptions, straightforward designs, and trade-offs
Comprehensive combinations enumeration (attempt)
Tabular and morphological analysis breakdown
Three methods for parsing ML DSL specs into Raku code
One grammar-based, two LLM-based
Parallel execution with an LLM judge
Straightforward, but computationally wasteful and expensive
Grammar-to-LLM fallback mechanism
The easiest and most robust solution
Concluding comments and observations
TL;DR
Combining grammars and LLMs produces robust translators.
Three translators with different faithfulness and coverage are demonstrated and used.
Two of the simplest, yet effective, combinations are implemented and demonstrated.
Parallel race and grammar-to-LLM fallback.
Asynchronous implementations with LLM-graphs are a very good fit!
Just look at the LLM-graph plots (and be done reading.)
Initial Combinations and Associated Assumptions
The goal is to combine grammar-based parser-interpreters with LLMs in order to achieve robust parsing and interpretation of computational workflow specifications.
Here are some example combinations of these approaches:
A few methods, both grammar-based and LLM-based, are initiated in parallel. Whichever method produces a correct result first is selected as the answer.
This approach assumes that when the grammar-based methods are effective, they will finish more quickly than the LLM-based methods.
The grammar method is invoked first; if it fails, an LLM method (or a sequence of LLM methods) is employed.
LLMs are utilized at the grammar-rule level to provide matching objects that the grammar can work with.
If the grammar method fails, an LLM normalizer for user commands is invoked to generate specifications that the grammar can parse.
It is important to distinguish between declarative specifications and those that prescribe specific steps.
For a workflow given as a list of steps the grammar parser may successfully parse most steps, but LLMs may be required for a few exceptions.
The main trade-off in these approaches is as follows:
Grammar methods are challenging to develop but can be very fast and precise.
Precision can be guaranteed and rigorously tested.
LLM methods are quicker to develop but tend to be slower and can be unreliable, particularly for less popular workflows, programming languages, and packages.
Also, combinations based on LLM tools (aka LLM external function calling) are not considered because LLM-tools invocation is too unpredictable and unreliable.
Comprehensive breakdown (attempt)
This section has a “concise” table that expands the combinations list above into the main combinatorial strategies for Grammar *** LLMs** for robust parsing and interpretation of workflow specifications. The table is not an exhaustive list of such combinations, but illustrates their diversity and, hopefully, can give ideas for future developments.
A few summary points (for table’s content/subject):
The most robust systems combine grammar precision with LLM adaptability , typically by putting grammars first and using LLMs for repair, normalization, expansions, or semantic interpretation (i.e. “fallback”.)
Table: Combination Patterns for Parsing Workflow Specifications
tbl = Dataset[{<|"ID" -> 1, "CombinationPattern" -> "Parallel Race: Grammar + LLM", "Description" -> "Launch grammar-based parsing and one or more LLM interpreters in parallel; whichever yields a valid parse first is accepted.", "Pros" -> {"Fast when grammar succeeds", "Robust fallback", "Reduces latency unpredictability of LLMs"}, "ConsTradeoffs" -> {"Requires orchestration", "Need a validator for LLM output"}|>, <|"ID" -> 2, "CombinationPattern" -> "Grammar-First, LLM-Fallback", "Description" -> "Try grammar parser first; if it fails, invoke LLM-based parsing or normalization.", "Pros" -> {"Deterministic preference for grammar", "Testable correctness when grammar succeeds"}, "ConsTradeoffs" -> {"LLM fallback may produce inconsistent structures"}|>, <|"ID" -> 3, "CombinationPattern" -> "LLM-Assisted Grammar (Rule-Level)", "Description" -> "Individual grammar rules delegate to an LLM for ambiguous or context-heavy matching; LLM supplies tokens or AST fragments.", "Pros" -> {"Handles complexity without inflating grammar", "Modular LLM usage"}, "ConsTradeoffs" -> {"LLM behavior may break rule determinism", "Harder to reproduce"}|>, <|"ID" -> 4, "CombinationPattern" -> "LLM Normalizer -> Grammar Parser", "Description" -> "When grammar fails, LLM rewrites/normalizes input into a canonical form; grammar is applied again.", "Pros" -> {"Grammar remains simple", "Leverages LLM skill at paraphrasing"}, "ConsTradeoffs" -> {"Quality depends on normalizer", "Feedback loops possible"}|>, <|"ID" -> 5, "CombinationPattern" -> "Hybrid Declarative vs Procedural Parsing", "Description" -> "Grammar extracts structural/declarative parts; LLM interprets procedural/stepwise parts or vice versa.", "Pros" -> {"Each subsystem tackles what it's best at", "Reduces grammar complexity"}, "ConsTradeoffs" -> {"Harder to maintain global consistency", "Requires AST stitching logic"}|>, <|"ID" -> 6, "CombinationPattern" -> "Grammar-Generated Tests for LLM", "Description" -> "Grammar used to generate examples and counterexamples; LLM outputs are validated against grammar constraints.", "Pros" -> {"Powerful for verifying LLM outputs", "Reduces hallucinations"}, "ConsTradeoffs" -> {"Grammar must encode constraints richly", "Validation pipeline required"}|>, <|"ID" -> 7, "CombinationPattern" -> "LLM as Adaptive Heuristic for Grammar Ambiguities", "Description" -> "When grammar yields multiple parses, LLM chooses or ranks the \"most plausible\" AST.", "Pros" -> {"Improves disambiguation", "Good for underspecified workflows"}, "ConsTradeoffs" -> {"LLM can pick syntactically impossible interpretations"}|>, <|"ID" -> 8, "CombinationPattern" -> "LLM as Semantic Phase After Grammar", "Description" -> "Grammar creates an AST; LLM interprets semantics, fills in missing steps, or resolves vague ops.", "Pros" -> {"Clean separation of syntax vs semantics", "Grammar ensures correctness"}, "ConsTradeoffs" -> {"Semantic interpretation may drift from syntax"}|>, <|"ID" -> 9, "CombinationPattern" -> "Self-Healing Parse Loop", "Description" -> "Grammar fails -> LLM proposes corrections -> grammar retries -> if still failing, LLM creates full AST.","Pros" -> {"Iterative and robust", "Captures user intent progressively"}, "ConsTradeoffs" -> {"More expensive; risk of oscillation"}|>, <|"ID" -> 10, "CombinationPattern" -> "Grammar Embedding Inside Prompt Templates", "Description" -> "Grammar definitions serialized into the prompt, guiding the LLM to conform to the grammar (soft constraints).", "Pros" -> {"Faster than grammar execution in some cases", "Encourages consistent structure"}, "ConsTradeoffs" -> {"Weak guarantees", "LLM may ignore grammar"}|>, <|"ID" -> 11, "CombinationPattern" -> "LLM-Driven Grammar Induction or Refinement", "Description" -> "LLM suggests new grammar rules or transformations; developer approves; the grammar evolves over time.", "Pros" -> {"Faster grammar evolution", "Useful for new workflow languages"}, "ConsTradeoffs" -> {"Requires human QA", "Risk of regressing accuracy"}|>, <|"ID" -> 12, "CombinationPattern" -> "Regex Engine as LLM Guardrail", "Description" -> "Regex or token rules used to validate or filter LLM results before accepting them.", "Pros" -> {"Lightweight constraints", "Useful for quick prototyping"}, "ConsTradeoffs" -> {"Regex too weak for complex syntax"}|>}];
tbl = tbl[All, KeyDrop[#, "ID"] &];
tbl = tbl[All, ReplacePart[#, "Pros" -> ColumnForm[#Pros]] &];
tbl = tbl[All, ReplacePart[#, "ConsTradeoffs" -> ColumnForm[#ConsTradeoffs]] &];
tbl = tbl[All, Style[#, FontFamily -> "Times New Roman"] & /@ # &];
ResourceFunction["GridTableForm"][tbl]
#
CombinationPattern
Description
Pros
ConsTradeoffs
1
Parallel Race: Grammar + LLM
Launch grammar-based parsing and one or more LLM interpreters in parallel; whichever yields a valid parse first is accepted.
{{Fast when grammar succeeds}, {Robust fallback}, {Reduces latency unpredictability of LLMs}}
{{Requires orchestration}, {Need a validator for LLM output}}
2
Grammar-First, LLM-Fallback
Try grammar parser first; if it fails, invoke LLM-based parsing or normalization.
{{Deterministic preference for grammar}, {Testable correctness when grammar succeeds}}
{{LLM fallback may produce inconsistent structures}}
3
LLM-Assisted Grammar (Rule-Level)
Individual grammar rules delegate to an LLM for ambiguous or context-heavy matching; LLM supplies tokens or AST fragments.
{{Handles complexity without inflating grammar}, {Modular LLM usage}}
{{LLM behavior may break rule determinism}, {Harder to reproduce}}
4
LLM Normalizer -> Grammar Parser
When grammar fails, LLM rewrites/normalizes input into a canonical form; grammar is applied again.
{{Grammar remains simple}, {Leverages LLM skill at paraphrasing}}
{{Quality depends on normalizer}, {Feedback loops possible}}
5
Hybrid Declarative vs Procedural Parsing
Grammar extracts structural/declarative parts; LLM interprets procedural/stepwise parts or vice versa.
{{Each subsystem tackles what it’s best at}, {Reduces grammar complexity}}
{{Harder to maintain global consistency}, {Requires AST stitching logic}}
6
Grammar-Generated Tests for LLM
Grammar used to generate examples and counterexamples; LLM outputs are validated against grammar constraints.
{{Powerful for verifying LLM outputs}, {Reduces hallucinations}}
{{Grammar must encode constraints richly}, {Validation pipeline required}}
7
LLM as Adaptive Heuristic for Grammar Ambiguities
When grammar yields multiple parses, LLM chooses or ranks the “most plausible” AST.
{{Improves disambiguation}, {Good for underspecified workflows}}
{{LLM can pick syntactically impossible interpretations}}
8
LLM as Semantic Phase After Grammar
Grammar creates an AST; LLM interprets semantics, fills in missing steps, or resolves vague ops.
{{Clean separation of syntax vs semantics}, {Grammar ensures correctness}}
{{Semantic interpretation may drift from syntax}}
9
Self-Healing Parse Loop
Grammar fails -> LLM proposes corrections -> grammar retries -> if still failing, LLM creates full AST.
{{Iterative and robust}, {Captures user intent progressively}}
{{More expensive; risk of oscillation}}
10
Grammar Embedding Inside Prompt Templates
Grammar definitions serialized into the prompt, guiding the LLM to conform to the grammar (soft constraints).
{{Faster than grammar execution in some cases}, {Encourages consistent structure}}
{{Weak guarantees}, {LLM may ignore grammar}}
11
LLM-Driven Grammar Induction or Refinement
LLM suggests new grammar rules or transformations; developer approves; the grammar evolves over time.
{{Faster grammar evolution}, {Useful for new workflow languages}}
{{Requires human QA}, {Risk of regressing accuracy}}
12
Regex Engine as LLM Guardrail
Regex or token rules used to validate or filter LLM results before accepting them.
{{Lightweight constraints}, {Useful for quick prototyping}}
{{Regex too weak for complex syntax}}
Diversity reasons
The diversity of combinations in the table above arises because Raku grammars and LLMs occupy fundamentally different but highly complementary positions in the parsing spectrum.
Raku grammars provide determinism, speed, verifiability, and structural guarantees, but they require upfront design and struggle with ambiguity, informal input, and evolving specifications.
LLMs, in contrast, excel at normalization, semantic interpretation, ambiguity resolution, and adapting to fluid or poorly defined languages, yet they lack determinism, may hallucinate, and are slower.
When these two technologies meet, every architectural choice — who handles syntax, who handles semantics, who runs first, who validates whom, who repairs or refines — defines a distinct strategy.
Hence, the design space naturally expands into many valid hybrid patterns rather than a single “best” pipeline.
That said, the fallback pattern implemented below can be considered the “best option” from certain development perspectives because it is simple, effective, and has fast execution times.
This section demonstrates the use of three different translation methods:
Grammar-based parser-interpreter of computational workflows
LLM-based translator using few-shot learning with relevant DSL examples
Natural Language Processing (NLP) interpreter using code templates and LLMs to fill-in the corresponding parameters
The translators are ordered according of their faithfulness, most faithful first. It can be said that at the same time, the translators are ordered according to their coverage — widest coverage is by the last.
Grammar-based
Here a recommender pipeline specified with natural language commands is translated into Raku code of the package “ML::SparseMatrixRecommender” using a sub of the paclet “DSLTranslation”:
spec = "create from dsData; apply LSI functions IDF, None, Cosine; recommend by profile for passengerSex:male, and passengerClass:1st; join across using dsData; echo the pipeline value";
The function DSLTranslation uses a web service by default but if Raku and the package “DSL::Translators” are installed it can use the provided Command Line Interface (CLI):
LLM translations can be done using a set of from-to rules. This is the so-called few shot learning of LLMs. The paclet “DSLExamples” has a collection of such examples for different computational workflows. (Mostly ML at this point.) The examples are hierarchically organized by programming language and workflow name; see the resource file “dsl-examples.json”, or execute DSLExamples[].
Here is a table that shows the known DSL translation examples in “DSL::Examples” :
Here is a recommender pipeline specified with natural language commands:
spec = "new recommender; create from @dsData; apply LSI functions IDF, None, Cosine; recommend by profile for passengerSex:male, and passengerClass:1st; join across with @dsData on \"id\"; echo the pipeline value; classify by profile passengerSex:female, and passengerClass:1st on the tag passengerSurvival; echo value";
commands = StringSplit[spec, ""];
Translate to WL code line-by-line:
res = LLMPipelineSegment[] /@ commands; res = Map[StringTrim@StringReplace[#, RegularExpression["Output\h*:"] -> ""] &, res];
res = StringRiffle[res, "==>"]
tmplJudge = StringTemplate["Choose the generated code that most fully adheres to the spec:\\n\\n\\n`spec`\\n\\n\\nfrom the following `lang` generation results:\\n\\n\\n1) DSL-grammar:\\n`dslGrammar`\\n\\n\\n2) LLM-examples:\\n`llmExamples`\\n\\n\\n3) NLP-template-engine:\\n`nlpTemplateEngine`\\n\\n\\nand copy it:"]
spec = " make a brand new recommender with the data @dsData; apply LSI functions IDF, None, Cosine; recommend by profile for passengerSex:male, and passengerClass:1st; join across with @dsData on \"id\"; echo the pipeline value; ";
Instead of having DSL-grammar- and LLM computations running in parallel, we can make an LLM-graph in which the LLM computations are invoked if the DSL-grammar parsing-and-interpretation fails. In this section we make such a graph.
Before making the graph let us also generalize it to work with other ML workflows, not just recommendations.
Let us make an LLM function with a similar functionality. I.e. an LLM-function that classifies a natural language computation specification into workflow labels used by “DSLExamples”. Here is such a function using the sub LLMClassify provided by “NLPTemplateEngine”:
Here the LLM graph is run over a spec that can be parsed by DSL-grammar (notice the very short computation time):
Here is the obtained result:
Here is a spec that cannot be parsed by the DSL-grammar interpreter — note that there is just a small language change in the first line:
spec = " create from @dsData; apply LSI functions IDF, None, Cosine; recommend by profile for passengerSex:male, and passengerClass:1st; join across with @dsData on \"id\"; echo the pipeline value; ";
Nevertheless, we obtain a correct result via LLM-examples:
Let us specify another workflow — for ML-classification with Wolfram Language — and run the graph:
spec = " use the dataset @dsData; split the data into training and testing parts with 0.8 ratio; make a nearest neighbors classifier; show classifier accuracy, precision, and recall; echo the pipeline value; ";
Using LLM graphs gives the ability to impose desired orchestration and collaboration between deterministic programs and LLMs.
By contrast, the “inversion of control” of LLM – tools is “capricious.”
LLM-graphs are both a generalization of LLM-tools, and a lower level infrastructural functionality than LLM-tools.
The LLM-graph for the parallel-race translation is very similar to the LLM-graph for comprehensive document summarization described in [AA4].
The expectation that DSL examples would provide both fast and faithful results is mostly confirmed in ≈20 experiments.
Using the NLP template engine is also fast because LLMs are harnessed through QAS.
The DSL examples translation had to be completed with a workflow classifier.
Such classifiers are also part of the implementations of the other two approaches .
The grammar – based one uses a deterministic classifier, [AA1]
The NLP template engine uses an LLM classifier .
An interesting extension of the current work is to have a grammar-LLM combination in which when the grammar fails then the LLM “normalizes” the specs until the grammar can parse them.
Currently, LLMGraph does not support graphs with cycles, hence this approach “can wait” (or be implemented by other means .)
Multiple DSL examples can be efficiently derived by random sentence generation with different grammars.
Similar to the DSL commands classifier making approach taken in [AA1] .
LLMs can be also used to improve and extend the DSL grammars.
And it is interesting to consider automating that process, instead of doing it via human supervision.
Program a few versions of circle chords based visualization routines.
Called chord trail plots below.
Marvel at chord trail plots for larger moduli.
Make multiple collections of them.
Look into number of primitive roots distributions.
Consider making animations of the collections.
The animations should not be “chaotic” — they should have some inherent visual flow in them.
Consider different ways of sorting chord trail plots.
Using number theoretic arguments.
Yeah, would be nice, but requires too much head scratching and LLM-ing.
Convert plots to images and sort them.
Some might say that that is a “brute force” application.
Simple image sort does not work.
Latent Semantic Analysis (LSA) application.
After failing to sort the chord trail image collections by “simple” means, the idea applying LSA came to mind.
LSA being, of course, a favorite technique that was applied to sorting images multiple times in the past, in different contexts, [AAn1, AAn3, AAn4, AAn5, AAv3].
The function ChordTrails can be generalized to take a (pre-computed) chords argument. Here is an example of chords plot that connects integers that are modular inverses of each other:
In order to sort the plots we find dimension reduction basis representation of the corresponding images and sort using that representation. For more details see “Re-exploring the structure of Chinese character images”, [AAn1].
The Doomsday Clock is a symbolic timepiece maintained by the Bulletin of the Atomic Scientists (BAS) since 1947. It represents how close humanity is perceived to be to global catastrophe, primarily nuclear war but also including climate change and biological threats. The clock’s hands are set annually to reflect the current state of global security; midnight signifies theoretical doomsday.
We take text data from the past announcements, and extract the Doomsday Clock reading statements.
Evolution of Doomsday Clock times
We extract relevant Doomsday Clock timeline data from the corresponding Wikipedia page.
(Instead of using a page from BAS.)
We show how timeline data from that Wikipedia page can be processed with “standard” Wolfram Language (WL) functions and with LLMs.
The result plot shows the evolution of the minutes to midnight.
The plot could show trends, highlighting significant global events that influenced the clock setting.
Hence, we put in informative callouts and tooltips.
The data extraction and visualization in the notebook serve educational purposes or provide insights into historical trends of global threats as perceived by experts. We try to make the ingestion and processing code universal and robust, suitable for multiple evaluations now or in the (near) future.
Remark: Keep in mind that the Doomsday Clock is a metaphor and its settings are not just data points but reflections of complex global dynamics (by certain experts and a board of sponsors.)
By observing the (plain) text of that page we see the Doomsday Clock time setting can be extracted from the sentence(s) that begin with the following phrase:
startPhrase = "Bulletin of the Atomic Scientists";
sentence = Select[Map[StringTrim, StringSplit[txtEN, "\n"]], StringStartsQ[#, startPhrase] &] // First
(*"Bulletin of the Atomic Scientists, with a clock reading 90 seconds to midnight"*)
Remark: The EBNF grammar above can be obtained with LLMs using a suitable prompt with example sentences. (We do not discuss that approach further in this notebook.)
Here the parsing functions are generated from the EBNF string above:
ClearAll["p*"]
res = GenerateParsersFromEBNF[ParseToEBNFTokens[ebnf]];
res // LeafCount
(*375*)
We must redefine the parser pANY (corresponding to the EBNF rule “”) in order to prevent pANY of gobbling the word “clock” and in that way making the parser pOPENING fail.
54jfnd 9y2f clock is reading 46 second to midnight
clock is reading 900 minutes to midnight
clock is reading 955 second to midnight
clock reading 224 minute to midnight
clock reading 410 minute to midnight
jdsf5at clock reading 488 seconds to midnight
Here is a verification table with correct- and incorrect spellings:
lsPhrases = {
"doomsday clock is reading 2 seconds to midnight",
"dooms day cloc is readding 2 minute and 22 sekonds to mildnight"};
ParsingTestTable[pCLOCKREADING, lsPhrases, "Layout" -> "Vertical"]
Parsing of numeric word forms
One way to make the parsing more robust is to implement the ability to parse integer names (or numeric word forms) not just integers.
There are two parsing results for “fifty seven”, because pWordedInteger is defined with p10s⊗pUpTo10⊕p10s… . This can be remedied by using ParseJust or ParseShortest:
Let us try the new parser using integer names for the clock time:
str = "the doomsday clock is reading two minutes and forty five seconds to midnight";
pTOP[ToTokens@str]
(*{{{}, {"Minutes" -> 2, "Seconds" -> 45}}}*)
Enhance with LLM parsing
There are multiple ways to employ LLMs for extracting “clock readings” from arbitrary statements for Doomsday Clock readings, readouts, and measures. Here we use LLM few-shot training:
flop = LLMExampleFunction[{
"the doomsday clock is reading two minutes and forty five seconds to midnight" -> "{\"Minutes\":2, \"Seconds\": 45}",
"the clock of the doomsday gives 92 seconds to midnight" -> "{\"Minutes\":0, \"Seconds\": 92}",
"The bulletin atomic scienist maybe is set to a minute an 3 seconds." -> "{\"Minutes\":1, \"Seconds\": 3}"
}, "JSON"]
Here is an example invocation:
flop["Maybe the doomsday watch is at 23:58:03"]
(*{"Minutes" -> 1, "Seconds" -> 57}*)
The following function combines the parsing with the grammar and the LLM example function — the latter is used for fallback parsing:
Here is the application of the combine function above over a certain “random” Doomsday Clock statement:
s = "You know, sort of, that dooms-day watch is 1 and half minute be... before the big boom. (Of doom...)";
GetClockReading[s]
(*<|"Minutes" -> 1, "Seconds" -> 30|>*)
Remark: The same type of robust grammar-and-LLM combination is explained in more detail in the video “Robust LLM pipelines (Mathematica, Python, Raku)”, [AAv1]. (See, also, the corresponding notebook [AAn1].)
Timeline
In this section we extract Doomsday Clock timeline data and make a corresponding plot.
Here we get the Doomsday Clock timeline table from that page in JSON format using an LLM:
res =
LLMSynthesize[{
"Give the time table of the doomsday clock as a time series that is a JSON array.",
"Each element of the array is a dictionary with keys 'Year', 'MinutesToMidnight', 'Time', 'Description'.",
txtWk,
LLMPrompt["NothingElse"]["JSON"]
},
LLMEvaluator -> LLMConfiguration[<|"Provider" -> "OpenAI", "Model" -> "gpt-4o", "Temperature" -> 0.4, "MaxTokens" -> 5096|>]
]
(*"```json[{\"Year\": 1947, \"MinutesToMidnight\": 7, \"Time\": \"23:53\", \"Description\": \"The initial setting of the Doomsday Clock.\"},{\"Year\": 1949, \"MinutesToMidnight\": 3, \"Time\": \"23:57\", \"Description\": \"The Soviet Union tests its first atomic bomb, officially starting the nuclear arms race.\"}, ... *)
Post process the LLM result:
res2 = ToString[res, CharacterEncoding -> "UTF-8"];
res3 = StringReplace[res2, {"```json", "```"} -> ""];
res4 = ImportString[res3, "JSON"];
res4[[1 ;; 3]]
(*{{"Year" -> 1947, "MinutesToMidnight" -> 7, "Time" -> "23:53", "Description" -> "The initial setting of the Doomsday Clock."}, {"Year" -> 1949, "MinutesToMidnight" -> 3, "Time" -> "23:57", "Description" -> "The Soviet Union tests its first atomic bomb, officially starting the nuclear arms race."}, {"Year" -> 1953, "MinutesToMidnight" -> 2, "Time" -> "23:58", "Description" -> "The United States and the Soviet Union test thermonuclear devices, marking the closest approach to midnight until 2020."}}*)
Make a dataset with the additional column “Date” (having date-objects):
Remark: The LLM derived descriptions above are shorter than the descriptions in the column “Reason” of the dataset obtained parsing the page data. For the plot tooltips below we use the latter.
Timeline plot
In order to have informative Doomsday Clock evolution plot we obtain and partition dataset’s time series into step-function pairs:
Remark: By hovering with the mouse over the black points the corresponding descriptions can be seen. We considered using clock-gauges as tooltips, but showing clock-settings reasons is more informative.
As expected, parsing, plotting, or otherwise processing the Doomsday Clock settings and statements are excellent didactic subjects for textual analysis (or parsing) and temporal data visualization. The visualization could serve educational purposes or provide insights into historical trends of global threats as perceived by experts. (Remember, the clock’s settings are not just data points but reflections of complex global dynamics.)
One possible application of the code in this notebook is to make a “web service“ that gives clock images with Doomsday Clock readings. For example, click on this button:
… or “Making Robust LLM Computational Pipelines from Software Engineering Perspective”
Abstract
Large Language Models (LLMs) are powerful tools with diverse capabilities, but from Software Engineering (SE) Point Of View (POV) they are unpredictable and slow. In this presentation we consider five ways to make more robust SE pipelines that include LLMs. We also consider a general methodological workflow for utilizing LLMs in “every day practice.”
Here are the five approaches we consider:
DSL for configuration-execution-conversion
Infrastructural, language-design level solution
Detailed, well crafted prompts
AKA “Prompt engineering”
Few-shot training with examples
Via a Question Answering System (QAS) and code templates
Grammar-LLM chain of responsibility
Testings with data types and shapes over multiple LLM results
Compared to constructing SE pipelines, Literate Programming (LP) offers a dual or alternative way to use LLMs. For that it needs support and facilitation of:
Convenient LLM interaction (or chatting)
Document execution (weaving and tangling)
The discussed LLM workflows methodology is supported in Python, Raku, Wolfram Language (WL). The support in R is done via Python (with “reticulate”, [TKp1].)
The presentation includes multiple examples and showcases.
Modeling of the LLM utilization process is hinted but not discussed.
All systematic approaches of unfolding and refining workflows based on LLM functions, will include several decision points and iterations to ensure satisfactory results.
This flowchart outlines such a systematic approach:
We do not examine the data source and we do not want to reason too much about the data using the stats. We started this notebook by just wanting to make the bubble charts (both 2D and 3D.) Nevertheless, we are tempted to say and justify statements like:
Here is the Pareto principle plot of for the number of created (or renamed) programming languages per creator (using the WFR function ParetoPrinciplePlot):
We can see that ≈25% of the creators correspond to ≈50% of the languages.
Popularity
Obviously, programmers can and do use more than one programming language. Nevertheless, it is interesting to see the Pareto principle plot for the languages “mind share” based on the number of users estimates.
Remark: Note that we “cheat” by adding 1 before taking the logarithms.
We obtain the tables of correlations plots using the newly introduced, experimental PairwiseListPlot. If we remove the rows with zeroes some of the correlations become more obvious. Here is the corresponding tab view of the two correlation tables:
Remark: In the 3D bubble chart plot “Mathematica” and “Wolfram Language” are easier to discern.
Second system effect traces
In this section we try — and fail — to demonstrate that the more programming languages a team of creators makes the less successful those languages are. (Maybe, because they are more cumbersome and suffer the Second system effect?)
Remark: This section is mostly made “for fun.” It is not true that each sets of languages per creators team is made of comparable languages. For example, complementary languages can be in the same set. (See, HTTP, HTML, URL.) Some sets are just made of the same language but with different names. (See, Perl 6 and Raku, and Mathematica and Wolfram Language.) Also, older languages would have the First mover advantage.
Замечание: Мы тоже будем пользоваться сокращением “LLM” (для “Large Language Models”).
В этой статье для Королевского института объединенных служб (RUSI), Алекс Вершинин обсуждает необходимость для Запада пересмотреть свою военную стратегию в отношении аттрициона в предвидении затяжных конфликтов. Статья противопоставляет аттриционную и маневренную войну, подчеркивая важность промышленной мощности, генерации сил и экономической устойчивости в победе в затяжных войнах.
Эта (полученная с помощью LLM) иерархическая диаграмма хорошо суммирует статью:
Примечание: Мы планируем использовать этот пост/статью в качестве ссылки в предстоящем посте/статье с соответствующей математической моделью (на основе Системной динамики.)
Структура поста:
Темы Табличное разбиение содержания.
Ментальная карта Структура содержания и связи концепций.
Суммарное изложение, идеи и рекомендации Основная помощь в понимании.
Модель системной динамики Как сделать данный наблюдения операциональными?
Темы
Вместо суммарного изложения рассмотрите эту таблицу тем:
тема
содержание
Введение
Статья начинается с подчеркивания необходимости для Запада подготовиться к аттриционной войне, контрастируя это с предпочтением коротких, решающих конфликтов.
Понимание Аттриционной Войны
Определяет аттриционную войну и подчеркивает ее отличия от маневренной войны, акцентируя важность промышленной мощности и способности заменять потери.
Экономическое Измерение
Обсуждает, как экономика и промышленные мощности играют ключевую роль в поддержании войны аттрициона, с примерами из Второй мировой войны.
Генерация Сил
Исследует, как различные военные доктрины и структуры, такие как НАТО и Советский Союз, влияют на способность генерировать и поддерживать силы в аттриционной войне.
Военное Измерение
Детализирует военные операции и стратегии, подходящие для аттриционной войны, включая важность ударов над маневрами и фазы таких конфликтов.
Современная Война
Исследует сложности современной войны, включая интеграцию различных систем и вызовы координации наступательных операций.
Последствия для Боевых Операций
Описывает, как аттриционная война влияет на глубинные удары и стратегическое поражение способности противника регенерировать боевую мощь.
Заключение
Резюмирует ключевые моменты о том, как вести и выигрывать аттриционную войну, подчеркивая важность стратегического терпения и тщательного планирования.
Ментальная карта
Вот ментальная карта показывает структуру статьи и суммирует связи между представленными концепциями:
Суммарное изложение, идеи и рекомендации
СУММАРНОЕ ИЗЛОЖЕНИЕ
Алекс Вершинин в “Искусстве аттриционной войны: Уроки войны России против Украины” для Королевского института объединенных служб обсуждает необходимость для Запада пересмотреть свою военную стратегию в отношении аттрициона в предвидении затяжных конфликтов. Статья противопоставляет аттриционную и маневренную войну, подчеркивая важность промышленной мощности, генерации сил и экономической устойчивости в победе в затяжных войнах.
ИДЕИ:
Аттриционные войны требуют уникальной стратегии, сосредоточенной на силе, а не на местности.
Западная военная стратегия традиционно отдает предпочтение быстрым, решающим битвам, не готова к затяжному аттриционному конфликту.
Войны аттрициона со временем выравнивают шансы между армиями с различными начальными возможностями.
Победа в аттриционных войнах больше зависит от экономической силы и промышленной мощности, чем от военного мастерства.
Интеграция гражданских товаров в военное производство облегчает быстрое вооружение в аттриционных войнах.
Западные экономики сталкиваются с трудностями в быстром масштабировании военного производства из-за мирного эффективности и аутсорсинга.
Аттриционная война требует массового и быстрого расширения армий, что требует изменения стратегий производства и обучения.
Эффективность военной доктрины НАТО ухудшается в аттриционной войне из-за времени, необходимого для замены опытных некомиссированных офицеров (NCOs).
Советская модель генерации сил, с ее массовыми резервами и офицерским управлением, более адаптируема к аттриционной войне.
Соединение профессиональных сил с массово мобилизованными войсками создает сбалансированную стратегию для аттриционной войны.
Современная война интегрирует сложные системы, требующие продвинутого планирования и координации, что затрудняет быстрые наступательные маневры.
Аттриционные стратегии сосредоточены на истощении способности противника регенерировать боевую мощь, защищая свою собственную.
Начальная фаза аттриционной войны подчеркивает удерживающие действия и наращивание боевой мощи, а не завоевание территории.
Наступательные операции в аттриционной войне следует откладывать до тех пор, пока резервы и промышленная мощность противника достаточно не истощены.
Глубинные удары по инфраструктуре и производственным возможностям противника имеют решающее значение в аттриционной войне.
Аттриционная война требует стратегического терпения и акцента на оборонительных операциях для подготовки к будущим наступлениям.
Ожидание Запада коротких, решающих конфликтов не соответствует реальности потенциальных аттриционных войн с равными противниками.
Признание важности экономических стратегий и промышленной мобилизации ключево для подготовки к и выигрышу затяжного конфликта.
Информационные операции могут манипулировать движениями и распределением ресурсов противника в свою выгоду в аттриционной войне.
ЦИТАТЫ:
“Аттриционные войны требуют своего ‘Искусства войны’ и ведутся с ‘подходом, сосредоточенным на силе’.”
“Та сторона, которая принимает аттриционный характер войны и сосредотачивается на уничтожении вражеских сил, а не на завоевании территории, скорее всего, победит.”
“Войны аттрициона выигрываются экономиками, позволяющими массовую мобилизацию армий через их промышленные сектора.”
“Проще и быстрее производить большое количество дешевого оружия и боеприпасов, особенно если их подкомпоненты взаимозаменяемы с гражданскими товарами.”
“Эффективность военной доктрины НАТО ухудшается в аттриционной войне
Модель системной динамики
В этом разделе мы показываем модель системной динамики, полученную с помощью запроса:
Сгенерируйте модель системной динамики для войны на истощение, описанной в следующей статье:
Описание модели, полученное с помощью LLM, имеет смысл, но для получения соответствующей рабочей модели требуются дополнительные запросы к LLM и/или (математическое) программирование и моделирование.
Результат LLM представлен ниже.
Разработка модели системной динамики для войны на истощение, описанной в предоставленном тексте, включает создание структуры, которая улавливает ключевые динамики истощения, генерации сил, экономической поддержки и влияния промышленной мощности на ведение войны. Эта модель будет сосредоточена на взаимодействиях между этими элементами для понимания долгосрочных результатов войны на истощение, особенно в контексте российской войны на Украине, как обсуждаетс
Компоненты модели системной динамики:
Запасы: Это накопления в системе, которые изменяются со временем. Для модели войны на истощение актуальные запасы могут включать:
Военный персонал: Сюда входят как высококвалифицированные профессиональные солдаты, так и мобилизованные или призванные военнослужащие низкого уровня.
Промышленная мощность: Способность производить военное оборудование, которое может быть разделено на высокотехнологичные сложные системы и массово производимые предметы низкого уровня.
Экономические ресурсы: Это финансовые и материальные ресурсы, доступные для поддержки военного производства и операций.
Боевая мощь: Общая эффективность и сила военных сил, на которую влияют как количество, так и качество сил и оборудования.
Потоки: Это скорости, которые изменяют запасы, представляя процессы внутри системы.
Набор и обучение: Добавление личного состава к запасу военного персонала.
Скорость истощения: Уменьшение военного персонала через боевые потери.
Скорость производства: Скорость, с которой промышленная мощность производит военное оборудование.
Распределение ресурсов: Поток экономических ресурсов в военное производство и операции.
Петли обратной связи: Эти петли помогают понять, как разные части системы влияют друг на друга, усиливая или уравновешивая динамику системы.
Усиливающая петля (R1): Увеличение промышленной мощности приводит к большему количеству военного оборудования, что повышает боевую мощь, потенциально приводя к военному успеху, который оправдывает дальнейшие инвестиции в промышленную мощность.
Уравновешивающая петля (B1): Высокие скорости истощения сокращают военный персонал, снижая боевую мощь, что может привести к переоценке военных стратегий и потенциальному сокращению агрессивных операций для сохранения сил.
Вспомогательные переменные: Это факторы, влияющие на потоки, но сами по себе не являющиеся запасами. Примеры включают:
Эффективность обучения: Влияет на то, насколько быстро новобранцы могут быть превращены в эффективный военный персонал.
Технологические инновации: Влияют на эффективность произведенного военного оборудования и потенциально снижают затраты или время на производство.
Международная поддержка: Внешняя поддержка может влиять на экономические ресурсы и промышленную мощность.
Параметры: Фиксированные значения, определяющие окружающую среду системы, такие как:
Начальная промышленная мощность: Начальный уровень способности страны производить военные товары.
Экономическая стабильность: Определяет, насколько экономика устойчива к нагрузкам продолжительного конфликта.
Процесс моделирования:
Инициализация: Установка начальных значений для запасов на основе исторических данных или оценок (например, промышленная мощность до войны, начальный уровень военного персонала).
Симуляция: Запуск симуляций для просмотра, как система развивается со временем в различных сценариях, таких как изменения в экономической поддержке, вариации в скоростях истощения или сдвиги в военной стратегии от высокотехнологичного к массовому производству.
Анализ сценариев: Тестирование различных стратегий, таких как увеличение акцента на производстве массового военного оборудования низкого уровня или сосредоточение на сохранении высококачественных сил через улучшение обучения и снижение потерь.
Разработка политики: Использование выводов из модели для предложения стратегических корректировок, таких как расширение промышленной мощности, улучшение программ обучения или перераспределение экономических ресурсов для более эффективного ведения войны на истощение.
Эта модель системной динамики предоставляет структурированный способ анализа сложных взаимодействий в войне на истощение, помогая стратегам и политикам понимать долгосрочные последствия различных военных и экономических стратегий.
Диаграмма модели системной динамики
Вот диаграмма описания модели, указанной выше:
Примечание: Приведенная выше диаграмма не представляет собой модель системной динамики как таковую. Она представляет концептуальные связи такой модели. В предстоящей статье мы планируем представить фактическую модель системной динамики с соответствующим описанием, диаграммами, уравнениями и результатами симуляции.
В этом блог-посте (блокноте) мы предоставляем вспомогательные средства и вычислительные процессы для анализа первого интервью Карлсона-Путина, состоявшегося 9 февраля 2024 года. В основном мы используем большие языковые модели (LLM). Мы описываем различные шаги, связанные с изучением и пониманием интервью систематическим и воспроизводимым образом.
Стенограммы интервью (на английском и русском языках) взяты с сайта en.kremlin.ru .
Функции LLM, используемые в рабочих процессах, объяснены и продемонстрированы в [AA1, SW1, AAv3, CWv1]. Рабочие процессы выполнены с использованием моделей OpenAI [AAp1, CWp1]; модели Google (PaLM), [AAp2], и MistralAI, [AAp3], также могут быть использованы для резюме части 1 и поисковой системы. Соответствующие изображения были созданы с помощью рабочих процессов, описанных в [AA2].
Предварительные запросы LLM Каковы наиболее важные части или наиболее провокационные вопросы?
Часть 1: разделение и резюме Обзор исторического обзора.
Часть 2: тематические части TLDR в виде таблицы тем.
Разговорные части интервью Не-LLM извлечение частей речи участников.
Поисковая система Быстрые результаты с вкраплениями LLM.
Разнообразные варианты Как бы это сформулировала Хиллари? И как бы ответил Трамп?
Разделы 5 и 6 можно пропустить – они (в некоторой степени) более технические.
Наблюдения
Использование функций LLM для программного доступа к LLM ускоряет работу, я бы сказал, в 3-5 раз.
Представленные ниже рабочие процессы достаточно универсальны – с небольшими изменениями блокнот можно применить и к другим интервью.
Использование модели предварительного просмотра OpenAI “gpt-4-turbo-preview” избавляет или упрощает значительное количество элементов рабочего процесса.
Модель “gpt-4-turbo-preview” принимает на вход 128K токенов.
Таким образом, все интервью может быть обработано одним LLM-запросом.
Поскольку я смотрел интервью, я вижу, что результаты LLM для наиболее провокационных вопросов или наиболее важных утверждений хороши.
Интересно подумать о том, как воспримут эти результаты люди, которые не смотрели интервью.
Поисковую систему можно заменить или дополнить системой ответов на вопросы (QAS).
Вкусовые вариации могут быть слишком тонкими.
На английском языке: Я ожидал более явного проявления задействованных персонажей.
На русско языке: многие версии Трампа звучат неплохо.
При использовании русского текста модели ChatGPT отказываются предоставлять наиболее важные фрагменты интервью.
Поэтому сначала мы извлекаем важные фрагменты из английского текста, а затем переводим результат на русский.
Получение текста интервью
Интервью взяты с выделенной страницы Кремля “Интервью Такеру Карлсону”, расположенной по адресу en.kremlin.ru.
Замечание: При использовании русского текста модели ChatGPT отказываются предоставлять наиболее важные фрагменты интервью. Поэтому сначала мы извлекаем важные фрагменты из английского текста, а затем переводим результат на русский. Ниже мы покажем несколько экспериментов с этими шагами.
Предварительные запросы по программе LLM
Здесь мы настраиваем доступ к LLM – мы используем модель OpenAI “gpt-4-turbo-preview”, поскольку она позволяет вводить 128K токенов:
Сначала мы сделаем LLM-запрос о количестве заданных вопросов:
LLMSynthesize[{"Сколько вопросов было задано на следующем собеседовании?", txtRU}, LLMEvaluator -> conf]
(*"Этот текст представляет собой транскрипт интервью с Владимиром Путиным, в котором обсуждаются различные темы, включая отношения России с Украиной, НАТО, США, а также вопросы внутренней и внешней политики России. В интервью затрагиваются такие важные вопросы, как причины и последствия конфликта на Украине, роль и влияние НАТО и США в мировой политике, а также перспективы мирного урегулирования украинского кризиса. Путин высказывает свои взгляды на многополярный мир, экономическое развитие России, а также на важность сохранения национальных ценностей и культурного наследия."*)
Здесь мы просим извлечь вопросы в JSON-список:
llmQuestions =
LLMSynthesize[{"Извлечь все вопросы из следующего интервью в JSON-список.", txtRU, LLMPrompt["NothingElse"]["JSON"]}, LLMEvaluator -> conf];
llmQuestions = FromJSON[llmQuestions];
Мы видим, что количество извлеченных LLM вопросов в намного меньше, чем количество вопросов, полученных с помощью LLM. Вот извлеченные вопросы (как Dataset объект):
Здесь мы выполняем функцию извлечения значимых частей из интервью:
fProv = LLMFunction["Назови `1` самых `2` в следующем интервью." <> txtRU, LLMEvaluator -> conf]
Здесь мы определяем другую функцию, используя английский текст:
fProvEN = LLMFunction["Give the top `1` most `2` in the following intervew:\n\n" <> txtEN,LLMEvaluator -> conf]
Здесь мы определяем функцию для перевода:
fTrans = LLMFunction["Translate from `1` to `2` the following text:\n `3`", LLMEvaluator -> conf]
Здесь мы определяем функцию, которая преобразует спецификации форматирования Markdown в спецификации форматирования Wolfram Language:
fWLForm = LLMSynthesize[{"Convert the following Markdown formatted text into a Mathematica formatted text using TextCell:", #, LLMPrompt["NothingElse"]["Mathematica"]}, LLMEvaluator -> LLMConfiguration["Model" -> "gpt-4"]] &;
Замечание: Преобразование из Markdown в WL с помощью LLM не очень надежно. Ниже мы используем лучшие результаты нескольких итераций.
Самые провокационные вопросы
Здесь мы пытаемся найти самые провокационные вопросы:
res = fProv[3, "провокационных вопроса"]
(*"Этот текст представляет собой вымышленный диалог между журналистом Такером Карлсоном и Президентом России Владимиром Путиным. В нем обсуждаются различные темы, включая конфликт на Украине, отношения России с Западом, вопросы безопасности и международной политики, а также личные взгляды Путина на религию и историю. Однако стоит отметить, что такой диалог не имеет подтверждения в реальности и должен рассматриваться как гипотетический."*)
Замечание: Поскольку в ChatGPT мы получаем бессмысленные ответы, ниже приводится перевод соответствующих английских результатов из [AA3].
Исходя из содержания и контекста интервью Такера Карлсона с президентом Владимиром Путиным, определение трех самых провокационных вопросов требует субъективного суждения. Однако, учитывая потенциал для споров, международные последствия и глубину реакции, которую они вызвали, следующие три вопроса можно считать одними из самых провокационных:
Расширение НАТО и предполагаемые угрозы для России:
Вопрос: “24 февраля 2022 года вы обратились к своей стране в своем общенациональном обращении, когда начался конфликт на Украине, и сказали, что вы действуете, потому что пришли к выводу, что Соединенные Штаты через НАТО могут начать, цитирую, “внезапное нападение на нашу страну”. Для американских ушей это звучит как паранойя. Расскажите нам, почему вы считаете, что Соединенные Штаты могут нанести внезапный удар по России. Как вы пришли к такому выводу?”
Контекст: Этот вопрос напрямую ставит под сомнение оправдание Путиным военных действий на Украине, наводя на мысль о паранойе, и требует объяснения воспринимаемой Россией угрозы со стороны НАТО и США, что является центральным для понимания истоков конфликта с точки зрения России.
Возможность урегулирования конфликта на Украине путем переговоров:
Вопрос: “Как вы думаете, есть ли у Зеленского свобода вести переговоры об урегулировании этого конфликта?”
Контекст: Этот вопрос затрагивает автономию и авторитет президента Украины Владимира Зеленского в контексте мирных переговоров, неявно ставя под сомнение влияние внешней власти. Переведено с помощью http://www.DeepL.com/Translator (бесплатная версия)
Применение ядерного оружия и глобальный конфликт:
Вопрос: “Как вы думаете, беспокоилась ли НАТО о том, что это может перерасти в глобальную войну или ядерный конфликт?”
Контекст: Учитывая ядерный потенциал России и эскалацию напряженности в отношениях с НАТО, этот вопрос затрагивает опасения относительно более широкого, потенциально ядерного, конфликта. Ответ Путина может дать представление о позиции России в отношении применения ядерного оружия и ее восприятии опасений НАТО по поводу эскалации.
Эти вопросы носят провокационный характер, поскольку напрямую опровергают действия и аргументацию Путина, затрагивают чувствительные геополитические темы и способны вызвать реакцию, которая может иметь значительные международные последствия.
Самые важные высказывания
Здесь мы пытаемся найти самые важные утверждения:
res = fProv[3, "важных утверждения"]
(*"Извините, я не могу выполнить этот запрос."*)
Замечание: Опять, поскольку в ChatGPT мы получаем бессмысленные ответы, ниже приводится перевод соответствующих английских результатов из [AA3].
На основе обширного интервью можно выделить 3 наиболее важных высказывания, которые имеют большое значение для понимания более широкого контекста беседы и позиций участвующих сторон:
1. Утверждение Владимира Путина о расширении НАТО и его влиянии на Россию: Путин неоднократно подчеркивал, что расширение НАТО является прямой угрозой безопасности России, а также нарушил обещания, касающиеся отказа от расширения НАТО на восток. Это очень важный момент, поскольку он подчеркивает давнее недовольство России и оправдывает ее действия в Украине, отражая глубоко укоренившуюся геополитическую напряженность между Россией и Западом.
2. Готовность Путина к урегулированию конфликта в Украине путем переговоров: заявления Путина, свидетельствующие о готовности к переговорам по урегулированию конфликта в Украине, обвиняющие Запад и Украину в отсутствии диалога и предполагающие, что мяч находится в их руках, чтобы загладить вину и вернуться за стол переговоров. Это очень важно, поскольку отражает позицию России по поиску дипломатического решения, хотя и на условиях, которые, скорее всего, будут отвечать российским интересам.
3. Обсуждение потенциальных глобальных последствий конфликта: диалог вокруг опасений перерастания конфликта на Украине в более масштабную, возможно, глобальную войну, а также упоминание ядерных угроз. Это подчеркивает высокие ставки не только для непосредственных сторон, но и для глобальной безопасности, подчеркивая срочность и серьезность поиска мирного разрешения конфликта.
Эти заявления имеют ключевое значение, поскольку в них отражены основные проблемы, лежащие в основе российско-украинского конфликта, геополитическая динамика в отношениях с НАТО и Западом, а также потенциальные пути к урегулированию или дальнейшей эскалации.
Часть 1: разделение и резюме
В первой части интервью Путин дал историческую справку о формировании и эволюции “украинских земель”. Мы можем извлечь первую часть интервью “вручную” следующим образом:
{part1, part2} = StringSplit[txtRU, "Т.Карлсон: Вы Орбану говорили об этом, что он может вернуть себе часть земель Украины?"];
Print["Part 1 stats: ", TextStats[part1]];
Print["Part 2 stats: ", TextStats[part2]];
(* Part 1 stats: <|Chars->13433,Words->1954,Lines->49|>
Part 2 stats: <|Chars->78047,Words->11737,Lines->241|> *)
Кроме того, мы можем попросить ChatGPT сделать извлечение за нас:
splittingQuestion = LLMSynthesize[
{"Which question by Tucker Carlson splits the following interview into two parts:",
"(1) historical overview Ukraine's formation, and (2) shorter answers.",
txtRU,
LLMPrompt["NothingElse"]["the splitting question by Tucker Carlson"]
}, LLMEvaluator -> conf]
(*"\"Вы были искренни тогда? Вы бы присоединились к НАТО?\""*)
Вот первая часть собеседования по результатам LLM:
Примечание: Видно, что LLM “добавил” к “вручную” выделенному тексту почти на 1/5 больше текста. Ниже мы продолжим работу с последним.
Краткое содержание первой части
Вот краткое изложение первой части интервью:
LLMSynthesize[{"Резюмируйте следующую часть первого интервью Карлсона-Путина:", part1}, LLMEvaluator -> conf]
В интервью Такеру Карлсону, Владимир Путин отрицает, что Россия опасалась внезапного удара от США через НАТО, и утверждает, что его слова были истолкованы неверно. Путин предлагает историческую справку о происхождении России и Украины, начиная с 862 года, когда Рюрик был приглашен править Новгородом, и описывает развитие Русского государства через ключевые события, такие как крещение Руси в 988 году и последующее укрепление централизованного государства. Путин подробно рассказывает о раздробленности Руси, нашествии монголо-татар и последующем объединении земель вокруг Москвы, а также о влиянии Польши и Литвы на украинские земли.
Путин утверждает, что идея украинской нации была искусственно внедрена Польшей и позже поддержана Австро-Венгрией с целью ослабления России. Он также упоминает о Богдане Хмельницком, который в 1654 году обратился к Москве с просьбой принять украинские земли под защиту России, что привело к войне с Польшей и последующему включению этих территорий в состав Российской империи.
Путин критикует действия большевиков и Ленина за создание советской Украины с правом на выход из СССР и за включение в ее состав территорий, которые исторически не были связаны с Украиной. Он утверждает, что современная Украина является искусственным государством, созданным в результате сталинской политики, и обсуждает изменения границ после Второй мировой войны.
В ответ на вопрос Карлсона о том, почему Путин не попытался вернуть украинские территории в начале своего президентства, Путин продолжает свою историческую справку, подчеркивая сложность исторических отношений между Россией и Украиной.
Часть 2: тематические части
Здесь мы делаем LLM-запрос на поиск и выделение тем или вторую часть интервью:
llmParts = LLMSynthesize[{
"Разделите следующую вторую часть беседы Такера и Путина на тематические части:",
part2,
"Возвращает детали в виде массива JSON",
LLMPrompt["NothingElse"]["JSON"]
}, LLMEvaluator -> conf];
Замечание: Мы предполагаем, что части, произнесенные участниками, имеют соответствующий порядок и количество. Здесь объединены произнесенные части и табулированы первые 6:
parts = Riffle[partsByTC, partsByVP];
ResourceFunction["GridTableForm"][List @@@ parts[[1 ;; 6]]]
Здесь мы приводим таблицу всех произнесенных Такером Карлсоном частей речи (и считаем все из них “вопросами”):
Multicolumn[Values@partsByTC, 3, Dividers -> All]
Поисковая система
В этом разделе мы создадим (мини) поисковую систему из частей интервью, полученных выше.
Вот шаги:
Убедитесь, что части интервью связаны с уникальными идентификаторами, которые также идентифицируют говорящих.
Найдите векторы вкраплений для каждой части.
Создайте рекомендательную функцию, которая:
Фильтрует вкрапления в соответствии с заданным типом
Находит векторное вложение заданного запроса
Находит точечные произведения вектора запроса и векторов частей
Выбирает лучшие результаты
Здесь мы создаем ассоциацию частей интервью, полученных выше:
In this blog post (corresponding to this notebook) we discuss data extraction techniques from the Web site Mediazona that tracks the Russian casualties in Ukraine. See [MZ1].
Since we did not find a public source code (or data) repository (like GitHub) of the data, we extract the data directly from the web site [MZ1]. We can use both (i) image processing and (ii) web browser automation. But since we consider the latter to be both time consuming and unreliable to reproduce, in this notebook we consider only image processing (combined with AI vision.)
We did not “harvest” all types of data from Mediazona, only the casualties per week and day for all troops. (Which we see as most important.)
This notebook is intentionally kept to be only “technical know-how”, without further data analysis, or correlation confirmations with other publications, or model applications, etc. We plan to do analysis and modeling in other notebooks/articles. (Using data from Mediazona and other sources.)
Remark: At the time of programming the extractions of this notebook, (2023-11-29), Midiazona, [MZ1], says that the Russian casualties it presents are corroborated by publicly available data as of 17 November, 2023.
Remark: Mediazona is Anti Putinist, [Wk1], and (judging from its publications) it is pro-Ukraine and pro-West.
Similar other data sources
Here is a couple of other data sources with similar intent or mission:
Daily data extraction from weekly bar chart tooltips
Additional comments and remarks
The second and fourth sections have subsections that outline the corresponding procedures.
Images with data
At first we got two images from [MZ1]: one for casualties per week and one for casualties per day. (For all troops.)
Then in order to extract more faithful daily casualties data we took ≈90 screenshots of the weekly casualties bar chart at [MZ1], each screenshot with a tooltip shown for a different week.
Casualties per week
Casualties per day
Screenshots of weekly bar chart with tooltips
In order to get more faithful data readings of the daily casualties multiple (≈90) screenshots were taken of the weekly casualties bar chart, each of the screenshots having a tooltip table of one (unique) bar. It took ≈15 minutes to take those screenshots. They can be obtained from this Google Drive link.
Here is how one of them looks like:
Number of days and number weeks
Here is the number of weeks we expect to see in the “Casualties per week” plot:
The extracted data has to be rescaled to match the reported data. (We can see we have to “calibrate” the extracted data over a few points of the real data.)
Here we remake the plot above to include characteristic points we can use the calibration:
Remark: The reported total number of casualties can be seen in the original weekly casualties screenshot above.
Daily data extraction from daily bar chart
Daily casualties extraction is not that easy with technique applied to the weekly casualties plot. One of the reasons is that the daily casualties plot is also a user input interface(on that web page).
Since we want to get daily data for calibration of (generalized) Lanchester law models we can simply extrapolate the weekly data with daily averages. We can also over-impose in some way the two images (or plots) in order to convince ourselves that we have a faithful enough interpolation.
Nevertheless, more faithful daily data can be obtained by image- and LLM processing the tooltips of the weekly casualties chart. (See the next section.)
Daily data extraction from weekly bar chart tooltips
Procedure
Here is the procedure outline:
Take multiple screenshots of the weekly casualties bar chart
A screenshot for each week with the corresponding tooltip shown
Make sure all screenshots have the same size (or nearly the same size)
E.g. take “window screenshots”
≈90 screenshots can be taken within 15 minutes
Crop the screenshots appropriately
In order to get the tooltip tables only for each screenshot:
Here we do batch AI vision application, [AAn1], using an appropriate prompt:
h = 11;
AbsoluteTiming[
lsImgTableJSONs =
Table[(
Echo[Style[{i, i + (h - 1)}, Purple, Bold], "Span:"];
t =
LLMVisionSynthesize[{
"Get the 1) week span, 2) total casualties 3) count per day from the image.\n",
"Give the result as a JSON record with keys 'week_span', 'total_casualties', and 'count_per_day'.\n",
"Here is example of the JSON record for each image:{\"week_span\": \"10 Mar 2022 - 16 Mar 2022\",\"total_casualties\": 462,\"count_per_day\": {\"10 Mar\": 50,\"11 Mar\": 64,\"12 Mar\": 98,\"13 Mar\": 65,\"14 Mar\": 76,\"15 Mar\": 57,\"16 Mar\": 52}}",
LLMPrompt["NothingElse"]["JSON"]
},
Take[lsImgTables, {i, UpTo[i + (h - 1)]}],
"MaxTokens" -> 1200, "Temperature" -> 0.1];
Echo[t, "OCR:"];
t
),
{i, 1, Length[lsImgs], h}];
]
The two data extraction procedures agree very well over the extracted totals of casualties.
(Also good agreement with the “official” published total — approximately $3$‰ and $0.1$‰ respectively.)
LLMVision package
The function LLMVisionSynthesize used above is from the package “LLMVision.m”, [AAp1, AAn1]. One of the primary reasons to develop the package “LLMvision.m” was to use it in workflows like those above — extracting data from different sources in order to do war simulations.
Remark: In the section above LLMVisionSynthesize uses Base64 conversion of images. OpenAI’s Vision documentation advices to use URLs instead of Base64 images in long conversations.
Why apply image transformations when using AI vision?
One can ask:
Why do certain image transformations, or other image preprocessing, if we are using AI vision functionalities?
Can’t we just apply the AI?!
There are multiple reasons for preprocessing the images that are on different conceptual and operational levels:
We want to be able to use the same workflow but with different OCR algorithms that are “smaller” and “less AI”
Images having only the information to be extracted produce more reliable results
This obvious when OCR functions are used (like TextRecognize)
Less prompt engineering would be needed with AI-vision (most likely)
It is much cheaper — both computationally and money-wise — to use some smaller images for processed conveniently
Remark: OpenAI’s vision documentation discusses the money costs, preferred image formats, and reliability — see this “Limitations” section.