From 83c16de74b7d190519f20dd0587226cfc29b49c7 Mon Sep 17 00:00:00 2001 From: Duane Milne Date: Wed, 18 Jun 2025 07:44:20 -0400 Subject: [PATCH 01/10] Add Polya prompting --- dialoghelper/_modidx.py | 19 +++- dialoghelper/polya.py | 101 +++++++++++++++++ nbs/01_polya.ipynb | 241 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 360 insertions(+), 1 deletion(-) create mode 100644 dialoghelper/polya.py create mode 100644 nbs/01_polya.ipynb diff --git a/dialoghelper/_modidx.py b/dialoghelper/_modidx.py index 9b351d1..1725f43 100644 --- a/dialoghelper/_modidx.py +++ b/dialoghelper/_modidx.py @@ -24,4 +24,21 @@ 'dialoghelper.core.read_msg': ('core.html#read_msg', 'dialoghelper/core.py'), 'dialoghelper.core.read_msg_ids': ('core.html#read_msg_ids', 'dialoghelper/core.py'), 'dialoghelper.core.update_msg': ('core.html#update_msg', 'dialoghelper/core.py')}, - 'dialoghelper.db_dc': {}}} + 'dialoghelper.db_dc': {}, + 'dialoghelper.polya': { 'dialoghelper.polya.PolyaAct': ('polya.html#polyaact', 'dialoghelper/polya.py'), + 'dialoghelper.polya.PolyaAct.__init__': ('polya.html#polyaact.__init__', 'dialoghelper/polya.py'), + 'dialoghelper.polya.PolyaPlan': ('polya.html#polyaplan', 'dialoghelper/polya.py'), + 'dialoghelper.polya.PolyaPlan.__init__': ('polya.html#polyaplan.__init__', 'dialoghelper/polya.py'), + 'dialoghelper.polya.PolyaReview': ('polya.html#polyareview', 'dialoghelper/polya.py'), + 'dialoghelper.polya.PolyaReview.__init__': ('polya.html#polyareview.__init__', 'dialoghelper/polya.py'), + 'dialoghelper.polya.PolyaUnderstand': ('polya.html#polyaunderstand', 'dialoghelper/polya.py'), + 'dialoghelper.polya.PolyaUnderstand.__init__': ( 'polya.html#polyaunderstand.__init__', + 'dialoghelper/polya.py'), + 'dialoghelper.polya.QQ': ('polya.html#qq', 'dialoghelper/polya.py'), + 'dialoghelper.polya.QQ.__call__': ('polya.html#qq.__call__', 'dialoghelper/polya.py'), + 'dialoghelper.polya.QQ.__init__': ('polya.html#qq.__init__', 'dialoghelper/polya.py'), + 'dialoghelper.polya.QQ.__repr__': ('polya.html#qq.__repr__', 'dialoghelper/polya.py'), + 'dialoghelper.polya.Step': ('polya.html#step', 'dialoghelper/polya.py'), + 'dialoghelper.polya.Step.__iter__': ('polya.html#step.__iter__', 'dialoghelper/polya.py'), + 'dialoghelper.polya.Step.__repr__': ('polya.html#step.__repr__', 'dialoghelper/polya.py'), + 'dialoghelper.polya.Step._children': ('polya.html#step._children', 'dialoghelper/polya.py')}}} diff --git a/dialoghelper/polya.py b/dialoghelper/polya.py new file mode 100644 index 0000000..82b07de --- /dev/null +++ b/dialoghelper/polya.py @@ -0,0 +1,101 @@ +"""Implement Polya questions as SolveIt prompt messages""" + +# AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/01_polya.ipynb. + +# %% auto 0 +__all__ = ['understand', 'plan', 'act', 'review', 'Step', 'QQ', 'PolyaUnderstand', 'PolyaPlan', 'PolyaAct', 'PolyaReview'] + +# %% ../nbs/01_polya.ipynb +from .core import * + +# %% ../nbs/01_polya.ipynb +# Step: inspired by contextpack.Topic +class Step: + def _children(self): + return sorted(list(set(c for c in dir(self) if not c.startswith('_')) - {'get','getter','docs'})) + def __iter__(self): + yield from (getattr(self, name) for name in self._children() + if isinstance(getattr(self, name),QQ)) + def __repr__(self): + s = '' + if self.__doc__: s += f"doc: {self.__doc__}\n" + if (cs := self._children()): s += f"question: {cs}\n" + return s + +# QQ replaces the SolveIt cell with its given question/prompt/note +class QQ: + def __init__(self, content, msg_type="prompt"): + self.content = content + self.msg_type = msg_type + + def __call__(self): + add_msg(content=self.content, msg_type=self.msg_type, sid=read_msg(0).sid) + + def __repr__(self): + f"{self.msg_type}: \"{self.content}\"" + + +# %% ../nbs/01_polya.ipynb +class PolyaUnderstand(Step): + def __init__(self): + self.summary = QQ("Could you please give a concise summary of the problem?") + self.info = QQ("What information do we have? What information do we not have? What might change as we learn more?") + self.similar = QQ("Have you seen a similar problem before?") + self.lateral = QQ("Can you relate this problem to a more general or a more specific problem?") + self.related = QQ("Can you think of a related problem that we can solve? It could even be a simpler one we could solve first to help understand this one.") + self.viz = QQ("Can we create a figure or diagram to represent of the problem?") + self.notation = QQ("Can we pick a suitable notation (e.g. symbols for quantities/data, states, and transitions)?") + self.simplest = QQ("What might be the simplest way to look at this problem?") + self.simplify = QQ("Can we separate the various parts of the problem (e.g. break down complex conditions into simpler ones)?") + + +# %% ../nbs/01_polya.ipynb +class PolyaPlan(Step): + def __init__(self): + self.chunks = QQ("Could you please break down the problem into smaller sub-problems?") + self.partial = QQ("Is there a smaller part or representation of the problem we could solve?") + self.known_approach = QQ("Could we use a known algorithm or library to solve the problem, or some of it?") + self.verifiable = QQ("How would we verify if our solution is consistent and correct?") + self.backward = QQ("Can we work backward from the desired result?") + self.aux = QQ("Could we use an auxiliary element (e.g., a variable, diagram, or example) to clarify the path?") + self.analogy = QQ("Can you use analogy or similarity to relate the problem to a known solution?") + + + + + +# %% ../nbs/01_polya.ipynb +class PolyaAct(Step): + def __init__(self): + self.review = QQ("Could you please critique the plan of attack? Be frank, do not be afraid to be critical.") + self.doubt = QQ("Are we using the right approach?") + self.other = QQ("Is there another way to look at this?") + self.partial = QQ("Are there any intermediate results or milestones that we can aim for?") + self.symmetry = QQ("Are there any symmetries or patterns in the problem that we can exploit?") + self.next = QQ("What is next?") + self.valid = QQ("Does this step seem to have been a valid step?") + self.check = QQ("Does this step seem correct?") + self.simpler = QQ("Was there a simpler way we could have done this step?") + self.all = QQ("Did we cover all of the data or examples for this step?") + + +# %% ../nbs/01_polya.ipynb +class PolyaReview(Step): + def __init__(self): + self.all = QQ("Did we cover all of the data or examples for this problem?") + self.sanity = QQ("Does the result make sense? Can we verify by substition or another method?") + self.grok = QQ("**To consider:** Can I understand the solution without having to perform all the steps?", "note") + self.learned = QQ("What lessons have I learned from this?") + self.general = QQ("Can we generalize the solution to other similar problems?") + self.alter = QQ("Can you think of alternative solutions or approaches that might be more efficient or effective?") + self.other = QQ("Can we derive the result differently?") + self.simpler = QQ("Can we derive the result in a simpler way?") + self.principles = QQ("Can you identify any underlying principles or patterns that emerged during the solution process?") + self.test = QQ("What are some different ways we can test this?") + + +# %% ../nbs/01_polya.ipynb +understand = PolyaUnderstand() +plan = PolyaPlan() +act = PolyaAct() +review = PolyaReview() diff --git a/nbs/01_polya.ipynb b/nbs/01_polya.ipynb new file mode 100644 index 0000000..351a42b --- /dev/null +++ b/nbs/01_polya.ipynb @@ -0,0 +1,241 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "#| default_exp polya" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# dialoghelper.polya\n", + "> Implement Polya questions as SolveIt prompt messages\n", + "> - each function will replace the code cell with a prompt cell\n", + "> - the user then can click the cell header and click \"Submit\" to ask SolveIt\n", + "\n", + "Example usage:\n", + "```python\n", + "# In SolveIt...\n", + "\n", + "# Cell 1\n", + "\n", + "import dialoghelper.polya as dhp\n", + "\n", + "# Cell 2\n", + "dhp.understand.summary()\n", + "\n", + "# Cell 3\n", + "dhp.plan.chunks()\n", + "\n", + "# Cell 4\n", + "dhp.act.next()\n", + "\n", + "# Cell 5\n", + "dhp.review.learned()\n", + "\n", + "# Cell 6\n", + "dhp.review.improve()\n", + "\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "from dialoghelper.core import *" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "\n", + "# Step: inspired by contextpack.Topic\n", + "class Step:\n", + " def _children(self):\n", + " return sorted(list(set(c for c in dir(self) if not c.startswith('_')) - {'get','getter','docs'}))\n", + " def __iter__(self): \n", + " yield from (getattr(self, name) for name in self._children() \n", + " if isinstance(getattr(self, name),QQ))\n", + " def __repr__(self):\n", + " s = ''\n", + " if self.__doc__: s += f\"doc: {self.__doc__}\\n\"\n", + " if (cs := self._children()): s += f\"question: {cs}\\n\" \n", + " return s\n", + "\n", + "# QQ replaces the SolveIt cell with its given question/prompt/note\n", + "class QQ:\n", + " def __init__(self, content, msg_type=\"prompt\"):\n", + " self.content = content\n", + " self.msg_type = msg_type\n", + "\n", + " def __call__(self):\n", + " add_msg(content=self.content, msg_type=self.msg_type, sid=read_msg(0).sid)\n", + "\n", + " def __repr__(self):\n", + " f\"{self.msg_type}: \\\"{self.content}\\\"\"\n" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "\n", + "class PolyaUnderstand(Step):\n", + " def __init__(self):\n", + " self.summary = QQ(\"Could you please give a concise summary of the problem?\")\n", + " self.info = QQ(\"What information do we have? What information do we not have? What might change as we learn more?\")\n", + " self.similar = QQ(\"Have you seen a similar problem before?\")\n", + " self.lateral = QQ(\"Can you relate this problem to a more general or a more specific problem?\")\n", + " self.related = QQ(\"Can you think of a related problem that we can solve? It could even be a simpler one we could solve first to help understand this one.\")\n", + " self.viz = QQ(\"Can we create a figure or diagram to represent of the problem?\")\n", + " self.notation = QQ(\"Can we pick a suitable notation (e.g. symbols for quantities/data, states, and transitions)?\") \n", + " self.simplest = QQ(\"What might be the simplest way to look at this problem?\") \n", + " self.simplify = QQ(\"Can we separate the various parts of the problem (e.g. break down complex conditions into simpler ones)?\")\n", + " " + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "\n", + "class PolyaPlan(Step):\n", + " def __init__(self):\n", + " self.chunks = QQ(\"Could you please break down the problem into smaller sub-problems?\")\n", + " self.partial = QQ(\"Is there a smaller part or representation of the problem we could solve?\")\n", + " self.known_approach = QQ(\"Could we use a known algorithm or library to solve the problem, or some of it?\")\n", + " self.verifiable = QQ(\"How would we verify if our solution is consistent and correct?\")\n", + " self.backward = QQ(\"Can we work backward from the desired result?\")\n", + " self.aux = QQ(\"Could we use an auxiliary element (e.g., a variable, diagram, or example) to clarify the path?\")\n", + " self.analogy = QQ(\"Can you use analogy or similarity to relate the problem to a known solution?\")\n", + "\n", + "\n", + " \n" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "\n", + "class PolyaAct(Step):\n", + " def __init__(self):\n", + " self.review = QQ(\"Could you please critique the plan of attack? Be frank, do not be afraid to be critical.\")\n", + " self.doubt = QQ(\"Are we using the right approach?\")\n", + " self.other = QQ(\"Is there another way to look at this?\")\n", + " self.partial = QQ(\"Are there any intermediate results or milestones that we can aim for?\")\n", + " self.symmetry = QQ(\"Are there any symmetries or patterns in the problem that we can exploit?\")\n", + " self.next = QQ(\"What is next?\")\n", + " self.valid = QQ(\"Does this step seem to have been a valid step?\")\n", + " self.check = QQ(\"Does this step seem correct?\")\n", + " self.simpler = QQ(\"Was there a simpler way we could have done this step?\")\n", + " self.all = QQ(\"Did we cover all of the data or examples for this step?\") \n", + " " + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "\n", + "class PolyaReview(Step):\n", + " def __init__(self):\n", + " self.all = QQ(\"Did we cover all of the data or examples for this problem?\")\n", + " self.sanity = QQ(\"Does the result make sense? Can we verify by substition or another method?\")\n", + " self.grok = QQ(\"**To consider:** Can I understand the solution without having to perform all the steps?\", \"note\")\n", + " self.learned = QQ(\"What lessons have I learned from this?\")\n", + " self.general = QQ(\"Can we generalize the solution to other similar problems?\")\n", + " self.alter = QQ(\"Can you think of alternative solutions or approaches that might be more efficient or effective?\")\n", + " self.other = QQ(\"Can we derive the result differently?\")\n", + " self.simpler = QQ(\"Can we derive the result in a simpler way?\")\n", + " self.principles = QQ(\"Can you identify any underlying principles or patterns that emerged during the solution process?\")\n", + " self.test = QQ(\"What are some different ways we can test this?\")\n" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "\n", + "understand = PolyaUnderstand()\n", + "plan = PolyaPlan()\n", + "act = PolyaAct()\n", + "review = PolyaReview()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## export -" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [], + "source": [ + "#|hide\n", + "from nbdev import nbdev_export\n", + "nbdev_export()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.7" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} From 8aadf9736839733788aca0dbce3bb98eea28e77c Mon Sep 17 00:00:00 2001 From: Duane Milne Date: Wed, 18 Jun 2025 07:52:37 -0400 Subject: [PATCH 02/10] Use update_msg to replace current message --- dialoghelper/polya.py | 2 +- nbs/01_polya.ipynb | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/dialoghelper/polya.py b/dialoghelper/polya.py index 82b07de..9d5073a 100644 --- a/dialoghelper/polya.py +++ b/dialoghelper/polya.py @@ -29,7 +29,7 @@ def __init__(self, content, msg_type="prompt"): self.msg_type = msg_type def __call__(self): - add_msg(content=self.content, msg_type=self.msg_type, sid=read_msg(0).sid) + update_msg(content=self.content, msg_type=self.msg_type, sid=read_msg(0).sid) def __repr__(self): f"{self.msg_type}: \"{self.content}\"" diff --git a/nbs/01_polya.ipynb b/nbs/01_polya.ipynb index 351a42b..204e69d 100644 --- a/nbs/01_polya.ipynb +++ b/nbs/01_polya.ipynb @@ -82,7 +82,7 @@ " self.msg_type = msg_type\n", "\n", " def __call__(self):\n", - " add_msg(content=self.content, msg_type=self.msg_type, sid=read_msg(0).sid)\n", + " update_msg(content=self.content, msg_type=self.msg_type, sid=read_msg(0).sid)\n", "\n", " def __repr__(self):\n", " f\"{self.msg_type}: \\\"{self.content}\\\"\"\n" @@ -200,7 +200,7 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 9, "metadata": {}, "outputs": [], "source": [ From d2a94d4d481a3ab1b423fd5cde1608760b9fe827 Mon Sep 17 00:00:00 2001 From: Duane Milne Date: Wed, 18 Jun 2025 08:02:46 -0400 Subject: [PATCH 03/10] Update 'last message' --- dialoghelper/polya.py | 2 +- nbs/01_polya.ipynb | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/dialoghelper/polya.py b/dialoghelper/polya.py index 9d5073a..5964b57 100644 --- a/dialoghelper/polya.py +++ b/dialoghelper/polya.py @@ -29,7 +29,7 @@ def __init__(self, content, msg_type="prompt"): self.msg_type = msg_type def __call__(self): - update_msg(content=self.content, msg_type=self.msg_type, sid=read_msg(0).sid) + update_msg(content=self.content, msg_type=self.msg_type, sid=read_msg(-1).sid) def __repr__(self): f"{self.msg_type}: \"{self.content}\"" diff --git a/nbs/01_polya.ipynb b/nbs/01_polya.ipynb index 204e69d..6d96968 100644 --- a/nbs/01_polya.ipynb +++ b/nbs/01_polya.ipynb @@ -56,7 +56,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 10, "metadata": {}, "outputs": [], "source": [ @@ -82,7 +82,7 @@ " self.msg_type = msg_type\n", "\n", " def __call__(self):\n", - " update_msg(content=self.content, msg_type=self.msg_type, sid=read_msg(0).sid)\n", + " update_msg(content=self.content, msg_type=self.msg_type, sid=read_msg(-1).sid)\n", "\n", " def __repr__(self):\n", " f\"{self.msg_type}: \\\"{self.content}\\\"\"\n" From 8dcd31c66ac43099d3d066a82a85dfcc4ff98b51 Mon Sep 17 00:00:00 2001 From: Duane Milne Date: Thu, 19 Jun 2025 05:12:32 -0400 Subject: [PATCH 04/10] Use selectone in read_msg --- dialoghelper/core.py | 2 +- nbs/00_core.ipynb | 16 ++++++++++++++-- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/dialoghelper/core.py b/dialoghelper/core.py index 43bc495..57cb7b7 100644 --- a/dialoghelper/core.py +++ b/dialoghelper/core.py @@ -92,7 +92,7 @@ def read_msg(n:int=-1, # Message index (if relative, +ve is downwards) if not 0<=idx Date: Thu, 19 Jun 2025 05:20:54 -0400 Subject: [PATCH 05/10] Restore msg logic --- dialoghelper/polya.py | 2 +- nbs/01_polya.ipynb | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/dialoghelper/polya.py b/dialoghelper/polya.py index 5964b57..9d5073a 100644 --- a/dialoghelper/polya.py +++ b/dialoghelper/polya.py @@ -29,7 +29,7 @@ def __init__(self, content, msg_type="prompt"): self.msg_type = msg_type def __call__(self): - update_msg(content=self.content, msg_type=self.msg_type, sid=read_msg(-1).sid) + update_msg(content=self.content, msg_type=self.msg_type, sid=read_msg(0).sid) def __repr__(self): f"{self.msg_type}: \"{self.content}\"" diff --git a/nbs/01_polya.ipynb b/nbs/01_polya.ipynb index 6d96968..e6acf47 100644 --- a/nbs/01_polya.ipynb +++ b/nbs/01_polya.ipynb @@ -16,7 +16,7 @@ "# dialoghelper.polya\n", "> Implement Polya questions as SolveIt prompt messages\n", "> - each function will replace the code cell with a prompt cell\n", - "> - the user then can click the cell header and click \"Submit\" to ask SolveIt\n", + "> - the user then can click the cell header, edit if desired, and click \"Submit\" to ask SolveIt\n", "\n", "Example usage:\n", "```python\n", @@ -56,7 +56,7 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 3, "metadata": {}, "outputs": [], "source": [ @@ -82,7 +82,7 @@ " self.msg_type = msg_type\n", "\n", " def __call__(self):\n", - " update_msg(content=self.content, msg_type=self.msg_type, sid=read_msg(-1).sid)\n", + " update_msg(content=self.content, msg_type=self.msg_type, sid=read_msg(0).sid)\n", "\n", " def __repr__(self):\n", " f\"{self.msg_type}: \\\"{self.content}\\\"\"\n" From 3946292b3b4ff7d5082cf054899994b4d13024c4 Mon Sep 17 00:00:00 2001 From: Duane Milne Date: Thu, 19 Jun 2025 06:02:40 -0400 Subject: [PATCH 06/10] Clarify that note cells could be created too --- nbs/01_polya.ipynb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nbs/01_polya.ipynb b/nbs/01_polya.ipynb index e6acf47..ffd6370 100644 --- a/nbs/01_polya.ipynb +++ b/nbs/01_polya.ipynb @@ -15,7 +15,7 @@ "source": [ "# dialoghelper.polya\n", "> Implement Polya questions as SolveIt prompt messages\n", - "> - each function will replace the code cell with a prompt cell\n", + "> - each function will replace the code cell with a prompt cell (or sometimes a note cell)\n", "> - the user then can click the cell header, edit if desired, and click \"Submit\" to ask SolveIt\n", "\n", "Example usage:\n", From 4cadadc7f8c2eaf8bd8d6ef784868f51dd7eafa2 Mon Sep 17 00:00:00 2001 From: Duane Milne Date: Fri, 20 Jun 2025 05:07:09 -0400 Subject: [PATCH 07/10] Fix repr Questions/Prompt texts were not showing in SolveIt due to __repr__ returning None --- dialoghelper/polya.py | 2 +- nbs/01_polya.ipynb | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/dialoghelper/polya.py b/dialoghelper/polya.py index 9d5073a..f63a5b8 100644 --- a/dialoghelper/polya.py +++ b/dialoghelper/polya.py @@ -32,7 +32,7 @@ def __call__(self): update_msg(content=self.content, msg_type=self.msg_type, sid=read_msg(0).sid) def __repr__(self): - f"{self.msg_type}: \"{self.content}\"" + return f"{self.msg_type}: \"{self.content}\"" # %% ../nbs/01_polya.ipynb diff --git a/nbs/01_polya.ipynb b/nbs/01_polya.ipynb index ffd6370..771f3f1 100644 --- a/nbs/01_polya.ipynb +++ b/nbs/01_polya.ipynb @@ -85,7 +85,7 @@ " update_msg(content=self.content, msg_type=self.msg_type, sid=read_msg(0).sid)\n", "\n", " def __repr__(self):\n", - " f\"{self.msg_type}: \\\"{self.content}\\\"\"\n" + " return f\"{self.msg_type}: \\\"{self.content}\\\"\"\n" ] }, { @@ -200,7 +200,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 11, "metadata": {}, "outputs": [], "source": [ From f3d6990f121f791ff95a98792910c0d5f840bb91 Mon Sep 17 00:00:00 2001 From: Duane Milne Date: Fri, 20 Jun 2025 06:10:15 -0400 Subject: [PATCH 08/10] Improve repr of steps --- dialoghelper/polya.py | 11 ++-- nbs/01_polya.ipynb | 131 +++++++++++++++++++++++++++++++++++++++--- 2 files changed, 126 insertions(+), 16 deletions(-) diff --git a/dialoghelper/polya.py b/dialoghelper/polya.py index f63a5b8..edb61dd 100644 --- a/dialoghelper/polya.py +++ b/dialoghelper/polya.py @@ -12,14 +12,14 @@ # Step: inspired by contextpack.Topic class Step: def _children(self): - return sorted(list(set(c for c in dir(self) if not c.startswith('_')) - {'get','getter','docs'})) + return [c for c in dir(self) if not c.startswith('_') or c in ('get','getter','docs')] def __iter__(self): yield from (getattr(self, name) for name in self._children() if isinstance(getattr(self, name),QQ)) def __repr__(self): s = '' if self.__doc__: s += f"doc: {self.__doc__}\n" - if (cs := self._children()): s += f"question: {cs}\n" + if (cs := self._children()): s += "\n".join([c + ": " + repr(getattr(self, c)) for c in cs]) return s # QQ replaces the SolveIt cell with its given question/prompt/note @@ -30,9 +30,9 @@ def __init__(self, content, msg_type="prompt"): def __call__(self): update_msg(content=self.content, msg_type=self.msg_type, sid=read_msg(0).sid) - + def __repr__(self): - return f"{self.msg_type}: \"{self.content}\"" + return f"({self.msg_type}) \"{self.content}\"" # %% ../nbs/01_polya.ipynb @@ -61,9 +61,6 @@ def __init__(self): self.analogy = QQ("Can you use analogy or similarity to relate the problem to a known solution?") - - - # %% ../nbs/01_polya.ipynb class PolyaAct(Step): def __init__(self): diff --git a/nbs/01_polya.ipynb b/nbs/01_polya.ipynb index 771f3f1..edadd1d 100644 --- a/nbs/01_polya.ipynb +++ b/nbs/01_polya.ipynb @@ -65,14 +65,14 @@ "# Step: inspired by contextpack.Topic\n", "class Step:\n", " def _children(self):\n", - " return sorted(list(set(c for c in dir(self) if not c.startswith('_')) - {'get','getter','docs'}))\n", + " return [c for c in dir(self) if not c.startswith('_') or c in ('get','getter','docs')]\n", " def __iter__(self): \n", " yield from (getattr(self, name) for name in self._children() \n", " if isinstance(getattr(self, name),QQ))\n", " def __repr__(self):\n", " s = ''\n", " if self.__doc__: s += f\"doc: {self.__doc__}\\n\"\n", - " if (cs := self._children()): s += f\"question: {cs}\\n\" \n", + " if (cs := self._children()): s += \"\\n\".join([c + \": \" + repr(getattr(self, c)) for c in cs])\n", " return s\n", "\n", "# QQ replaces the SolveIt cell with its given question/prompt/note\n", @@ -83,9 +83,9 @@ "\n", " def __call__(self):\n", " update_msg(content=self.content, msg_type=self.msg_type, sid=read_msg(0).sid)\n", - "\n", + " \n", " def __repr__(self):\n", - " return f\"{self.msg_type}: \\\"{self.content}\\\"\"\n" + " return f\"({self.msg_type}) \\\"{self.content}\\\"\"\n" ] }, { @@ -126,10 +126,7 @@ " self.verifiable = QQ(\"How would we verify if our solution is consistent and correct?\")\n", " self.backward = QQ(\"Can we work backward from the desired result?\")\n", " self.aux = QQ(\"Could we use an auxiliary element (e.g., a variable, diagram, or example) to clarify the path?\")\n", - " self.analogy = QQ(\"Can you use analogy or similarity to relate the problem to a known solution?\")\n", - "\n", - "\n", - " \n" + " self.analogy = QQ(\"Can you use analogy or similarity to relate the problem to a known solution?\")\n" ] }, { @@ -191,6 +188,122 @@ "review = PolyaReview()" ] }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "info: (prompt) \"What information do we have? What information do we not have? What might change as we learn more?\"\n", + "lateral: (prompt) \"Can you relate this problem to a more general or a more specific problem?\"\n", + "notation: (prompt) \"Can we pick a suitable notation (e.g. symbols for quantities/data, states, and transitions)?\"\n", + "related: (prompt) \"Can you think of a related problem that we can solve? It could even be a simpler one we could solve first to help understand this one.\"\n", + "similar: (prompt) \"Have you seen a similar problem before?\"\n", + "simplest: (prompt) \"What might be the simplest way to look at this problem?\"\n", + "simplify: (prompt) \"Can we separate the various parts of the problem (e.g. break down complex conditions into simpler ones)?\"\n", + "summary: (prompt) \"Could you please give a concise summary of the problem?\"\n", + "viz: (prompt) \"Can we create a figure or diagram to represent of the problem?\"" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "#| exec_doc\n", + "understand" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "analogy: (prompt) \"Can you use analogy or similarity to relate the problem to a known solution?\"\n", + "aux: (prompt) \"Could we use an auxiliary element (e.g., a variable, diagram, or example) to clarify the path?\"\n", + "backward: (prompt) \"Can we work backward from the desired result?\"\n", + "chunks: (prompt) \"Could you please break down the problem into smaller sub-problems?\"\n", + "known_approach: (prompt) \"Could we use a known algorithm or library to solve the problem, or some of it?\"\n", + "partial: (prompt) \"Is there a smaller part or representation of the problem we could solve?\"\n", + "verifiable: (prompt) \"How would we verify if our solution is consistent and correct?\"" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "#| exec_doc\n", + "plan" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "all: (prompt) \"Did we cover all of the data or examples for this step?\"\n", + "check: (prompt) \"Does this step seem correct?\"\n", + "doubt: (prompt) \"Are we using the right approach?\"\n", + "next: (prompt) \"What is next?\"\n", + "other: (prompt) \"Is there another way to look at this?\"\n", + "partial: (prompt) \"Are there any intermediate results or milestones that we can aim for?\"\n", + "review: (prompt) \"Could you please critique the plan of attack? Be frank, do not be afraid to be critical.\"\n", + "simpler: (prompt) \"Was there a simpler way we could have done this step?\"\n", + "symmetry: (prompt) \"Are there any symmetries or patterns in the problem that we can exploit?\"\n", + "valid: (prompt) \"Does this step seem to have been a valid step?\"" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "#| exec_doc\n", + "act" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "all: (prompt) \"Did we cover all of the data or examples for this problem?\"\n", + "alter: (prompt) \"Can you think of alternative solutions or approaches that might be more efficient or effective?\"\n", + "general: (prompt) \"Can we generalize the solution to other similar problems?\"\n", + "grok: (note) \"**To consider:** Can I understand the solution without having to perform all the steps?\"\n", + "learned: (prompt) \"What lessons have I learned from this?\"\n", + "other: (prompt) \"Can we derive the result differently?\"\n", + "principles: (prompt) \"Can you identify any underlying principles or patterns that emerged during the solution process?\"\n", + "sanity: (prompt) \"Does the result make sense? Can we verify by substition or another method?\"\n", + "simpler: (prompt) \"Can we derive the result in a simpler way?\"\n", + "test: (prompt) \"What are some different ways we can test this?\"" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "#| exec_doc\n", + "review" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -200,7 +313,7 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 13, "metadata": {}, "outputs": [], "source": [ From a7a000c0c8a87a6a10a4a133928ec4d872b03611 Mon Sep 17 00:00:00 2001 From: Duane Milne Date: Fri, 20 Jun 2025 07:51:29 -0400 Subject: [PATCH 09/10] Use item instead of selectone Due to a breaking change in apswutils 0.1.0 --- dialoghelper/core.py | 2 +- nbs/00_core.ipynb | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/dialoghelper/core.py b/dialoghelper/core.py index 57cb7b7..225cf5b 100644 --- a/dialoghelper/core.py +++ b/dialoghelper/core.py @@ -92,7 +92,7 @@ def read_msg(n:int=-1, # Message index (if relative, +ve is downwards) if not 0<=idx Date: Fri, 20 Jun 2025 08:01:30 -0400 Subject: [PATCH 10/10] Revert to fetchone Going back to fetchone because apswutils still has it plus the selectone was from a different class it seems --- dialoghelper/core.py | 2 +- nbs/00_core.ipynb | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/dialoghelper/core.py b/dialoghelper/core.py index 225cf5b..43bc495 100644 --- a/dialoghelper/core.py +++ b/dialoghelper/core.py @@ -92,7 +92,7 @@ def read_msg(n:int=-1, # Message index (if relative, +ve is downwards) if not 0<=idx