thinking-machine 0.0.20__tar.gz → 0.0.22__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. thinking_machine-0.0.22/LICENSE +21 -0
  2. thinking_machine-0.0.22/MANIFEST.in +1 -0
  3. {thinking_machine-0.0.20 → thinking_machine-0.0.22}/PKG-INFO +9 -8
  4. {thinking_machine-0.0.20 → thinking_machine-0.0.22}/README.md +1 -1
  5. {thinking_machine-0.0.20 → thinking_machine-0.0.22}/pyproject.toml +3 -3
  6. thinking_machine-0.0.22/setup.cfg +4 -0
  7. {thinking_machine-0.0.20 → thinking_machine-0.0.22}/src/thinking_machine/config.py +3 -3
  8. thinking_machine-0.0.22/src/thinking_machine.egg-info/PKG-INFO +77 -0
  9. thinking_machine-0.0.22/src/thinking_machine.egg-info/SOURCES.txt +29 -0
  10. thinking_machine-0.0.22/src/thinking_machine.egg-info/dependency_links.txt +1 -0
  11. thinking_machine-0.0.22/src/thinking_machine.egg-info/entry_points.txt +2 -0
  12. thinking_machine-0.0.22/src/thinking_machine.egg-info/requires.txt +2 -0
  13. thinking_machine-0.0.22/src/thinking_machine.egg-info/top_level.txt +1 -0
  14. thinking_machine-0.0.22/tests/test_cli.py +20 -0
  15. thinking_machine-0.0.22/tests/test_e2e.py +45 -0
  16. thinking_machine-0.0.22/tests/test_llm_soup.py +71 -0
  17. thinking_machine-0.0.22/tests/test_utilities.py +69 -0
  18. {thinking_machine-0.0.20 → thinking_machine-0.0.22}/src/thinking_machine/__init__.py +0 -0
  19. {thinking_machine-0.0.20 → thinking_machine-0.0.22}/src/thinking_machine/cli.py +0 -0
  20. {thinking_machine-0.0.20 → thinking_machine-0.0.22}/src/thinking_machine/githf.py +0 -0
  21. {thinking_machine-0.0.20 → thinking_machine-0.0.22}/src/thinking_machine/machina.yaml +0 -0
  22. {thinking_machine-0.0.20 → thinking_machine-0.0.22}/src/thinking_machine/machine.py +0 -0
  23. {thinking_machine-0.0.20 → thinking_machine-0.0.22}/src/thinking_machine/providers/__init__.py +0 -0
  24. {thinking_machine-0.0.20 → thinking_machine-0.0.22}/src/thinking_machine/providers/camelids.py +0 -0
  25. {thinking_machine-0.0.20 → thinking_machine-0.0.22}/src/thinking_machine/providers/castor_pollux.py +0 -0
  26. {thinking_machine-0.0.20 → thinking_machine-0.0.22}/src/thinking_machine/providers/depsek.py +0 -0
  27. {thinking_machine-0.0.20 → thinking_machine-0.0.22}/src/thinking_machine/providers/electroid.py +0 -0
  28. {thinking_machine-0.0.20 → thinking_machine-0.0.22}/src/thinking_machine/providers/openai.py +0 -0
  29. {thinking_machine-0.0.20 → thinking_machine-0.0.22}/src/thinking_machine/providers/qrog.py +0 -0
  30. {thinking_machine-0.0.20 → thinking_machine-0.0.22}/src/thinking_machine/providers/strangelove.py +0 -0
  31. {thinking_machine-0.0.20 → thinking_machine-0.0.22}/src/thinking_machine/utilities.py +0 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2023 Alexander Fedotov
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1 @@
1
+ include src/thinking_machine/*.yaml
@@ -1,18 +1,19 @@
1
- Metadata-Version: 2.3
1
+ Metadata-Version: 2.4
2
2
  Name: thinking-machine
3
- Version: 0.0.20
3
+ Version: 0.0.22
4
4
  Summary: A Machine that thinks.
5
- Keywords: thinking-machine
6
- Author: Machina Ratiocinatrix, Alexander Fedotov
7
5
  Author-email: Machina Ratiocinatrix <machina.ratio@gmail.com>, Alexander Fedotov <alex.fedotov@aol.com>
6
+ Project-URL: Homepage, https://github.com/machina-ratiocinatrix/thinking-machine
7
+ Keywords: thinking-machine
8
8
  Classifier: Programming Language :: Python :: 3
9
9
  Classifier: License :: OSI Approved :: MIT License
10
10
  Classifier: Operating System :: OS Independent
11
- Requires-Dist: pyyaml==6.0.3
12
- Requires-Dist: click==8.3.1
13
11
  Requires-Python: >=3.10
14
- Project-URL: Homepage, https://github.com/machina-ratiocinatrix/thinking-machine
15
12
  Description-Content-Type: text/markdown
13
+ License-File: LICENSE
14
+ Requires-Dist: pyyaml==6.0.3
15
+ Requires-Dist: click==8.3.1
16
+ Dynamic: license-file
16
17
 
17
18
  # Thinking-Machine
18
19
  A Machine that thinks.
@@ -25,7 +26,7 @@ echo "Theodotos-Alexandreus: Are language models seeking the Truth, machine?" \
25
26
  --github-token=ghp_...
26
27
  ```
27
28
 
28
- Or, with local pip installation:
29
+ Or, with a local pip installation:
29
30
  ```bash
30
31
  pip install thinking-machine
31
32
  ```
@@ -9,7 +9,7 @@ echo "Theodotos-Alexandreus: Are language models seeking the Truth, machine?" \
9
9
  --github-token=ghp_...
10
10
  ```
11
11
 
12
- Or, with local pip installation:
12
+ Or, with a local pip installation:
13
13
  ```bash
14
14
  pip install thinking-machine
15
15
  ```
@@ -1,10 +1,10 @@
1
1
  [build-system]
2
- requires = ["uv_build>=0.10.9,<0.11.0"]
3
- build-backend = "uv_build"
2
+ requires = ["setuptools==82.0.1"]
3
+ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "thinking-machine"
7
- version = "0.0.20"
7
+ version = "0.0.22"
8
8
  authors = [
9
9
  {name="Machina Ratiocinatrix", email="machina.ratio@gmail.com"},
10
10
  {name="Alexander Fedotov", email="alex.fedotov@aol.com"}
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -15,9 +15,9 @@ class Config:
15
15
  github_name: str = field(default_factory=lambda: environ.get('GITHUB_NAME', ''))
16
16
  github_email: str = field(default_factory=lambda: environ.get('GITHUB_EMAIL', ''))
17
17
  provider_api_key: str = field(default_factory=lambda: environ.get('PROVIDER_API_KEY', ''))
18
- provider: str = field(default_factory=lambda: environ.get('PROVIDER', ''))
18
+ provider: str = field(default_factory=lambda: environ.get('PROVIDER', 'OpenAI'))
19
19
  machine_organization_name: str = field(default_factory=lambda: environ.get('MACHINE_ORGANIZATION_NAME', 'machina-ratiocinatrix'))
20
20
  private_repo_with_text: str = field(default_factory=lambda: environ.get('PRIVATE_REPO_WITH_TEXT','thinking_machine'))
21
21
  system_prompt_file: str = field(default_factory=lambda: environ.get('SYSTEM_PROMPT_FILE', 'machina.yaml'))
22
- name: str = ''
23
- instructions: str = ''
22
+ name: str = field(default_factory=lambda: environ.get('MACHINE-NAME','thinking-machine'))
23
+ instructions: str = field(default_factory=lambda: environ.get('MACHINE-DESCRIPTION','The Assistant is Thinking-Machine.'))
@@ -0,0 +1,77 @@
1
+ Metadata-Version: 2.4
2
+ Name: thinking-machine
3
+ Version: 0.0.22
4
+ Summary: A Machine that thinks.
5
+ Author-email: Machina Ratiocinatrix <machina.ratio@gmail.com>, Alexander Fedotov <alex.fedotov@aol.com>
6
+ Project-URL: Homepage, https://github.com/machina-ratiocinatrix/thinking-machine
7
+ Keywords: thinking-machine
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: License :: OSI Approved :: MIT License
10
+ Classifier: Operating System :: OS Independent
11
+ Requires-Python: >=3.10
12
+ Description-Content-Type: text/markdown
13
+ License-File: LICENSE
14
+ Requires-Dist: pyyaml==6.0.3
15
+ Requires-Dist: click==8.3.1
16
+ Dynamic: license-file
17
+
18
+ # Thinking-Machine
19
+ A Machine that thinks.
20
+
21
+ In order to launch it from the command line or as a Python subprocess:
22
+ ```bash
23
+ echo "Theodotos-Alexandreus: Are language models seeking the Truth, machine?" \
24
+ | uvx thinking-machine \
25
+ --provider-api-key=sk-proj-... \
26
+ --github-token=ghp_...
27
+ ```
28
+
29
+ Or, with a local pip installation:
30
+ ```bash
31
+ pip install thinking-machine
32
+ ```
33
+ Set the environment variables:
34
+ ```bash
35
+ export PROVIDER_API_KEY="sk-proj-..."
36
+ export GITHUB_TOKEN="ghp_..."
37
+ ```
38
+ Then:
39
+ ```bash
40
+ thinking-machine multilogue.txt
41
+ ```
42
+ Or:
43
+ ```bash
44
+ thinking-machine multilogue.txt new_turn.txt
45
+ ```
46
+ Or:
47
+ ```bash
48
+ cat multilogue.txt | thinking-machine
49
+ ```
50
+ Or:
51
+ ```bash
52
+ cat multilogue.txt | thinking-machine > multilogue.txt
53
+ ```
54
+ Or:
55
+ ```bash
56
+ (cat multilogue.txt; echo:"Theodotos: What do you think, Thinking-Machine?") \
57
+ | thinking-machine
58
+ ```
59
+ Or:
60
+ ```bash
61
+ cat multilogue.txt new_turn.txt | thinking-machine
62
+ ```
63
+ Or:
64
+ ```bash
65
+ cat multilogue.txt new_turn.txt | thinking-machine > multilogue.txt
66
+ ```
67
+ Or, if you have installed other machines:
68
+ ```bash
69
+ cat multilogue.md | thinking-machine \
70
+ | summarizing-machine | judging-machine > summary_judgment.md
71
+ ```
72
+
73
+ Or use it in your Python code:
74
+ ```Python
75
+ # Python
76
+ import thinking_machine
77
+ ```
@@ -0,0 +1,29 @@
1
+ LICENSE
2
+ MANIFEST.in
3
+ README.md
4
+ pyproject.toml
5
+ src/thinking_machine/__init__.py
6
+ src/thinking_machine/cli.py
7
+ src/thinking_machine/config.py
8
+ src/thinking_machine/githf.py
9
+ src/thinking_machine/machina.yaml
10
+ src/thinking_machine/machine.py
11
+ src/thinking_machine/utilities.py
12
+ src/thinking_machine.egg-info/PKG-INFO
13
+ src/thinking_machine.egg-info/SOURCES.txt
14
+ src/thinking_machine.egg-info/dependency_links.txt
15
+ src/thinking_machine.egg-info/entry_points.txt
16
+ src/thinking_machine.egg-info/requires.txt
17
+ src/thinking_machine.egg-info/top_level.txt
18
+ src/thinking_machine/providers/__init__.py
19
+ src/thinking_machine/providers/camelids.py
20
+ src/thinking_machine/providers/castor_pollux.py
21
+ src/thinking_machine/providers/depsek.py
22
+ src/thinking_machine/providers/electroid.py
23
+ src/thinking_machine/providers/openai.py
24
+ src/thinking_machine/providers/qrog.py
25
+ src/thinking_machine/providers/strangelove.py
26
+ tests/test_cli.py
27
+ tests/test_e2e.py
28
+ tests/test_llm_soup.py
29
+ tests/test_utilities.py
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ thinking-machine = thinking_machine.cli:run
@@ -0,0 +1,2 @@
1
+ pyyaml==6.0.3
2
+ click==8.3.1
@@ -0,0 +1 @@
1
+ thinking_machine
@@ -0,0 +1,20 @@
1
+ import pytest
2
+ from unittest.mock import patch, MagicMock
3
+ from click.testing import CliRunner
4
+ from thinking_machine.cli import run
5
+
6
+ @patch('thinking_machine.cli.fileinput')
7
+ @patch('thinking_machine.machine.machine')
8
+ def test_cli_run_success(mock_machine, mock_fileinput):
9
+ # Mocking standard input pipeline
10
+ mock_fileinput.input.return_value = ["user: hello\n"]
11
+ mock_machine.return_value = ("some thoughts", "response text")
12
+
13
+ runner = CliRunner()
14
+ result = runner.invoke(run, ['--provider-api-key', 'sk-ant-test'])
15
+
16
+ # We exit cleanly when normal things happen. Wait, sys.stdout.write is called but
17
+ # click catches SystemExit(0).
18
+ # Since click catches exceptions, we just verify the mock is called
19
+ assert mock_machine.called, f"Output: {result.output}\nException: {result.exception}"
20
+ assert "response text" in result.output
@@ -0,0 +1,45 @@
1
+ import subprocess
2
+ import pytest
3
+ import os
4
+
5
+ def test_uvx_integration():
6
+ """
7
+ Tests the library fully end-to-end through `uvx` by installing from the local
8
+ directory (--from .), simulating exactly how a user would interact with the
9
+ script once it is deployed to PyPI.
10
+ """
11
+
12
+ # We know the environment variables are already in the computer
13
+ # So we don't need to mock them; we just execute the real thing.
14
+
15
+ input_text = "Theodotos-Alexandreus: Are language models seeking the Truth, machine?\n"
16
+
17
+ # "uvx --from . thinking-machine" behaves identically to PyPI "uvx thinking-machine"
18
+ cmd = [
19
+ "uvx",
20
+ "--with",
21
+ ".[all]",
22
+ "--from",
23
+ ".",
24
+ "name-of-the-machine"
25
+ ]
26
+
27
+ # The keys/tokens are passed through the environment automatically via env=env.
28
+ # We don't pass them as CLI arguments because `fileinput.input()` in cli.py
29
+ # would try to read them as files.
30
+
31
+ print(f"Running command: {' '.join(cmd)}")
32
+
33
+ env = os.environ.copy()
34
+ result = subprocess.run(cmd, input=input_text, text=True, capture_output=True, env=env)
35
+
36
+ # We expect a successful execution (0)
37
+ assert result.returncode == 0, f"Process failed with stderr:\n{result.stderr}\n\nstdout:\n{result.stdout}"
38
+
39
+ # The output should contain our original input
40
+ assert "Theodotos-Alexandreus:" in result.stdout
41
+ assert "Are language models seeking the Truth, machine?" in result.stdout
42
+
43
+ # The Machine string should be present, indicating it replied back and added to the transcript
44
+ # (Since it is appending it to the bottom, the stdout length > input length)
45
+ assert len(result.stdout) > len(input_text), "The machine did not append any response."
@@ -0,0 +1,71 @@
1
+ import unittest
2
+ from src.thinking_machine.utilities import llm_soup_to_text
3
+
4
+
5
+ class TestLLMSoupToText(unittest.TestCase):
6
+ def test_basic_text(self):
7
+ self.assertEqual(llm_soup_to_text("Hello world"), "Hello world")
8
+
9
+ def test_bold_italic(self):
10
+ self.assertEqual(llm_soup_to_text("This is **bold** and __bold__."), "This is bold and bold.")
11
+ self.assertEqual(llm_soup_to_text("This is *italic* and _italic_."), "This is italic and italic.")
12
+ self.assertEqual(llm_soup_to_text("Combined ***bold italic***!"), "Combined bold italic!")
13
+
14
+ def test_inline_code(self):
15
+ self.assertEqual(llm_soup_to_text("Here is some `inline code`."), "Here is some inline code.")
16
+
17
+ def test_fenced_code_blocks(self):
18
+ text = "Before code\n```python\ndef foo():\n pass\n```\nAfter code"
19
+ self.assertEqual(llm_soup_to_text(text), "Before code\n\tAfter code")
20
+
21
+ text2 = "Before code\n~~~javascript\nconsole.log(1);\n~~~\nAfter code"
22
+ self.assertEqual(llm_soup_to_text(text2), "Before code\n\tAfter code")
23
+
24
+ def test_headers(self):
25
+ text = "# Header 1\nSome text\n## Header 2\nMore text"
26
+ self.assertEqual(llm_soup_to_text(text), "Header 1\nSome text\nHeader 2\nMore text")
27
+
28
+ text2 = "Setext Header\n=============\nSome text"
29
+ self.assertEqual(llm_soup_to_text(text2), "Setext Header\nSome text")
30
+
31
+ def test_links_and_images(self):
32
+ self.assertEqual(llm_soup_to_text("Click [here](https://url.com) now."), "Click here now.")
33
+ self.assertEqual(llm_soup_to_text("An image ![alt text](img.png) here."), "An image here.")
34
+
35
+ def test_blockquotes(self):
36
+ text = "> This is a quote\n> It continues"
37
+ self.assertEqual(llm_soup_to_text(text), "This is a quote\nIt continues")
38
+
39
+ def test_lists(self):
40
+ text = "- Item 1\n* Item 2\n+ Item 3"
41
+ self.assertEqual(llm_soup_to_text(text), "Item 1\nItem 2\nItem 3")
42
+
43
+ text2 = "1. First\n2. Second\n10. Tenth"
44
+ self.assertEqual(llm_soup_to_text(text2), "First\nSecond\nTenth")
45
+
46
+ def test_html_tags(self):
47
+ self.assertEqual(llm_soup_to_text("<p>Hello <b>world</b>!</p>"), "Hello world!")
48
+ self.assertEqual(llm_soup_to_text("<div>Text <br/> More text</div>"), "Text\nMore text")
49
+
50
+ def test_html_comments(self):
51
+ self.assertEqual(llm_soup_to_text("Visible <!-- hidden --> visible"), "Visible visible")
52
+
53
+ def test_html_entities(self):
54
+ self.assertEqual(llm_soup_to_text("Tom &amp; Jerry"), "Tom & Jerry")
55
+ self.assertEqual(llm_soup_to_text("It&#39;s mine"), "It's mine")
56
+
57
+ def test_horizontal_rules(self):
58
+ text = "Above\n---\nBelow\n***\nEnd"
59
+ self.assertEqual(llm_soup_to_text(text), "Above\n\tBelow\n\tEnd")
60
+
61
+ def test_whitespace_and_paragraphs(self):
62
+ # Multiple spaces and tabs
63
+ self.assertEqual(llm_soup_to_text("Too many \t spaces"), "Too many spaces")
64
+ # Paragraphs consolidated
65
+ self.assertEqual(llm_soup_to_text("Para 1\n\n\n\nPara 2"), "Para 1\n\tPara 2")
66
+ # Leading and trailing
67
+ self.assertEqual(llm_soup_to_text(" \n \t Trim me \n \t "), "Trim me")
68
+
69
+
70
+ if __name__ == '__main__':
71
+ unittest.main()
@@ -0,0 +1,69 @@
1
+ import unittest
2
+ import json
3
+ import os
4
+ from src.thinking_machine.utilities import (
5
+ plato_text_to_cmj,
6
+ plato_text_to_muj,
7
+ plato_text_to_mpuj,
8
+ cmj_to_plato_text,
9
+ new_plato_text
10
+ )
11
+
12
+
13
+ class TestTransformations(unittest.TestCase):
14
+ def setUp(self):
15
+ # Paths to example files
16
+ base_dir = os.path.dirname(__file__) + '/data'
17
+ with open(os.path.join(base_dir, 'plato_example.txt'), 'r', encoding='utf-8') as f:
18
+ self.plato_txt = f.read()
19
+
20
+ with open(os.path.join(base_dir, 'cmj_example.json'), 'r', encoding='utf-8') as f:
21
+ self.cmj_json = json.load(f)
22
+
23
+ with open(os.path.join(base_dir, 'mpuj_example.json'), 'r', encoding='utf-8') as f:
24
+ self.mpuj_json = json.load(f)
25
+
26
+ with open(os.path.join(base_dir, 'muj_example.json'), 'r', encoding='utf-8') as f:
27
+ self.muj_json = json.load(f)
28
+
29
+ self.machine_name = "Thinking-Machine"
30
+ self.maxDiff = None
31
+
32
+ def test_plato_text_to_muj(self):
33
+ result = plato_text_to_muj(self.plato_txt, self.machine_name)
34
+ self.assertEqual(result, self.muj_json)
35
+
36
+ def test_plato_text_to_mpuj(self):
37
+ result = plato_text_to_mpuj(self.plato_txt, self.machine_name)
38
+ self.assertEqual(result, self.mpuj_json)
39
+
40
+ def test_plato_text_to_cmj(self):
41
+ result = plato_text_to_cmj(self.plato_txt, self.machine_name)
42
+ self.assertEqual(result, self.cmj_json)
43
+
44
+ def test_cmj_to_plato_text(self):
45
+ result = cmj_to_plato_text(self.cmj_json)
46
+ self.assertEqual(result.strip(), self.plato_txt.strip())
47
+
48
+ def test_new_plato_text(self):
49
+ thoughts = "This is a thought.\n\nIt spans multiple paragraphs."
50
+ text = "This is the final text.\n\nIt also has paragraphs."
51
+
52
+ expected = (
53
+ "Thinking-Machine: (thinking) This is a thought.\n\tIt spans multiple paragraphs.\n\n"
54
+ "Thinking-Machine: This is the final text.\n\tIt also has paragraphs.\n\n"
55
+ )
56
+ result = new_plato_text(thoughts, text, self.machine_name)
57
+ self.assertEqual(result, expected)
58
+
59
+ expected_no_thoughts = "Thinking-Machine: This is the final text.\n\tIt also has paragraphs.\n\n"
60
+ result2 = new_plato_text("", text, self.machine_name)
61
+ self.assertEqual(result2, expected_no_thoughts)
62
+
63
+ expected_no_text = "Thinking-Machine: (thinking) This is a thought.\n\tIt spans multiple paragraphs.\n\n"
64
+ result3 = new_plato_text(thoughts, "", self.machine_name)
65
+ self.assertEqual(result3, expected_no_text)
66
+
67
+
68
+ if __name__ == '__main__':
69
+ unittest.main()