Dixing Xu commited on
Commit
2fc6b05
·
unverified ·
1 Parent(s): 3e7f863
Files changed (43) hide show
  1. .github/ISSUE_TEMPLATE/bug_report.yml +65 -0
  2. .github/ISSUE_TEMPLATE/feature_request.md +18 -0
  3. .github/ISSUE_TEMPLATE/technical_proposal.md +18 -0
  4. .github/pull_request_template.md +8 -0
  5. .github/workflows/linter.yml +25 -0
  6. .github/workflows/python-publish.yml +39 -0
  7. .gitignore +172 -0
  8. .python-version +1 -0
  9. .streamlit/config.toml +17 -0
  10. LICENSE +21 -0
  11. aide/__init__.py +62 -0
  12. aide/agent.py +339 -0
  13. aide/backend/__init__.py +52 -0
  14. aide/backend/backend_anthropic.py +107 -0
  15. aide/backend/backend_openai.py +127 -0
  16. aide/backend/utils.py +101 -0
  17. aide/example_tasks/bitcoin_price.md +5 -0
  18. aide/example_tasks/bitcoin_price/BTC-USD.csv +501 -0
  19. aide/example_tasks/house_prices.md +24 -0
  20. aide/example_tasks/house_prices/data_description.txt +523 -0
  21. aide/example_tasks/house_prices/sample_submission.csv +1460 -0
  22. aide/example_tasks/house_prices/test.csv +0 -0
  23. aide/example_tasks/house_prices/train.csv +0 -0
  24. aide/interpreter.py +311 -0
  25. aide/journal.py +192 -0
  26. aide/journal2report.py +31 -0
  27. aide/run.py +148 -0
  28. aide/utils/__init__.py +100 -0
  29. aide/utils/config.py +199 -0
  30. aide/utils/config.yaml +58 -0
  31. aide/utils/data_preview.py +153 -0
  32. aide/utils/metric.py +78 -0
  33. aide/utils/response.py +91 -0
  34. aide/utils/serialize.py +51 -0
  35. aide/utils/tree_export.py +94 -0
  36. aide/utils/viz_templates/template.html +61 -0
  37. aide/utils/viz_templates/template.js +362 -0
  38. aide/webui/__init__.py +0 -0
  39. aide/webui/app.py +599 -0
  40. aide/webui/style.css +173 -0
  41. app.py +2 -2
  42. requirements.txt +94 -0
  43. style.css +173 -0
.github/ISSUE_TEMPLATE/bug_report.yml ADDED
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ name: Bug
2
+ description: Report a problem with AIDE
3
+ title: '[Bug]: '
4
+ labels: ['bug']
5
+ body:
6
+ - type: markdown
7
+ attributes:
8
+ value: Thank you for taking the time to fill out this bug report. Please provide as much information as possible to help us understand and address the issue effectively.
9
+
10
+ - type: checkboxes
11
+ attributes:
12
+ label: Is there an existing issue for the same bug?
13
+ description: Please check if an issue already exists for the bug you encountered.
14
+ options:
15
+ - label: I have checked the existing issues.
16
+ required: true
17
+
18
+ - type: textarea
19
+ id: bug-description
20
+ attributes:
21
+ label: Describe the bug and reproduction steps
22
+ description: Provide a description of the issue along with any reproduction steps.
23
+ validations:
24
+ required: true
25
+
26
+ - type: dropdown
27
+ id: installation
28
+ attributes:
29
+ label: AIDE Installation
30
+ description: How are you running AIDE?
31
+ options:
32
+ - Commandline
33
+ - Docker
34
+ - Python Script
35
+ - Other
36
+ default: 0
37
+
38
+ - type: input
39
+ id: aideml-version
40
+ attributes:
41
+ label: AIDE Version
42
+ description: What version of AIDE are you using?
43
+ placeholder: ex. 0.1.4, main, etc.
44
+
45
+ - type: input
46
+ id: llm
47
+ attributes:
48
+ label: LLM
49
+ description: Which llm are you using?
50
+ placeholder: ex. gpt-4-turbo, claude-3-5-sonnet, etc.
51
+
52
+ - type: dropdown
53
+ id: os
54
+ attributes:
55
+ label: Operating System
56
+ options:
57
+ - MacOS
58
+ - Linux
59
+ - WSL on Windows
60
+
61
+ - type: textarea
62
+ id: additional-context
63
+ attributes:
64
+ label: Logs, Errors, Screenshots, and Additional Context
65
+ description: Please provide any additional information you think might help.
.github/ISSUE_TEMPLATE/feature_request.md ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ name: Feature Request
3
+ about: Suggest an idea for new AIDE features
4
+ title: ''
5
+ labels: 'enhancement'
6
+ assignees: ''
7
+
8
+ ---
9
+
10
+ **What problem or use case are you trying to solve?**
11
+
12
+ **Describe the UX of the solution you'd like**
13
+
14
+ **Do you have thoughts on the technical implementation?**
15
+
16
+ **Describe alternatives you've considered**
17
+
18
+ **Additional context**
.github/ISSUE_TEMPLATE/technical_proposal.md ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ name: Technical Proposal
3
+ about: Propose a new architecture or technology
4
+ title: ''
5
+ labels: 'proposal'
6
+ assignees: ''
7
+
8
+ ---
9
+
10
+ **Summary**
11
+
12
+ **Motivation**
13
+
14
+ **Technical Design**
15
+
16
+ **Alternatives to Consider**
17
+
18
+ **Additional context**
.github/pull_request_template.md ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ ## Description
2
+
3
+ * a simple description of what you're trying to accomplish
4
+ * a summary of changes in code
5
+ * which issues it fixes, if any
6
+
7
+ ## Screenshots/videos:
8
+
.github/workflows/linter.yml ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ name: Linter
2
+
3
+ on:
4
+ - push
5
+ - pull_request
6
+
7
+ jobs:
8
+ lint-python:
9
+ name: Python Linting
10
+ runs-on: ubuntu-latest
11
+ if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name
12
+ steps:
13
+ - name: Checkout Code
14
+ uses: actions/checkout@v4
15
+ - uses: actions/setup-python@v5
16
+ with:
17
+ python-version: 3.11
18
+ - name: Install Dependencies
19
+ run: |
20
+ pip install ruff==0.7.1
21
+ pip install black==24.3.0
22
+ - name: Run Ruff
23
+ run: ruff check --output-format=github aide/
24
+ - name: Run Black
25
+ run: black --check --diff aide/
.github/workflows/python-publish.yml ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # This workflow will upload a Python Package using Twine when a release is created
2
+ # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python#publishing-to-package-registries
3
+
4
+ # This workflow uses actions that are not certified by GitHub.
5
+ # They are provided by a third-party and are governed by
6
+ # separate terms of service, privacy policy, and support
7
+ # documentation.
8
+
9
+ name: Publish on PyPI
10
+
11
+ on:
12
+ release:
13
+ types: [published]
14
+
15
+ permissions:
16
+ contents: read
17
+
18
+ jobs:
19
+ deploy:
20
+
21
+ runs-on: ubuntu-latest
22
+
23
+ steps:
24
+ - uses: actions/checkout@v4
25
+ - name: Set up Python
26
+ uses: actions/setup-python@v3
27
+ with:
28
+ python-version: '3.10'
29
+ - name: Install dependencies
30
+ run: |
31
+ python -m pip install --upgrade pip
32
+ pip install build
33
+ - name: Build package
34
+ run: python -m build
35
+ - name: Publish package
36
+ uses: pypa/gh-action-pypi-publish@27b31702a0e7fc50959f5ad993c78deac1bdfc29
37
+ with:
38
+ user: __token__
39
+ password: ${{ secrets.PYPI_API_TOKEN }}
.gitignore ADDED
@@ -0,0 +1,172 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ build/
12
+ develop-eggs/
13
+ dist/
14
+ downloads/
15
+ eggs/
16
+ .eggs/
17
+ lib/
18
+ lib64/
19
+ parts/
20
+ sdist/
21
+ var/
22
+ wheels/
23
+ share/python-wheels/
24
+ *.egg-info/
25
+ .installed.cfg
26
+ *.egg
27
+ MANIFEST
28
+
29
+ # PyInstaller
30
+ # Usually these files are written by a python script from a template
31
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
32
+ *.manifest
33
+ *.spec
34
+
35
+ # Installer logs
36
+ pip-log.txt
37
+ pip-delete-this-directory.txt
38
+
39
+ # Unit test / coverage reports
40
+ htmlcov/
41
+ .tox/
42
+ .nox/
43
+ .coverage
44
+ .coverage.*
45
+ .cache
46
+ nosetests.xml
47
+ coverage.xml
48
+ *.cover
49
+ *.py,cover
50
+ .hypothesis/
51
+ .pytest_cache/
52
+ cover/
53
+
54
+ # Translations
55
+ *.mo
56
+ *.pot
57
+
58
+ # Django stuff:
59
+ *.log
60
+ local_settings.py
61
+ db.sqlite3
62
+ db.sqlite3-journal
63
+
64
+ # Flask stuff:
65
+ instance/
66
+ .webassets-cache
67
+
68
+ # Scrapy stuff:
69
+ .scrapy
70
+
71
+ # Sphinx documentation
72
+ docs/_build/
73
+
74
+ # PyBuilder
75
+ .pybuilder/
76
+ target/
77
+
78
+ # Jupyter Notebook
79
+ .ipynb_checkpoints
80
+
81
+ # IPython
82
+ profile_default/
83
+ ipython_config.py
84
+
85
+ # pyenv
86
+ # For a library or package, you might want to ignore these files since the code is
87
+ # intended to run in multiple environments; otherwise, check them in:
88
+ # .python-version
89
+
90
+ # pipenv
91
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
92
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
93
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
94
+ # install all needed dependencies.
95
+ #Pipfile.lock
96
+
97
+ # poetry
98
+ # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
99
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
100
+ # commonly ignored for libraries.
101
+ # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
102
+ #poetry.lock
103
+
104
+ # pdm
105
+ # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
106
+ #pdm.lock
107
+ # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
108
+ # in version control.
109
+ # https://pdm.fming.dev/#use-with-ide
110
+ .pdm.toml
111
+
112
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
113
+ __pypackages__/
114
+
115
+ # Celery stuff
116
+ celerybeat-schedule
117
+ celerybeat.pid
118
+
119
+ # SageMath parsed files
120
+ *.sage.py
121
+
122
+ # Environments
123
+ .env
124
+ .venv
125
+ env/
126
+ venv/
127
+ ENV/
128
+ env.bak/
129
+ venv.bak/
130
+
131
+ # Spyder project settings
132
+ .spyderproject
133
+ .spyproject
134
+
135
+ # Rope project settings
136
+ .ropeproject
137
+
138
+ # mkdocs documentation
139
+ /site
140
+
141
+ # mypy
142
+ .mypy_cache/
143
+ .dmypy.json
144
+ dmypy.json
145
+
146
+ # Pyre type checker
147
+ .pyre/
148
+
149
+ # pytype static type analyzer
150
+ .pytype/
151
+
152
+ # Cython debug symbols
153
+ cython_debug/
154
+
155
+ # PyCharm
156
+ # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
157
+ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
158
+ # and can be added to the global gitignore or merged into this file. For a more nuclear
159
+ # option (not recommended) you can uncomment the following to ignore the entire idea folder.
160
+ .idea/
161
+ .vscode/
162
+
163
+ workspaces
164
+ logs
165
+
166
+ .DS_STORE
167
+ .trunk
168
+
169
+ .gradio/
170
+ .ruff_cache/
171
+
172
+ .env
.python-version ADDED
@@ -0,0 +1 @@
 
 
1
+ 3.10
.streamlit/config.toml ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [theme]
2
+ # Primary colors
3
+ primaryColor="#0D0F18" # --wecopink: 343 98% 63%
4
+ backgroundColor="#F0EFE9" # --background: 49 10% 94%
5
+ secondaryBackgroundColor="#FFFFFF" # --card: 60 33.3% 98%
6
+ textColor="#0A0A0A" # --primary: 0 0% 17%
7
+
8
+ # Font
9
+ font="sans serif"
10
+
11
+ [ui]
12
+ hideTopBar = true
13
+
14
+ [client]
15
+ toolbarMode = "minimal"
16
+ showErrorDetails = true
17
+ showSidebarNavigation = false
LICENSE ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Weco AI Ltd
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.
aide/__init__.py ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from dataclasses import dataclass
2
+
3
+ from .agent import Agent
4
+ from .interpreter import Interpreter
5
+ from .journal import Journal
6
+ from omegaconf import OmegaConf
7
+ from rich.status import Status
8
+ from .utils.config import (
9
+ load_task_desc,
10
+ prep_agent_workspace,
11
+ save_run,
12
+ _load_cfg,
13
+ prep_cfg,
14
+ )
15
+
16
+
17
+ @dataclass
18
+ class Solution:
19
+ code: str
20
+ valid_metric: float
21
+
22
+
23
+ class Experiment:
24
+
25
+ def __init__(self, data_dir: str, goal: str, eval: str | None = None):
26
+ """Initialize a new experiment run.
27
+
28
+ Args:
29
+ data_dir (str): Path to the directory containing the data files.
30
+ goal (str): Description of the goal of the task.
31
+ eval (str | None, optional): Optional description of the preferred way for the agent to evaluate its solutions.
32
+ """
33
+
34
+ _cfg = _load_cfg(use_cli_args=False)
35
+ _cfg.data_dir = data_dir
36
+ _cfg.goal = goal
37
+ _cfg.eval = eval
38
+ self.cfg = prep_cfg(_cfg)
39
+
40
+ self.task_desc = load_task_desc(self.cfg)
41
+
42
+ with Status("Preparing agent workspace (copying and extracting files) ..."):
43
+ prep_agent_workspace(self.cfg)
44
+
45
+ self.journal = Journal()
46
+ self.agent = Agent(
47
+ task_desc=self.task_desc,
48
+ cfg=self.cfg,
49
+ journal=self.journal,
50
+ )
51
+ self.interpreter = Interpreter(
52
+ self.cfg.workspace_dir, **OmegaConf.to_container(self.cfg.exec) # type: ignore
53
+ )
54
+
55
+ def run(self, steps: int) -> Solution:
56
+ for _i in range(steps):
57
+ self.agent.step(exec_callback=self.interpreter.run)
58
+ save_run(self.cfg, self.journal)
59
+ self.interpreter.cleanup_session()
60
+
61
+ best_node = self.journal.get_best_node(only_good=False)
62
+ return Solution(code=best_node.code, valid_metric=best_node.metric.value)
aide/agent.py ADDED
@@ -0,0 +1,339 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import logging
2
+ import random
3
+ from typing import Any, Callable, cast
4
+
5
+ import humanize
6
+ from .backend import FunctionSpec, query
7
+ from .interpreter import ExecutionResult
8
+ from .journal import Journal, Node
9
+ from .utils import data_preview
10
+ from .utils.config import Config
11
+ from .utils.metric import MetricValue, WorstMetricValue
12
+ from .utils.response import extract_code, extract_text_up_to_code, wrap_code
13
+
14
+ logger = logging.getLogger("aide")
15
+
16
+
17
+ ExecCallbackType = Callable[[str, bool], ExecutionResult]
18
+
19
+ review_func_spec = FunctionSpec(
20
+ name="submit_review",
21
+ json_schema={
22
+ "type": "object",
23
+ "properties": {
24
+ "is_bug": {
25
+ "type": "boolean",
26
+ "description": "true if the output log shows that the execution failed or has some bug, otherwise false.",
27
+ },
28
+ "summary": {
29
+ "type": "string",
30
+ "description": "if there is a bug, propose a fix. Otherwise, write a short summary (2-3 sentences) describing the empirical findings.",
31
+ },
32
+ "metric": {
33
+ "type": "number",
34
+ "description": "If the code ran successfully, report the value of the validation metric. Otherwise, leave it null.",
35
+ },
36
+ "lower_is_better": {
37
+ "type": "boolean",
38
+ "description": "true if the metric should be minimized (i.e. a lower metric value is better, such as with MSE), false if the metric should be maximized (i.e. a higher metric value is better, such as with accuracy).",
39
+ },
40
+ },
41
+ "required": ["is_bug", "summary", "metric", "lower_is_better"],
42
+ },
43
+ description="Submit a review evaluating the output of the training script.",
44
+ )
45
+
46
+
47
+ class Agent:
48
+ def __init__(
49
+ self,
50
+ task_desc: str,
51
+ cfg: Config,
52
+ journal: Journal,
53
+ ):
54
+ super().__init__()
55
+ self.task_desc = task_desc
56
+ self.cfg = cfg
57
+ self.acfg = cfg.agent
58
+ self.journal = journal
59
+ self.data_preview: str | None = None
60
+
61
+ def search_policy(self) -> Node | None:
62
+ """Select a node to work on (or None to draft a new node)."""
63
+ search_cfg = self.acfg.search
64
+
65
+ # initial drafting
66
+ if len(self.journal.draft_nodes) < search_cfg.num_drafts:
67
+ logger.debug("[search policy] drafting new node (not enough drafts)")
68
+ return None
69
+
70
+ # debugging
71
+ if random.random() < search_cfg.debug_prob:
72
+ # nodes that are buggy + leaf nodes + debug depth < max debug depth
73
+ debuggable_nodes = [
74
+ n
75
+ for n in self.journal.buggy_nodes
76
+ if (n.is_leaf and n.debug_depth <= search_cfg.max_debug_depth)
77
+ ]
78
+ if debuggable_nodes:
79
+ logger.debug("[search policy] debugging")
80
+ return random.choice(debuggable_nodes)
81
+ logger.debug("[search policy] not debugging by chance")
82
+
83
+ # back to drafting if no nodes to improve
84
+ good_nodes = self.journal.good_nodes
85
+ if not good_nodes:
86
+ logger.debug("[search policy] drafting new node (no good nodes)")
87
+ return None
88
+
89
+ # greedy
90
+ greedy_node = self.journal.get_best_node()
91
+ logger.debug("[search policy] greedy node selected")
92
+ return greedy_node
93
+
94
+ @property
95
+ def _prompt_environment(self):
96
+ pkgs = [
97
+ "numpy",
98
+ "pandas",
99
+ "scikit-learn",
100
+ "statsmodels",
101
+ "xgboost",
102
+ "lightGBM",
103
+ "torch",
104
+ "torchvision",
105
+ "torch-geometric",
106
+ "bayesian-optimization",
107
+ "timm",
108
+ ]
109
+ random.shuffle(pkgs)
110
+ pkg_str = ", ".join([f"`{p}`" for p in pkgs])
111
+
112
+ env_prompt = {
113
+ "Installed Packages": f"Your solution can use any relevant machine learning packages such as: {pkg_str}. Feel free to use any other packages too (all packages are already installed!). For neural networks we suggest using PyTorch rather than TensorFlow."
114
+ }
115
+ return env_prompt
116
+
117
+ @property
118
+ def _prompt_impl_guideline(self):
119
+ impl_guideline = [
120
+ "The code should **implement the proposed solution** and **print the value of the evaluation metric computed on a hold-out validation set**.",
121
+ "The code should be a single-file python program that is self-contained and can be executed as-is.",
122
+ "No parts of the code should be skipped, don't terminate the before finishing the script.",
123
+ "Your response should only contain a single code block.",
124
+ f"Be aware of the running time of the code, it should complete within {humanize.naturaldelta(self.cfg.exec.timeout)}.",
125
+ 'All the provided input data is stored in "./input" directory.',
126
+ '**If there is test data provided for this task, please save the test predictions in a `submission.csv` file in the "./working" directory as described in the task description** This is extremely important since this file is used for grading/evaluation. DO NOT FORGET THE submission.csv file!',
127
+ 'You can also use the "./working" directory to store any temporary files that your code needs to create.',
128
+ ]
129
+ if self.acfg.expose_prediction:
130
+ impl_guideline.append(
131
+ "The implementation should include a predict() function, "
132
+ "allowing users to seamlessly reuse the code to make predictions on new data. "
133
+ "The prediction function should be well-documented, especially the function signature."
134
+ )
135
+
136
+ if self.acfg.k_fold_validation > 1:
137
+ impl_guideline.append(
138
+ f"The evaluation should be based on {self.acfg.k_fold_validation}-fold cross-validation but only if that's an appropriate evaluation for the task at hand."
139
+ )
140
+
141
+ return {"Implementation guideline": impl_guideline}
142
+
143
+ @property
144
+ def _prompt_resp_fmt(self):
145
+ return {
146
+ "Response format": (
147
+ "Your response should be a brief outline/sketch of your proposed solution in natural language (3-5 sentences), "
148
+ "followed by a single markdown code block (wrapped in ```) which implements this solution and prints out the evaluation metric. "
149
+ "There should be no additional headings or text in your response. Just natural language text followed by a newline and then the markdown code block. "
150
+ )
151
+ }
152
+
153
+ def plan_and_code_query(self, prompt, retries=3) -> tuple[str, str]:
154
+ """Generate a natural language plan + code in the same LLM call and split them apart."""
155
+ completion_text = None
156
+ for _ in range(retries):
157
+ completion_text = query(
158
+ system_message=prompt,
159
+ user_message=None,
160
+ model=self.acfg.code.model,
161
+ temperature=self.acfg.code.temp,
162
+ )
163
+
164
+ code = extract_code(completion_text)
165
+ nl_text = extract_text_up_to_code(completion_text)
166
+
167
+ if code and nl_text:
168
+ # merge all code blocks into a single string
169
+ return nl_text, code
170
+
171
+ print("Plan + code extraction failed, retrying...")
172
+ print("Final plan + code extraction attempt failed, giving up...")
173
+ return "", completion_text # type: ignore
174
+
175
+ def _draft(self) -> Node:
176
+ prompt: Any = {
177
+ "Introduction": (
178
+ "You are a Kaggle grandmaster attending a competition. "
179
+ "In order to win this competition, you need to come up with an excellent and creative plan "
180
+ "for a solution and then implement this solution in Python. We will now provide a description of the task."
181
+ ),
182
+ "Task description": self.task_desc,
183
+ "Memory": self.journal.generate_summary(),
184
+ "Instructions": {},
185
+ }
186
+ prompt["Instructions"] |= self._prompt_resp_fmt
187
+ prompt["Instructions"] |= {
188
+ "Solution sketch guideline": [
189
+ "This first solution design should be relatively simple, without ensembling or hyper-parameter optimization.",
190
+ "Take the Memory section into consideration when proposing the design,"
191
+ " don't propose the same modelling solution but keep the evaluation the same.",
192
+ "The solution sketch should be 3-5 sentences.",
193
+ "Propose an evaluation metric that is reasonable for this task.",
194
+ "Don't suggest to do EDA.",
195
+ "The data is already prepared and available in the `./input` directory. There is no need to unzip any files.",
196
+ ],
197
+ }
198
+ prompt["Instructions"] |= self._prompt_impl_guideline
199
+ prompt["Instructions"] |= self._prompt_environment
200
+
201
+ if self.acfg.data_preview:
202
+ prompt["Data Overview"] = self.data_preview
203
+
204
+ plan, code = self.plan_and_code_query(prompt)
205
+ return Node(plan=plan, code=code)
206
+
207
+ def _improve(self, parent_node: Node) -> Node:
208
+ prompt: Any = {
209
+ "Introduction": (
210
+ "You are a Kaggle grandmaster attending a competition. You are provided with a previously developed "
211
+ "solution below and should improve it in order to further increase the (test time) performance. "
212
+ "For this you should first outline a brief plan in natural language for how the solution can be improved and "
213
+ "then implement this improvement in Python based on the provided previous solution. "
214
+ ),
215
+ "Task description": self.task_desc,
216
+ "Memory": self.journal.generate_summary(),
217
+ "Instructions": {},
218
+ }
219
+ prompt["Previous solution"] = {
220
+ "Code": wrap_code(parent_node.code),
221
+ }
222
+
223
+ prompt["Instructions"] |= self._prompt_resp_fmt
224
+ prompt["Instructions"] |= {
225
+ "Solution improvement sketch guideline": [
226
+ "The solution sketch should be a brief natural language description of how the previous solution can be improved.",
227
+ "You should be very specific and should only propose a single actionable improvement.",
228
+ "This improvement should be atomic so that we can experimentally evaluate the effect of the proposed change.",
229
+ "Take the Memory section into consideration when proposing the improvement.",
230
+ "The solution sketch should be 3-5 sentences.",
231
+ "Don't suggest to do EDA.",
232
+ ],
233
+ }
234
+ prompt["Instructions"] |= self._prompt_impl_guideline
235
+
236
+ plan, code = self.plan_and_code_query(prompt)
237
+ return Node(
238
+ plan=plan,
239
+ code=code,
240
+ parent=parent_node,
241
+ )
242
+
243
+ def _debug(self, parent_node: Node) -> Node:
244
+ prompt: Any = {
245
+ "Introduction": (
246
+ "You are a Kaggle grandmaster attending a competition. "
247
+ "Your previous solution had a bug, so based on the information below, you should revise it in order to fix this bug. "
248
+ "Your response should be an implementation outline in natural language,"
249
+ " followed by a single markdown code block which implements the bugfix/solution."
250
+ ),
251
+ "Task description": self.task_desc,
252
+ "Previous (buggy) implementation": wrap_code(parent_node.code),
253
+ "Execution output": wrap_code(parent_node.term_out, lang=""),
254
+ "Instructions": {},
255
+ }
256
+ prompt["Instructions"] |= self._prompt_resp_fmt
257
+ prompt["Instructions"] |= {
258
+ "Bugfix improvement sketch guideline": [
259
+ "You should write a brief natural language description (3-5 sentences) of how the issue in the previous implementation can be fixed.",
260
+ "Don't suggest to do EDA.",
261
+ ],
262
+ }
263
+ prompt["Instructions"] |= self._prompt_impl_guideline
264
+
265
+ if self.acfg.data_preview:
266
+ prompt["Data Overview"] = self.data_preview
267
+
268
+ plan, code = self.plan_and_code_query(prompt)
269
+ return Node(plan=plan, code=code, parent=parent_node)
270
+
271
+ def update_data_preview(
272
+ self,
273
+ ):
274
+ self.data_preview = data_preview.generate(self.cfg.workspace_dir)
275
+
276
+ def step(self, exec_callback: ExecCallbackType):
277
+ if not self.journal.nodes or self.data_preview is None:
278
+ self.update_data_preview()
279
+
280
+ parent_node = self.search_policy()
281
+ logger.debug(f"Agent is generating code, parent node type: {type(parent_node)}")
282
+
283
+ if parent_node is None:
284
+ result_node = self._draft()
285
+ elif parent_node.is_buggy:
286
+ result_node = self._debug(parent_node)
287
+ else:
288
+ result_node = self._improve(parent_node)
289
+
290
+ self.parse_exec_result(
291
+ node=result_node,
292
+ exec_result=exec_callback(result_node.code, True),
293
+ )
294
+ self.journal.append(result_node)
295
+
296
+ def parse_exec_result(self, node: Node, exec_result: ExecutionResult):
297
+ logger.info(f"Agent is parsing execution results for node {node.id}")
298
+
299
+ node.absorb_exec_result(exec_result)
300
+
301
+ prompt = {
302
+ "Introduction": (
303
+ "You are a Kaggle grandmaster attending a competition. "
304
+ "You have written code to solve this task and now need to evaluate the output of the code execution. "
305
+ "You should determine if there were any bugs as well as report the empirical findings."
306
+ ),
307
+ "Task description": self.task_desc,
308
+ "Implementation": wrap_code(node.code),
309
+ "Execution output": wrap_code(node.term_out, lang=""),
310
+ }
311
+
312
+ response = cast(
313
+ dict,
314
+ query(
315
+ system_message=prompt,
316
+ user_message=None,
317
+ func_spec=review_func_spec,
318
+ model=self.acfg.feedback.model,
319
+ temperature=self.acfg.feedback.temp,
320
+ ),
321
+ )
322
+
323
+ # if the metric isn't a float then fill the metric with the worst metric
324
+ if not isinstance(response["metric"], float):
325
+ response["metric"] = None
326
+
327
+ node.analysis = response["summary"]
328
+ node.is_buggy = (
329
+ response["is_bug"]
330
+ or node.exc_type is not None
331
+ or response["metric"] is None
332
+ )
333
+
334
+ if node.is_buggy:
335
+ node.metric = WorstMetricValue()
336
+ else:
337
+ node.metric = MetricValue(
338
+ response["metric"], maximize=not response["lower_is_better"]
339
+ )
aide/backend/__init__.py ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from . import backend_anthropic, backend_openai
2
+ from .utils import FunctionSpec, OutputType, PromptType, compile_prompt_to_md
3
+
4
+
5
+ def query(
6
+ system_message: PromptType | None,
7
+ user_message: PromptType | None,
8
+ model: str,
9
+ temperature: float | None = None,
10
+ max_tokens: int | None = None,
11
+ func_spec: FunctionSpec | None = None,
12
+ **model_kwargs,
13
+ ) -> OutputType:
14
+ """
15
+ General LLM query for various backends with a single system and user message.
16
+ Supports function calling for some backends.
17
+
18
+ Args:
19
+ system_message (PromptType | None): Uncompiled system message (will generate a message following the OpenAI/Anthropic format)
20
+ user_message (PromptType | None): Uncompiled user message (will generate a message following the OpenAI/Anthropic format)
21
+ model (str): string identifier for the model to use (e.g. "gpt-4-turbo")
22
+ temperature (float | None, optional): Temperature to sample at. Defaults to the model-specific default.
23
+ max_tokens (int | None, optional): Maximum number of tokens to generate. Defaults to the model-specific max tokens.
24
+ func_spec (FunctionSpec | None, optional): Optional FunctionSpec object defining a function call. If given, the return value will be a dict.
25
+
26
+ Returns:
27
+ OutputType: A string completion if func_spec is None, otherwise a dict with the function call details.
28
+ """
29
+
30
+ model_kwargs = model_kwargs | {
31
+ "model": model,
32
+ "temperature": temperature,
33
+ "max_tokens": max_tokens,
34
+ }
35
+
36
+ # Handle models with beta limitations
37
+ # ref: https://platform.openai.com/docs/guides/reasoning/beta-limitations
38
+ if model.startswith("o1"):
39
+ if system_message:
40
+ user_message = system_message
41
+ system_message = None
42
+ model_kwargs["temperature"] = 1
43
+
44
+ query_func = backend_anthropic.query if "claude-" in model else backend_openai.query
45
+ output, req_time, in_tok_count, out_tok_count, info = query_func(
46
+ system_message=compile_prompt_to_md(system_message) if system_message else None,
47
+ user_message=compile_prompt_to_md(user_message) if user_message else None,
48
+ func_spec=func_spec,
49
+ **model_kwargs,
50
+ )
51
+
52
+ return output
aide/backend/backend_anthropic.py ADDED
@@ -0,0 +1,107 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Backend for Anthropic API."""
2
+
3
+ import logging
4
+ import time
5
+
6
+ from .utils import FunctionSpec, OutputType, opt_messages_to_list, backoff_create
7
+ from funcy import notnone, once, select_values
8
+ import anthropic
9
+
10
+ logger = logging.getLogger("aide")
11
+
12
+ _client: anthropic.Anthropic = None # type: ignore
13
+
14
+ ANTHROPIC_TIMEOUT_EXCEPTIONS = (
15
+ anthropic.RateLimitError,
16
+ anthropic.APIConnectionError,
17
+ anthropic.APITimeoutError,
18
+ anthropic.InternalServerError,
19
+ )
20
+
21
+ ANTHROPIC_MODEL_ALIASES = {
22
+ "claude-3.5-sonnet": "claude-3-sonnet-20241022",
23
+ }
24
+
25
+
26
+ @once
27
+ def _setup_anthropic_client():
28
+ global _client
29
+ _client = anthropic.Anthropic(max_retries=0)
30
+
31
+
32
+ def query(
33
+ system_message: str | None,
34
+ user_message: str | None,
35
+ func_spec: FunctionSpec | None = None,
36
+ **model_kwargs,
37
+ ) -> tuple[OutputType, float, int, int, dict]:
38
+ """
39
+ Query Anthropic's API, optionally with tool use (Anthropic's equivalent to function calling).
40
+ """
41
+ _setup_anthropic_client()
42
+
43
+ filtered_kwargs: dict = select_values(notnone, model_kwargs) # type: ignore
44
+ if "max_tokens" not in filtered_kwargs:
45
+ filtered_kwargs["max_tokens"] = 4096 # default for Claude models
46
+
47
+ model_name = filtered_kwargs.get("model", "")
48
+ logger.debug(f"Anthropic query called with model='{model_name}'")
49
+
50
+ if model_name in ANTHROPIC_MODEL_ALIASES:
51
+ model_name = ANTHROPIC_MODEL_ALIASES[model_name]
52
+
53
+ if func_spec is not None and func_spec.name == "submit_review":
54
+ filtered_kwargs["tools"] = [func_spec.as_anthropic_tool_dict]
55
+ # Force tool use
56
+ filtered_kwargs["tool_choice"] = func_spec.anthropic_tool_choice_dict
57
+
58
+ # Anthropic doesn't allow not having user messages
59
+ # if we only have system msg -> use it as user msg
60
+ if system_message is not None and user_message is None:
61
+ system_message, user_message = user_message, system_message
62
+
63
+ # Anthropic passes system messages as a separate argument
64
+ if system_message is not None:
65
+ filtered_kwargs["system"] = system_message
66
+
67
+ messages = opt_messages_to_list(None, user_message)
68
+
69
+ t0 = time.time()
70
+ message = backoff_create(
71
+ _client.messages.create,
72
+ ANTHROPIC_TIMEOUT_EXCEPTIONS,
73
+ messages=messages,
74
+ **filtered_kwargs,
75
+ )
76
+ req_time = time.time() - t0
77
+
78
+ # Handle tool calls if present
79
+ if (
80
+ func_spec is not None
81
+ and "tools" in filtered_kwargs
82
+ and len(message.content) > 0
83
+ and message.content[0].type == "tool_use"
84
+ ):
85
+ block = message.content[0] # This is a "ToolUseBlock"
86
+ # block has attributes: type, id, name, input
87
+ assert (
88
+ block.name == func_spec.name
89
+ ), f"Function name mismatch: expected {func_spec.name}, got {block.name}"
90
+ output = block.input # Anthropic calls the parameters "input"
91
+ else:
92
+ # For non-tool responses, ensure we have text content
93
+ assert len(message.content) == 1, "Expected single content item"
94
+ assert (
95
+ message.content[0].type == "text"
96
+ ), f"Expected text response, got {message.content[0].type}"
97
+ output = message.content[0].text
98
+
99
+ in_tokens = message.usage.input_tokens
100
+ out_tokens = message.usage.output_tokens
101
+
102
+ info = {
103
+ "stop_reason": message.stop_reason,
104
+ "model": message.model,
105
+ }
106
+
107
+ return output, req_time, in_tokens, out_tokens, info
aide/backend/backend_openai.py ADDED
@@ -0,0 +1,127 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Backend for OpenAI API."""
2
+
3
+ import json
4
+ import logging
5
+ import time
6
+
7
+ from .utils import FunctionSpec, OutputType, opt_messages_to_list, backoff_create
8
+ from funcy import notnone, once, select_values
9
+ import openai
10
+
11
+ logger = logging.getLogger("aide")
12
+
13
+ _client: openai.OpenAI = None # type: ignore
14
+
15
+ OPENAI_TIMEOUT_EXCEPTIONS = (
16
+ openai.RateLimitError,
17
+ openai.APIConnectionError,
18
+ openai.APITimeoutError,
19
+ openai.InternalServerError,
20
+ )
21
+
22
+
23
+ @once
24
+ def _setup_openai_client():
25
+ global _client
26
+ _client = openai.OpenAI(max_retries=0)
27
+
28
+
29
+ def query(
30
+ system_message: str | None,
31
+ user_message: str | None,
32
+ func_spec: FunctionSpec | None = None,
33
+ **model_kwargs,
34
+ ) -> tuple[OutputType, float, int, int, dict]:
35
+ """
36
+ Query the OpenAI API, optionally with function calling.
37
+ If the model doesn't support function calling, gracefully degrade to text generation.
38
+ """
39
+ _setup_openai_client()
40
+ filtered_kwargs: dict = select_values(notnone, model_kwargs)
41
+
42
+ # Convert system/user messages to the format required by the client
43
+ messages = opt_messages_to_list(system_message, user_message)
44
+
45
+ # If function calling is requested, attach the function spec
46
+ if func_spec is not None:
47
+ filtered_kwargs["tools"] = [func_spec.as_openai_tool_dict]
48
+ filtered_kwargs["tool_choice"] = func_spec.openai_tool_choice_dict
49
+
50
+ completion = None
51
+ t0 = time.time()
52
+
53
+ # Attempt the API call
54
+ try:
55
+ completion = backoff_create(
56
+ _client.chat.completions.create,
57
+ OPENAI_TIMEOUT_EXCEPTIONS,
58
+ messages=messages,
59
+ **filtered_kwargs,
60
+ )
61
+ except openai.error.BadRequestError as e:
62
+ # Check whether the error indicates that function calling is not supported
63
+ if "function calling" in str(e).lower() or "tools" in str(e).lower():
64
+ logger.warning(
65
+ "Function calling was attempted but is not supported by this model. "
66
+ "Falling back to plain text generation."
67
+ )
68
+ # Remove function-calling parameters and retry
69
+ filtered_kwargs.pop("tools", None)
70
+ filtered_kwargs.pop("tool_choice", None)
71
+
72
+ # Retry without function calling
73
+ completion = backoff_create(
74
+ _client.chat.completions.create,
75
+ OPENAI_TIMEOUT_EXCEPTIONS,
76
+ messages=messages,
77
+ **filtered_kwargs,
78
+ )
79
+ else:
80
+ # If it's some other error, re-raise
81
+ raise
82
+
83
+ req_time = time.time() - t0
84
+ choice = completion.choices[0]
85
+
86
+ # Decide how to parse the response
87
+ if func_spec is None or "tools" not in filtered_kwargs:
88
+ # No function calling was ultimately used
89
+ output = choice.message.content
90
+ else:
91
+ # Attempt to extract tool calls
92
+ tool_calls = getattr(choice.message, "tool_calls", None)
93
+ if not tool_calls:
94
+ logger.warning(
95
+ "No function call was used despite function spec. Fallback to text.\n"
96
+ f"Message content: {choice.message.content}"
97
+ )
98
+ output = choice.message.content
99
+ else:
100
+ first_call = tool_calls[0]
101
+ # Optional: verify that the function name matches
102
+ if first_call.function.name != func_spec.name:
103
+ logger.warning(
104
+ f"Function name mismatch: expected {func_spec.name}, "
105
+ f"got {first_call.function.name}. Fallback to text."
106
+ )
107
+ output = choice.message.content
108
+ else:
109
+ try:
110
+ output = json.loads(first_call.function.arguments)
111
+ except json.JSONDecodeError as ex:
112
+ logger.error(
113
+ "Error decoding function arguments:\n"
114
+ f"{first_call.function.arguments}"
115
+ )
116
+ raise ex
117
+
118
+ in_tokens = completion.usage.prompt_tokens
119
+ out_tokens = completion.usage.completion_tokens
120
+
121
+ info = {
122
+ "system_fingerprint": completion.system_fingerprint,
123
+ "model": completion.model,
124
+ "created": completion.created,
125
+ }
126
+
127
+ return output, req_time, in_tokens, out_tokens, info
aide/backend/utils.py ADDED
@@ -0,0 +1,101 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from dataclasses import dataclass
2
+
3
+ import jsonschema
4
+ from dataclasses_json import DataClassJsonMixin
5
+ import backoff
6
+ import logging
7
+ from typing import Callable
8
+
9
+ PromptType = str | dict | list
10
+ FunctionCallType = dict
11
+ OutputType = str | FunctionCallType
12
+
13
+
14
+ logger = logging.getLogger("aide")
15
+
16
+
17
+ @backoff.on_predicate(
18
+ wait_gen=backoff.expo,
19
+ max_value=60,
20
+ factor=1.5,
21
+ )
22
+ def backoff_create(
23
+ create_fn: Callable, retry_exceptions: list[Exception], *args, **kwargs
24
+ ):
25
+ try:
26
+ return create_fn(*args, **kwargs)
27
+ except retry_exceptions as e:
28
+ logger.info(f"Backoff exception: {e}")
29
+ return False
30
+
31
+
32
+ def opt_messages_to_list(
33
+ system_message: str | None, user_message: str | None
34
+ ) -> list[dict[str, str]]:
35
+ messages = []
36
+ if system_message:
37
+ messages.append({"role": "system", "content": system_message})
38
+ if user_message:
39
+ messages.append({"role": "user", "content": user_message})
40
+ return messages
41
+
42
+
43
+ def compile_prompt_to_md(prompt: PromptType, _header_depth: int = 1) -> str:
44
+ if isinstance(prompt, str):
45
+ return prompt.strip() + "\n"
46
+ elif isinstance(prompt, list):
47
+ return "\n".join([f"- {s.strip()}" for s in prompt] + ["\n"])
48
+
49
+ out = []
50
+ header_prefix = "#" * _header_depth
51
+ for k, v in prompt.items():
52
+ out.append(f"{header_prefix} {k}\n")
53
+ out.append(compile_prompt_to_md(v, _header_depth=_header_depth + 1))
54
+ return "\n".join(out)
55
+
56
+
57
+ @dataclass
58
+ class FunctionSpec(DataClassJsonMixin):
59
+ name: str
60
+ json_schema: dict # JSON schema
61
+ description: str
62
+
63
+ def __post_init__(self):
64
+ # validate the schema
65
+ jsonschema.Draft7Validator.check_schema(self.json_schema)
66
+
67
+ @property
68
+ def as_openai_tool_dict(self):
69
+ """Convert to OpenAI's function format."""
70
+ return {
71
+ "type": "function",
72
+ "function": {
73
+ "name": self.name,
74
+ "description": self.description,
75
+ "parameters": self.json_schema,
76
+ },
77
+ }
78
+
79
+ @property
80
+ def openai_tool_choice_dict(self):
81
+ return {
82
+ "type": "function",
83
+ "function": {"name": self.name},
84
+ }
85
+
86
+ @property
87
+ def as_anthropic_tool_dict(self):
88
+ """Convert to Anthropic's tool format."""
89
+ return {
90
+ "name": self.name,
91
+ "description": self.description,
92
+ "input_schema": self.json_schema, # Anthropic uses input_schema instead of parameters
93
+ }
94
+
95
+ @property
96
+ def anthropic_tool_choice_dict(self):
97
+ """Convert to Anthropic's tool choice format."""
98
+ return {
99
+ "type": "tool", # Anthropic uses "tool" instead of "function"
100
+ "name": self.name,
101
+ }
aide/example_tasks/bitcoin_price.md ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ ## Goal
2
+ Build a timeseries forcasting model for bitcoin close price.
3
+
4
+ ## Evaluation metric
5
+ Root-Mean-Squared-Error (RMSE) between the logarithm of the predicted value and the logarithm of the observed price.
aide/example_tasks/bitcoin_price/BTC-USD.csv ADDED
@@ -0,0 +1,501 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Date,Open,High,Low,Close,Adj Close,Volume
2
+ 2014-09-15,465.864014,468.174011,384.532013,398.821014,398.821014,156903400
3
+ 2014-09-22,399.100006,441.557007,374.332001,377.181000,377.181000,186772600
4
+ 2014-09-29,376.928009,391.378998,289.295990,320.510010,320.510010,276657896
5
+ 2014-10-06,320.389008,382.726013,302.559998,378.549011,378.549011,341152804
6
+ 2014-10-13,377.920990,411.697998,368.897003,389.545990,389.545990,156902070
7
+ 2014-10-20,389.230988,392.645996,342.877014,354.704010,354.704010,113691800
8
+ 2014-10-27,354.777008,359.984009,320.626007,325.891998,325.891998,107075700
9
+ 2014-11-03,325.569000,363.626007,325.076996,363.264008,363.264008,116793470
10
+ 2014-11-10,362.265015,457.092987,357.561005,387.881989,387.881989,208239500
11
+ 2014-11-17,388.348999,410.199005,344.112000,367.572998,367.572998,178181000
12
+ 2014-11-24,366.947998,394.700989,358.454987,378.046997,378.046997,131238570
13
+ 2014-12-01,378.248993,384.037994,365.756012,375.095001,375.095001,80679570
14
+ 2014-12-08,374.964996,376.028992,338.763000,351.631989,351.631989,141754100
15
+ 2014-12-15,351.360992,351.815002,304.231995,320.842987,320.842987,184757400
16
+ 2014-12-22,321.067993,336.286987,311.078003,317.239014,317.239014,107137540
17
+ 2014-12-29,317.700989,320.434998,257.612000,264.195007,264.195007,143354400
18
+ 2015-01-05,265.084015,298.753998,265.039001,265.660004,265.660004,164241500
19
+ 2015-01-12,266.145996,272.203003,171.509995,210.339005,210.339005,363112212
20
+ 2015-01-19,211.470993,255.074005,205.153000,253.718002,253.718002,189165500
21
+ 2015-01-26,254.078995,309.384003,212.014999,226.972000,226.972000,306840500
22
+ 2015-02-02,226.490997,245.957001,214.725006,223.412003,223.412003,183691200
23
+ 2015-02-09,223.389008,265.610992,215.332001,234.824997,234.824997,230343800
24
+ 2015-02-16,234.824997,255.320007,229.022003,235.977005,235.977005,154676000
25
+ 2015-02-23,235.994995,261.660004,232.421005,260.201996,260.201996,138892900
26
+ 2015-03-02,260.356995,285.795990,258.312988,274.354004,274.354004,242425100
27
+ 2015-03-09,274.812012,300.044006,273.893005,286.393005,286.393005,259502000
28
+ 2015-03-16,285.684998,294.112000,248.636002,267.959991,267.959991,206778200
29
+ 2015-03-23,267.894989,277.296997,236.514999,242.712997,242.712997,179497700
30
+ 2015-03-30,242.878998,260.674988,239.214005,260.597992,260.597992,150120700
31
+ 2015-04-06,260.721008,261.798004,232.770996,236.153000,236.153000,147866600
32
+ 2015-04-13,235.949997,236.934998,216.322998,222.600006,222.600006,158658500
33
+ 2015-04-20,222.612000,237.908997,214.873993,219.429993,219.429993,148576200
34
+ 2015-04-27,219.429001,243.240005,218.022995,240.358002,240.358002,162643200
35
+ 2015-05-04,240.356003,247.804001,228.572998,240.296005,240.296005,166059200
36
+ 2015-05-11,240.298996,244.270004,234.057007,236.802002,236.802002,130322100
37
+ 2015-05-18,236.886993,241.977997,231.817001,240.953003,240.953003,114746500
38
+ 2015-05-25,240.927002,241.020996,229.542007,230.190002,230.190002,107149900
39
+ 2015-06-01,230.233002,231.712997,221.296005,222.880997,222.880997,121536400
40
+ 2015-06-08,222.878998,234.858002,222.839005,233.542999,233.542999,121541200
41
+ 2015-06-15,233.421997,256.852997,233.421997,243.944000,243.944000,191537000
42
+ 2015-06-22,243.968994,251.339005,240.365005,249.011002,249.011002,115888900
43
+ 2015-06-29,248.720993,274.506012,248.580994,271.912994,271.912994,206668700
44
+ 2015-07-06,271.108002,314.394012,264.385986,310.867004,310.867004,353198700
45
+ 2015-07-13,310.826996,310.947998,272.042999,273.614014,273.614014,235861300
46
+ 2015-07-20,273.498993,293.052002,272.959991,292.686005,292.686005,157457100
47
+ 2015-07-27,292.639008,297.773987,277.528992,282.614014,282.614014,162700300
48
+ 2015-08-03,282.806000,285.714996,260.467987,265.083008,265.083008,207110300
49
+ 2015-08-10,265.477997,270.673004,257.040985,258.506989,258.506989,177043500
50
+ 2015-08-17,258.489990,260.505005,211.078995,228.169006,228.169006,221695600
51
+ 2015-08-24,228.112000,235.218994,199.567001,228.761002,228.761002,241915000
52
+ 2015-08-31,229.113998,242.912003,225.914993,239.839996,239.839996,144635800
53
+ 2015-09-07,239.934006,245.781006,229.332001,230.511993,230.511993,148588700
54
+ 2015-09-14,230.608994,259.182007,227.401993,231.212006,231.212006,126654700
55
+ 2015-09-21,231.216995,237.427002,225.117004,232.757004,232.757004,137307600
56
+ 2015-09-28,232.835999,239.802002,232.466995,238.259003,238.259003,136796200
57
+ 2015-10-05,238.147003,247.242996,237.035004,247.050003,247.050003,142478600
58
+ 2015-10-12,246.875000,273.578003,243.757004,261.643005,261.643005,199808300
59
+ 2015-10-19,261.860992,294.058990,260.950989,283.679993,283.679993,220696500
60
+ 2015-10-26,283.627991,334.169006,280.510010,325.431000,325.431000,357648800
61
+ 2015-11-02,325.941986,495.562012,323.209015,373.368011,373.368011,954934692
62
+ 2015-11-09,374.324005,385.278015,300.997009,320.165985,320.165985,484398204
63
+ 2015-11-16,319.734985,338.350006,312.217010,324.536011,324.536011,292569400
64
+ 2015-11-23,324.350006,371.938995,316.769989,371.294006,371.294006,337018400
65
+ 2015-11-30,371.437012,402.808990,349.464996,388.782990,388.782990,416857500
66
+ 2015-12-07,389.977997,469.102997,385.411011,433.755005,433.755005,562276900
67
+ 2015-12-14,433.272003,465.580994,430.455994,442.684998,442.684998,553061704
68
+ 2015-12-21,442.838013,458.455994,405.760010,422.822998,422.822998,441634396
69
+ 2015-12-28,423.342987,436.246002,418.480988,430.010986,430.010986,300130400
70
+ 2016-01-04,430.061005,462.933990,426.341003,447.990997,447.990997,319871700
71
+ 2016-01-11,448.697998,450.661987,354.914001,382.299011,382.299011,692913108
72
+ 2016-01-18,381.733002,425.266998,375.282013,402.971008,402.971008,493900500
73
+ 2016-01-25,402.316986,402.316986,365.451996,368.766998,368.766998,378185696
74
+ 2016-02-01,369.350006,391.608002,367.957001,376.619995,376.619995,337404904
75
+ 2016-02-08,376.756989,407.230011,372.898010,407.230011,407.230011,465920396
76
+ 2016-02-15,407.567993,448.045990,397.748993,438.798004,438.798004,546633900
77
+ 2016-02-22,438.989014,439.858002,413.907013,433.503998,433.503998,465584792
78
+ 2016-02-29,433.437988,441.506989,394.035004,407.707001,407.707001,628483380
79
+ 2016-03-07,407.756989,423.925995,406.308990,414.065002,414.065002,548114688
80
+ 2016-03-14,414.200989,420.997009,406.136993,413.755005,413.755005,520066400
81
+ 2016-03-21,413.417999,428.796997,410.381012,426.765015,426.765015,426699404
82
+ 2016-03-28,426.548004,426.856995,412.496002,420.903992,420.903992,405154204
83
+ 2016-04-04,421.299011,425.360992,416.515015,421.563995,421.563995,415027900
84
+ 2016-04-11,421.872009,432.625000,420.532990,427.398987,427.398987,382137900
85
+ 2016-04-18,427.610992,460.145996,427.085999,458.554993,458.554993,427064400
86
+ 2016-04-25,459.121002,467.964996,436.649994,451.875000,451.875000,492934504
87
+ 2016-05-02,451.933014,461.375000,441.776001,458.548004,458.548004,403817800
88
+ 2016-05-09,458.205994,462.480988,448.954010,457.567993,457.567993,351471700
89
+ 2016-05-16,457.585999,458.200012,437.389008,439.322998,439.322998,470557100
90
+ 2016-05-23,439.347992,553.960022,438.822998,526.232971,526.232971,741517392
91
+ 2016-05-30,528.471008,590.132019,520.661987,574.976990,574.976990,658668096
92
+ 2016-06-06,574.601990,684.843994,567.513977,672.783997,672.783997,757909588
93
+ 2016-06-13,671.653992,777.989990,662.804016,763.781006,763.781006,1553070776
94
+ 2016-06-20,763.927002,764.083984,558.138977,629.367004,629.367004,1464507992
95
+ 2016-06-27,629.348999,704.968018,620.523987,658.664001,658.664001,918252000
96
+ 2016-07-04,658.804016,683.661987,611.833984,649.359985,649.359985,1040574400
97
+ 2016-07-11,648.484009,682.364990,644.979980,679.458984,679.458984,682454600
98
+ 2016-07-18,679.809021,681.554993,646.721985,661.284973,661.284973,607681700
99
+ 2016-07-25,661.263000,661.828003,624.364990,624.681030,624.681030,747178496
100
+ 2016-08-01,624.601990,626.119019,531.333984,592.690002,592.690002,1015417588
101
+ 2016-08-08,592.736023,599.984009,564.781006,570.473022,570.473022,504473696
102
+ 2016-08-15,570.494019,584.158020,563.239990,581.307983,581.307983,364239500
103
+ 2016-08-22,581.310974,589.473999,568.630005,573.911987,573.911987,545508100
104
+ 2016-08-29,574.070984,611.836975,570.810974,608.633972,608.633972,670372392
105
+ 2016-09-05,608.989990,628.817993,600.505981,606.718994,606.718994,505899104
106
+ 2016-09-12,607.005005,611.952026,605.192017,609.874023,609.874023,417858304
107
+ 2016-09-19,609.870972,610.932007,595.786011,600.825989,600.825989,397773096
108
+ 2016-09-26,600.807007,615.237000,600.348999,610.892029,610.892029,364686600
109
+ 2016-10-03,610.968018,619.848999,609.479004,616.752014,616.752014,367150204
110
+ 2016-10-10,616.822021,642.898010,616.197021,641.630981,641.630981,462540104
111
+ 2016-10-17,641.817993,661.129028,628.013000,657.070984,657.070984,438931392
112
+ 2016-10-24,657.161011,720.401978,652.594971,701.864014,701.864014,654150896
113
+ 2016-10-31,702.640015,745.773010,678.156006,711.521973,711.521973,698826796
114
+ 2016-11-07,710.736023,740.046021,687.315002,702.031006,702.031006,554004996
115
+ 2016-11-14,701.997009,756.237000,699.807983,731.026001,731.026001,736991600
116
+ 2016-11-21,731.265015,753.869995,729.625000,732.034973,732.034973,528543596
117
+ 2016-11-28,732.484009,781.296021,732.484009,773.872009,773.872009,552642604
118
+ 2016-12-05,773.393982,777.091980,751.713013,769.731018,769.731018,578980796
119
+ 2016-12-12,770.039978,794.737000,770.039978,790.530029,790.530029,538898096
120
+ 2016-12-19,790.692017,925.117004,790.320007,896.182983,896.182983,1087074704
121
+ 2016-12-26,896.905029,1003.080017,896.898010,998.325012,998.325012,1161413112
122
+ 2017-01-02,998.617004,1191.099976,823.556030,911.198975,911.198975,2052639008
123
+ 2017-01-09,913.244019,919.447998,755.755981,821.797974,821.797974,1123984880
124
+ 2017-01-16,821.783020,937.525024,820.270996,924.672974,924.672974,883611600
125
+ 2017-01-23,925.499023,928.265991,891.687012,919.495972,919.495972,693151900
126
+ 2017-01-30,920.151001,1045.900024,919.473999,1027.339966,1027.339966,1009290288
127
+ 2017-02-06,1028.400024,1088.989990,946.690979,999.181030,999.181030,1227087016
128
+ 2017-02-13,998.885010,1061.099976,976.002014,1047.869995,1047.869995,763560200
129
+ 2017-02-20,1048.689941,1200.390015,1041.689941,1165.199951,1165.199951,1209106992
130
+ 2017-02-27,1163.780029,1280.310059,1163.380005,1267.119995,1267.119995,1546994008
131
+ 2017-03-06,1267.469971,1276.000000,1077.250000,1221.380005,1221.380005,2064090976
132
+ 2017-03-13,1221.780029,1257.979980,957.655029,1036.739990,1036.739990,3296504976
133
+ 2017-03-20,1037.239990,1122.430054,903.713013,966.724976,966.724976,2483811008
134
+ 2017-03-27,972.054993,1107.589966,971.984009,1102.170044,1102.170044,2601401984
135
+ 2017-04-03,1102.949951,1197.209961,1102.949951,1187.869995,1187.869995,2711437088
136
+ 2017-04-10,1187.300049,1208.069946,1156.439941,1182.939941,1182.939941,1714353040
137
+ 2017-04-17,1183.250000,1240.790039,1172.650024,1207.209961,1207.209961,1907337008
138
+ 2017-04-24,1209.630005,1347.910034,1209.630005,1347.890015,1347.890015,2620499984
139
+ 2017-05-01,1348.300049,1618.030029,1348.300049,1596.709961,1596.709961,5316902848
140
+ 2017-05-08,1596.920044,1873.930054,1596.920044,1808.910034,1808.910034,5981268000
141
+ 2017-05-15,1808.439941,2119.080078,1661.910034,2041.199951,2041.199951,6916110976
142
+ 2017-05-22,2043.189941,2763.709961,1855.829956,2155.800049,2155.800049,12064150016
143
+ 2017-05-29,2159.429932,2585.889893,2107.169922,2511.810059,2511.810059,9823705088
144
+ 2017-06-05,2512.399902,2999.909912,2510.219971,2958.110107,2958.110107,11378039936
145
+ 2017-06-12,2953.219971,2997.260010,2212.959961,2548.290039,2548.290039,11981910016
146
+ 2017-06-19,2549.030029,2772.010010,2549.030029,2589.409912,2589.409912,9130718976
147
+ 2017-06-26,2590.570068,2615.250000,2332.989990,2506.469971,2506.469971,7730852928
148
+ 2017-07-03,2498.560059,2916.139893,2480.469971,2518.439941,2518.439941,5831748992
149
+ 2017-07-10,2525.250000,2537.159912,1843.030029,1929.819946,1929.819946,7453121024
150
+ 2017-07-17,1932.619995,2900.699951,1932.619995,2730.399902,2730.399902,9947990080
151
+ 2017-07-24,2732.699951,2897.449951,2450.800049,2757.179932,2757.179932,6942860928
152
+ 2017-07-31,2763.239990,3293.290039,2668.590088,3213.939941,3213.939941,8137841920
153
+ 2017-08-07,3212.780029,4208.390137,3180.889893,4073.260010,4073.260010,13618979840
154
+ 2017-08-14,4066.100098,4484.700195,3906.179932,4087.659912,4087.659912,18573839872
155
+ 2017-08-21,4090.479980,4455.700195,3674.580078,4382.879883,4382.879883,15749739904
156
+ 2017-08-28,4384.450195,4975.040039,4224.640137,4582.959961,4582.959961,15582599936
157
+ 2017-09-04,4591.629883,4661.000000,3951.040039,4122.939941,4122.939941,15468230272
158
+ 2017-09-11,4122.470215,4344.649902,2946.620117,3582.879883,3582.879883,15563199872
159
+ 2017-09-18,3591.090088,4094.070068,3553.530029,3682.840088,3682.840088,9023459008
160
+ 2017-09-25,3681.580078,4403.740234,3681.580078,4403.740234,4403.740234,9599860096
161
+ 2017-10-02,4395.810059,4624.140137,4164.049805,4610.479980,4610.479980,8289027968
162
+ 2017-10-09,4614.520020,5852.479980,4564.250000,5678.189941,5678.189941,14840320000
163
+ 2017-10-16,5687.569824,6194.879883,5151.439941,6008.419922,6008.419922,14605609856
164
+ 2017-10-23,6006.000000,6255.709961,5397.879883,6153.850098,6153.850098,14982660096
165
+ 2017-10-30,6114.850098,7617.479980,6040.850098,7407.410156,7407.410156,19841690624
166
+ 2017-11-06,7403.220215,7776.419922,5519.009766,5950.069824,5950.069824,32340969984
167
+ 2017-11-13,5938.250000,8101.910156,5844.290039,8036.490234,8036.490234,30253229824
168
+ 2017-11-20,8039.069824,9522.929688,7762.709961,9330.549805,9330.549805,30501020160
169
+ 2017-11-27,9352.719727,11858.700195,9202.049805,11323.200195,11323.200195,50411559424
170
+ 2017-12-04,11315.400391,18353.400391,11081.799805,15455.400391,15455.400391,92115268608
171
+ 2017-12-11,15427.400391,20089.000000,15404.799805,19140.800781,19140.800781,93877198848
172
+ 2017-12-18,19106.400391,19371.000000,11833.000000,13925.799805,13925.799805,117256598528
173
+ 2017-12-25,13995.900391,16930.900391,12350.099609,14156.400391,14156.400391,88557499392
174
+ 2018-01-01,14112.200195,17712.400391,13154.700195,16477.599609,16477.599609,123814400000
175
+ 2018-01-08,16476.199219,16537.900391,13105.900391,13772.000000,13772.000000,106022199296
176
+ 2018-01-15,13767.299805,14445.500000,9402.290039,11600.099609,11600.099609,97932879872
177
+ 2018-01-22,11633.099609,12040.299805,10129.700195,11786.299805,11786.299805,64691999232
178
+ 2018-01-29,11755.500000,11875.599609,7796.490234,8277.009766,8277.009766,60810019840
179
+ 2018-02-05,8270.540039,9122.549805,6048.259766,8129.970215,8129.970215,62489091072
180
+ 2018-02-12,8141.430176,11349.799805,8141.430176,10551.799805,10551.799805,53626569728
181
+ 2018-02-19,10552.599609,11958.500000,9407.059570,9664.730469,9664.730469,55388419584
182
+ 2018-02-26,9669.429688,11528.200195,9501.730469,11512.599609,11512.599609,48902649856
183
+ 2018-03-05,11532.400391,11704.099609,8513.030273,9578.629883,9578.629883,49671590400
184
+ 2018-03-12,9602.929688,9937.500000,7397.990234,8223.679688,8223.679688,42075919360
185
+ 2018-03-19,8344.120117,9177.370117,8182.399902,8495.780273,8495.780273,40853020160
186
+ 2018-03-26,8498.469727,8530.080078,6526.870117,6844.229980,6844.229980,37970689536
187
+ 2018-04-02,6844.859863,7530.939941,6575.000000,7023.520020,7023.520020,31804380416
188
+ 2018-04-09,7044.319824,8338.419922,6661.990234,8329.110352,8329.110352,40915320320
189
+ 2018-04-16,8337.570313,9001.639648,7881.720215,8802.459961,8802.459961,48741869568
190
+ 2018-04-23,8794.389648,9745.320313,8727.089844,9419.080078,9419.080078,61882420224
191
+ 2018-04-30,9426.110352,9964.500000,8891.049805,9654.799805,9654.799805,57244449280
192
+ 2018-05-07,9645.669922,9665.849609,8223.500000,8723.940430,8723.940430,50119759872
193
+ 2018-05-14,8713.099609,8881.120117,7974.819824,8513.250000,8513.250000,42360260096
194
+ 2018-05-21,8522.330078,8557.519531,7270.959961,7368.220215,7368.220215,35808230144
195
+ 2018-05-28,7371.310059,7754.890137,7090.680176,7720.250000,7720.250000,35465450496
196
+ 2018-06-04,7722.529785,7753.819824,6709.069824,6786.020020,6786.020020,33010609408
197
+ 2018-06-11,6799.290039,6910.180176,6285.629883,6499.270020,6499.270020,29844289792
198
+ 2018-06-18,6510.069824,6822.500000,5826.410156,6173.229980,6173.229980,28592079872
199
+ 2018-06-25,6171.970215,6465.509766,5835.750000,6385.819824,6385.819824,28842940160
200
+ 2018-07-02,6380.379883,6885.910156,6305.700195,6773.879883,6773.879883,29906419968
201
+ 2018-07-09,6775.080078,6838.680176,6136.419922,6359.640137,6359.640137,25200120064
202
+ 2018-07-16,6357.009766,7594.669922,6357.009766,7418.490234,7418.490234,34261730048
203
+ 2018-07-23,7414.709961,8424.269531,7409.100098,8218.459961,8218.459961,36446479872
204
+ 2018-07-30,8221.580078,8235.500000,6940.700195,7068.479980,7068.479980,32425310000
205
+ 2018-08-06,7062.939941,7166.549805,6109.029785,6322.689941,6322.689941,32181950000
206
+ 2018-08-13,6341.359863,6617.350098,5971.049805,6506.069824,6506.069824,30898230000
207
+ 2018-08-20,6500.509766,6816.790039,6297.930176,6707.259766,6707.259766,25842490000
208
+ 2018-08-27,6710.799805,7306.310059,6689.709961,7272.720215,7272.720215,30229310000
209
+ 2018-09-03,7279.029785,7388.430176,6197.520020,6300.859863,6300.859863,31456960000
210
+ 2018-09-10,6301.569824,6596.100098,6260.209961,6517.180176,6517.180176,26405400000
211
+ 2018-09-17,6514.060059,6814.560059,6208.339844,6710.629883,6710.629883,32109420000
212
+ 2018-09-24,6704.770020,6785.029785,6381.859863,6625.560059,6625.560059,31328000000
213
+ 2018-10-01,6619.850098,6653.299805,6454.029785,6602.950195,6602.950195,25943820000
214
+ 2018-10-08,6600.189941,6675.060059,6236.470215,6290.930176,6290.930176,26462410000
215
+ 2018-10-15,6292.640137,6965.060059,6258.680176,6482.350098,6482.350098,29669680000
216
+ 2018-10-22,6486.049805,6543.799805,6447.029785,6486.390137,6486.390137,24188720000
217
+ 2018-10-29,6492.350098,6547.140137,6294.569824,6376.129883,6376.129883,28245180000
218
+ 2018-11-05,6363.620117,6552.160156,6350.169922,6411.270020,6411.270020,30472560000
219
+ 2018-11-12,6411.759766,6434.209961,5358.379883,5623.540039,5623.540039,36972800000
220
+ 2018-11-19,5620.779785,5620.779785,3585.060059,4009.969971,4009.969971,42533970000
221
+ 2018-11-26,4015.070068,4413.020508,3643.919922,4139.877930,4139.877930,42945276472
222
+ 2018-12-03,4147.323730,4155.979492,3280.228760,3614.234375,3614.234375,38386467708
223
+ 2018-12-10,3612.046387,3647.332520,3191.303467,3252.839111,3252.839111,29869247431
224
+ 2018-12-17,3253.123047,4198.429688,3253.123047,3998.980225,3998.980225,46021506218
225
+ 2018-12-24,4000.331787,4271.792480,3642.632080,3865.952637,3865.952637,39249734918
226
+ 2018-12-31,3866.839111,4093.297363,3707.231201,4076.632568,4076.632568,34343716582
227
+ 2019-01-07,4078.584961,4109.020996,3544.927246,3552.953125,3552.953125,37523454177
228
+ 2019-01-14,3557.311035,3758.533447,3552.285156,3601.013672,3601.013672,38588596987
229
+ 2019-01-21,3600.372803,3654.933105,3539.721436,3583.965820,3583.965820,36949379050
230
+ 2019-01-28,3584.283203,3586.750977,3400.819824,3464.013428,3464.013428,40130888766
231
+ 2019-02-04,3467.211670,3695.614014,3391.023682,3690.188232,3690.188232,41224140801
232
+ 2019-02-11,3695.613037,3695.613037,3607.697754,3673.836182,3673.836182,44533597993
233
+ 2019-02-18,3671.369873,4210.641602,3669.982422,3810.427490,3810.427490,63853356366
234
+ 2019-02-25,3807.002441,3913.707275,3787.058838,3847.175781,3847.175781,56444684748
235
+ 2019-03-04,3845.091553,3987.237793,3733.749756,3951.599854,3951.599854,69110769320
236
+ 2019-03-11,3953.740234,4077.036377,3863.559082,4025.229004,4025.229004,67357766371
237
+ 2019-03-18,4029.968506,4097.359863,4005.151367,4022.168213,4022.168213,67975640775
238
+ 2019-03-25,4024.112793,4296.806641,3934.031250,4105.404297,4105.404297,71015021591
239
+ 2019-04-01,4105.362305,5307.003418,4096.901367,5198.896973,5198.896973,123047080530
240
+ 2019-04-08,5199.835449,5421.651367,4955.852539,5167.722168,5167.722168,98826873355
241
+ 2019-04-15,5167.321777,5359.924805,5024.069336,5314.531250,5314.531250,90285516253
242
+ 2019-04-22,5312.494629,5642.044434,5177.368652,5285.139160,5285.139160,105590631334
243
+ 2019-04-29,5284.858398,5886.893555,5216.487793,5795.708496,5795.708496,107035835884
244
+ 2019-05-06,5791.693359,7503.872070,5653.687500,6972.371582,6972.371582,141929602925
245
+ 2019-05-13,6971.178223,8320.824219,6898.282227,8197.689453,8197.689453,199543788416
246
+ 2019-05-20,8196.923828,8687.520508,7533.196777,8673.215820,8673.215820,173001140580
247
+ 2019-05-27,8674.072266,9008.314453,8172.550781,8742.958008,8742.958008,173016477871
248
+ 2019-06-03,8741.747070,8743.500000,7564.488770,7688.077148,7688.077148,140124650113
249
+ 2019-06-10,7692.284668,9335.867188,7586.730957,8994.488281,8994.488281,135051141522
250
+ 2019-06-17,8988.923828,11246.144531,8988.923828,10855.371094,10855.371094,136422336191
251
+ 2019-06-24,10853.744141,13796.489258,10491.852539,10817.155273,10817.155273,221502737682
252
+ 2019-07-01,10796.930664,12006.075195,9737.884766,11450.846680,11450.846680,181410821667
253
+ 2019-07-08,11446.596680,13129.529297,10234.576172,10256.058594,10256.058594,180936684097
254
+ 2019-07-15,10257.838867,11052.766602,9163.134766,10599.105469,10599.105469,157356814406
255
+ 2019-07-22,10596.948242,10651.791016,9252.296875,9552.860352,9552.860352,112459229432
256
+ 2019-07-29,9548.178711,11009.207031,9437.335938,10970.184570,10970.184570,110790788891
257
+ 2019-08-05,10960.735352,12273.821289,10960.735352,11523.579102,11523.579102,141427393788
258
+ 2019-08-12,11528.189453,11528.189453,9675.316406,10345.810547,10345.810547,120224711798
259
+ 2019-08-19,10350.283203,10947.041992,9831.462891,10138.517578,10138.517578,112893851548
260
+ 2019-08-26,10126.299805,10512.328125,9421.629883,9757.970703,9757.970703,104346358671
261
+ 2019-09-02,9757.473633,10898.761719,9730.650391,10441.276367,10441.276367,116441433312
262
+ 2019-09-09,10443.228516,10450.311523,9980.776367,10347.712891,10347.712891,102876391724
263
+ 2019-09-16,10347.222656,10386.867188,9851.692383,10070.392578,10070.392578,107930839412
264
+ 2019-09-23,10067.962891,10074.238281,7895.629395,8104.185547,8104.185547,124735468740
265
+ 2019-09-30,8104.226563,8497.692383,7830.758789,7988.155762,7988.155762,97716137179
266
+ 2019-10-07,7989.120605,8721.780273,7905.766113,8321.005859,8321.005859,118550918408
267
+ 2019-10-14,8320.832031,8410.714844,7902.164063,8222.078125,8222.078125,105710167423
268
+ 2019-10-21,8225.115234,10021.744141,7446.988770,9551.714844,9551.714844,176678165128
269
+ 2019-10-28,9565.101563,9805.118164,9028.717773,9235.354492,9235.354492,180364809056
270
+ 2019-11-04,9235.607422,9505.051758,8775.534180,9055.526367,9055.526367,160702732609
271
+ 2019-11-11,9056.917969,9081.279297,8473.973633,8577.975586,8577.975586,134166660428
272
+ 2019-11-18,8573.980469,8653.280273,6936.706543,7047.916992,7047.916992,171626385789
273
+ 2019-11-25,7039.977051,7836.102051,6617.166992,7424.292480,7424.292480,162444865040
274
+ 2019-12-02,7424.036133,7743.431641,7170.922852,7564.345215,7564.345215,121327747581
275
+ 2019-12-09,7561.795410,7618.091797,6924.375977,7152.301758,7152.301758,122542519854
276
+ 2019-12-16,7153.663086,7518.033203,6540.049316,7511.588867,7511.588867,165399102665
277
+ 2019-12-23,7508.902344,7656.176270,7189.934082,7422.652832,7422.652832,161758217053
278
+ 2019-12-30,7420.272949,7544.497070,6914.996094,7411.317383,7411.317383,149690652648
279
+ 2020-01-06,7410.452148,8396.738281,7409.292969,8192.494141,8192.494141,184901289966
280
+ 2020-01-13,8189.771973,9164.362305,8079.700684,8706.245117,8706.245117,241668743794
281
+ 2020-01-20,8704.631836,8792.994141,8266.840820,8596.830078,8596.830078,165113602391
282
+ 2020-01-27,8597.308594,9553.125977,8597.308594,9344.365234,9344.365234,212298356923
283
+ 2020-02-03,9344.683594,10129.435547,9112.811523,10116.673828,10116.673828,239180811399
284
+ 2020-02-10,10115.559570,10457.626953,9722.386719,9934.433594,9934.433594,300413081965
285
+ 2020-02-17,9936.560547,10191.675781,9507.637695,9924.515625,9924.515625,303140360741
286
+ 2020-02-24,9921.583008,9951.746094,8471.212891,8562.454102,8562.454102,299233009521
287
+ 2020-03-02,8563.264648,9167.695313,8105.252930,8108.116211,8108.116211,276706069337
288
+ 2020-03-09,8111.146484,8177.793457,4106.980957,5392.314941,5392.314941,326123224372
289
+ 2020-03-16,5385.229492,6844.261719,4575.357910,5830.254883,5830.254883,309907233901
290
+ 2020-03-23,5831.374512,6892.511230,5785.004395,5922.042969,5922.042969,272468247401
291
+ 2020-03-30,5925.538574,7088.247559,5903.234375,6791.129395,6791.129395,259568096070
292
+ 2020-04-06,6788.049805,7427.939453,6782.889648,6971.091797,6971.091797,274123270580
293
+ 2020-04-13,6965.616699,7280.521973,6555.504395,7189.424805,7189.424805,248073118275
294
+ 2020-04-20,7186.873535,7700.594238,6834.442383,7679.867188,7679.867188,247735013853
295
+ 2020-04-27,7679.418945,9440.650391,7679.418945,8897.468750,8897.468750,327820350244
296
+ 2020-05-04,8895.745117,9996.743164,8395.107422,8756.430664,8756.430664,361023995652
297
+ 2020-05-11,8755.535156,9823.001953,8374.323242,9670.739258,9670.739258,325655447393
298
+ 2020-05-18,9675.695313,9906.030273,8787.250977,8790.368164,8790.368164,247011272897
299
+ 2020-05-25,8786.107422,9704.030273,8719.667969,9461.058594,9461.058594,221372861711
300
+ 2020-06-01,9463.605469,10199.565430,9450.899414,9758.852539,9758.852539,194228716225
301
+ 2020-06-08,9760.063477,9938.297852,9263.069336,9386.788086,9386.788086,160324519712
302
+ 2020-06-15,9386.035156,9579.430664,8990.175781,9303.629883,9303.629883,138300100692
303
+ 2020-06-22,9300.915039,9680.367188,8975.525391,9143.582031,9143.582031,125863637229
304
+ 2020-06-29,9140.029297,9309.754883,8977.015625,9073.942383,9073.942383,102779717630
305
+ 2020-07-06,9072.849609,9450.335938,9058.664063,9276.500000,9276.500000,113994286210
306
+ 2020-07-13,9277.205078,9306.405273,9088.947266,9185.817383,9185.817383,106299733734
307
+ 2020-07-20,9187.220703,10023.807617,9137.509766,9905.166992,9905.166992,120174678243
308
+ 2020-07-27,9905.217773,12034.144531,9903.969727,11053.614258,11053.614258,188247005753
309
+ 2020-08-03,11043.768555,11902.335938,11012.415039,11675.739258,11675.739258,147527884833
310
+ 2020-08-10,11662.256836,12150.994141,11195.708984,11892.803711,11892.803711,173916901671
311
+ 2020-08-17,11895.658203,12359.056641,11448.805664,11664.847656,11664.847656,161417688724
312
+ 2020-08-24,11663.689453,11807.631836,11185.941406,11711.505859,11711.505859,149742951013
313
+ 2020-08-31,11713.306641,12067.081055,9946.675781,10280.351563,10280.351563,221515306287
314
+ 2020-09-07,10280.998047,10578.837891,9916.493164,10323.755859,10323.755859,264126813725
315
+ 2020-09-14,10328.734375,11134.092773,10266.008789,10938.271484,10938.271484,210690462551
316
+ 2020-09-21,10934.925781,10988.304688,10197.865234,10775.269531,10775.269531,263386919085
317
+ 2020-09-28,10776.613281,10945.347656,10416.689453,10669.583008,10669.583008,343112501609
318
+ 2020-10-05,10676.529297,11442.210938,10528.890625,11384.181641,11384.181641,256921249410
319
+ 2020-10-12,11392.635742,11698.467773,11223.012695,11483.359375,11483.359375,162045277956
320
+ 2020-10-19,11495.038086,13329.183594,11408.290039,13031.173828,13031.173828,210845277262
321
+ 2020-10-26,13031.201172,14028.213867,12822.382813,13737.109375,13737.109375,240919962782
322
+ 2020-11-02,13737.032227,15903.437500,13243.160156,15479.567383,15479.567383,238108964192
323
+ 2020-11-09,15479.595703,16463.177734,14865.529297,15955.587891,15955.587891,206407256877
324
+ 2020-11-16,15955.577148,18936.621094,15880.706055,18370.001953,18370.001953,274506990351
325
+ 2020-11-23,18370.017578,19390.964844,16351.035156,18177.484375,18177.484375,301939363508
326
+ 2020-11-30,18178.322266,19845.974609,18178.322266,19345.121094,19345.121094,253088772491
327
+ 2020-12-07,19343.128906,19411.828125,17619.533203,19142.382813,19142.382813,193678842258
328
+ 2020-12-14,19144.492188,24209.660156,19012.708984,23477.294922,23477.294922,281723269352
329
+ 2020-12-21,23474.455078,28288.839844,22159.367188,26272.294922,26272.294922,339132207025
330
+ 2020-12-28,26280.822266,34608.558594,25987.298828,32782.023438,32782.023438,379626054545
331
+ 2021-01-04,32810.949219,41946.738281,28722.755859,38356.441406,38356.441406,538834804975
332
+ 2021-01-11,38346.531250,39966.406250,30549.599609,35791.277344,35791.277344,508900951412
333
+ 2021-01-18,35792.238281,37755.890625,28953.373047,32289.378906,32289.378906,423439379849
334
+ 2021-01-25,32285.798828,38406.261719,29367.138672,33114.359375,33114.359375,495037340009
335
+ 2021-02-01,33114.578125,40846.546875,32384.228516,38903.441406,38903.441406,449918619842
336
+ 2021-02-08,38886.828125,49487.640625,38076.324219,48717.289063,48717.289063,580021243858
337
+ 2021-02-15,48696.535156,58330.570313,46347.476563,57539.945313,57539.945313,470533297170
338
+ 2021-02-22,57532.738281,57533.390625,43241.617188,45137.769531,45137.769531,766679775805
339
+ 2021-03-01,45159.503906,52535.136719,45115.093750,51206.691406,51206.691406,333113779409
340
+ 2021-03-08,51174.117188,61683.863281,49506.054688,59302.316406,59302.316406,373838576722
341
+ 2021-03-15,59267.429688,60540.992188,53555.027344,57523.421875,57523.421875,393542542227
342
+ 2021-03-22,57517.890625,58471.480469,50856.570313,55950.746094,55950.746094,403128836645
343
+ 2021-03-29,55947.898438,60267.187500,55139.339844,58758.554688,58758.554688,408348561550
344
+ 2021-04-05,58760.875000,61276.664063,55604.023438,60204.964844,60204.964844,406637390979
345
+ 2021-04-12,60175.945313,64863.097656,52829.535156,56216.183594,56216.183594,508118943571
346
+ 2021-04-19,56191.585938,57520.054688,47159.484375,49004.253906,49004.253906,444719708699
347
+ 2021-04-26,49077.792969,58448.339844,48852.796875,56631.078125,56631.078125,335231529997
348
+ 2021-05-03,56620.273438,59464.613281,52969.054688,58232.316406,58232.316406,458766142208
349
+ 2021-05-10,58250.871094,59519.355469,43963.351563,46456.058594,46456.058594,483967915938
350
+ 2021-05-17,46415.898438,46623.558594,30681.496094,34770.582031,34770.582031,563629210102
351
+ 2021-05-24,34700.363281,40782.078125,33520.738281,35678.128906,35678.128906,350206489990
352
+ 2021-05-31,35658.593750,39478.953125,34241.945313,35862.378906,35862.378906,248884892724
353
+ 2021-06-07,35835.265625,39322.781250,31114.443359,39097.859375,39097.859375,298428017340
354
+ 2021-06-14,39016.968750,41295.269531,33432.074219,35698.296875,35698.296875,269949570053
355
+ 2021-06-21,35641.144531,35721.640625,28893.621094,34649.644531,34649.644531,305541799334
356
+ 2021-06-28,34679.121094,36542.109375,32770.679688,35287.781250,35287.781250,231729218470
357
+ 2021-07-05,35284.343750,35284.343750,32133.183594,34240.187500,34240.187500,178445862441
358
+ 2021-07-12,34254.015625,34592.156250,31100.673828,31796.810547,31796.810547,147501894180
359
+ 2021-07-19,31800.011719,35364.925781,29360.955078,35350.187500,35350.187500,156414750211
360
+ 2021-07-26,35384.031250,42541.679688,35287.312500,39974.894531,39974.894531,237553113912
361
+ 2021-08-02,39907.261719,45282.351563,37458.003906,43798.117188,43798.117188,226902699564
362
+ 2021-08-09,43791.925781,48098.683594,42848.687500,47047.003906,47047.003906,234268000892
363
+ 2021-08-16,47019.960938,49717.019531,43998.316406,49321.652344,49321.652344,236289722726
364
+ 2021-08-23,49291.675781,50482.078125,46394.281250,48829.832031,48829.832031,223947952688
365
+ 2021-08-30,48834.851563,51868.679688,46562.437500,51753.410156,51753.410156,256225023619
366
+ 2021-09-06,51769.003906,52853.765625,43285.207031,46063.269531,46063.269531,293311066613
367
+ 2021-09-13,46057.214844,48791.781250,43591.320313,47260.218750,47260.218750,226141953163
368
+ 2021-09-20,47261.406250,47328.199219,39787.609375,43208.539063,43208.539063,270099994433
369
+ 2021-09-27,43234.183594,49130.691406,40829.667969,48199.953125,48199.953125,223042115392
370
+ 2021-10-04,48208.906250,56401.304688,47045.003906,54771.578125,54771.578125,261919545521
371
+ 2021-10-11,54734.125000,62757.128906,54370.972656,61553.617188,61553.617188,277084548345
372
+ 2021-10-18,61548.804688,66930.390625,59643.343750,60930.835938,60930.835938,257856648064
373
+ 2021-10-25,60893.925781,63729.324219,58206.917969,61318.957031,61318.957031,256114057651
374
+ 2021-11-01,61320.449219,64242.792969,59695.183594,63326.988281,63326.988281,227064607869
375
+ 2021-11-08,63344.066406,68789.625000,62333.914063,65466.839844,65466.839844,259776276520
376
+ 2021-11-15,65521.289063,66281.570313,55705.179688,58730.476563,58730.476563,253419951009
377
+ 2021-11-22,58706.847656,59367.968750,53569.765625,57248.457031,57248.457031,243930001011
378
+ 2021-11-29,57291.906250,59113.402344,42874.617188,49368.847656,49368.847656,276690611812
379
+ 2021-12-06,49413.480469,51934.781250,46942.347656,50098.335938,50098.335938,208148497532
380
+ 2021-12-13,50114.742188,50205.000000,45598.441406,46707.015625,46707.015625,214770398202
381
+ 2021-12-20,46707.062500,51814.027344,45579.808594,50809.515625,50809.515625,175052499792
382
+ 2021-12-27,50802.609375,51956.328125,45819.953125,47345.218750,47345.218750,203998848909
383
+ 2022-01-03,47343.542969,47510.726563,40672.277344,41911.601563,41911.601563,276182787152
384
+ 2022-01-10,41910.230469,44278.421875,39796.570313,43113.878906,43113.878906,199473804544
385
+ 2022-01-17,43118.121094,43413.023438,34349.250000,36276.804688,36276.804688,196326044073
386
+ 2022-01-24,36275.734375,38825.410156,33184.058594,37917.601563,37917.601563,178727434896
387
+ 2022-01-31,37920.281250,42500.785156,36375.539063,42412.433594,42412.433594,143977109319
388
+ 2022-02-07,42406.781250,45661.171875,41748.156250,42197.515625,42197.515625,176958095731
389
+ 2022-02-14,42157.398438,44667.218750,38112.812500,38431.378906,38431.378906,144975794552
390
+ 2022-02-21,38423.210938,40005.347656,34459.218750,37709.785156,37709.785156,190469710084
391
+ 2022-02-28,37706.000000,45077.578125,37518.214844,38419.984375,38419.984375,187557375751
392
+ 2022-03-07,38429.304688,42465.671875,37260.203125,37849.664063,37849.664063,175966999156
393
+ 2022-03-14,37846.316406,42316.554688,37680.734375,41247.824219,41247.824219,184097042034
394
+ 2022-03-21,41246.132813,46827.546875,40668.042969,46820.492188,46820.492188,188591889758
395
+ 2022-03-28,46821.851563,48086.835938,44403.140625,46453.566406,46453.566406,223334181931
396
+ 2022-04-04,46445.273438,47106.140625,42021.207031,42207.671875,42207.671875,188557001876
397
+ 2022-04-11,42201.039063,42424.589844,39373.058594,39716.953125,39716.953125,174652159709
398
+ 2022-04-18,39721.203125,42893.582031,38696.191406,39469.292969,39469.292969,184314843516
399
+ 2022-04-25,39472.605469,40713.890625,37585.789063,38469.093750,38469.093750,216681007567
400
+ 2022-05-02,38472.187500,39902.949219,33878.964844,34059.265625,34059.265625,239044762282
401
+ 2022-05-09,34060.015625,34222.074219,26350.490234,31305.113281,31305.113281,357800928090
402
+ 2022-05-16,31304.375000,31305.341797,28708.955078,30323.722656,30323.722656,196429842104
403
+ 2022-05-23,30309.396484,30590.585938,28261.906250,29445.957031,29445.957031,212594819496
404
+ 2022-05-30,29443.365234,32249.863281,29303.572266,29906.662109,29906.662109,203063587161
405
+ 2022-06-06,29910.283203,31693.291016,26762.648438,26762.648438,26762.648438,215929645934
406
+ 2022-06-13,26737.578125,26795.589844,17708.623047,20553.271484,20553.271484,309685915250
407
+ 2022-06-20,20553.371094,21783.724609,19689.169922,21027.294922,21027.294922,175909056122
408
+ 2022-06-27,21028.238281,21478.089844,18729.656250,19297.076172,19297.076172,157426002965
409
+ 2022-07-04,19297.314453,22314.941406,19063.066406,20860.449219,20860.449219,206953871021
410
+ 2022-07-11,20856.353516,21600.640625,18999.953125,20779.343750,20779.343750,187297974219
411
+ 2022-07-18,20781.912109,24196.818359,20781.912109,22609.164063,22609.164063,244312089708
412
+ 2022-07-25,22607.156250,24572.580078,20776.816406,23336.896484,23336.896484,223759636595
413
+ 2022-08-01,23336.718750,23578.650391,22485.701172,23175.890625,23175.890625,166393135564
414
+ 2022-08-08,23179.527344,24974.914063,22771.519531,24319.333984,24319.333984,195343016900
415
+ 2022-08-15,24318.316406,25135.589844,20856.730469,21534.121094,21534.121094,208764012537
416
+ 2022-08-22,21531.462891,21804.908203,19616.814453,19616.814453,19616.814453,223346042309
417
+ 2022-08-29,19615.154297,20542.644531,19600.785156,19986.712891,19986.712891,208511390280
418
+ 2022-09-05,19988.789063,21770.552734,18644.466797,21769.255859,21769.255859,259528892947
419
+ 2022-09-12,21770.148438,22673.820313,19387.492188,19419.505859,19419.505859,261900187496
420
+ 2022-09-19,19418.572266,19674.630859,18290.314453,18802.097656,18802.097656,252873598365
421
+ 2022-09-26,18803.900391,20338.455078,18553.296875,19044.107422,19044.107422,280290121527
422
+ 2022-10-03,19044.068359,20408.392578,19025.226563,19446.425781,19446.425781,196809212801
423
+ 2022-10-10,19446.416016,19889.146484,18319.822266,19268.093750,19268.093750,197940078443
424
+ 2022-10-17,19268.562500,19666.994141,18770.970703,19567.007813,19567.007813,175664450104
425
+ 2022-10-24,19567.769531,20988.394531,19206.324219,20635.603516,20635.603516,302335723765
426
+ 2022-10-31,20633.695313,21446.886719,20086.240234,20926.486328,20926.486328,321270158405
427
+ 2022-11-07,20924.621094,21053.246094,15682.692383,16353.365234,16353.365234,471409252759
428
+ 2022-11-14,16352.028320,17109.324219,15872.941406,16291.832031,16291.832031,212305927001
429
+ 2022-11-21,16291.223633,16771.474609,15599.046875,16444.626953,16444.626953,184366390569
430
+ 2022-11-28,16440.222656,17197.498047,16054.530273,17130.486328,17130.486328,156325682750
431
+ 2022-12-05,17128.894531,17378.152344,16750.558594,17104.193359,17104.193359,129428712529
432
+ 2022-12-12,17102.500000,18318.531250,16584.701172,16757.976563,16757.976563,142170798266
433
+ 2022-12-19,16759.041016,17012.984375,16398.136719,16841.986328,16841.986328,107997970888
434
+ 2022-12-26,16842.250000,16959.845703,16408.474609,16625.080078,16625.080078,95526200508
435
+ 2023-01-02,16625.509766,17091.144531,16572.228516,17091.144531,17091.144531,90012614323
436
+ 2023-01-09,17093.992188,21075.142578,17093.992188,20880.798828,20880.798828,175267920183
437
+ 2023-01-16,20882.224609,23282.347656,20541.544922,22720.416016,22720.416016,188938770069
438
+ 2023-01-23,22721.087891,23919.890625,22406.076172,23774.566406,23774.566406,177486927537
439
+ 2023-01-30,23774.648438,24167.210938,22657.582031,22955.666016,22955.666016,171080243769
440
+ 2023-02-06,22954.021484,23367.958984,21539.392578,21788.203125,21788.203125,170212590188
441
+ 2023-02-13,21787.000000,25134.117188,21460.087891,24327.642578,24327.642578,209050300776
442
+ 2023-02-20,24336.623047,25126.851563,22861.558594,23561.212891,23561.212891,180472737469
443
+ 2023-02-27,23561.451172,23880.632813,22198.980469,22435.513672,22435.513672,138790785900
444
+ 2023-03-06,22436.816406,22584.292969,19628.253906,22163.949219,22163.949219,192057466346
445
+ 2023-03-13,22156.406250,28440.560547,21918.199219,28038.675781,28038.675781,305833103060
446
+ 2023-03-20,28041.601563,28803.335938,26759.996094,27994.330078,27994.330078,191720356212
447
+ 2023-03-27,27994.068359,29159.902344,26606.689453,28199.308594,28199.308594,121255230918
448
+ 2023-04-03,28183.080078,28739.238281,27276.720703,28333.050781,28333.050781,98141424556
449
+ 2023-04-10,28336.027344,31005.607422,28189.271484,30315.355469,30315.355469,122998807738
450
+ 2023-04-17,30317.146484,30470.302734,27169.570313,27591.384766,27591.384766,129935327803
451
+ 2023-04-24,27591.730469,29995.837891,27070.849609,29268.806641,29268.806641,137303647007
452
+ 2023-05-01,29227.103516,29820.126953,27680.792969,28454.978516,28454.978516,114911964253
453
+ 2023-05-08,28450.457031,28663.271484,25878.429688,26930.638672,26930.638672,109959496438
454
+ 2023-05-15,26931.384766,27646.347656,26415.101563,26753.826172,26753.826172,84459727715
455
+ 2023-05-22,26749.892578,28193.449219,25890.593750,28085.646484,28085.646484,90053064704
456
+ 2023-05-29,28075.591797,28432.039063,26574.644531,27119.066406,27119.066406,91351657572
457
+ 2023-06-05,27123.109375,27332.181641,25434.867188,25940.167969,25940.167969,116498927148
458
+ 2023-06-12,25934.285156,26769.394531,24797.167969,26336.212891,26336.212891,92905085602
459
+ 2023-06-19,26335.441406,31389.539063,26312.832031,30480.261719,30480.261719,138005623534
460
+ 2023-06-26,30480.523438,31256.863281,29600.275391,30620.769531,30620.769531,106681707513
461
+ 2023-07-03,30624.515625,31460.052734,29777.285156,30171.234375,30171.234375,90491031635
462
+ 2023-07-10,30172.423828,31814.515625,29966.386719,30249.132813,30249.132813,102917922458
463
+ 2023-07-17,30249.626953,30336.400391,29556.427734,30084.539063,30084.539063,81229098742
464
+ 2023-07-24,30081.662109,30093.394531,28934.294922,29275.308594,29275.308594,76309629498
465
+ 2023-07-31,29278.314453,29987.998047,28657.023438,29041.855469,29041.855469,87827001052
466
+ 2023-08-07,29038.513672,30176.796875,28724.140625,29282.914063,29282.914063,85153014454
467
+ 2023-08-14,29283.263672,29660.253906,25409.111328,26189.583984,26189.583984,116418274959
468
+ 2023-08-21,26188.691406,26786.898438,25520.728516,26089.693359,26089.693359,83086807452
469
+ 2023-08-28,26089.615234,28089.337891,25362.609375,25969.566406,25969.566406,113161627781
470
+ 2023-09-04,25968.169922,26414.005859,25404.359375,25832.226563,25832.226563,69814611152
471
+ 2023-09-11,25831.714844,26840.498047,24930.296875,26534.187500,26534.187500,85796699860
472
+ 2023-09-18,26532.994141,27488.763672,26221.050781,26256.826172,26256.826172,82251905213
473
+ 2023-09-25,26253.775391,28047.238281,26011.468750,27983.750000,27983.750000,73012240734
474
+ 2023-10-02,27976.798828,28494.458984,27215.552734,27935.089844,27935.089844,82183775698
475
+ 2023-10-09,27934.472656,27989.470703,26558.320313,27159.652344,27159.652344,72673654487
476
+ 2023-10-16,27162.628906,30287.482422,27130.472656,29993.896484,29993.896484,113402383094
477
+ 2023-10-23,30140.685547,35150.433594,30097.828125,34538.480469,34538.480469,165718773022
478
+ 2023-10-30,34531.742188,35919.843750,34083.308594,35049.355469,35049.355469,115520056635
479
+ 2023-11-06,35044.789063,37926.257813,34545.816406,37054.519531,37054.519531,134767494805
480
+ 2023-11-13,37070.304688,37964.894531,34948.500000,37386.546875,37386.546875,143535361089
481
+ 2023-11-20,37374.074219,38415.339844,35670.972656,37479.121094,37479.121094,130439893957
482
+ 2023-11-27,37454.191406,40135.605469,36750.128906,39978.390625,39978.390625,134360107955
483
+ 2023-12-04,39978.628906,44705.515625,39978.628906,43779.699219,43779.699219,188503614895
484
+ 2023-12-11,43792.019531,43808.375000,40234.578125,41364.664063,41364.664063,168493481950
485
+ 2023-12-18,41348.203125,44367.957031,40530.257813,43016.117188,43016.117188,152084171491
486
+ 2023-12-25,43010.574219,43804.781250,41424.062500,42265.187500,42265.187500,157807126208
487
+ 2024-01-01,42280.234375,45899.707031,40813.535156,43943.097656,43943.097656,202311773985
488
+ 2024-01-08,43948.707031,48969.371094,41724.613281,41796.269531,41796.269531,259971819745
489
+ 2024-01-15,41715.066406,43566.273438,40297.457031,41545.785156,41545.785156,139135824835
490
+ 2024-01-22,41553.652344,42797.175781,38521.894531,42035.593750,42035.593750,155314602893
491
+ 2024-01-29,42030.914063,43838.945313,41818.332031,42583.582031,42583.582031,135184187433
492
+ 2024-02-05,42577.621094,48535.937500,42264.816406,48293.917969,48293.917969,157826395448
493
+ 2024-02-12,48296.386719,52820.066406,47745.761719,52122.546875,52122.546875,213560041471
494
+ 2024-02-19,52134.812500,52945.050781,50561.777344,51733.238281,51733.238281,160769145627
495
+ 2024-02-26,51730.539063,63913.132813,50931.031250,63167.371094,63167.371094,322895666089
496
+ 2024-03-04,63137.003906,70083.054688,59323.910156,69019.789063,69019.789063,405709693297
497
+ 2024-03-11,69020.546875,73750.070313,64545.316406,68390.625000,68390.625000,405957750577
498
+ 2024-03-18,68371.304688,68897.132813,60807.785156,67234.171875,67234.171875,328097121682
499
+ 2024-03-25,67234.093750,71727.687500,66414.835938,71333.648438,71333.648438,216324625836
500
+ 2024-04-01,71333.484375,71342.093750,68110.695313,69702.148438,69702.148438,34873527352
501
+ 2024-04-02,69694.046875,69694.046875,64610.968750,66042.132813,66042.132813,49630113792
aide/example_tasks/house_prices.md ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ## Goal
2
+ It is your job to predict the sales price for each house. For each Id in the test set, you must predict the value of the SalePrice variable.
3
+
4
+ ## Background
5
+ Ask a home buyer to describe their dream house, and they probably won't begin with the height of the basement ceiling or the proximity to an east-west railroad. But this playground competition's dataset proves that much more influences price negotiations than the number of bedrooms or a white-picket fence.
6
+ With 79 explanatory variables describing (almost) every aspect of residential homes in Ames, Iowa, this competition challenges you to predict the final price of each home.
7
+
8
+ ## Evaluation
9
+ Submissions are evaluated on [Root-Mean-Squared-Error (RMSE)](https://en.wikipedia.org/wiki/Root-mean-square_deviation) between the logarithm of the predicted value and the logarithm of the observed sales price. (Taking logs means that errors in predicting expensive houses and cheap houses will affect the result equally.)
10
+
11
+ The file should contain a header and have the following format:
12
+
13
+ ```
14
+ Id,SalePrice
15
+ 1461,169000.1
16
+ 1462,187724.1233
17
+ 1463,175221
18
+ etc.
19
+ ```
20
+
21
+ ## Data description
22
+ - **train.csv** - the training set
23
+ - **test.csv** - the test set
24
+ - **data_description.txt** - full description of each column, originally prepared by Dean De Cock but lightly edited to match the column names used here
aide/example_tasks/house_prices/data_description.txt ADDED
@@ -0,0 +1,523 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ MSSubClass: Identifies the type of dwelling involved in the sale.
2
+
3
+ 20 1-STORY 1946 & NEWER ALL STYLES
4
+ 30 1-STORY 1945 & OLDER
5
+ 40 1-STORY W/FINISHED ATTIC ALL AGES
6
+ 45 1-1/2 STORY - UNFINISHED ALL AGES
7
+ 50 1-1/2 STORY FINISHED ALL AGES
8
+ 60 2-STORY 1946 & NEWER
9
+ 70 2-STORY 1945 & OLDER
10
+ 75 2-1/2 STORY ALL AGES
11
+ 80 SPLIT OR MULTI-LEVEL
12
+ 85 SPLIT FOYER
13
+ 90 DUPLEX - ALL STYLES AND AGES
14
+ 120 1-STORY PUD (Planned Unit Development) - 1946 & NEWER
15
+ 150 1-1/2 STORY PUD - ALL AGES
16
+ 160 2-STORY PUD - 1946 & NEWER
17
+ 180 PUD - MULTILEVEL - INCL SPLIT LEV/FOYER
18
+ 190 2 FAMILY CONVERSION - ALL STYLES AND AGES
19
+
20
+ MSZoning: Identifies the general zoning classification of the sale.
21
+
22
+ A Agriculture
23
+ C Commercial
24
+ FV Floating Village Residential
25
+ I Industrial
26
+ RH Residential High Density
27
+ RL Residential Low Density
28
+ RP Residential Low Density Park
29
+ RM Residential Medium Density
30
+
31
+ LotFrontage: Linear feet of street connected to property
32
+
33
+ LotArea: Lot size in square feet
34
+
35
+ Street: Type of road access to property
36
+
37
+ Grvl Gravel
38
+ Pave Paved
39
+
40
+ Alley: Type of alley access to property
41
+
42
+ Grvl Gravel
43
+ Pave Paved
44
+ NA No alley access
45
+
46
+ LotShape: General shape of property
47
+
48
+ Reg Regular
49
+ IR1 Slightly irregular
50
+ IR2 Moderately Irregular
51
+ IR3 Irregular
52
+
53
+ LandContour: Flatness of the property
54
+
55
+ Lvl Near Flat/Level
56
+ Bnk Banked - Quick and significant rise from street grade to building
57
+ HLS Hillside - Significant slope from side to side
58
+ Low Depression
59
+
60
+ Utilities: Type of utilities available
61
+
62
+ AllPub All public Utilities (E,G,W,& S)
63
+ NoSewr Electricity, Gas, and Water (Septic Tank)
64
+ NoSeWa Electricity and Gas Only
65
+ ELO Electricity only
66
+
67
+ LotConfig: Lot configuration
68
+
69
+ Inside Inside lot
70
+ Corner Corner lot
71
+ CulDSac Cul-de-sac
72
+ FR2 Frontage on 2 sides of property
73
+ FR3 Frontage on 3 sides of property
74
+
75
+ LandSlope: Slope of property
76
+
77
+ Gtl Gentle slope
78
+ Mod Moderate Slope
79
+ Sev Severe Slope
80
+
81
+ Neighborhood: Physical locations within Ames city limits
82
+
83
+ Blmngtn Bloomington Heights
84
+ Blueste Bluestem
85
+ BrDale Briardale
86
+ BrkSide Brookside
87
+ ClearCr Clear Creek
88
+ CollgCr College Creek
89
+ Crawfor Crawford
90
+ Edwards Edwards
91
+ Gilbert Gilbert
92
+ IDOTRR Iowa DOT and Rail Road
93
+ MeadowV Meadow Village
94
+ Mitchel Mitchell
95
+ Names North Ames
96
+ NoRidge Northridge
97
+ NPkVill Northpark Villa
98
+ NridgHt Northridge Heights
99
+ NWAmes Northwest Ames
100
+ OldTown Old Town
101
+ SWISU South & West of Iowa State University
102
+ Sawyer Sawyer
103
+ SawyerW Sawyer West
104
+ Somerst Somerset
105
+ StoneBr Stone Brook
106
+ Timber Timberland
107
+ Veenker Veenker
108
+
109
+ Condition1: Proximity to various conditions
110
+
111
+ Artery Adjacent to arterial street
112
+ Feedr Adjacent to feeder street
113
+ Norm Normal
114
+ RRNn Within 200' of North-South Railroad
115
+ RRAn Adjacent to North-South Railroad
116
+ PosN Near positive off-site feature--park, greenbelt, etc.
117
+ PosA Adjacent to postive off-site feature
118
+ RRNe Within 200' of East-West Railroad
119
+ RRAe Adjacent to East-West Railroad
120
+
121
+ Condition2: Proximity to various conditions (if more than one is present)
122
+
123
+ Artery Adjacent to arterial street
124
+ Feedr Adjacent to feeder street
125
+ Norm Normal
126
+ RRNn Within 200' of North-South Railroad
127
+ RRAn Adjacent to North-South Railroad
128
+ PosN Near positive off-site feature--park, greenbelt, etc.
129
+ PosA Adjacent to postive off-site feature
130
+ RRNe Within 200' of East-West Railroad
131
+ RRAe Adjacent to East-West Railroad
132
+
133
+ BldgType: Type of dwelling
134
+
135
+ 1Fam Single-family Detached
136
+ 2FmCon Two-family Conversion; originally built as one-family dwelling
137
+ Duplx Duplex
138
+ TwnhsE Townhouse End Unit
139
+ TwnhsI Townhouse Inside Unit
140
+
141
+ HouseStyle: Style of dwelling
142
+
143
+ 1Story One story
144
+ 1.5Fin One and one-half story: 2nd level finished
145
+ 1.5Unf One and one-half story: 2nd level unfinished
146
+ 2Story Two story
147
+ 2.5Fin Two and one-half story: 2nd level finished
148
+ 2.5Unf Two and one-half story: 2nd level unfinished
149
+ SFoyer Split Foyer
150
+ SLvl Split Level
151
+
152
+ OverallQual: Rates the overall material and finish of the house
153
+
154
+ 10 Very Excellent
155
+ 9 Excellent
156
+ 8 Very Good
157
+ 7 Good
158
+ 6 Above Average
159
+ 5 Average
160
+ 4 Below Average
161
+ 3 Fair
162
+ 2 Poor
163
+ 1 Very Poor
164
+
165
+ OverallCond: Rates the overall condition of the house
166
+
167
+ 10 Very Excellent
168
+ 9 Excellent
169
+ 8 Very Good
170
+ 7 Good
171
+ 6 Above Average
172
+ 5 Average
173
+ 4 Below Average
174
+ 3 Fair
175
+ 2 Poor
176
+ 1 Very Poor
177
+
178
+ YearBuilt: Original construction date
179
+
180
+ YearRemodAdd: Remodel date (same as construction date if no remodeling or additions)
181
+
182
+ RoofStyle: Type of roof
183
+
184
+ Flat Flat
185
+ Gable Gable
186
+ Gambrel Gabrel (Barn)
187
+ Hip Hip
188
+ Mansard Mansard
189
+ Shed Shed
190
+
191
+ RoofMatl: Roof material
192
+
193
+ ClyTile Clay or Tile
194
+ CompShg Standard (Composite) Shingle
195
+ Membran Membrane
196
+ Metal Metal
197
+ Roll Roll
198
+ Tar&Grv Gravel & Tar
199
+ WdShake Wood Shakes
200
+ WdShngl Wood Shingles
201
+
202
+ Exterior1st: Exterior covering on house
203
+
204
+ AsbShng Asbestos Shingles
205
+ AsphShn Asphalt Shingles
206
+ BrkComm Brick Common
207
+ BrkFace Brick Face
208
+ CBlock Cinder Block
209
+ CemntBd Cement Board
210
+ HdBoard Hard Board
211
+ ImStucc Imitation Stucco
212
+ MetalSd Metal Siding
213
+ Other Other
214
+ Plywood Plywood
215
+ PreCast PreCast
216
+ Stone Stone
217
+ Stucco Stucco
218
+ VinylSd Vinyl Siding
219
+ Wd Sdng Wood Siding
220
+ WdShing Wood Shingles
221
+
222
+ Exterior2nd: Exterior covering on house (if more than one material)
223
+
224
+ AsbShng Asbestos Shingles
225
+ AsphShn Asphalt Shingles
226
+ BrkComm Brick Common
227
+ BrkFace Brick Face
228
+ CBlock Cinder Block
229
+ CemntBd Cement Board
230
+ HdBoard Hard Board
231
+ ImStucc Imitation Stucco
232
+ MetalSd Metal Siding
233
+ Other Other
234
+ Plywood Plywood
235
+ PreCast PreCast
236
+ Stone Stone
237
+ Stucco Stucco
238
+ VinylSd Vinyl Siding
239
+ Wd Sdng Wood Siding
240
+ WdShing Wood Shingles
241
+
242
+ MasVnrType: Masonry veneer type
243
+
244
+ BrkCmn Brick Common
245
+ BrkFace Brick Face
246
+ CBlock Cinder Block
247
+ None None
248
+ Stone Stone
249
+
250
+ MasVnrArea: Masonry veneer area in square feet
251
+
252
+ ExterQual: Evaluates the quality of the material on the exterior
253
+
254
+ Ex Excellent
255
+ Gd Good
256
+ TA Average/Typical
257
+ Fa Fair
258
+ Po Poor
259
+
260
+ ExterCond: Evaluates the present condition of the material on the exterior
261
+
262
+ Ex Excellent
263
+ Gd Good
264
+ TA Average/Typical
265
+ Fa Fair
266
+ Po Poor
267
+
268
+ Foundation: Type of foundation
269
+
270
+ BrkTil Brick & Tile
271
+ CBlock Cinder Block
272
+ PConc Poured Contrete
273
+ Slab Slab
274
+ Stone Stone
275
+ Wood Wood
276
+
277
+ BsmtQual: Evaluates the height of the basement
278
+
279
+ Ex Excellent (100+ inches)
280
+ Gd Good (90-99 inches)
281
+ TA Typical (80-89 inches)
282
+ Fa Fair (70-79 inches)
283
+ Po Poor (<70 inches
284
+ NA No Basement
285
+
286
+ BsmtCond: Evaluates the general condition of the basement
287
+
288
+ Ex Excellent
289
+ Gd Good
290
+ TA Typical - slight dampness allowed
291
+ Fa Fair - dampness or some cracking or settling
292
+ Po Poor - Severe cracking, settling, or wetness
293
+ NA No Basement
294
+
295
+ BsmtExposure: Refers to walkout or garden level walls
296
+
297
+ Gd Good Exposure
298
+ Av Average Exposure (split levels or foyers typically score average or above)
299
+ Mn Mimimum Exposure
300
+ No No Exposure
301
+ NA No Basement
302
+
303
+ BsmtFinType1: Rating of basement finished area
304
+
305
+ GLQ Good Living Quarters
306
+ ALQ Average Living Quarters
307
+ BLQ Below Average Living Quarters
308
+ Rec Average Rec Room
309
+ LwQ Low Quality
310
+ Unf Unfinshed
311
+ NA No Basement
312
+
313
+ BsmtFinSF1: Type 1 finished square feet
314
+
315
+ BsmtFinType2: Rating of basement finished area (if multiple types)
316
+
317
+ GLQ Good Living Quarters
318
+ ALQ Average Living Quarters
319
+ BLQ Below Average Living Quarters
320
+ Rec Average Rec Room
321
+ LwQ Low Quality
322
+ Unf Unfinshed
323
+ NA No Basement
324
+
325
+ BsmtFinSF2: Type 2 finished square feet
326
+
327
+ BsmtUnfSF: Unfinished square feet of basement area
328
+
329
+ TotalBsmtSF: Total square feet of basement area
330
+
331
+ Heating: Type of heating
332
+
333
+ Floor Floor Furnace
334
+ GasA Gas forced warm air furnace
335
+ GasW Gas hot water or steam heat
336
+ Grav Gravity furnace
337
+ OthW Hot water or steam heat other than gas
338
+ Wall Wall furnace
339
+
340
+ HeatingQC: Heating quality and condition
341
+
342
+ Ex Excellent
343
+ Gd Good
344
+ TA Average/Typical
345
+ Fa Fair
346
+ Po Poor
347
+
348
+ CentralAir: Central air conditioning
349
+
350
+ N No
351
+ Y Yes
352
+
353
+ Electrical: Electrical system
354
+
355
+ SBrkr Standard Circuit Breakers & Romex
356
+ FuseA Fuse Box over 60 AMP and all Romex wiring (Average)
357
+ FuseF 60 AMP Fuse Box and mostly Romex wiring (Fair)
358
+ FuseP 60 AMP Fuse Box and mostly knob & tube wiring (poor)
359
+ Mix Mixed
360
+
361
+ 1stFlrSF: First Floor square feet
362
+
363
+ 2ndFlrSF: Second floor square feet
364
+
365
+ LowQualFinSF: Low quality finished square feet (all floors)
366
+
367
+ GrLivArea: Above grade (ground) living area square feet
368
+
369
+ BsmtFullBath: Basement full bathrooms
370
+
371
+ BsmtHalfBath: Basement half bathrooms
372
+
373
+ FullBath: Full bathrooms above grade
374
+
375
+ HalfBath: Half baths above grade
376
+
377
+ Bedroom: Bedrooms above grade (does NOT include basement bedrooms)
378
+
379
+ Kitchen: Kitchens above grade
380
+
381
+ KitchenQual: Kitchen quality
382
+
383
+ Ex Excellent
384
+ Gd Good
385
+ TA Typical/Average
386
+ Fa Fair
387
+ Po Poor
388
+
389
+ TotRmsAbvGrd: Total rooms above grade (does not include bathrooms)
390
+
391
+ Functional: Home functionality (Assume typical unless deductions are warranted)
392
+
393
+ Typ Typical Functionality
394
+ Min1 Minor Deductions 1
395
+ Min2 Minor Deductions 2
396
+ Mod Moderate Deductions
397
+ Maj1 Major Deductions 1
398
+ Maj2 Major Deductions 2
399
+ Sev Severely Damaged
400
+ Sal Salvage only
401
+
402
+ Fireplaces: Number of fireplaces
403
+
404
+ FireplaceQu: Fireplace quality
405
+
406
+ Ex Excellent - Exceptional Masonry Fireplace
407
+ Gd Good - Masonry Fireplace in main level
408
+ TA Average - Prefabricated Fireplace in main living area or Masonry Fireplace in basement
409
+ Fa Fair - Prefabricated Fireplace in basement
410
+ Po Poor - Ben Franklin Stove
411
+ NA No Fireplace
412
+
413
+ GarageType: Garage location
414
+
415
+ 2Types More than one type of garage
416
+ Attchd Attached to home
417
+ Basment Basement Garage
418
+ BuiltIn Built-In (Garage part of house - typically has room above garage)
419
+ CarPort Car Port
420
+ Detchd Detached from home
421
+ NA No Garage
422
+
423
+ GarageYrBlt: Year garage was built
424
+
425
+ GarageFinish: Interior finish of the garage
426
+
427
+ Fin Finished
428
+ RFn Rough Finished
429
+ Unf Unfinished
430
+ NA No Garage
431
+
432
+ GarageCars: Size of garage in car capacity
433
+
434
+ GarageArea: Size of garage in square feet
435
+
436
+ GarageQual: Garage quality
437
+
438
+ Ex Excellent
439
+ Gd Good
440
+ TA Typical/Average
441
+ Fa Fair
442
+ Po Poor
443
+ NA No Garage
444
+
445
+ GarageCond: Garage condition
446
+
447
+ Ex Excellent
448
+ Gd Good
449
+ TA Typical/Average
450
+ Fa Fair
451
+ Po Poor
452
+ NA No Garage
453
+
454
+ PavedDrive: Paved driveway
455
+
456
+ Y Paved
457
+ P Partial Pavement
458
+ N Dirt/Gravel
459
+
460
+ WoodDeckSF: Wood deck area in square feet
461
+
462
+ OpenPorchSF: Open porch area in square feet
463
+
464
+ EnclosedPorch: Enclosed porch area in square feet
465
+
466
+ 3SsnPorch: Three season porch area in square feet
467
+
468
+ ScreenPorch: Screen porch area in square feet
469
+
470
+ PoolArea: Pool area in square feet
471
+
472
+ PoolQC: Pool quality
473
+
474
+ Ex Excellent
475
+ Gd Good
476
+ TA Average/Typical
477
+ Fa Fair
478
+ NA No Pool
479
+
480
+ Fence: Fence quality
481
+
482
+ GdPrv Good Privacy
483
+ MnPrv Minimum Privacy
484
+ GdWo Good Wood
485
+ MnWw Minimum Wood/Wire
486
+ NA No Fence
487
+
488
+ MiscFeature: Miscellaneous feature not covered in other categories
489
+
490
+ Elev Elevator
491
+ Gar2 2nd Garage (if not described in garage section)
492
+ Othr Other
493
+ Shed Shed (over 100 SF)
494
+ TenC Tennis Court
495
+ NA None
496
+
497
+ MiscVal: $Value of miscellaneous feature
498
+
499
+ MoSold: Month Sold (MM)
500
+
501
+ YrSold: Year Sold (YYYY)
502
+
503
+ SaleType: Type of sale
504
+
505
+ WD Warranty Deed - Conventional
506
+ CWD Warranty Deed - Cash
507
+ VWD Warranty Deed - VA Loan
508
+ New Home just constructed and sold
509
+ COD Court Officer Deed/Estate
510
+ Con Contract 15% Down payment regular terms
511
+ ConLw Contract Low Down payment and low interest
512
+ ConLI Contract Low Interest
513
+ ConLD Contract Low Down
514
+ Oth Other
515
+
516
+ SaleCondition: Condition of sale
517
+
518
+ Normal Normal Sale
519
+ Abnorml Abnormal Sale - trade, foreclosure, short sale
520
+ AdjLand Adjoining Land Purchase
521
+ Alloca Allocation - two linked properties with separate deeds, typically condo with a garage unit
522
+ Family Sale between family members
523
+ Partial Home was not completed when last assessed (associated with New Homes)
aide/example_tasks/house_prices/sample_submission.csv ADDED
@@ -0,0 +1,1460 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Id,SalePrice
2
+ 1461,169277.0524984
3
+ 1462,187758.393988768
4
+ 1463,183583.683569555
5
+ 1464,179317.47751083
6
+ 1465,150730.079976501
7
+ 1466,177150.989247307
8
+ 1467,172070.659229164
9
+ 1468,175110.956519547
10
+ 1469,162011.698831665
11
+ 1470,160726.247831419
12
+ 1471,157933.279456005
13
+ 1472,145291.245020389
14
+ 1473,159672.017631819
15
+ 1474,164167.518301885
16
+ 1475,150891.638244053
17
+ 1476,179460.96518734
18
+ 1477,185034.62891405
19
+ 1478,182352.192644656
20
+ 1479,183053.458213802
21
+ 1480,187823.339254278
22
+ 1481,186544.114327568
23
+ 1482,158230.77520516
24
+ 1483,190552.829321091
25
+ 1484,147183.67487199
26
+ 1485,185855.300905493
27
+ 1486,174350.470676986
28
+ 1487,201740.620690863
29
+ 1488,162986.378895754
30
+ 1489,162330.199085679
31
+ 1490,165845.938616539
32
+ 1491,180929.622876974
33
+ 1492,163481.501519718
34
+ 1493,187798.076714233
35
+ 1494,198822.198942566
36
+ 1495,194868.409899858
37
+ 1496,152605.298564403
38
+ 1497,147797.702836811
39
+ 1498,150521.96899297
40
+ 1499,146991.630153739
41
+ 1500,150306.307814534
42
+ 1501,151164.372534604
43
+ 1502,151133.706960953
44
+ 1503,156214.042540726
45
+ 1504,171992.760735142
46
+ 1505,173214.912549738
47
+ 1506,192429.187345783
48
+ 1507,190878.69508543
49
+ 1508,194542.544135519
50
+ 1509,191849.439072822
51
+ 1510,176363.773907793
52
+ 1511,176954.185412429
53
+ 1512,176521.216975696
54
+ 1513,179436.704810176
55
+ 1514,220079.756777048
56
+ 1515,175502.918109444
57
+ 1516,188321.073833569
58
+ 1517,163276.324450004
59
+ 1518,185911.366293097
60
+ 1519,171392.830997252
61
+ 1520,174418.207020775
62
+ 1521,179682.709603774
63
+ 1522,179423.751581665
64
+ 1523,171756.918091777
65
+ 1524,166849.638174419
66
+ 1525,181122.168676666
67
+ 1526,170934.462746566
68
+ 1527,159738.292580329
69
+ 1528,174445.759557658
70
+ 1529,174706.363659627
71
+ 1530,164507.672539365
72
+ 1531,163602.512172832
73
+ 1532,154126.270249525
74
+ 1533,171104.853481351
75
+ 1534,167735.39270528
76
+ 1535,183003.613338104
77
+ 1536,172580.381161499
78
+ 1537,165407.889104689
79
+ 1538,176363.773907793
80
+ 1539,175182.950898522
81
+ 1540,190757.177789246
82
+ 1541,167186.995771991
83
+ 1542,167839.376779276
84
+ 1543,173912.421165137
85
+ 1544,154034.917445551
86
+ 1545,156002.955794336
87
+ 1546,168173.94329857
88
+ 1547,168882.437104132
89
+ 1548,168173.94329857
90
+ 1549,157580.177551642
91
+ 1550,181922.15256011
92
+ 1551,155134.227842592
93
+ 1552,188885.573319552
94
+ 1553,183963.193012381
95
+ 1554,161298.762306335
96
+ 1555,188613.66763056
97
+ 1556,175080.111822945
98
+ 1557,174744.400305232
99
+ 1558,168175.911336919
100
+ 1559,182333.472575006
101
+ 1560,158307.206742274
102
+ 1561,193053.055502348
103
+ 1562,175031.089987177
104
+ 1563,160713.294602908
105
+ 1564,173186.215014436
106
+ 1565,191736.7598055
107
+ 1566,170401.630997116
108
+ 1567,164626.577880222
109
+ 1568,205469.409444832
110
+ 1569,209561.784211885
111
+ 1570,182271.503072356
112
+ 1571,178081.549427793
113
+ 1572,178425.956138831
114
+ 1573,162015.318511503
115
+ 1574,181722.420373045
116
+ 1575,156705.730169433
117
+ 1576,182902.420342386
118
+ 1577,157574.595395085
119
+ 1578,184380.739100813
120
+ 1579,169364.469225677
121
+ 1580,175846.179822063
122
+ 1581,189673.295302136
123
+ 1582,174401.317715566
124
+ 1583,179021.448718583
125
+ 1584,189196.845337149
126
+ 1585,139647.095720655
127
+ 1586,161468.198288911
128
+ 1587,171557.32317862
129
+ 1588,179447.36804185
130
+ 1589,169611.619017694
131
+ 1590,172088.872655744
132
+ 1591,171190.624128768
133
+ 1592,154850.508361878
134
+ 1593,158617.655719941
135
+ 1594,209258.33693701
136
+ 1595,177939.027626751
137
+ 1596,194631.100299584
138
+ 1597,213618.871562568
139
+ 1598,198342.504228533
140
+ 1599,138607.971472497
141
+ 1600,150778.958976731
142
+ 1601,146966.230339786
143
+ 1602,162182.59620952
144
+ 1603,176825.940961269
145
+ 1604,152799.812402444
146
+ 1605,180322.322067129
147
+ 1606,177508.027228367
148
+ 1607,208029.642652019
149
+ 1608,181987.282510201
150
+ 1609,160172.72797397
151
+ 1610,176761.317654248
152
+ 1611,176515.497545231
153
+ 1612,176270.453065471
154
+ 1613,183050.846258475
155
+ 1614,150011.102062216
156
+ 1615,159270.537808667
157
+ 1616,163419.663729346
158
+ 1617,163399.983345859
159
+ 1618,173364.161505756
160
+ 1619,169556.835902417
161
+ 1620,183690.595995738
162
+ 1621,176980.914909382
163
+ 1622,204773.36222471
164
+ 1623,174728.655998442
165
+ 1624,181873.458244461
166
+ 1625,177322.000823979
167
+ 1626,193927.939041863
168
+ 1627,181715.622732304
169
+ 1628,199270.841200324
170
+ 1629,177109.589956218
171
+ 1630,153909.578271486
172
+ 1631,162931.203336223
173
+ 1632,166386.7567182
174
+ 1633,173719.30379824
175
+ 1634,179757.925656704
176
+ 1635,179007.601964376
177
+ 1636,180370.808623106
178
+ 1637,185102.616730563
179
+ 1638,198825.563452058
180
+ 1639,184294.576009142
181
+ 1640,200443.7920562
182
+ 1641,181294.784484153
183
+ 1642,174354.336267919
184
+ 1643,172023.677781517
185
+ 1644,181666.922855025
186
+ 1645,179024.491269586
187
+ 1646,178324.191575907
188
+ 1647,184534.676687694
189
+ 1648,159397.250378784
190
+ 1649,178430.966728182
191
+ 1650,177743.799385967
192
+ 1651,179395.305519087
193
+ 1652,151713.38474815
194
+ 1653,151713.38474815
195
+ 1654,168434.977996215
196
+ 1655,153999.100311019
197
+ 1656,164096.097354123
198
+ 1657,166335.403036551
199
+ 1658,163020.725375757
200
+ 1659,155862.510668829
201
+ 1660,182760.651095509
202
+ 1661,201912.270622883
203
+ 1662,185988.233987516
204
+ 1663,183778.44888032
205
+ 1664,170935.85921771
206
+ 1665,184468.908382254
207
+ 1666,191569.089663229
208
+ 1667,232991.025583822
209
+ 1668,180980.721388278
210
+ 1669,164279.13048219
211
+ 1670,183859.460411109
212
+ 1671,185922.465682076
213
+ 1672,191742.778119363
214
+ 1673,199954.072465842
215
+ 1674,180690.274752587
216
+ 1675,163099.3096358
217
+ 1676,140791.922472443
218
+ 1677,166481.86647592
219
+ 1678,172080.434496773
220
+ 1679,191719.161659178
221
+ 1680,160741.098612515
222
+ 1681,157829.546854733
223
+ 1682,196896.748596341
224
+ 1683,159675.423990355
225
+ 1684,182084.790901946
226
+ 1685,179233.926374487
227
+ 1686,155774.270901623
228
+ 1687,181354.326716058
229
+ 1688,179605.563663918
230
+ 1689,181609.34866147
231
+ 1690,178221.531623281
232
+ 1691,175559.920735795
233
+ 1692,200328.822792041
234
+ 1693,178630.060559899
235
+ 1694,177174.535221728
236
+ 1695,172515.687368714
237
+ 1696,204032.992922943
238
+ 1697,176023.232787689
239
+ 1698,202202.073341595
240
+ 1699,181734.480075862
241
+ 1700,183982.158993126
242
+ 1701,188007.94241481
243
+ 1702,185922.966763517
244
+ 1703,183978.544874918
245
+ 1704,177199.618638821
246
+ 1705,181878.647956764
247
+ 1706,173622.088728263
248
+ 1707,180728.168562655
249
+ 1708,176477.026606328
250
+ 1709,184282.266697609
251
+ 1710,162062.47538448
252
+ 1711,182550.070992189
253
+ 1712,180987.949624695
254
+ 1713,178173.79762147
255
+ 1714,179980.635948606
256
+ 1715,173257.637826205
257
+ 1716,177271.291059307
258
+ 1717,175338.355442312
259
+ 1718,177548.140549508
260
+ 1719,175969.91662932
261
+ 1720,175011.481953462
262
+ 1721,185199.372568143
263
+ 1722,188514.050228937
264
+ 1723,185080.145268797
265
+ 1724,157304.402574096
266
+ 1725,194260.859481297
267
+ 1726,181262.329995106
268
+ 1727,157003.292706732
269
+ 1728,182924.499359899
270
+ 1729,181902.586375439
271
+ 1730,188985.371708134
272
+ 1731,185290.904495068
273
+ 1732,177304.425752748
274
+ 1733,166274.900490809
275
+ 1734,177807.420530107
276
+ 1735,180330.624816201
277
+ 1736,179069.112234629
278
+ 1737,175943.371816948
279
+ 1738,185199.050609653
280
+ 1739,167350.910824524
281
+ 1740,149315.311876449
282
+ 1741,139010.847766793
283
+ 1742,155412.151845447
284
+ 1743,171308.313985441
285
+ 1744,176220.543265638
286
+ 1745,177643.434991809
287
+ 1746,187222.653264601
288
+ 1747,185635.132083154
289
+ 1748,206492.534215854
290
+ 1749,181681.021081956
291
+ 1750,180500.198072685
292
+ 1751,206486.17086841
293
+ 1752,161334.301195429
294
+ 1753,176156.558313965
295
+ 1754,191642.223478994
296
+ 1755,191945.808027777
297
+ 1756,164146.306037354
298
+ 1757,179883.057071096
299
+ 1758,178071.137668844
300
+ 1759,188241.637896875
301
+ 1760,174559.656173171
302
+ 1761,182347.363042264
303
+ 1762,191507.251872857
304
+ 1763,199751.865597358
305
+ 1764,162106.416145131
306
+ 1765,164575.982314367
307
+ 1766,179176.352180931
308
+ 1767,177327.403857584
309
+ 1768,177818.083761781
310
+ 1769,186965.204048443
311
+ 1770,178762.742169197
312
+ 1771,183322.866146283
313
+ 1772,178903.295931891
314
+ 1773,186570.129421778
315
+ 1774,199144.242829024
316
+ 1775,172154.713310956
317
+ 1776,177444.019201603
318
+ 1777,166200.938073485
319
+ 1778,158995.770555632
320
+ 1779,168273.282454755
321
+ 1780,189680.453052788
322
+ 1781,181681.021081956
323
+ 1782,160277.142643643
324
+ 1783,197318.54715833
325
+ 1784,162228.935604196
326
+ 1785,187340.455456083
327
+ 1786,181065.347037275
328
+ 1787,190233.609102705
329
+ 1788,157929.594852031
330
+ 1789,168557.001935469
331
+ 1790,160805.584645628
332
+ 1791,221648.391978216
333
+ 1792,180539.88079815
334
+ 1793,182105.616283853
335
+ 1794,166380.852603154
336
+ 1795,178942.155617426
337
+ 1796,162804.747800461
338
+ 1797,183077.684392615
339
+ 1798,171728.4720292
340
+ 1799,164786.741540638
341
+ 1800,177427.267170302
342
+ 1801,197318.54715833
343
+ 1802,178658.114178223
344
+ 1803,185437.320523764
345
+ 1804,169759.652489529
346
+ 1805,173986.635055186
347
+ 1806,168607.664289468
348
+ 1807,194138.519145183
349
+ 1808,192502.440921994
350
+ 1809,176746.969818601
351
+ 1810,177604.891703134
352
+ 1811,193283.746584832
353
+ 1812,181627.061006609
354
+ 1813,169071.62025834
355
+ 1814,167398.006470987
356
+ 1815,150106.505141704
357
+ 1816,159650.304285848
358
+ 1817,179471.23597476
359
+ 1818,177109.589956218
360
+ 1819,166558.113328453
361
+ 1820,153796.714319583
362
+ 1821,174520.152570658
363
+ 1822,196297.95829524
364
+ 1823,169100.681601175
365
+ 1824,176911.319164431
366
+ 1825,169234.6454828
367
+ 1826,172386.297919134
368
+ 1827,156031.904802362
369
+ 1828,168202.892306596
370
+ 1829,166505.984017547
371
+ 1830,176507.37022149
372
+ 1831,180116.752553161
373
+ 1832,183072.740591406
374
+ 1833,189595.964677698
375
+ 1834,167523.919076265
376
+ 1835,210817.775863413
377
+ 1836,172942.930813351
378
+ 1837,145286.278144089
379
+ 1838,176468.653371492
380
+ 1839,159040.069562187
381
+ 1840,178518.204332507
382
+ 1841,169163.980786825
383
+ 1842,189786.685274579
384
+ 1843,181246.728523853
385
+ 1844,176349.927153587
386
+ 1845,205266.631009142
387
+ 1846,187397.993362224
388
+ 1847,208943.427726113
389
+ 1848,165014.532907657
390
+ 1849,182492.037566236
391
+ 1850,161718.71259042
392
+ 1851,180084.118941162
393
+ 1852,178534.950802179
394
+ 1853,151217.259961305
395
+ 1854,156342.717587562
396
+ 1855,188511.443835239
397
+ 1856,183570.337896789
398
+ 1857,225810.160292177
399
+ 1858,214217.401131694
400
+ 1859,187665.64101603
401
+ 1860,161157.177744039
402
+ 1861,187643.992594193
403
+ 1862,228156.372839158
404
+ 1863,220449.534665317
405
+ 1864,220522.352084222
406
+ 1865,156647.763531624
407
+ 1866,187388.833374873
408
+ 1867,178640.723791573
409
+ 1868,180847.216739049
410
+ 1869,159505.170529478
411
+ 1870,164305.538020654
412
+ 1871,180181.19673723
413
+ 1872,184602.734989972
414
+ 1873,193440.372174434
415
+ 1874,184199.788209911
416
+ 1875,196241.892907637
417
+ 1876,175588.618271096
418
+ 1877,179503.046546829
419
+ 1878,183658.076582555
420
+ 1879,193700.976276404
421
+ 1880,165399.62450704
422
+ 1881,186847.944787446
423
+ 1882,198127.73287817
424
+ 1883,183320.898107934
425
+ 1884,181613.606696657
426
+ 1885,178298.791761954
427
+ 1886,185733.534000593
428
+ 1887,180008.188485489
429
+ 1888,175127.59621604
430
+ 1889,183467.176862723
431
+ 1890,182705.546021743
432
+ 1891,152324.943593181
433
+ 1892,169878.515981342
434
+ 1893,183735.975076576
435
+ 1894,224118.280105941
436
+ 1895,169355.202465146
437
+ 1896,180054.276407441
438
+ 1897,174081.601977368
439
+ 1898,168494.985022146
440
+ 1899,181871.598843299
441
+ 1900,173554.489658383
442
+ 1901,169805.382165577
443
+ 1902,176192.990728755
444
+ 1903,204264.39284654
445
+ 1904,169630.906956928
446
+ 1905,185724.838807268
447
+ 1906,195699.036281861
448
+ 1907,189494.276162169
449
+ 1908,149607.905673439
450
+ 1909,154650.199045978
451
+ 1910,151579.558140433
452
+ 1911,185147.380531144
453
+ 1912,196314.53120359
454
+ 1913,210802.395364155
455
+ 1914,166271.2863726
456
+ 1915,154865.359142973
457
+ 1916,173575.5052865
458
+ 1917,179399.563554274
459
+ 1918,164280.776562049
460
+ 1919,171247.48948121
461
+ 1920,166878.587182445
462
+ 1921,188129.459710994
463
+ 1922,183517.34369691
464
+ 1923,175522.026925727
465
+ 1924,190060.105331152
466
+ 1925,174179.824771856
467
+ 1926,171059.523675194
468
+ 1927,183004.186769318
469
+ 1928,183601.647387418
470
+ 1929,163539.327185998
471
+ 1930,164677.676391525
472
+ 1931,162395.073865424
473
+ 1932,182207.6323195
474
+ 1933,192223.939790304
475
+ 1934,176391.829390125
476
+ 1935,181913.179121348
477
+ 1936,179136.097888261
478
+ 1937,196595.568243212
479
+ 1938,194822.365690957
480
+ 1939,148356.669440918
481
+ 1940,160387.604263899
482
+ 1941,181276.500571809
483
+ 1942,192474.817899346
484
+ 1943,157699.907796437
485
+ 1944,215785.540813051
486
+ 1945,181824.300998793
487
+ 1946,221813.00948166
488
+ 1947,165281.292597397
489
+ 1948,255629.49047034
490
+ 1949,173154.590990955
491
+ 1950,183884.65246539
492
+ 1951,200210.353608489
493
+ 1952,186599.221265342
494
+ 1953,192718.532696106
495
+ 1954,178628.665952764
496
+ 1955,180650.342418406
497
+ 1956,206003.107947263
498
+ 1957,166457.67844853
499
+ 1958,202916.221653487
500
+ 1959,192463.969983091
501
+ 1960,171775.497189898
502
+ 1961,175249.222149411
503
+ 1962,147086.59893993
504
+ 1963,149709.672100371
505
+ 1964,171411.404533743
506
+ 1965,178188.964799425
507
+ 1966,156491.711373235
508
+ 1967,180953.241201168
509
+ 1968,203909.759061135
510
+ 1969,175470.149087545
511
+ 1970,205578.333622415
512
+ 1971,199428.857699441
513
+ 1972,187599.163869476
514
+ 1973,192265.198109864
515
+ 1974,196666.554897677
516
+ 1975,155537.862252682
517
+ 1976,169543.240620935
518
+ 1977,202487.010170501
519
+ 1978,208232.716273485
520
+ 1979,173621.195202569
521
+ 1980,172414.608571812
522
+ 1981,164400.75641556
523
+ 1982,160480.424024781
524
+ 1983,156060.853810389
525
+ 1984,157437.192820581
526
+ 1985,158163.720929772
527
+ 1986,154849.043268978
528
+ 1987,152186.609341561
529
+ 1988,180340.215399228
530
+ 1989,178344.62451356
531
+ 1990,190170.382266827
532
+ 1991,168092.975480832
533
+ 1992,178757.912566805
534
+ 1993,174518.256882082
535
+ 1994,198168.490116289
536
+ 1995,176882.693978902
537
+ 1996,183801.672896251
538
+ 1997,196400.046680661
539
+ 1998,172281.605004025
540
+ 1999,196380.366297173
541
+ 2000,198228.354306682
542
+ 2001,195556.581268962
543
+ 2002,186453.264469043
544
+ 2003,181869.381196234
545
+ 2004,175610.840124147
546
+ 2005,183438.730800145
547
+ 2006,179584.488673295
548
+ 2007,182386.152242034
549
+ 2008,160750.367237054
550
+ 2009,182477.505046008
551
+ 2010,187720.359207171
552
+ 2011,187201.942081511
553
+ 2012,176385.102235149
554
+ 2013,175901.787841278
555
+ 2014,182584.280198283
556
+ 2015,195664.686104237
557
+ 2016,181420.346494222
558
+ 2017,176676.04995228
559
+ 2018,181594.678867334
560
+ 2019,178521.747964951
561
+ 2020,175895.883726231
562
+ 2021,168468.005916477
563
+ 2022,200973.129447888
564
+ 2023,197030.641992202
565
+ 2024,192867.417844592
566
+ 2025,196449.247639381
567
+ 2026,141684.196398607
568
+ 2027,153353.334123901
569
+ 2028,151143.549016705
570
+ 2029,163753.087114229
571
+ 2030,158682.460013921
572
+ 2031,144959.835250915
573
+ 2032,160144.390548579
574
+ 2033,156286.534303521
575
+ 2034,165726.707619571
576
+ 2035,182427.481047359
577
+ 2036,173310.56154032
578
+ 2037,173310.56154032
579
+ 2038,151556.01403002
580
+ 2039,158908.146068683
581
+ 2040,209834.383092536
582
+ 2041,192410.516550815
583
+ 2042,174026.247294886
584
+ 2043,195499.830115336
585
+ 2044,200918.018812493
586
+ 2045,207243.616023976
587
+ 2046,196149.783851876
588
+ 2047,192097.914850217
589
+ 2048,178570.948923671
590
+ 2049,228617.968325428
591
+ 2050,199929.884438451
592
+ 2051,160206.365612859
593
+ 2052,179854.431885567
594
+ 2053,185987.340461822
595
+ 2054,161122.505607926
596
+ 2055,175949.342720138
597
+ 2056,183683.590595324
598
+ 2057,176401.34762338
599
+ 2058,205832.532527897
600
+ 2059,177799.799849436
601
+ 2060,167565.362080406
602
+ 2061,186348.958436557
603
+ 2062,179782.759465081
604
+ 2063,169837.623333323
605
+ 2064,178817.275675758
606
+ 2065,174444.479149339
607
+ 2066,192834.968917174
608
+ 2067,196564.717984981
609
+ 2068,206977.567039357
610
+ 2069,157054.253944128
611
+ 2070,175142.948078577
612
+ 2071,159932.1643654
613
+ 2072,182801.408333628
614
+ 2073,181510.375176825
615
+ 2074,181613.035129451
616
+ 2075,186920.512597635
617
+ 2076,157950.170625222
618
+ 2077,176115.159022876
619
+ 2078,182744.514344465
620
+ 2079,180660.683691591
621
+ 2080,160775.629777099
622
+ 2081,186711.715848082
623
+ 2082,223581.758190888
624
+ 2083,172330.943236652
625
+ 2084,163474.633393212
626
+ 2085,175308.263299874
627
+ 2086,187462.725306432
628
+ 2087,180655.101535034
629
+ 2088,152121.98603454
630
+ 2089,159856.233909727
631
+ 2090,186559.854936737
632
+ 2091,183962.550959411
633
+ 2092,162107.168699296
634
+ 2093,162582.288981283
635
+ 2094,154407.701597409
636
+ 2095,181625.666399474
637
+ 2096,164810.609473548
638
+ 2097,176429.401241704
639
+ 2098,179188.089925259
640
+ 2099,145997.635377703
641
+ 2100,218676.768270367
642
+ 2101,188323.861214226
643
+ 2102,168690.0722914
644
+ 2103,165088.746797705
645
+ 2104,191435.007885166
646
+ 2105,168864.404664512
647
+ 2106,176041.882371574
648
+ 2107,215911.674390325
649
+ 2108,167388.238629016
650
+ 2109,163854.786753017
651
+ 2110,163299.477980171
652
+ 2111,178298.214633119
653
+ 2112,176376.586164775
654
+ 2113,170211.043976522
655
+ 2114,170818.344786366
656
+ 2115,174388.867432503
657
+ 2116,161112.987374671
658
+ 2117,172179.082325307
659
+ 2118,157798.309713876
660
+ 2119,169106.151422924
661
+ 2120,170129.531364292
662
+ 2121,157680.227412949
663
+ 2122,162690.209131977
664
+ 2123,146968.379365095
665
+ 2124,181507.721372455
666
+ 2125,191215.589752983
667
+ 2126,189432.689844522
668
+ 2127,207271.484957719
669
+ 2128,170030.807488363
670
+ 2129,148409.806476335
671
+ 2130,193850.613979055
672
+ 2131,193808.319298263
673
+ 2132,166300.235380627
674
+ 2133,163474.633393212
675
+ 2134,177473.606564978
676
+ 2135,157443.925537187
677
+ 2136,180681.007992057
678
+ 2137,183463.17030026
679
+ 2138,182481.763081195
680
+ 2139,193717.15117887
681
+ 2140,182782.55099007
682
+ 2141,175530.651633287
683
+ 2142,177804.057884623
684
+ 2143,159448.670848577
685
+ 2144,181338.976717529
686
+ 2145,178553.558537021
687
+ 2146,162820.928264556
688
+ 2147,188832.479997186
689
+ 2148,164682.185899437
690
+ 2149,181549.735943801
691
+ 2150,199158.097008868
692
+ 2151,152889.520990566
693
+ 2152,181150.551679116
694
+ 2153,181416.732376013
695
+ 2154,164391.238182305
696
+ 2155,185421.046498812
697
+ 2156,193981.327550004
698
+ 2157,178824.324789223
699
+ 2158,209270.051606246
700
+ 2159,177801.266806344
701
+ 2160,179053.762236101
702
+ 2161,178762.170601992
703
+ 2162,184655.300458183
704
+ 2163,191284.655779772
705
+ 2164,179598.085818785
706
+ 2165,167517.628078595
707
+ 2166,182873.903794044
708
+ 2167,177484.91371363
709
+ 2168,188444.597319524
710
+ 2169,179184.153848562
711
+ 2170,184365.175780982
712
+ 2171,184479.322005212
713
+ 2172,182927.863869391
714
+ 2173,178611.639373646
715
+ 2174,181943.343613558
716
+ 2175,175080.614768394
717
+ 2176,190720.794649138
718
+ 2177,198422.868144723
719
+ 2178,184482.11308349
720
+ 2179,139214.952187861
721
+ 2180,169233.113601757
722
+ 2181,180664.118686848
723
+ 2182,178818.742632666
724
+ 2183,180422.049969947
725
+ 2184,178601.93645581
726
+ 2185,183083.159775993
727
+ 2186,173163.101499699
728
+ 2187,185968.161159774
729
+ 2188,171226.050683054
730
+ 2189,281643.976116786
731
+ 2190,160031.711281258
732
+ 2191,162775.979779394
733
+ 2192,160735.445970193
734
+ 2193,166646.109048572
735
+ 2194,188384.548444549
736
+ 2195,165830.697255197
737
+ 2196,182138.358533039
738
+ 2197,171595.397975647
739
+ 2198,160337.079183809
740
+ 2199,191215.088671543
741
+ 2200,166956.093232213
742
+ 2201,186581.830878692
743
+ 2202,176450.548582099
744
+ 2203,193743.194909801
745
+ 2204,198882.566078408
746
+ 2205,176385.102235149
747
+ 2206,162447.639333636
748
+ 2207,193782.555676777
749
+ 2208,183653.890897141
750
+ 2209,210578.623546866
751
+ 2210,158527.164107319
752
+ 2211,163081.025723456
753
+ 2212,174388.867432503
754
+ 2213,191905.870131966
755
+ 2214,174388.867432503
756
+ 2215,161642.711648983
757
+ 2216,186939.507215101
758
+ 2217,172482.165792649
759
+ 2218,159695.999763546
760
+ 2219,157230.369671007
761
+ 2220,179188.089925259
762
+ 2221,157972.82120994
763
+ 2222,156804.951429181
764
+ 2223,211491.972463654
765
+ 2224,186537.246201062
766
+ 2225,200468.161070551
767
+ 2226,182241.340444154
768
+ 2227,157342.225898399
769
+ 2228,182022.387105998
770
+ 2229,181244.510876788
771
+ 2230,178556.671573788
772
+ 2231,189547.199876284
773
+ 2232,187948.65165563
774
+ 2233,194107.287565956
775
+ 2234,183521.710369283
776
+ 2235,183682.123638416
777
+ 2236,178483.353073443
778
+ 2237,184003.879764736
779
+ 2238,171318.59033449
780
+ 2239,162039.754313997
781
+ 2240,154846.252190699
782
+ 2241,194822.365690957
783
+ 2242,169788.738771463
784
+ 2243,178891.554489941
785
+ 2244,152084.772428865
786
+ 2245,139169.86642879
787
+ 2246,192439.536044606
788
+ 2247,161067.859766557
789
+ 2248,158762.648504781
790
+ 2249,175569.690441774
791
+ 2250,183659.795012187
792
+ 2251,280618.132617258
793
+ 2252,180051.809151659
794
+ 2253,176519.18031559
795
+ 2254,179028.429210291
796
+ 2255,177161.583857224
797
+ 2256,180081.508849842
798
+ 2257,205895.254584712
799
+ 2258,183389.78131415
800
+ 2259,178543.647859512
801
+ 2260,194798.320499104
802
+ 2261,162845.613675766
803
+ 2262,148103.867006579
804
+ 2263,201016.171121215
805
+ 2264,277936.12694354
806
+ 2265,249768.279823405
807
+ 2266,161596.052159825
808
+ 2267,158011.114889899
809
+ 2268,194089.683858004
810
+ 2269,181733.336941451
811
+ 2270,182852.32772198
812
+ 2271,189893.003058465
813
+ 2272,194650.210979875
814
+ 2273,187904.461286262
815
+ 2274,171774.925622692
816
+ 2275,177998.685921479
817
+ 2276,175648.484325498
818
+ 2277,196918.071362067
819
+ 2278,184299.838071218
820
+ 2279,182379.855682734
821
+ 2280,184050.725802482
822
+ 2281,158296.975970284
823
+ 2282,175053.355553278
824
+ 2283,162293.376090644
825
+ 2284,186328.880047186
826
+ 2285,151422.116936538
827
+ 2286,181969.358707768
828
+ 2287,189122.67702416
829
+ 2288,185645.475220346
830
+ 2289,182829.898109257
831
+ 2290,195848.788183328
832
+ 2291,198785.059550672
833
+ 2292,181676.126555428
834
+ 2293,194131.012663328
835
+ 2294,201416.004864508
836
+ 2295,185096.577205616
837
+ 2296,195158.972598372
838
+ 2297,184795.783735112
839
+ 2298,189168.263864671
840
+ 2299,216855.260149095
841
+ 2300,184946.642483576
842
+ 2301,189317.51282069
843
+ 2302,180803.277842406
844
+ 2303,175061.18585763
845
+ 2304,179074.839090732
846
+ 2305,145708.764336107
847
+ 2306,142398.022752011
848
+ 2307,161474.534863641
849
+ 2308,157025.945155458
850
+ 2309,163424.037827357
851
+ 2310,164692.778645345
852
+ 2311,152163.2443541
853
+ 2312,192383.215486656
854
+ 2313,182520.230322476
855
+ 2314,187254.507549722
856
+ 2315,176489.659740359
857
+ 2316,181520.466841293
858
+ 2317,186414.978214721
859
+ 2318,185197.764639705
860
+ 2319,178657.794083741
861
+ 2320,179731.198023759
862
+ 2321,161748.271317074
863
+ 2322,158608.749069322
864
+ 2323,178807.370559878
865
+ 2324,184187.158803897
866
+ 2325,181686.10402108
867
+ 2326,190311.050228337
868
+ 2327,192252.496354076
869
+ 2328,193954.849525775
870
+ 2329,181044.201560887
871
+ 2330,180258.131219792
872
+ 2331,199641.657313834
873
+ 2332,197530.775205517
874
+ 2333,191777.196949138
875
+ 2334,195779.543033588
876
+ 2335,202112.046522999
877
+ 2336,192343.34807661
878
+ 2337,185191.359443218
879
+ 2338,186760.207965688
880
+ 2339,177733.78193528
881
+ 2340,164430.391189608
882
+ 2341,185299.601552401
883
+ 2342,186414.012339254
884
+ 2343,176401.921054593
885
+ 2344,182381.322639642
886
+ 2345,176334.184710805
887
+ 2346,184901.735847457
888
+ 2347,180085.766885029
889
+ 2348,184901.735847457
890
+ 2349,183967.561548763
891
+ 2350,193046.301574659
892
+ 2351,168538.969495849
893
+ 2352,170157.842016969
894
+ 2353,196559.709259637
895
+ 2354,177133.709361852
896
+ 2355,181553.279576244
897
+ 2356,185770.606634739
898
+ 2357,177017.595099274
899
+ 2358,184123.358536806
900
+ 2359,165970.357492196
901
+ 2360,158151.985049452
902
+ 2361,177086.476441481
903
+ 2362,196373.896176551
904
+ 2363,172465.707083115
905
+ 2364,168590.782409896
906
+ 2365,158820.474171061
907
+ 2366,151611.37057651
908
+ 2367,152125.028585543
909
+ 2368,158404.073081048
910
+ 2369,160692.078640755
911
+ 2370,170175.22684199
912
+ 2371,169854.436591138
913
+ 2372,183410.785819008
914
+ 2373,180347.194026928
915
+ 2374,178930.528374292
916
+ 2375,153346.220086301
917
+ 2376,182675.204270589
918
+ 2377,180770.649792036
919
+ 2378,188714.148087543
920
+ 2379,191393.608594076
921
+ 2380,174016.157494425
922
+ 2381,183189.685319552
923
+ 2382,183621.508757866
924
+ 2383,168991.29635758
925
+ 2384,185306.650665866
926
+ 2385,189030.680303208
927
+ 2386,179208.665698449
928
+ 2387,174901.452792889
929
+ 2388,168337.406544343
930
+ 2389,158234.96461859
931
+ 2390,179562.453368834
932
+ 2391,174176.391640607
933
+ 2392,173931.531845427
934
+ 2393,184111.729429665
935
+ 2394,179374.482001188
936
+ 2395,207348.811884535
937
+ 2396,186983.419339031
938
+ 2397,206779.094049527
939
+ 2398,177472.074683935
940
+ 2399,156727.948324862
941
+ 2400,157090.568462479
942
+ 2401,160387.032696693
943
+ 2402,172410.28005086
944
+ 2403,191603.365657467
945
+ 2404,182152.207151253
946
+ 2405,180161.697340702
947
+ 2406,169652.235284283
948
+ 2407,182503.520140218
949
+ 2408,179714.630677039
950
+ 2409,180282.570719908
951
+ 2410,192600.338060371
952
+ 2411,166115.491248565
953
+ 2412,186379.553524443
954
+ 2413,184361.992258449
955
+ 2414,186220.965458121
956
+ 2415,198176.47090687
957
+ 2416,168437.776500131
958
+ 2417,178003.582312015
959
+ 2418,179180.469244588
960
+ 2419,191930.561104806
961
+ 2420,175590.266214964
962
+ 2421,176713.19307219
963
+ 2422,180159.090947005
964
+ 2423,188090.100808026
965
+ 2424,186184.717727913
966
+ 2425,223055.588672278
967
+ 2426,158270.753116401
968
+ 2427,184733.12846644
969
+ 2428,199926.378957429
970
+ 2429,175075.785166001
971
+ 2430,180917.925148076
972
+ 2431,182067.760625207
973
+ 2432,178238.60191545
974
+ 2433,173454.944606532
975
+ 2434,176821.936262814
976
+ 2435,183642.191304235
977
+ 2436,177254.582741058
978
+ 2437,168715.950111702
979
+ 2438,180096.931198144
980
+ 2439,160620.728178758
981
+ 2440,175286.544392273
982
+ 2441,153494.783276297
983
+ 2442,156407.65915545
984
+ 2443,162162.525245786
985
+ 2444,166809.886827197
986
+ 2445,172929.156408918
987
+ 2446,193514.330894137
988
+ 2447,181612.141603756
989
+ 2448,191745.386377068
990
+ 2449,171369.325038261
991
+ 2450,184425.470567051
992
+ 2451,170563.252355189
993
+ 2452,184522.369240168
994
+ 2453,164968.947931153
995
+ 2454,157939.621592364
996
+ 2455,151520.381580069
997
+ 2456,176129.508722531
998
+ 2457,171112.978971478
999
+ 2458,169762.081624282
1000
+ 2459,162246.828936295
1001
+ 2460,171339.303381589
1002
+ 2461,189034.753653813
1003
+ 2462,175758.873595981
1004
+ 2463,163351.721489893
1005
+ 2464,189806.546645026
1006
+ 2465,175370.990918319
1007
+ 2466,196895.599900301
1008
+ 2467,176905.917994834
1009
+ 2468,176866.557227858
1010
+ 2469,163590.677170026
1011
+ 2470,212693.502958393
1012
+ 2471,192686.931747717
1013
+ 2472,181578.684951827
1014
+ 2473,166475.457581812
1015
+ 2474,185998.255166219
1016
+ 2475,185527.714877908
1017
+ 2476,159027.118197683
1018
+ 2477,181169.654933769
1019
+ 2478,176732.915304722
1020
+ 2479,191619.294648838
1021
+ 2480,189114.303789324
1022
+ 2481,180934.635330334
1023
+ 2482,164573.372223048
1024
+ 2483,173902.011270196
1025
+ 2484,165625.127741229
1026
+ 2485,179555.219570787
1027
+ 2486,196899.720661579
1028
+ 2487,207566.12470446
1029
+ 2488,163899.981149274
1030
+ 2489,189179.428177786
1031
+ 2490,193892.880023125
1032
+ 2491,178980.874331431
1033
+ 2492,179749.876244365
1034
+ 2493,197999.674975598
1035
+ 2494,203717.470295797
1036
+ 2495,185249.261156892
1037
+ 2496,201691.208274848
1038
+ 2497,181956.548314794
1039
+ 2498,171895.936275806
1040
+ 2499,187245.168439419
1041
+ 2500,157816.77461318
1042
+ 2501,191702.912573325
1043
+ 2502,198599.420028908
1044
+ 2503,187193.313676329
1045
+ 2504,220514.993999535
1046
+ 2505,181814.527595192
1047
+ 2506,183750.755371907
1048
+ 2507,183000.431679579
1049
+ 2508,185830.971906573
1050
+ 2509,185497.872344187
1051
+ 2510,179613.437681321
1052
+ 2511,164454.967963631
1053
+ 2512,185127.237217638
1054
+ 2513,178750.613844623
1055
+ 2514,160927.61044889
1056
+ 2515,192562.808057836
1057
+ 2516,180990.24148554
1058
+ 2517,180064.941503122
1059
+ 2518,196070.997393789
1060
+ 2519,180352.919019023
1061
+ 2520,183367.953769362
1062
+ 2521,176734.841494027
1063
+ 2522,180848.220765939
1064
+ 2523,187806.059368823
1065
+ 2524,180521.52640004
1066
+ 2525,181502.754496154
1067
+ 2526,174525.87942676
1068
+ 2527,188927.984063168
1069
+ 2528,184728.870431253
1070
+ 2529,179857.975518011
1071
+ 2530,180962.868071609
1072
+ 2531,179194.066390078
1073
+ 2532,179591.789259484
1074
+ 2533,180638.463702549
1075
+ 2534,185846.215131922
1076
+ 2535,195174.031139141
1077
+ 2536,192474.56829063
1078
+ 2537,164200.595496827
1079
+ 2538,178403.094096818
1080
+ 2539,170774.84018302
1081
+ 2540,179879.945898337
1082
+ 2541,177668.192752792
1083
+ 2542,180174.328610725
1084
+ 2543,170643.303572141
1085
+ 2544,165448.004289838
1086
+ 2545,195531.754886222
1087
+ 2546,165314.177682121
1088
+ 2547,172532.757660882
1089
+ 2548,203310.218069877
1090
+ 2549,175090.062515883
1091
+ 2550,230841.338626282
1092
+ 2551,155225.19006632
1093
+ 2552,168322.342441945
1094
+ 2553,165956.259265265
1095
+ 2554,193956.817564124
1096
+ 2555,171070.367893827
1097
+ 2556,166285.243628001
1098
+ 2557,182875.801346628
1099
+ 2558,218108.536769738
1100
+ 2559,174378.777632042
1101
+ 2560,164731.316372391
1102
+ 2561,156969.695083273
1103
+ 2562,173388.854342604
1104
+ 2563,177559.628685119
1105
+ 2564,194297.789279905
1106
+ 2565,174894.588364005
1107
+ 2566,196544.144075798
1108
+ 2567,179036.158528149
1109
+ 2568,211423.986511149
1110
+ 2569,208156.398935188
1111
+ 2570,159233.941347257
1112
+ 2571,210820.115134931
1113
+ 2572,140196.10979821
1114
+ 2573,198678.469082978
1115
+ 2574,186818.610760803
1116
+ 2575,175044.797633861
1117
+ 2576,180031.162892704
1118
+ 2577,176889.171525162
1119
+ 2578,159638.856165666
1120
+ 2579,154287.264375509
1121
+ 2580,191885.618181273
1122
+ 2581,177503.378612934
1123
+ 2582,166548.31684976
1124
+ 2583,164475.14942856
1125
+ 2584,167484.744857879
1126
+ 2585,188683.160555403
1127
+ 2586,162243.399502668
1128
+ 2587,180807.213919103
1129
+ 2588,176279.079637039
1130
+ 2589,163438.959094218
1131
+ 2590,161495.5393685
1132
+ 2591,216032.303722443
1133
+ 2592,176632.181541401
1134
+ 2593,168743.001567144
1135
+ 2594,183810.11848086
1136
+ 2595,156794.36054728
1137
+ 2596,169136.43011395
1138
+ 2597,183203.318752456
1139
+ 2598,213252.926930889
1140
+ 2599,190550.327866959
1141
+ 2600,234707.209860273
1142
+ 2601,135751.318892816
1143
+ 2602,164228.45886894
1144
+ 2603,153219.437030419
1145
+ 2604,164210.746523801
1146
+ 2605,163883.229117973
1147
+ 2606,154892.776269956
1148
+ 2607,197092.08733832
1149
+ 2608,228148.376399122
1150
+ 2609,178680.587503997
1151
+ 2610,165643.341167808
1152
+ 2611,222406.642660249
1153
+ 2612,184021.843582599
1154
+ 2613,170871.094939159
1155
+ 2614,189562.873697309
1156
+ 2615,170591.884966356
1157
+ 2616,172934.351682851
1158
+ 2617,186425.069879189
1159
+ 2618,218648.131133006
1160
+ 2619,183035.606761141
1161
+ 2620,178378.906069427
1162
+ 2621,184516.716597846
1163
+ 2622,181419.5253183
1164
+ 2623,196858.923438425
1165
+ 2624,189228.701486278
1166
+ 2625,208973.380761028
1167
+ 2626,180269.86896412
1168
+ 2627,159488.713683953
1169
+ 2628,191490.299507521
1170
+ 2629,228684.245137946
1171
+ 2630,201842.998700429
1172
+ 2631,209242.82289186
1173
+ 2632,202357.62258493
1174
+ 2633,168238.61218265
1175
+ 2634,202524.12465369
1176
+ 2635,170588.771929588
1177
+ 2636,198375.31512987
1178
+ 2637,170636.827889889
1179
+ 2638,181991.079479377
1180
+ 2639,183994.54251844
1181
+ 2640,182951.482193584
1182
+ 2641,174126.297156192
1183
+ 2642,170575.496742588
1184
+ 2643,175332.239869971
1185
+ 2644,167522.061539111
1186
+ 2645,168095.583738538
1187
+ 2646,154406.415627461
1188
+ 2647,170996.973346087
1189
+ 2648,159056.890245639
1190
+ 2649,181373.6165193
1191
+ 2650,152272.560975937
1192
+ 2651,168664.346821336
1193
+ 2652,211007.008292301
1194
+ 2653,182909.515032911
1195
+ 2654,203926.829353303
1196
+ 2655,179082.825442944
1197
+ 2656,206260.099795032
1198
+ 2657,181732.443415757
1199
+ 2658,189698.740693148
1200
+ 2659,203074.34678979
1201
+ 2660,201670.634365666
1202
+ 2661,173756.812589691
1203
+ 2662,181387.076390881
1204
+ 2663,184859.155270535
1205
+ 2664,158313.615666777
1206
+ 2665,151951.955409666
1207
+ 2666,162537.52704471
1208
+ 2667,178998.337067854
1209
+ 2668,186732.584943041
1210
+ 2669,187323.318406165
1211
+ 2670,199437.232798284
1212
+ 2671,185546.680858653
1213
+ 2672,161595.015798593
1214
+ 2673,154672.422763036
1215
+ 2674,159355.710116165
1216
+ 2675,155919.014077746
1217
+ 2676,182424.87095604
1218
+ 2677,178100.589622319
1219
+ 2678,202577.900044456
1220
+ 2679,177862.778940605
1221
+ 2680,182056.024744887
1222
+ 2681,191403.199177104
1223
+ 2682,196264.754980043
1224
+ 2683,209375.003419718
1225
+ 2684,196691.81930173
1226
+ 2685,192458.431539585
1227
+ 2686,182242.80926507
1228
+ 2687,183259.503900506
1229
+ 2688,188108.243748841
1230
+ 2689,171418.640195797
1231
+ 2690,194698.882220432
1232
+ 2691,174841.84007522
1233
+ 2692,172965.476488899
1234
+ 2693,189386.323677132
1235
+ 2694,185682.618340257
1236
+ 2695,176412.012719061
1237
+ 2696,174976.489722867
1238
+ 2697,180718.581707643
1239
+ 2698,186131.188248242
1240
+ 2699,165220.786354033
1241
+ 2700,164115.893800435
1242
+ 2701,182125.729127024
1243
+ 2702,182285.140233276
1244
+ 2703,196325.442210366
1245
+ 2704,164865.215329881
1246
+ 2705,182694.492209823
1247
+ 2706,185425.485520958
1248
+ 2707,171414.7041191
1249
+ 2708,183433.472466085
1250
+ 2709,176844.981155794
1251
+ 2710,180568.187753206
1252
+ 2711,185948.625475832
1253
+ 2712,189388.291715481
1254
+ 2713,142754.489165865
1255
+ 2714,156106.800760811
1256
+ 2715,155895.397617561
1257
+ 2716,159851.977738548
1258
+ 2717,185157.832305524
1259
+ 2718,180716.291710805
1260
+ 2719,176901.093954071
1261
+ 2720,181017.222455218
1262
+ 2721,183269.159407668
1263
+ 2722,193550.830097069
1264
+ 2723,170625.842699726
1265
+ 2724,182012.405942725
1266
+ 2725,179162.507290733
1267
+ 2726,183269.159407668
1268
+ 2727,180589.836175042
1269
+ 2728,181465.935198741
1270
+ 2729,196053.029878304
1271
+ 2730,183421.020319014
1272
+ 2731,167926.839083612
1273
+ 2732,168027.530997889
1274
+ 2733,182164.26685407
1275
+ 2734,172469.071592608
1276
+ 2735,181059.374300472
1277
+ 2736,182997.570115536
1278
+ 2737,166140.504179894
1279
+ 2738,198515.546934075
1280
+ 2739,193789.648503294
1281
+ 2740,173550.025727531
1282
+ 2741,176487.943174734
1283
+ 2742,188813.302559147
1284
+ 2743,178531.911979192
1285
+ 2744,182145.731469001
1286
+ 2745,179196.465024103
1287
+ 2746,169618.349900686
1288
+ 2747,170010.168655046
1289
+ 2748,181739.671652174
1290
+ 2749,172846.934955574
1291
+ 2750,195560.8830172
1292
+ 2751,180358.114292956
1293
+ 2752,211817.702818093
1294
+ 2753,176170.128686742
1295
+ 2754,234492.248263699
1296
+ 2755,182450.956536015
1297
+ 2756,174902.068073146
1298
+ 2757,173684.174293738
1299
+ 2758,147196.673677562
1300
+ 2759,175231.189709791
1301
+ 2760,193417.64740633
1302
+ 2761,183313.601249761
1303
+ 2762,180882.250849082
1304
+ 2763,186735.697979808
1305
+ 2764,172922.865411247
1306
+ 2765,202551.677190573
1307
+ 2766,190485.634074173
1308
+ 2767,173439.49362151
1309
+ 2768,196613.598849219
1310
+ 2769,178152.259700828
1311
+ 2770,174519.904825949
1312
+ 2771,172627.796932837
1313
+ 2772,173732.689486435
1314
+ 2773,209219.844787023
1315
+ 2774,181059.374300472
1316
+ 2775,188515.443002459
1317
+ 2776,182164.26685407
1318
+ 2777,188137.901597981
1319
+ 2778,158893.54306269
1320
+ 2779,189579.65066771
1321
+ 2780,165229.803505847
1322
+ 2781,162186.071220207
1323
+ 2782,166374.879866351
1324
+ 2783,161665.184974757
1325
+ 2784,175079.328798445
1326
+ 2785,203840.874021305
1327
+ 2786,152129.078861057
1328
+ 2787,181012.141380101
1329
+ 2788,161305.53503837
1330
+ 2789,203326.392972343
1331
+ 2790,168385.571141831
1332
+ 2791,183564.365159986
1333
+ 2792,163784.619440861
1334
+ 2793,171989.192193993
1335
+ 2794,180839.95616829
1336
+ 2795,170895.923185907
1337
+ 2796,174071.054808518
1338
+ 2797,259423.859147546
1339
+ 2798,188000.824679588
1340
+ 2799,179171.703565498
1341
+ 2800,171022.241447762
1342
+ 2801,174126.297156192
1343
+ 2802,187625.573271948
1344
+ 2803,199567.946369234
1345
+ 2804,205328.078219268
1346
+ 2805,166231.535025379
1347
+ 2806,154743.91606057
1348
+ 2807,159714.537012622
1349
+ 2808,185563.069082422
1350
+ 2809,171500.796725006
1351
+ 2810,180983.443844799
1352
+ 2811,183141.236914997
1353
+ 2812,178498.634450214
1354
+ 2813,224323.710512388
1355
+ 2814,218200.642127877
1356
+ 2815,182283.177756557
1357
+ 2816,190054.639237419
1358
+ 2817,160192.453934518
1359
+ 2818,171289.393581756
1360
+ 2819,151131.098733642
1361
+ 2820,181721.458225594
1362
+ 2821,172725.053851858
1363
+ 2822,222438.699143414
1364
+ 2823,235419.373448928
1365
+ 2824,185150.926027596
1366
+ 2825,184772.239624699
1367
+ 2826,180658.216435809
1368
+ 2827,209673.316647174
1369
+ 2828,205939.810625621
1370
+ 2829,165633.573325837
1371
+ 2830,186030.317211014
1372
+ 2831,160312.319589212
1373
+ 2832,190702.440251029
1374
+ 2833,175122.810326699
1375
+ 2834,183783.13937519
1376
+ 2835,178290.666302221
1377
+ 2836,181605.343963015
1378
+ 2837,187992.451444752
1379
+ 2838,188885.11781517
1380
+ 2839,189959.344795118
1381
+ 2840,179258.619211334
1382
+ 2841,181518.750275669
1383
+ 2842,193008.659237315
1384
+ 2843,186313.89385619
1385
+ 2844,181499.39185067
1386
+ 2845,174126.297156192
1387
+ 2846,183918.612062767
1388
+ 2847,184114.270899227
1389
+ 2848,158540.947801398
1390
+ 2849,197034.759055859
1391
+ 2850,185170.284452595
1392
+ 2851,221134.533635148
1393
+ 2852,184306.637575967
1394
+ 2853,199792.302740996
1395
+ 2854,143237.803559736
1396
+ 2855,177294.838897736
1397
+ 2856,182368.620883855
1398
+ 2857,176487.943174734
1399
+ 2858,183849.408762071
1400
+ 2859,184964.141507413
1401
+ 2860,196395.969632434
1402
+ 2861,188374.936650438
1403
+ 2862,176261.296806135
1404
+ 2863,163628.142248426
1405
+ 2864,180618.032628904
1406
+ 2865,161647.329794081
1407
+ 2866,167129.598867773
1408
+ 2867,174750.988352687
1409
+ 2868,177560.202116333
1410
+ 2869,192577.796112839
1411
+ 2870,199202.898960871
1412
+ 2871,182818.156667308
1413
+ 2872,148217.262540651
1414
+ 2873,188997.797082492
1415
+ 2874,185807.928877601
1416
+ 2875,177030.477842021
1417
+ 2876,175942.474593632
1418
+ 2877,172912.518576433
1419
+ 2878,198359.248864591
1420
+ 2879,184379.133036383
1421
+ 2880,194255.566948886
1422
+ 2881,209449.651603064
1423
+ 2882,169979.323958443
1424
+ 2883,188206.281858748
1425
+ 2884,186412.438609167
1426
+ 2885,196761.386409959
1427
+ 2886,208353.269558209
1428
+ 2887,166548.067241044
1429
+ 2888,175942.474593632
1430
+ 2889,166790.457916434
1431
+ 2890,160515.850579067
1432
+ 2891,192167.621096362
1433
+ 2892,178751.551083369
1434
+ 2893,198678.894117024
1435
+ 2894,164553.120272354
1436
+ 2895,156887.932862327
1437
+ 2896,164185.777305524
1438
+ 2897,212992.120630876
1439
+ 2898,197468.550532521
1440
+ 2899,180106.84373966
1441
+ 2900,183972.071056674
1442
+ 2901,245283.198337927
1443
+ 2902,170351.963410756
1444
+ 2903,195596.307707478
1445
+ 2904,189369.756330412
1446
+ 2905,223667.404551664
1447
+ 2906,169335.310624364
1448
+ 2907,167411.02835165
1449
+ 2908,187709.555003968
1450
+ 2909,196526.002998991
1451
+ 2910,137402.569855589
1452
+ 2911,165086.775061735
1453
+ 2912,188506.431412274
1454
+ 2913,172917.456816012
1455
+ 2914,166274.325225982
1456
+ 2915,167081.220948984
1457
+ 2916,164788.778231138
1458
+ 2917,219222.423400059
1459
+ 2918,184924.279658997
1460
+ 2919,187741.866657478
aide/example_tasks/house_prices/test.csv ADDED
The diff for this file is too large to render. See raw diff
 
aide/example_tasks/house_prices/train.csv ADDED
The diff for this file is too large to render. See raw diff
 
aide/interpreter.py ADDED
@@ -0,0 +1,311 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Python interpreter for executing code snippets and capturing their output.
3
+ Supports:
4
+ - captures stdout and stderr
5
+ - captures exceptions and stack traces
6
+ - limits execution time
7
+ """
8
+
9
+ import logging
10
+ import os
11
+ import queue
12
+ import signal
13
+ import sys
14
+ import time
15
+ import traceback
16
+ from dataclasses import dataclass
17
+ from multiprocessing import Process, Queue
18
+ from pathlib import Path
19
+
20
+ import humanize
21
+ from dataclasses_json import DataClassJsonMixin
22
+
23
+ logger = logging.getLogger("aide")
24
+
25
+
26
+ @dataclass
27
+ class ExecutionResult(DataClassJsonMixin):
28
+ """
29
+ Result of executing a code snippet in the interpreter.
30
+ Contains the output, execution time, and exception information.
31
+ """
32
+
33
+ term_out: list[str]
34
+ exec_time: float
35
+ exc_type: str | None
36
+ exc_info: dict | None = None
37
+ exc_stack: list[tuple] | None = None
38
+
39
+
40
+ def exception_summary(e, working_dir, exec_file_name, format_tb_ipython):
41
+ """Generates a string that summarizes an exception and its stack trace (either in standard python repl or in IPython format)."""
42
+ if format_tb_ipython:
43
+ import IPython.core.ultratb
44
+
45
+ # tb_offset = 1 to skip parts of the stack trace in weflow code
46
+ tb = IPython.core.ultratb.VerboseTB(tb_offset=1, color_scheme="NoColor")
47
+ tb_str = str(tb.text(*sys.exc_info()))
48
+ else:
49
+ tb_lines = traceback.format_exception(e)
50
+ # skip parts of stack trace in weflow code
51
+ tb_str = "".join(
52
+ [
53
+ line
54
+ for line in tb_lines
55
+ if "aide/" not in line and "importlib" not in line
56
+ ]
57
+ )
58
+ # tb_str = "".join([l for l in tb_lines])
59
+
60
+ # replace whole path to file with just filename (to remove agent workspace dir)
61
+ tb_str = tb_str.replace(str(working_dir / exec_file_name), exec_file_name)
62
+
63
+ exc_info = {}
64
+ if hasattr(e, "args"):
65
+ exc_info["args"] = [str(i) for i in e.args]
66
+ for att in ["name", "msg", "obj"]:
67
+ if hasattr(e, att):
68
+ exc_info[att] = str(getattr(e, att))
69
+
70
+ tb = traceback.extract_tb(e.__traceback__)
71
+ exc_stack = [(t.filename, t.lineno, t.name, t.line) for t in tb]
72
+
73
+ return tb_str, e.__class__.__name__, exc_info, exc_stack
74
+
75
+
76
+ class RedirectQueue:
77
+ def __init__(self, queue, timeout=5):
78
+ self.queue = queue
79
+ self.timeout = timeout
80
+
81
+ def write(self, msg):
82
+ try:
83
+ self.queue.put(msg, timeout=self.timeout)
84
+ except queue.Full:
85
+ logger.warning("Queue write timed out")
86
+
87
+ def flush(self):
88
+ pass
89
+
90
+
91
+ class Interpreter:
92
+ def __init__(
93
+ self,
94
+ working_dir: Path | str,
95
+ timeout: int = 3600,
96
+ format_tb_ipython: bool = False,
97
+ agent_file_name: str = "runfile.py",
98
+ ):
99
+ """
100
+ Simulates a standalone Python REPL with an execution time limit.
101
+
102
+ Args:
103
+ working_dir (Path | str): working directory of the agent
104
+ timeout (int, optional): Timeout for each code execution step. Defaults to 3600.
105
+ format_tb_ipython (bool, optional): Whether to use IPython or default python REPL formatting for exceptions. Defaults to False.
106
+ agent_file_name (str, optional): The name for the agent's code file. Defaults to "runfile.py".
107
+ """
108
+ # this really needs to be a path, otherwise causes issues that don't raise exc
109
+ self.working_dir = Path(working_dir).resolve()
110
+ assert (
111
+ self.working_dir.exists()
112
+ ), f"Working directory {self.working_dir} does not exist"
113
+ self.timeout = timeout
114
+ self.format_tb_ipython = format_tb_ipython
115
+ self.agent_file_name = agent_file_name
116
+ self.process: Process = None # type: ignore
117
+
118
+ def child_proc_setup(self, result_outq: Queue) -> None:
119
+ # disable all warnings (before importing anything)
120
+ import shutup
121
+
122
+ shutup.mute_warnings()
123
+ os.chdir(str(self.working_dir))
124
+
125
+ # this seems to only benecessary because we're exec'ing code from a string,
126
+ # a .py file should be able to import modules from the cwd anyway
127
+ sys.path.append(str(self.working_dir))
128
+
129
+ # capture stdout and stderr
130
+ # trunk-ignore(mypy/assignment)
131
+ sys.stdout = sys.stderr = RedirectQueue(result_outq)
132
+
133
+ def _run_session(
134
+ self, code_inq: Queue, result_outq: Queue, event_outq: Queue
135
+ ) -> None:
136
+ self.child_proc_setup(result_outq)
137
+
138
+ global_scope: dict = {}
139
+ while True:
140
+ code = code_inq.get()
141
+ os.chdir(str(self.working_dir))
142
+ with open(self.agent_file_name, "w") as f:
143
+ f.write(code)
144
+
145
+ event_outq.put(("state:ready",))
146
+ try:
147
+ exec(compile(code, self.agent_file_name, "exec"), global_scope)
148
+ except BaseException as e:
149
+ tb_str, e_cls_name, exc_info, exc_stack = exception_summary(
150
+ e,
151
+ self.working_dir,
152
+ self.agent_file_name,
153
+ self.format_tb_ipython,
154
+ )
155
+ result_outq.put(tb_str)
156
+ if e_cls_name == "KeyboardInterrupt":
157
+ e_cls_name = "TimeoutError"
158
+
159
+ event_outq.put(("state:finished", e_cls_name, exc_info, exc_stack))
160
+ else:
161
+ event_outq.put(("state:finished", None, None, None))
162
+
163
+ # remove the file after execution (otherwise it might be included in the data preview)
164
+ os.remove(self.agent_file_name)
165
+
166
+ # put EOF marker to indicate that we're done
167
+ result_outq.put("<|EOF|>")
168
+
169
+ def create_process(self) -> None:
170
+ # we use three queues to communicate with the child process:
171
+ # - code_inq: send code to child to execute
172
+ # - result_outq: receive stdout/stderr from child
173
+ # - event_outq: receive events from child (e.g. state:ready, state:finished)
174
+ # trunk-ignore(mypy/var-annotated)
175
+ self.code_inq, self.result_outq, self.event_outq = Queue(), Queue(), Queue()
176
+ self.process = Process(
177
+ target=self._run_session,
178
+ args=(self.code_inq, self.result_outq, self.event_outq),
179
+ )
180
+ self.process.start()
181
+
182
+ def cleanup_session(self):
183
+ if self.process is None:
184
+ return
185
+ try:
186
+ # Reduce grace period from 2 seconds to 0.5
187
+ self.process.terminate()
188
+ self.process.join(timeout=0.5)
189
+
190
+ if self.process.exitcode is None:
191
+ logger.warning("Process failed to terminate, killing immediately")
192
+ self.process.kill()
193
+ self.process.join(timeout=0.5)
194
+
195
+ if self.process.exitcode is None:
196
+ logger.error("Process refuses to die, using SIGKILL")
197
+ os.kill(self.process.pid, signal.SIGKILL)
198
+ except Exception as e:
199
+ logger.error(f"Error during process cleanup: {e}")
200
+ finally:
201
+ if self.process is not None:
202
+ self.process.close()
203
+ self.process = None
204
+
205
+ def run(self, code: str, reset_session=True) -> ExecutionResult:
206
+ """
207
+ Execute the provided Python command in a separate process and return its output.
208
+
209
+ Parameters:
210
+ code (str): Python code to execute.
211
+ reset_session (bool, optional): Whether to reset the interpreter session before executing the code. Defaults to True.
212
+
213
+ Returns:
214
+ ExecutionResult: Object containing the output and metadata of the code execution.
215
+
216
+ """
217
+
218
+ logger.debug(f"REPL is executing code (reset_session={reset_session})")
219
+
220
+ if reset_session:
221
+ if self.process is not None:
222
+ # terminate and clean up previous process
223
+ self.cleanup_session()
224
+ self.create_process()
225
+ else:
226
+ # reset_session needs to be True on first exec
227
+ assert self.process is not None
228
+
229
+ assert self.process.is_alive()
230
+
231
+ self.code_inq.put(code)
232
+
233
+ # wait for child to actually start execution (we don't want interrupt child setup)
234
+ try:
235
+ state = self.event_outq.get(timeout=10)
236
+ except queue.Empty:
237
+ msg = "REPL child process failed to start execution"
238
+ logger.critical(msg)
239
+ while not self.result_outq.empty():
240
+ logger.error(f"REPL output queue dump: {self.result_outq.get()}")
241
+ raise RuntimeError(msg) from None
242
+ assert state[0] == "state:ready", state
243
+ start_time = time.time()
244
+
245
+ # this flag indicates that the child ahs exceeded the time limit and an interrupt was sent
246
+ # if the child process dies without this flag being set, it's an unexpected termination
247
+ child_in_overtime = False
248
+
249
+ while True:
250
+ try:
251
+ # check if the child is done
252
+ state = self.event_outq.get(timeout=1) # wait for state:finished
253
+ assert state[0] == "state:finished", state
254
+ exec_time = time.time() - start_time
255
+ break
256
+ except queue.Empty:
257
+ # we haven't heard back from the child -> check if it's still alive (assuming overtime interrupt wasn't sent yet)
258
+ if not child_in_overtime and not self.process.is_alive():
259
+ msg = "REPL child process died unexpectedly"
260
+ logger.critical(msg)
261
+ while not self.result_outq.empty():
262
+ logger.error(
263
+ f"REPL output queue dump: {self.result_outq.get()}"
264
+ )
265
+ raise RuntimeError(msg) from None
266
+
267
+ # child is alive and still executing -> check if we should sigint..
268
+ if self.timeout is None:
269
+ continue
270
+ running_time = time.time() - start_time
271
+ if running_time > self.timeout:
272
+ logger.warning(f"Execution exceeded timeout of {self.timeout}s")
273
+ os.kill(self.process.pid, signal.SIGINT)
274
+ child_in_overtime = True
275
+
276
+ # terminate if we're overtime by more than 5 seconds
277
+ if running_time > self.timeout + 5:
278
+ logger.warning("Child failed to terminate, killing it..")
279
+ self.cleanup_session()
280
+
281
+ state = (None, "TimeoutError", {}, [])
282
+ exec_time = self.timeout
283
+ break
284
+
285
+ output: list[str] = []
286
+ # read all stdout/stderr from child up to the EOF marker
287
+ # waiting until the queue is empty is not enough since
288
+ # the feeder thread in child might still be adding to the queue
289
+ start_collect = time.time()
290
+ while not self.result_outq.empty() or not output or output[-1] != "<|EOF|>":
291
+ try:
292
+ # Add 5-second timeout for output collection
293
+ if time.time() - start_collect > 5:
294
+ logger.warning("Output collection timed out")
295
+ break
296
+ output.append(self.result_outq.get(timeout=1))
297
+ except queue.Empty:
298
+ continue
299
+ output.pop() # remove the EOF marker
300
+
301
+ e_cls_name, exc_info, exc_stack = state[1:]
302
+
303
+ if e_cls_name == "TimeoutError":
304
+ output.append(
305
+ f"TimeoutError: Execution exceeded the time limit of {humanize.naturaldelta(self.timeout)}"
306
+ )
307
+ else:
308
+ output.append(
309
+ f"Execution time: {humanize.naturaldelta(exec_time)} seconds (time limit is {humanize.naturaldelta(self.timeout)})."
310
+ )
311
+ return ExecutionResult(output, exec_time, e_cls_name, exc_info, exc_stack)
aide/journal.py ADDED
@@ -0,0 +1,192 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ The journal is the core datastructure in AIDE that contains:
3
+ - the generated code samples
4
+ - information how code samples relate to each other (the tree structure)
5
+ - code execution results
6
+ - evaluation information such as metrics
7
+ ...
8
+ """
9
+
10
+ import time
11
+ import uuid
12
+ from dataclasses import dataclass, field
13
+ from typing import Literal, Optional
14
+
15
+ from dataclasses_json import DataClassJsonMixin
16
+ from .interpreter import ExecutionResult
17
+ from .utils.metric import MetricValue
18
+ from .utils.response import trim_long_string
19
+
20
+
21
+ @dataclass(eq=False)
22
+ class Node(DataClassJsonMixin):
23
+ """A single node in the solution tree. Contains code, execution results, and evaluation information."""
24
+
25
+ # ---- code & plan ----
26
+ code: str
27
+ plan: str = field(default=None, kw_only=True) # type: ignore
28
+
29
+ # ---- general attrs ----
30
+ step: int = field(default=None, kw_only=True) # type: ignore
31
+ id: str = field(default_factory=lambda: uuid.uuid4().hex, kw_only=True)
32
+ ctime: float = field(default_factory=lambda: time.time(), kw_only=True)
33
+ parent: Optional["Node"] = field(default=None, kw_only=True)
34
+ children: set["Node"] = field(default_factory=set, kw_only=True)
35
+
36
+ # ---- execution info ----
37
+ _term_out: list[str] = field(default=None, kw_only=True) # type: ignore
38
+ exec_time: float = field(default=None, kw_only=True) # type: ignore
39
+ exc_type: str | None = field(default=None, kw_only=True)
40
+ exc_info: dict | None = field(default=None, kw_only=True)
41
+ exc_stack: list[tuple] | None = field(default=None, kw_only=True)
42
+
43
+ # ---- evaluation ----
44
+ # post-execution result analysis (findings/feedback)
45
+ analysis: str = field(default=None, kw_only=True) # type: ignore
46
+ metric: MetricValue = field(default=None, kw_only=True) # type: ignore
47
+ # whether the agent decided that the code is buggy
48
+ # -> always True if exc_type is not None or no valid metric
49
+ is_buggy: bool = field(default=None, kw_only=True) # type: ignore
50
+
51
+ def __post_init__(self) -> None:
52
+ if self.parent is not None:
53
+ self.parent.children.add(self)
54
+
55
+ @property
56
+ def stage_name(self) -> Literal["draft", "debug", "improve"]:
57
+ """
58
+ Return the stage of the node:
59
+ - "stage" if the node is an initial solution draft
60
+ - "debug" if the node is the result of a debugging step
61
+ - "improve" if the node is the result of an improvement step
62
+ """
63
+ if self.parent is None:
64
+ return "draft"
65
+ return "debug" if self.parent.is_buggy else "improve"
66
+
67
+ def absorb_exec_result(self, exec_result: ExecutionResult):
68
+ """Absorb the result of executing the code from this node."""
69
+ self._term_out = exec_result.term_out
70
+ self.exec_time = exec_result.exec_time
71
+ self.exc_type = exec_result.exc_type
72
+ self.exc_info = exec_result.exc_info
73
+ self.exc_stack = exec_result.exc_stack
74
+
75
+ @property
76
+ def term_out(self) -> str:
77
+ """Get the terminal output of the code execution (after truncating it)."""
78
+ return trim_long_string("".join(self._term_out))
79
+
80
+ @property
81
+ def is_leaf(self) -> bool:
82
+ """Check if the node is a leaf node in the solution tree."""
83
+ return not self.children
84
+
85
+ def __eq__(self, other):
86
+ return isinstance(other, Node) and self.id == other.id
87
+
88
+ def __hash__(self):
89
+ return hash(self.id)
90
+
91
+ @property
92
+ def debug_depth(self) -> int:
93
+ """
94
+ Length of the current debug path
95
+ - 0 if the node is not a debug node (parent is not buggy)
96
+ - 1 if the parent is buggy but the skip parent isn't
97
+ - n if there were n consecutive debugging steps
98
+ """
99
+ if self.stage_name != "debug":
100
+ return 0
101
+ return self.parent.debug_depth + 1 # type: ignore
102
+
103
+
104
+ @dataclass
105
+ class InteractiveSession(DataClassJsonMixin):
106
+ """
107
+ A collection of nodes for an interaction session
108
+ (when the agent interacts with a Jupyter notebook-like interface).
109
+ """
110
+
111
+ nodes: list[Node] = field(default_factory=list)
112
+ completed: bool = False
113
+
114
+ def append(self, node: Node) -> None:
115
+ node.step = len(self.nodes)
116
+ self.nodes.append(node)
117
+
118
+ def generate_nb_trace(self, include_prompt, comment_headers=True) -> str:
119
+ """Generate a trace of the interactive session in IPython format."""
120
+ trace = []
121
+ header_prefix = "## " if comment_headers else ""
122
+ for n in self.nodes:
123
+ trace.append(f"\n{header_prefix}In [{n.step+1}]:\n")
124
+ trace.append(n.code)
125
+ trace.append(f"\n{header_prefix}Out [{n.step+1}]:\n")
126
+ trace.append(n.term_out)
127
+
128
+ if include_prompt and self.nodes:
129
+ trace.append(f"\n{header_prefix}In [{self.nodes[-1].step+2}]:\n")
130
+
131
+ return "\n".join(trace).strip()
132
+
133
+
134
+ @dataclass
135
+ class Journal(DataClassJsonMixin):
136
+ """A collection of nodes representing the solution tree."""
137
+
138
+ nodes: list[Node] = field(default_factory=list)
139
+ # eda: InteractiveSession = field(default_factory=lambda: InteractiveSession())
140
+
141
+ def __getitem__(self, idx: int) -> Node:
142
+ return self.nodes[idx]
143
+
144
+ def __len__(self) -> int:
145
+ """Return the number of nodes in the journal."""
146
+ return len(self.nodes)
147
+
148
+ def append(self, node: Node) -> None:
149
+ """Append a new node to the journal."""
150
+ node.step = len(self.nodes)
151
+ self.nodes.append(node)
152
+
153
+ @property
154
+ def draft_nodes(self) -> list[Node]:
155
+ """Return a list of nodes representing intial coding drafts"""
156
+ return [n for n in self.nodes if n.parent is None]
157
+
158
+ @property
159
+ def buggy_nodes(self) -> list[Node]:
160
+ """Return a list of nodes that are considered buggy by the agent."""
161
+ return [n for n in self.nodes if n.is_buggy]
162
+
163
+ @property
164
+ def good_nodes(self) -> list[Node]:
165
+ """Return a list of nodes that are not considered buggy by the agent."""
166
+ return [n for n in self.nodes if not n.is_buggy]
167
+
168
+ def get_metric_history(self) -> list[MetricValue]:
169
+ """Return a list of all metric values in the journal."""
170
+ return [n.metric for n in self.nodes]
171
+
172
+ def get_best_node(self, only_good=True) -> None | Node:
173
+ """Return the best solution found so far (node with the highest validation metric)."""
174
+ if only_good:
175
+ nodes = self.good_nodes
176
+ if not nodes:
177
+ return None
178
+ else:
179
+ nodes = self.nodes
180
+ return max(nodes, key=lambda n: n.metric)
181
+
182
+ def generate_summary(self, include_code: bool = False) -> str:
183
+ """Generate a summary of the journal for the agent."""
184
+ summary = []
185
+ for n in self.good_nodes:
186
+ summary_part = f"Design: {n.plan}\n"
187
+ if include_code:
188
+ summary_part += f"Code: {n.code}\n"
189
+ summary_part += f"Results: {n.analysis}\n"
190
+ summary_part += f"Validation Metric: {n.metric.value}\n"
191
+ summary.append(summary_part)
192
+ return "\n-------------------------------\n".join(summary)
aide/journal2report.py ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from .backend import query
2
+ from .journal import Journal
3
+ from .utils.config import StageConfig
4
+
5
+
6
+ def journal2report(journal: Journal, task_desc: dict, rcfg: StageConfig):
7
+ """
8
+ Generate a report from a journal, the report will be in markdown format.
9
+ """
10
+ report_input = journal.generate_summary(include_code=True)
11
+ system_prompt_dict = {
12
+ "Role": "You are a research assistant that always uses concise language.",
13
+ "Goal": "The goal is to write a technical report summarising the empirical findings and technical decisions.",
14
+ "Input": "You are given a raw research journal with list of design attempts and their outcomes, and a task description.",
15
+ "Output": [
16
+ "Your output should be a single markdown document.",
17
+ "Your report should have the following sections: Introduction, Preprocessing, Modellind Methods, Results Discussion, Future Work",
18
+ "You can include subsections if needed.",
19
+ ],
20
+ }
21
+ context_prompt = (
22
+ f"Here is the research journal of the agent: <journal>{report_input}<\\journal>, "
23
+ f"and the task description is: <task>{task_desc}<\\task>."
24
+ )
25
+ return query(
26
+ system_message=system_prompt_dict,
27
+ user_message=context_prompt,
28
+ model=rcfg.model,
29
+ temperature=rcfg.temp,
30
+ max_tokens=4096,
31
+ )
aide/run.py ADDED
@@ -0,0 +1,148 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import atexit
2
+ import logging
3
+ import shutil
4
+
5
+ from . import backend
6
+
7
+ from .agent import Agent
8
+ from .interpreter import Interpreter
9
+ from .journal import Journal, Node
10
+ from .journal2report import journal2report
11
+ from omegaconf import OmegaConf
12
+ from rich.columns import Columns
13
+ from rich.console import Group
14
+ from rich.live import Live
15
+ from rich.padding import Padding
16
+ from rich.panel import Panel
17
+ from rich.progress import (
18
+ BarColumn,
19
+ MofNCompleteColumn,
20
+ Progress,
21
+ TextColumn,
22
+ TimeRemainingColumn,
23
+ )
24
+ from rich.text import Text
25
+ from rich.status import Status
26
+ from rich.tree import Tree
27
+ from .utils.config import load_task_desc, prep_agent_workspace, save_run, load_cfg
28
+
29
+ logger = logging.getLogger("aide")
30
+
31
+
32
+ def journal_to_rich_tree(journal: Journal):
33
+ best_node = journal.get_best_node()
34
+
35
+ def append_rec(node: Node, tree):
36
+ if node.is_buggy:
37
+ s = "[red]◍ bug"
38
+ else:
39
+ style = "bold " if node is best_node else ""
40
+
41
+ if node is best_node:
42
+ s = f"[{style}green]● {node.metric.value:.3f} (best)"
43
+ else:
44
+ s = f"[{style}green]● {node.metric.value:.3f}"
45
+
46
+ subtree = tree.add(s)
47
+ for child in node.children:
48
+ append_rec(child, subtree)
49
+
50
+ tree = Tree("[bold blue]Solution tree")
51
+ for n in journal.draft_nodes:
52
+ append_rec(n, tree)
53
+ return tree
54
+
55
+
56
+ def run():
57
+ cfg = load_cfg()
58
+ logger.info(f'Starting run "{cfg.exp_name}"')
59
+
60
+ task_desc = load_task_desc(cfg)
61
+ task_desc_str = backend.compile_prompt_to_md(task_desc)
62
+
63
+ with Status("Preparing agent workspace (copying and extracting files) ..."):
64
+ prep_agent_workspace(cfg)
65
+
66
+ def cleanup():
67
+ if global_step == 0:
68
+ shutil.rmtree(cfg.workspace_dir)
69
+
70
+ atexit.register(cleanup)
71
+
72
+ journal = Journal()
73
+ agent = Agent(
74
+ task_desc=task_desc,
75
+ cfg=cfg,
76
+ journal=journal,
77
+ )
78
+ interpreter = Interpreter(
79
+ cfg.workspace_dir, **OmegaConf.to_container(cfg.exec) # type: ignore
80
+ )
81
+
82
+ global_step = len(journal)
83
+ prog = Progress(
84
+ TextColumn("[progress.description]{task.description}"),
85
+ BarColumn(bar_width=20),
86
+ MofNCompleteColumn(),
87
+ TimeRemainingColumn(),
88
+ )
89
+ status = Status("[green]Generating code...")
90
+ prog.add_task("Progress:", total=cfg.agent.steps, completed=global_step)
91
+
92
+ def exec_callback(*args, **kwargs):
93
+ status.update("[magenta]Executing code...")
94
+ res = interpreter.run(*args, **kwargs)
95
+ status.update("[green]Generating code...")
96
+ return res
97
+
98
+ def generate_live():
99
+ tree = journal_to_rich_tree(journal)
100
+ prog.update(prog.task_ids[0], completed=global_step)
101
+
102
+ file_paths = [
103
+ f"Result visualization:\n[yellow]▶ {str((cfg.log_dir / 'tree_plot.html'))}",
104
+ f"Agent workspace directory:\n[yellow]▶ {str(cfg.workspace_dir)}",
105
+ f"Experiment log directory:\n[yellow]▶ {str(cfg.log_dir)}",
106
+ ]
107
+ left = Group(
108
+ Panel(Text(task_desc_str.strip()), title="Task description"), prog, status
109
+ )
110
+ right = tree
111
+ wide = Group(*file_paths)
112
+
113
+ return Panel(
114
+ Group(
115
+ Padding(wide, (1, 1, 1, 1)),
116
+ Columns(
117
+ [Padding(left, (1, 2, 1, 1)), Padding(right, (1, 1, 1, 2))],
118
+ equal=True,
119
+ ),
120
+ ),
121
+ title=f'[b]AIDE is working on experiment: [bold green]"{cfg.exp_name}[/b]"',
122
+ subtitle="Press [b]Ctrl+C[/b] to stop the run",
123
+ )
124
+
125
+ with Live(
126
+ generate_live(),
127
+ refresh_per_second=16,
128
+ screen=True,
129
+ ) as live:
130
+ while global_step < cfg.agent.steps:
131
+ agent.step(exec_callback=exec_callback)
132
+ save_run(cfg, journal)
133
+ global_step = len(journal)
134
+ live.update(generate_live())
135
+ interpreter.cleanup_session()
136
+
137
+ if cfg.generate_report:
138
+ print("Generating final report from journal...")
139
+ report = journal2report(journal, task_desc, cfg.report)
140
+ print(report)
141
+ report_file_path = cfg.log_dir / "report.md"
142
+ with open(report_file_path, "w") as f:
143
+ f.write(report)
144
+ print("Report written to file:", report_file_path)
145
+
146
+
147
+ if __name__ == "__main__":
148
+ run()
aide/utils/__init__.py ADDED
@@ -0,0 +1,100 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import logging
2
+ import shutil
3
+ import zipfile
4
+ from pathlib import Path
5
+
6
+ logger = logging.getLogger("aide")
7
+
8
+
9
+ def copytree(src: Path, dst: Path, use_symlinks=True):
10
+ """
11
+ Copy contents of `src` to `dst`. Unlike shutil.copytree, the dst dir can exist and will be merged.
12
+ If src is a file, only that file will be copied. Optionally uses symlinks instead of copying.
13
+
14
+ Args:
15
+ src (Path): source directory
16
+ dst (Path): destination directory
17
+ """
18
+ assert dst.is_dir()
19
+
20
+ if src.is_file():
21
+ dest_f = dst / src.name
22
+ assert not dest_f.exists(), dest_f
23
+ if use_symlinks:
24
+ (dest_f).symlink_to(src)
25
+ else:
26
+ shutil.copyfile(src, dest_f)
27
+ return
28
+
29
+ for f in src.iterdir():
30
+ dest_f = dst / f.name
31
+ assert not dest_f.exists(), dest_f
32
+ if use_symlinks:
33
+ (dest_f).symlink_to(f)
34
+ elif f.is_dir():
35
+ shutil.copytree(f, dest_f)
36
+ else:
37
+ shutil.copyfile(f, dest_f)
38
+
39
+
40
+ def clean_up_dataset(path: Path):
41
+ for item in path.rglob("__MACOSX"):
42
+ if item.is_dir():
43
+ shutil.rmtree(item)
44
+ for item in path.rglob(".DS_Store"):
45
+ if item.is_file():
46
+ item.unlink()
47
+
48
+
49
+ def extract_archives(path: Path):
50
+ """
51
+ unzips all .zip files within `path` and cleans up task dir
52
+
53
+ [TODO] handle nested zips
54
+ """
55
+ for zip_f in path.rglob("*.zip"):
56
+ f_out_dir = zip_f.with_suffix("")
57
+
58
+ # special case: the intended output path already exists (maybe data has already been extracted by user)
59
+ if f_out_dir.exists():
60
+ logger.debug(
61
+ f"Skipping {zip_f} as an item with the same name already exists."
62
+ )
63
+ # if it's a file, it's probably exactly the same as in the zip -> remove the zip
64
+ # [TODO] maybe add an extra check to see if zip file content matches the colliding file
65
+ if f_out_dir.is_file() and f_out_dir.suffix != "":
66
+ zip_f.unlink()
67
+ continue
68
+
69
+ logger.debug(f"Extracting: {zip_f}")
70
+ f_out_dir.mkdir(exist_ok=True)
71
+ with zipfile.ZipFile(zip_f, "r") as zip_ref:
72
+ zip_ref.extractall(f_out_dir)
73
+
74
+ # remove any unwanted files
75
+ clean_up_dataset(f_out_dir)
76
+
77
+ contents = list(f_out_dir.iterdir())
78
+
79
+ # special case: the zip contains a single dir/file with the same name as the zip
80
+ if len(contents) == 1 and contents[0].name == f_out_dir.name:
81
+ sub_item = contents[0]
82
+ # if it's a dir, move its contents to the parent and remove it
83
+ if sub_item.is_dir():
84
+ logger.debug(f"Special handling (child is dir) enabled for: {zip_f}")
85
+ for f in sub_item.rglob("*"):
86
+ shutil.move(f, f_out_dir)
87
+ sub_item.rmdir()
88
+ # if it's a file, rename it to the parent and remove the parent
89
+ elif sub_item.is_file():
90
+ logger.debug(f"Special handling (child is file) enabled for: {zip_f}")
91
+ sub_item_tmp = sub_item.rename(f_out_dir.with_suffix(".__tmp_rename"))
92
+ f_out_dir.rmdir()
93
+ sub_item_tmp.rename(f_out_dir)
94
+
95
+ zip_f.unlink()
96
+
97
+
98
+ def preproc_data(path: Path):
99
+ extract_archives(path)
100
+ clean_up_dataset(path)
aide/utils/config.py ADDED
@@ -0,0 +1,199 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """configuration and setup utils"""
2
+
3
+ from dataclasses import dataclass
4
+ from pathlib import Path
5
+ from typing import Hashable, cast
6
+
7
+ import coolname
8
+ import rich
9
+ from omegaconf import OmegaConf
10
+ from rich.syntax import Syntax
11
+ import shutup
12
+ from rich.logging import RichHandler
13
+ import logging
14
+
15
+ from . import tree_export
16
+ from . import copytree, preproc_data, serialize
17
+
18
+ shutup.mute_warnings()
19
+ logging.basicConfig(
20
+ level="WARNING", format="%(message)s", datefmt="[%X]", handlers=[RichHandler()]
21
+ )
22
+ logger = logging.getLogger("aide")
23
+ logger.setLevel(logging.WARNING)
24
+
25
+
26
+ """ these dataclasses are just for type hinting, the actual config is in config.yaml """
27
+
28
+
29
+ @dataclass
30
+ class StageConfig:
31
+ model: str
32
+ temp: float
33
+
34
+
35
+ @dataclass
36
+ class SearchConfig:
37
+ max_debug_depth: int
38
+ debug_prob: float
39
+ num_drafts: int
40
+
41
+
42
+ @dataclass
43
+ class AgentConfig:
44
+ steps: int
45
+ k_fold_validation: int
46
+ expose_prediction: bool
47
+ data_preview: bool
48
+
49
+ code: StageConfig
50
+ feedback: StageConfig
51
+
52
+ search: SearchConfig
53
+
54
+
55
+ @dataclass
56
+ class ExecConfig:
57
+ timeout: int
58
+ agent_file_name: str
59
+ format_tb_ipython: bool
60
+
61
+
62
+ @dataclass
63
+ class Config(Hashable):
64
+ data_dir: Path
65
+ desc_file: Path | None
66
+
67
+ goal: str | None
68
+ eval: str | None
69
+
70
+ log_dir: Path
71
+ workspace_dir: Path
72
+
73
+ preprocess_data: bool
74
+ copy_data: bool
75
+
76
+ exp_name: str
77
+
78
+ exec: ExecConfig
79
+ generate_report: bool
80
+ report: StageConfig
81
+ agent: AgentConfig
82
+
83
+
84
+ def _get_next_logindex(dir: Path) -> int:
85
+ """Get the next available index for a log directory."""
86
+ max_index = -1
87
+ for p in dir.iterdir():
88
+ try:
89
+ if current_index := int(p.name.split("-")[0]) > max_index:
90
+ max_index = current_index
91
+ except ValueError:
92
+ pass
93
+ return max_index + 1
94
+
95
+
96
+ def _load_cfg(
97
+ path: Path = Path(__file__).parent / "config.yaml", use_cli_args=True
98
+ ) -> Config:
99
+ cfg = OmegaConf.load(path)
100
+ if use_cli_args:
101
+ cfg = OmegaConf.merge(cfg, OmegaConf.from_cli())
102
+ return cfg
103
+
104
+
105
+ def load_cfg(path: Path = Path(__file__).parent / "config.yaml") -> Config:
106
+ """Load config from .yaml file and CLI args, and set up logging directory."""
107
+ return prep_cfg(_load_cfg(path))
108
+
109
+
110
+ def prep_cfg(cfg: Config):
111
+ if cfg.data_dir is None:
112
+ raise ValueError("`data_dir` must be provided.")
113
+
114
+ if cfg.desc_file is None and cfg.goal is None:
115
+ raise ValueError(
116
+ "You must provide either a description of the task goal (`goal=...`) or a path to a plaintext file containing the description (`desc_file=...`)."
117
+ )
118
+
119
+ if cfg.data_dir.startswith("example_tasks/"):
120
+ cfg.data_dir = Path(__file__).parent.parent / cfg.data_dir
121
+ cfg.data_dir = Path(cfg.data_dir).resolve()
122
+
123
+ if cfg.desc_file is not None:
124
+ cfg.desc_file = Path(cfg.desc_file).resolve()
125
+
126
+ top_log_dir = Path(cfg.log_dir).resolve()
127
+ top_log_dir.mkdir(parents=True, exist_ok=True)
128
+
129
+ top_workspace_dir = Path(cfg.workspace_dir).resolve()
130
+ top_workspace_dir.mkdir(parents=True, exist_ok=True)
131
+
132
+ # generate experiment name and prefix with consecutive index
133
+ ind = max(_get_next_logindex(top_log_dir), _get_next_logindex(top_workspace_dir))
134
+ cfg.exp_name = cfg.exp_name or coolname.generate_slug(3)
135
+ cfg.exp_name = f"{ind}-{cfg.exp_name}"
136
+
137
+ cfg.log_dir = (top_log_dir / cfg.exp_name).resolve()
138
+ cfg.workspace_dir = (top_workspace_dir / cfg.exp_name).resolve()
139
+
140
+ # validate the config
141
+ cfg_schema: Config = OmegaConf.structured(Config)
142
+ cfg = OmegaConf.merge(cfg_schema, cfg)
143
+
144
+ return cast(Config, cfg)
145
+
146
+
147
+ def print_cfg(cfg: Config) -> None:
148
+ rich.print(Syntax(OmegaConf.to_yaml(cfg), "yaml", theme="paraiso-dark"))
149
+
150
+
151
+ def load_task_desc(cfg: Config):
152
+ """Load task description from markdown file or config str."""
153
+
154
+ # either load the task description from a file
155
+ if cfg.desc_file is not None:
156
+ if not (cfg.goal is None and cfg.eval is None):
157
+ logger.warning(
158
+ "Ignoring goal and eval args because task description file is provided."
159
+ )
160
+
161
+ with open(cfg.desc_file) as f:
162
+ return f.read()
163
+
164
+ # or generate it from the goal and eval args
165
+ if cfg.goal is None:
166
+ raise ValueError(
167
+ "`goal` (and optionally `eval`) must be provided if a task description file is not provided."
168
+ )
169
+
170
+ task_desc = {"Task goal": cfg.goal}
171
+ if cfg.eval is not None:
172
+ task_desc["Task evaluation"] = cfg.eval
173
+
174
+ return task_desc
175
+
176
+
177
+ def prep_agent_workspace(cfg: Config):
178
+ """Setup the agent's workspace and preprocess data if necessary."""
179
+ (cfg.workspace_dir / "input").mkdir(parents=True, exist_ok=True)
180
+ (cfg.workspace_dir / "working").mkdir(parents=True, exist_ok=True)
181
+
182
+ copytree(cfg.data_dir, cfg.workspace_dir / "input", use_symlinks=not cfg.copy_data)
183
+ if cfg.preprocess_data:
184
+ preproc_data(cfg.workspace_dir / "input")
185
+
186
+
187
+ def save_run(cfg: Config, journal):
188
+ cfg.log_dir.mkdir(parents=True, exist_ok=True)
189
+
190
+ # save journal
191
+ serialize.dump_json(journal, cfg.log_dir / "journal.json")
192
+ # save config
193
+ OmegaConf.save(config=cfg, f=cfg.log_dir / "config.yaml")
194
+ # create the tree + code visualization
195
+ tree_export.generate(cfg, journal, cfg.log_dir / "tree_plot.html")
196
+ # save the best found solution
197
+ best_node = journal.get_best_node(only_good=False)
198
+ with open(cfg.log_dir / "best_solution.py", "w") as f:
199
+ f.write(best_node.code)
aide/utils/config.yaml ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # path to the task data directory
2
+ data_dir: null
3
+
4
+ # either provide a path to a plaintext file describing the task
5
+ desc_file: null
6
+ # or provide the task goal (and optionally evaluation information) as arguments
7
+ goal: null
8
+ eval: null
9
+
10
+ log_dir: logs
11
+ workspace_dir: workspaces
12
+
13
+ # whether to unzip any archives in the data directory
14
+ preprocess_data: True
15
+ # whether to copy the data to the workspace directory (otherwise it will be symlinked)
16
+ # copying is recommended to prevent the agent from accidentally modifying the original data
17
+ copy_data: True
18
+
19
+ exp_name: null # a random experiment name will be generated if not provided
20
+
21
+ # settings for code execution
22
+ exec:
23
+ timeout: 3600
24
+ agent_file_name: runfile.py
25
+ format_tb_ipython: False
26
+
27
+ generate_report: True
28
+ # LLM settings for final report from journal
29
+ report:
30
+ model: gpt-4-turbo
31
+ temp: 1.0
32
+
33
+ # agent hyperparams
34
+ agent:
35
+ # how many improvement iterations to run
36
+ steps: 20
37
+ # whether to instruct the agent to use CV (set to 1 to disable)
38
+ k_fold_validation: 5
39
+ # whether to instruct the agent to generate a prediction function
40
+ expose_prediction: False
41
+ # whether to provide the agent with a preview of the data
42
+ data_preview: True
43
+
44
+ # LLM settings for coding
45
+ code:
46
+ model: gpt-4-turbo
47
+ temp: 0.5
48
+
49
+ # LLM settings for evaluating program output / tracebacks
50
+ feedback:
51
+ model: gpt-4-turbo
52
+ temp: 0.5
53
+
54
+ # hyperparameters for the tree search
55
+ search:
56
+ max_debug_depth: 3
57
+ debug_prob: 0.5
58
+ num_drafts: 5
aide/utils/data_preview.py ADDED
@@ -0,0 +1,153 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Contains functions to manually generate a textual preview of some common file types (.csv, .json,..) for the agent.
3
+ """
4
+
5
+ import json
6
+ from pathlib import Path
7
+
8
+ import humanize
9
+ import pandas as pd
10
+ from genson import SchemaBuilder
11
+ from pandas.api.types import is_numeric_dtype
12
+
13
+ # these files are treated as code (e.g. markdown wrapped)
14
+ code_files = {".py", ".sh", ".yaml", ".yml", ".md", ".html", ".xml", ".log", ".rst"}
15
+ # we treat these files as text (rather than binary) files
16
+ plaintext_files = {".txt", ".csv", ".json", ".tsv"} | code_files
17
+
18
+
19
+ def get_file_len_size(f: Path) -> tuple[int, str]:
20
+ """
21
+ Calculate the size of a file (#lines for plaintext files, otherwise #bytes)
22
+ Also returns a human-readable string representation of the size.
23
+ """
24
+ if f.suffix in plaintext_files:
25
+ num_lines = sum(1 for _ in open(f))
26
+ return num_lines, f"{num_lines} lines"
27
+ else:
28
+ s = f.stat().st_size
29
+ return s, humanize.naturalsize(s)
30
+
31
+
32
+ def file_tree(path: Path, depth=0) -> str:
33
+ """Generate a tree structure of files in a directory"""
34
+ result = []
35
+ files = [p for p in Path(path).iterdir() if not p.is_dir()]
36
+ dirs = [p for p in Path(path).iterdir() if p.is_dir()]
37
+ max_n = 4 if len(files) > 30 else 8
38
+ for p in sorted(files)[:max_n]:
39
+ result.append(f"{' '*depth*4}{p.name} ({get_file_len_size(p)[1]})")
40
+ if len(files) > max_n:
41
+ result.append(f"{' '*depth*4}... and {len(files)-max_n} other files")
42
+
43
+ for p in sorted(dirs):
44
+ result.append(f"{' '*depth*4}{p.name}/")
45
+ result.append(file_tree(p, depth + 1))
46
+
47
+ return "\n".join(result)
48
+
49
+
50
+ def _walk(path: Path):
51
+ """Recursively walk a directory (analogous to os.walk but for pathlib.Path)"""
52
+ for p in sorted(Path(path).iterdir()):
53
+ if p.is_dir():
54
+ yield from _walk(p)
55
+ continue
56
+ yield p
57
+
58
+
59
+ def preview_csv(p: Path, file_name: str, simple=True) -> str:
60
+ """Generate a textual preview of a csv file
61
+
62
+ Args:
63
+ p (Path): the path to the csv file
64
+ file_name (str): the file name to use in the preview
65
+ simple (bool, optional): whether to use a simplified version of the preview. Defaults to True.
66
+
67
+ Returns:
68
+ str: the textual preview
69
+ """
70
+ df = pd.read_csv(p)
71
+
72
+ out = []
73
+
74
+ out.append(f"-> {file_name} has {df.shape[0]} rows and {df.shape[1]} columns.")
75
+
76
+ if simple:
77
+ cols = df.columns.tolist()
78
+ sel_cols = 15
79
+ cols_str = ", ".join(cols[:sel_cols])
80
+ res = f"The columns are: {cols_str}"
81
+ if len(cols) > sel_cols:
82
+ res += f"... and {len(cols)-sel_cols} more columns"
83
+ out.append(res)
84
+ else:
85
+ out.append("Here is some information about the columns:")
86
+ for col in sorted(df.columns):
87
+ dtype = df[col].dtype
88
+ name = f"{col} ({dtype})"
89
+
90
+ nan_count = df[col].isnull().sum()
91
+
92
+ if dtype == "bool":
93
+ v = df[col][df[col].notnull()].mean()
94
+ out.append(f"{name} is {v*100:.2f}% True, {100-v*100:.2f}% False")
95
+ elif df[col].nunique() < 10:
96
+ out.append(
97
+ f"{name} has {df[col].nunique()} unique values: {df[col].unique().tolist()}"
98
+ )
99
+ elif is_numeric_dtype(df[col]):
100
+ out.append(
101
+ f"{name} has range: {df[col].min():.2f} - {df[col].max():.2f}, {nan_count} nan values"
102
+ )
103
+ elif dtype == "object":
104
+ out.append(
105
+ f"{name} has {df[col].nunique()} unique values. Some example values: {df[col].value_counts().head(4).index.tolist()}"
106
+ )
107
+
108
+ return "\n".join(out)
109
+
110
+
111
+ def preview_json(p: Path, file_name: str):
112
+ """Generate a textual preview of a json file using a generated json schema"""
113
+ builder = SchemaBuilder()
114
+ with open(p) as f:
115
+ builder.add_object(json.load(f))
116
+ return f"-> {file_name} has auto-generated json schema:\n" + builder.to_json(
117
+ indent=2
118
+ )
119
+
120
+
121
+ def generate(base_path, include_file_details=True, simple=False):
122
+ """
123
+ Generate a textual preview of a directory, including an overview of the directory
124
+ structure and previews of individual files
125
+ """
126
+ tree = f"```\n{file_tree(base_path)}```"
127
+ out = [tree]
128
+
129
+ if include_file_details:
130
+ for fn in _walk(base_path):
131
+ file_name = str(fn.relative_to(base_path))
132
+
133
+ if fn.suffix == ".csv":
134
+ out.append(preview_csv(fn, file_name, simple=simple))
135
+ elif fn.suffix == ".json":
136
+ out.append(preview_json(fn, file_name))
137
+ elif fn.suffix in plaintext_files:
138
+ if get_file_len_size(fn)[0] < 30:
139
+ with open(fn) as f:
140
+ content = f.read()
141
+ if fn.suffix in code_files:
142
+ content = f"```\n{content}\n```"
143
+ out.append(f"-> {file_name} has content:\n\n{content}")
144
+
145
+ result = "\n\n".join(out)
146
+
147
+ # if the result is very long we generate a simpler version
148
+ if len(result) > 6_000 and not simple:
149
+ return generate(
150
+ base_path, include_file_details=include_file_details, simple=True
151
+ )
152
+
153
+ return result
aide/utils/metric.py ADDED
@@ -0,0 +1,78 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from dataclasses import dataclass, field
2
+ from functools import total_ordering
3
+ from typing import Any
4
+
5
+ import numpy as np
6
+ from dataclasses_json import DataClassJsonMixin
7
+
8
+
9
+ @dataclass
10
+ @total_ordering
11
+ class MetricValue(DataClassJsonMixin):
12
+ """
13
+ Represents the value of a metric to be optimized, which can be compared to other metric values.
14
+ Comparisons (and max, min) are based on which value is better, not which is larger.
15
+ """
16
+
17
+ value: float | int | np.number | np.floating | np.ndarray | None
18
+ maximize: bool | None = field(default=None, kw_only=True)
19
+
20
+ def __post_init__(self):
21
+ if self.value is not None:
22
+ assert isinstance(self.value, (float, int, np.number, np.floating))
23
+ self.value = float(self.value)
24
+
25
+ def __gt__(self, other) -> bool:
26
+ """True if self is a _better_ (not necessarily larger) metric value than other"""
27
+ if self.value is None:
28
+ return False
29
+ if other.value is None:
30
+ return True
31
+
32
+ assert type(self) is type(other) and (self.maximize == other.maximize)
33
+
34
+ if self.value == other.value:
35
+ return False
36
+
37
+ comp = self.value > other.value
38
+ return comp if self.maximize else not comp # type: ignore
39
+
40
+ def __eq__(self, other: Any) -> bool:
41
+ return self.value == other.value
42
+
43
+ def __repr__(self) -> str:
44
+ return str(self)
45
+
46
+ def __str__(self) -> str:
47
+ if self.maximize is None:
48
+ opt_dir = "?"
49
+ elif self.maximize:
50
+ opt_dir = "↑"
51
+ else:
52
+ opt_dir = "↓"
53
+ return f"Metric{opt_dir}({self.value_npsafe:.4f})"
54
+
55
+ @property
56
+ def is_worst(self):
57
+ """True if the metric value is the worst possible value."""
58
+ return self.value is None
59
+
60
+ @property
61
+ def value_npsafe(self):
62
+ return self.value if self.value is not None else float("nan")
63
+
64
+
65
+ @dataclass
66
+ class WorstMetricValue(MetricValue):
67
+ """
68
+ Represents an invalid metric value, e.g. when the agent creates a buggy solution.
69
+ Always compares worse than any valid metric value.
70
+ """
71
+
72
+ value: None = None
73
+
74
+ def __repr__(self):
75
+ return super().__repr__()
76
+
77
+ def __str__(self):
78
+ return super().__str__()
aide/utils/response.py ADDED
@@ -0,0 +1,91 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json
2
+ import re
3
+
4
+ import black
5
+
6
+
7
+ def wrap_code(code: str, lang="python") -> str:
8
+ """Wraps code with three backticks."""
9
+ return f"```{lang}\n{code}\n```"
10
+
11
+
12
+ def is_valid_python_script(script):
13
+ """Check if a script is a valid Python script."""
14
+ try:
15
+ compile(script, "<string>", "exec")
16
+ return True
17
+ except SyntaxError:
18
+ return False
19
+
20
+
21
+ def extract_jsons(text):
22
+ """Extract all JSON objects from the text. Caveat: This function cannot handle nested JSON objects."""
23
+ json_objects = []
24
+ matches = re.findall(r"\{.*?\}", text, re.DOTALL)
25
+ for match in matches:
26
+ try:
27
+ json_obj = json.loads(match)
28
+ json_objects.append(json_obj)
29
+ except json.JSONDecodeError:
30
+ pass
31
+
32
+ # Sometimes chatgpt-turbo forget the last curly bracket, so we try to add it back when no json is found
33
+ if len(json_objects) == 0 and not text.endswith("}"):
34
+ json_objects = extract_jsons(text + "}")
35
+ if len(json_objects) > 0:
36
+ return json_objects
37
+
38
+ return json_objects
39
+
40
+
41
+ def trim_long_string(string, threshold=5100, k=2500):
42
+ # Check if the length of the string is longer than the threshold
43
+ if len(string) > threshold:
44
+ # Output the first k and last k characters
45
+ first_k_chars = string[:k]
46
+ last_k_chars = string[-k:]
47
+
48
+ truncated_len = len(string) - 2 * k
49
+
50
+ return f"{first_k_chars}\n ... [{truncated_len} characters truncated] ... \n{last_k_chars}"
51
+ else:
52
+ return string
53
+
54
+
55
+ def extract_code(text):
56
+ """Extract python code blocks from the text."""
57
+ parsed_codes = []
58
+
59
+ # When code is in a text or python block
60
+ matches = re.findall(r"```(python)?\n*(.*?)\n*```", text, re.DOTALL)
61
+ for match in matches:
62
+ code_block = match[1]
63
+ parsed_codes.append(code_block)
64
+
65
+ # When the entire text is code or backticks of the code block is missing
66
+ if len(parsed_codes) == 0:
67
+ matches = re.findall(r"^(```(python)?)?\n?(.*?)\n?(```)?$", text, re.DOTALL)
68
+ if matches:
69
+ code_block = matches[0][2]
70
+ parsed_codes.append(code_block)
71
+
72
+ # validate the parsed codes
73
+ valid_code_blocks = [
74
+ format_code(c) for c in parsed_codes if is_valid_python_script(c)
75
+ ]
76
+ return format_code("\n\n".join(valid_code_blocks))
77
+
78
+
79
+ def extract_text_up_to_code(s):
80
+ """Extract (presumed) natural language text up to the start of the first code block."""
81
+ if "```" not in s:
82
+ return ""
83
+ return s[: s.find("```")].strip()
84
+
85
+
86
+ def format_code(code) -> str:
87
+ """Format Python code using Black."""
88
+ try:
89
+ return black.format_str(code, mode=black.FileMode())
90
+ except black.parsing.InvalidInput: # type: ignore
91
+ return code
aide/utils/serialize.py ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import copy
2
+ import json
3
+ from pathlib import Path
4
+ from typing import Type, TypeVar
5
+
6
+ import dataclasses_json
7
+ from ..journal import Journal
8
+
9
+
10
+ def dumps_json(obj: dataclasses_json.DataClassJsonMixin):
11
+ """Serialize AIDE dataclasses (such as Journals) to JSON."""
12
+ if isinstance(obj, Journal):
13
+ obj = copy.deepcopy(obj)
14
+ node2parent = {n.id: n.parent.id for n in obj.nodes if n.parent is not None}
15
+ for n in obj.nodes:
16
+ n.parent = None
17
+ n.children = set()
18
+
19
+ obj_dict = obj.to_dict()
20
+
21
+ if isinstance(obj, Journal):
22
+ obj_dict["node2parent"] = node2parent # type: ignore
23
+ obj_dict["__version"] = "2"
24
+
25
+ return json.dumps(obj_dict, separators=(",", ":"))
26
+
27
+
28
+ def dump_json(obj: dataclasses_json.DataClassJsonMixin, path: Path):
29
+ with open(path, "w") as f:
30
+ f.write(dumps_json(obj))
31
+
32
+
33
+ G = TypeVar("G", bound=dataclasses_json.DataClassJsonMixin)
34
+
35
+
36
+ def loads_json(s: str, cls: Type[G]) -> G:
37
+ """Deserialize JSON to AIDE dataclasses."""
38
+ obj_dict = json.loads(s)
39
+ obj = cls.from_dict(obj_dict)
40
+
41
+ if isinstance(obj, Journal):
42
+ id2nodes = {n.id: n for n in obj.nodes}
43
+ for child_id, parent_id in obj_dict["node2parent"].items():
44
+ id2nodes[child_id].parent = id2nodes[parent_id]
45
+ id2nodes[child_id].__post_init__()
46
+ return obj
47
+
48
+
49
+ def load_json(path: Path, cls: Type[G]) -> G:
50
+ with open(path, "r") as f:
51
+ return loads_json(f.read(), cls)
aide/utils/tree_export.py ADDED
@@ -0,0 +1,94 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Export journal to HTML visualization of tree + code."""
2
+
3
+ import json
4
+ import textwrap
5
+ from pathlib import Path
6
+
7
+ import numpy as np
8
+ from igraph import Graph
9
+ from ..journal import Journal
10
+
11
+
12
+ def get_edges(journal: Journal):
13
+ for node in journal:
14
+ for c in node.children:
15
+ yield (node.step, c.step)
16
+
17
+
18
+ def generate_layout(n_nodes, edges, layout_type="rt"):
19
+ """Generate visual layout of graph"""
20
+ layout = Graph(
21
+ n_nodes,
22
+ edges=edges,
23
+ directed=True,
24
+ ).layout(layout_type)
25
+ y_max = max(layout[k][1] for k in range(n_nodes))
26
+ layout_coords = []
27
+ for n in range(n_nodes):
28
+ layout_coords.append((layout[n][0], 2 * y_max - layout[n][1]))
29
+ return np.array(layout_coords)
30
+
31
+
32
+ def normalize_layout(layout: np.ndarray):
33
+ """Normalize layout to [0, 1]"""
34
+ layout = (layout - layout.min(axis=0)) / (layout.max(axis=0) - layout.min(axis=0))
35
+ layout[:, 1] = 1 - layout[:, 1]
36
+ layout[:, 1] = np.nan_to_num(layout[:, 1], nan=0)
37
+ layout[:, 0] = np.nan_to_num(layout[:, 0], nan=0.5)
38
+ return layout
39
+
40
+
41
+ def strip_code_markers(code: str) -> str:
42
+ """Remove markdown code block markers if present."""
43
+ code = code.strip()
44
+ if code.startswith("```"):
45
+ # Remove opening backticks and optional language identifier
46
+ first_newline = code.find("\n")
47
+ if first_newline != -1:
48
+ code = code[first_newline:].strip()
49
+ if code.endswith("```"):
50
+ code = code[:-3].strip()
51
+ return code
52
+
53
+
54
+ def cfg_to_tree_struct(cfg, jou: Journal):
55
+ edges = list(get_edges(jou))
56
+ layout = normalize_layout(generate_layout(len(jou), edges))
57
+
58
+ # metrics = np.array([n.metric.value_npsafe for n in jou])
59
+ # metrics = (metrics - np.nanmin(metrics)) / (np.nanmax(metrics) - np.nanmin(metrics))
60
+ # metrics = np.nan_to_num(metrics, nan=1)
61
+ # metrics[:] = 0
62
+ metrics = np.array([0 for n in jou])
63
+
64
+ return dict(
65
+ edges=edges,
66
+ layout=layout.tolist(),
67
+ plan=[textwrap.fill(n.plan, width=80) for n in jou.nodes],
68
+ code=[strip_code_markers(n.code) for n in jou],
69
+ term_out=[n.term_out for n in jou],
70
+ analysis=[n.analysis for n in jou],
71
+ exp_name=cfg.exp_name,
72
+ metrics=metrics.tolist(),
73
+ )
74
+
75
+
76
+ def generate_html(tree_graph_str: str):
77
+ template_dir = Path(__file__).parent / "viz_templates"
78
+
79
+ with open(template_dir / "template.js") as f:
80
+ js = f.read()
81
+ js = js.replace("<placeholder>", tree_graph_str)
82
+
83
+ with open(template_dir / "template.html") as f:
84
+ html = f.read()
85
+ html = html.replace("<!-- placeholder -->", js)
86
+
87
+ return html
88
+
89
+
90
+ def generate(cfg, jou: Journal, out_path: Path):
91
+ tree_graph_str = json.dumps(cfg_to_tree_struct(cfg, jou))
92
+ html = generate_html(tree_graph_str)
93
+ with open(out_path, "w") as f:
94
+ f.write(html)
aide/utils/viz_templates/template.html ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <script
7
+ id="p5scripttag"
8
+ src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.9.0/p5.min.js"
9
+ integrity="sha512-uaz5GpnQoE6t5echKlX8P52czvsIGgLPcvlzfvRubLZ1Hp8JemUDnbUiAahbVtPb+jUVrNETuXvAhDDF/N3M4w=="
10
+ crossorigin="anonymous"
11
+ referrerpolicy="no-referrer"
12
+ ></script>
13
+
14
+ <link
15
+ rel="stylesheet"
16
+ href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/atom-one-dark.min.css"
17
+ />
18
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script>
19
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/python.min.js"></script>
20
+
21
+ <script>
22
+ <!-- placeholder -->
23
+ </script>
24
+ <title>AIDE Run Visualization</title>
25
+ <style>
26
+ body,
27
+ * {
28
+ margin: 0;
29
+ padding: 0;
30
+ box-sizing: border-box;
31
+ overflow: scroll;
32
+ }
33
+ body {
34
+ background-color: #f2f0e7;
35
+ }
36
+ canvas {
37
+ float: left;
38
+ height: 100vh;
39
+ width: 40vw;
40
+ }
41
+ #text-container {
42
+ float: right;
43
+ height: 100vh;
44
+ width: 50vw;
45
+ background-color: #282c34;
46
+ }
47
+ #plan {
48
+ /* border-left: 2px solid #282c34; */
49
+ background-color: #282c34;
50
+ color: #f2f0e7;
51
+ min-height: 5rem;
52
+ padding: 1em 0 1em 1em;
53
+ }
54
+ </style>
55
+ </head>
56
+ <body>
57
+ <pre
58
+ id="text-container"
59
+ ><div id="plan"></div><hr><code id="code" class="language-python"></code></pre>
60
+ </body>
61
+ </html>
aide/utils/viz_templates/template.js ADDED
@@ -0,0 +1,362 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const bgCol = "#F2F0E7";
2
+ const accentCol = "#fd4578";
3
+
4
+ hljs.initHighlightingOnLoad();
5
+
6
+ const updateTargetDims = () => {
7
+ // width is max-width of `.contentContainer` - its padding
8
+ // return [min(windowWidth, 900 - 80), 700]
9
+ return [windowWidth * (1 / 2), windowHeight];
10
+ };
11
+
12
+ const setCodeAndPlan = (code, plan) => {
13
+ const codeElm = document.getElementById("code");
14
+ if (codeElm) {
15
+ // codeElm.innerText = code;
16
+ codeElm.innerHTML = hljs.highlight(code, { language: "python" }).value;
17
+ }
18
+
19
+ const planElm = document.getElementById("plan");
20
+ if (planElm) {
21
+ // planElm.innerText = plan.trim();
22
+ planElm.innerHTML = hljs.highlight(plan, { language: "plaintext" }).value;
23
+ }
24
+ };
25
+
26
+ windowResized = () => {
27
+ resizeCanvas(...updateTargetDims());
28
+ awaitingPostResizeOps = true;
29
+ };
30
+
31
+ const animEase = (t) => 1 - (1 - Math.min(t, 1.0)) ** 5;
32
+
33
+ // ---- global constants ----
34
+
35
+ const globalAnimSpeed = 1.1;
36
+ const scaleFactor = 0.57;
37
+
38
+ // ---- global vars ----
39
+
40
+ let globalTime = 0;
41
+ let manualSelection = false;
42
+
43
+ let currentElemInd = 0;
44
+
45
+ let treeStructData = <placeholder>
46
+
47
+ let lastClick = 0;
48
+ let firstFrameTime = undefined;
49
+
50
+ let nodes = [];
51
+ let edges = [];
52
+
53
+ let lastScrollPos = 0;
54
+
55
+ setup = () => {
56
+ canvas = createCanvas(...updateTargetDims());
57
+ };
58
+
59
+ class Node {
60
+ x;
61
+ y;
62
+ size;
63
+ xT;
64
+ yT;
65
+ xB;
66
+ yB;
67
+ treeInd;
68
+ color;
69
+ relSize;
70
+ animationStart = Number.MAX_VALUE;
71
+ animationProgress = 0;
72
+ isStatic = false;
73
+ hasChildren = false;
74
+ isRootNode = true;
75
+ isStarred = false;
76
+ selected = false;
77
+ renderSize = 10;
78
+ edges = [];
79
+ bgCol;
80
+
81
+ constructor(x, y, relSize, treeInd) {
82
+ const minSize = 35;
83
+ const maxSize = 60;
84
+
85
+ const maxColor = 10;
86
+ const minColor = 125;
87
+
88
+ this.relSize = relSize;
89
+ this.treeInd = treeInd;
90
+ this.size = minSize + (maxSize - minSize) * relSize;
91
+ this.color = minColor + (maxColor - minColor) * relSize;
92
+ this.bgCol = Math.round(Math.max(this.color / 2, 0));
93
+
94
+ this.x = x;
95
+ this.y = y;
96
+ this.xT = x;
97
+ this.yT = y - this.size / 2;
98
+ this.xB = x;
99
+ this.yB = y + this.size / 2;
100
+
101
+ nodes.push(this);
102
+ }
103
+
104
+ startAnimation = (offset = 0) => {
105
+ if (this.animationStart == Number.MAX_VALUE)
106
+ this.animationStart = globalTime + offset;
107
+ };
108
+
109
+ child = (node) => {
110
+ let edge = new Edge(this, node);
111
+ this.edges.push(edge);
112
+ edges.push(edge);
113
+ this.hasChildren = true;
114
+ node.isRootNode = false;
115
+ return node;
116
+ };
117
+
118
+ render = () => {
119
+ if (globalTime - this.animationStart < 0) return;
120
+
121
+ const mouseXlocalCoords = (mouseX - width / 2) / scaleFactor;
122
+ const mouseYlocalCoords = (mouseY - height / 2) / scaleFactor;
123
+ const isMouseOver =
124
+ dist(mouseXlocalCoords, mouseYlocalCoords, this.x, this.y) <
125
+ this.renderSize / 1.5;
126
+ if (isMouseOver) cursor(HAND);
127
+ if (isMouseOver && mouseIsPressed) {
128
+ nodes.forEach((n) => (n.selected = false));
129
+ this.selected = true;
130
+ setCodeAndPlan(
131
+ treeStructData.code[this.treeInd],
132
+ treeStructData.plan[this.treeInd],
133
+ );
134
+ manualSelection = true;
135
+ }
136
+
137
+ this.renderSize = this.size;
138
+ if (!this.isStatic) {
139
+ this.animationProgress = animEase(
140
+ (globalTime - this.animationStart) / 1000,
141
+ );
142
+ if (this.animationProgress >= 1) {
143
+ this.isStatic = true;
144
+ } else {
145
+ this.renderSize =
146
+ this.size *
147
+ (0.8 +
148
+ 0.2 *
149
+ (-3.33 * this.animationProgress ** 2 +
150
+ 4.33 * this.animationProgress));
151
+ }
152
+ }
153
+
154
+ fill(this.color);
155
+ if (this.selected) {
156
+ fill(accentCol);
157
+ }
158
+
159
+ noStroke();
160
+ square(
161
+ this.x - this.renderSize / 2,
162
+ this.y - this.renderSize / 2,
163
+ this.renderSize,
164
+ 10,
165
+ );
166
+
167
+ noStroke();
168
+ textAlign(CENTER, CENTER);
169
+ textSize(this.renderSize / 2);
170
+ fill(255);
171
+ // fill(lerpColor(color(accentCol), color(255), this.animationProgress))
172
+ text("{ }", this.x, this.y - 1);
173
+ // DEBUG PRINT:
174
+ // text(round(this.relSize, 2), this.x, this.y - 1)
175
+ // text(this.treeInd, this.x, this.y + 15)
176
+
177
+ const dotAnimThreshold = 0.85;
178
+ if (this.isStarred && this.animationProgress >= dotAnimThreshold) {
179
+ let dotAnimProgress =
180
+ (this.animationProgress - dotAnimThreshold) / (1 - dotAnimThreshold);
181
+ textSize(
182
+ ((-3.33 * dotAnimProgress ** 2 + 4.33 * dotAnimProgress) *
183
+ this.renderSize) /
184
+ 2,
185
+ );
186
+ if (this.selected) {
187
+ fill(0);
188
+ stroke(0);
189
+ } else {
190
+ fill(accentCol);
191
+ stroke(accentCol);
192
+ }
193
+ strokeWeight((-(dotAnimProgress ** 2) + dotAnimProgress) * 2);
194
+ text("*", this.x + 20, this.y - 11);
195
+ noStroke();
196
+ }
197
+
198
+ if (!this.isStatic) {
199
+ fill(bgCol);
200
+ const progressAnimBaseSize = this.renderSize + 5;
201
+ rect(
202
+ this.x - progressAnimBaseSize / 2,
203
+ this.y -
204
+ progressAnimBaseSize / 2 +
205
+ progressAnimBaseSize * this.animationProgress,
206
+ progressAnimBaseSize,
207
+ progressAnimBaseSize * (1 - this.animationProgress),
208
+ );
209
+ }
210
+ if (this.animationProgress >= 0.9) {
211
+ this.edges
212
+ .sort((a, b) => a.color() - b.color())
213
+ .forEach((e, i) => {
214
+ e.startAnimation((i / this.edges.length) ** 2 * 1000);
215
+ });
216
+ }
217
+ };
218
+ }
219
+
220
+ class Edge {
221
+ nodeT;
222
+ nodeB;
223
+ animX = 0;
224
+ animY = 0;
225
+ animationStart = Number.MAX_VALUE;
226
+ animationProgress = 0;
227
+ isStatic = false;
228
+ weight = 0;
229
+
230
+ constructor(nodeT, nodeB) {
231
+ this.nodeT = nodeT;
232
+ this.nodeB = nodeB;
233
+ this.weight = 2 + nodeB.relSize * 1;
234
+ }
235
+
236
+ color = () => this.nodeB.color;
237
+
238
+ startAnimation = (offset = 0) => {
239
+ if (this.animationStart == Number.MAX_VALUE)
240
+ this.animationStart = globalTime + offset;
241
+ };
242
+
243
+ render = () => {
244
+ if (globalTime - this.animationStart < 0) return;
245
+
246
+ if (!this.isStatic) {
247
+ this.animationProgress = animEase(
248
+ (globalTime - this.animationStart) / 1000,
249
+ );
250
+ if (this.animationProgress >= 1) {
251
+ this.isStatic = true;
252
+ this.animX = this.nodeB.xT;
253
+ this.animY = this.nodeB.yT;
254
+ } else {
255
+ this.animX = bezierPoint(
256
+ this.nodeT.xB,
257
+ this.nodeT.xB,
258
+ this.nodeB.xT,
259
+ this.nodeB.xT,
260
+ this.animationProgress,
261
+ );
262
+
263
+ this.animY = bezierPoint(
264
+ this.nodeT.yB,
265
+ (this.nodeT.yB + this.nodeB.yT) / 2,
266
+ (this.nodeT.yB + this.nodeB.yT) / 2,
267
+ this.nodeB.yT,
268
+ this.animationProgress,
269
+ );
270
+ }
271
+ }
272
+ if (this.animationProgress >= 0.97) {
273
+ this.nodeB.startAnimation();
274
+ }
275
+
276
+ strokeWeight(this.weight);
277
+ noFill();
278
+ stroke(
279
+ lerpColor(color(bgCol), color(accentCol), this.nodeB.relSize * 1 + 0.7),
280
+ );
281
+ bezier(
282
+ this.nodeT.xB,
283
+ this.nodeT.yB,
284
+ this.nodeT.xB,
285
+ (this.nodeT.yB + this.nodeB.yT) / 2,
286
+ this.animX,
287
+ (this.nodeT.yB + this.nodeB.yT) / 2,
288
+ this.animX,
289
+ this.animY,
290
+ );
291
+ };
292
+ }
293
+
294
+ draw = () => {
295
+ cursor(ARROW);
296
+ frameRate(120);
297
+ if (!firstFrameTime && frameCount <= 1) {
298
+ firstFrameTime = millis();
299
+ }
300
+ // ---- update global animation state ----
301
+ const initialSpeedScalingEaseIO =
302
+ (cos(min((millis() - firstFrameTime) / 8000, 1.0) * PI) + 1) / 2;
303
+ const initialSpeedScalingEase =
304
+ (cos(min((millis() - firstFrameTime) / 8000, 1.0) ** (1 / 2) * PI) + 1) / 2;
305
+ const initAnimationSpeedFactor = 1.0 - 0.4 * initialSpeedScalingEaseIO;
306
+ // update global scaling-aware clock
307
+ globalTime += globalAnimSpeed * initAnimationSpeedFactor * deltaTime;
308
+
309
+ if (nodes.length == 0) {
310
+ const spacingHeight = height * 1.3;
311
+ const spacingWidth = width * 1.3;
312
+ treeStructData.layout.forEach((lay, index) => {
313
+ new Node(
314
+ spacingWidth * lay[0] - spacingWidth / 2,
315
+ 20 + spacingHeight * lay[1] - spacingHeight / 2,
316
+ 1 - treeStructData.metrics[index],
317
+ index,
318
+ );
319
+ });
320
+ treeStructData.edges.forEach((ind) => {
321
+ nodes[ind[0]].child(nodes[ind[1]]);
322
+ });
323
+ nodes.forEach((n) => {
324
+ if (n.isRootNode) n.startAnimation();
325
+ });
326
+ nodes[0].selected = true;
327
+ setCodeAndPlan(
328
+ treeStructData.code[0],
329
+ treeStructData.plan[0],
330
+ )
331
+ }
332
+
333
+ const staticNodes = nodes.filter(
334
+ (n) => n.isStatic || n.animationProgress >= 0.7,
335
+ );
336
+ if (staticNodes.length > 0) {
337
+ const largestNode = staticNodes.reduce((prev, current) =>
338
+ prev.relSize > current.relSize ? prev : current,
339
+ );
340
+ if (!manualSelection) {
341
+ if (!largestNode.selected) {
342
+ setCodeAndPlan(
343
+ treeStructData.code[largestNode.treeInd],
344
+ treeStructData.plan[largestNode.treeInd],
345
+ );
346
+ }
347
+ staticNodes.forEach((node) => {
348
+ node.selected = node === largestNode;
349
+ });
350
+ }
351
+ }
352
+ background(bgCol);
353
+ // global animation transforms
354
+ translate(width / 2, height / 2);
355
+ scale(scaleFactor);
356
+
357
+
358
+ // ---- fg render ----
359
+ edges.forEach((e) => e.render());
360
+ nodes.forEach((n) => n.render());
361
+
362
+ };
aide/webui/__init__.py ADDED
File without changes
aide/webui/app.py ADDED
@@ -0,0 +1,599 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import streamlit.components.v1 as components
3
+ from pathlib import Path
4
+ import tempfile
5
+ import shutil
6
+ import os
7
+ import json
8
+ from omegaconf import OmegaConf
9
+ from rich.console import Console
10
+ import sys
11
+ from dotenv import load_dotenv
12
+ import logging
13
+ from aide import Experiment
14
+
15
+ # Set up logging configuration
16
+ logging.basicConfig(
17
+ level=logging.INFO,
18
+ format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
19
+ handlers=[logging.StreamHandler(sys.stderr)],
20
+ )
21
+
22
+ logger = logging.getLogger("aide")
23
+ logger.setLevel(logging.INFO)
24
+
25
+ console = Console(file=sys.stderr)
26
+
27
+
28
+ class WebUI:
29
+ """
30
+ WebUI encapsulates the Streamlit application logic for the AIDE Machine Learning Engineer Agent.
31
+ """
32
+
33
+ def __init__(self):
34
+ """
35
+ Initialize the WebUI with environment variables and session state.
36
+ """
37
+ self.env_vars = self.load_env_variables()
38
+ self.project_root = Path(__file__).parent.parent.parent
39
+ self.config_session_state()
40
+ self.setup_page()
41
+
42
+ @staticmethod
43
+ def load_env_variables():
44
+ """
45
+ Load API keys and environment variables from .env file.
46
+
47
+ Returns:
48
+ dict: Dictionary containing API keys.
49
+ """
50
+ load_dotenv()
51
+ return {
52
+ "openai_key": os.getenv("OPENAI_API_KEY", ""),
53
+ "anthropic_key": os.getenv("ANTHROPIC_API_KEY", ""),
54
+ }
55
+
56
+ @staticmethod
57
+ def config_session_state():
58
+ """
59
+ Configure default values for Streamlit session state.
60
+ """
61
+ if "is_running" not in st.session_state:
62
+ st.session_state.is_running = False
63
+ if "current_step" not in st.session_state:
64
+ st.session_state.current_step = 0
65
+ if "total_steps" not in st.session_state:
66
+ st.session_state.total_steps = 0
67
+ if "progress" not in st.session_state:
68
+ st.session_state.progress = 0
69
+ if "results" not in st.session_state:
70
+ st.session_state.results = None
71
+
72
+ @staticmethod
73
+ def setup_page():
74
+ """
75
+ Set up the Streamlit page configuration and load custom CSS.
76
+ """
77
+ st.set_page_config(
78
+ page_title="AIDE: Machine Learning Engineer Agent",
79
+ layout="wide",
80
+ )
81
+ WebUI.load_css()
82
+
83
+ @staticmethod
84
+ def load_css():
85
+ """
86
+ Load custom CSS styles from 'style.css' file.
87
+ """
88
+ css_file = Path(__file__).parent / "style.css"
89
+ if css_file.exists():
90
+ with open(css_file) as f:
91
+ st.markdown(f"<style>{f.read()}</style>", unsafe_allow_html=True)
92
+ else:
93
+ st.warning(f"CSS file not found at: {css_file}")
94
+
95
+ def run(self):
96
+ """
97
+ Run the main logic of the Streamlit application.
98
+ """
99
+ self.render_sidebar()
100
+ input_col, results_col = st.columns([1, 3])
101
+ with input_col:
102
+ self.render_input_section(results_col)
103
+
104
+ def render_sidebar(self):
105
+ """
106
+ Render the sidebar with API key settings.
107
+ """
108
+ with st.sidebar:
109
+ st.header("⚙️ Settings")
110
+ st.markdown(
111
+ "<p style='text-align: center;'>OpenAI API Key</p>",
112
+ unsafe_allow_html=True,
113
+ )
114
+ openai_key = st.text_input(
115
+ "OpenAI API Key",
116
+ value=self.env_vars["openai_key"],
117
+ type="password",
118
+ label_visibility="collapsed",
119
+ )
120
+ st.markdown(
121
+ "<p style='text-align: center;'>Anthropic API Key</p>",
122
+ unsafe_allow_html=True,
123
+ )
124
+ anthropic_key = st.text_input(
125
+ "Anthropic API Key",
126
+ value=self.env_vars["anthropic_key"],
127
+ type="password",
128
+ label_visibility="collapsed",
129
+ )
130
+ if st.button("Save API Keys", use_container_width=True):
131
+ st.session_state.openai_key = openai_key
132
+ st.session_state.anthropic_key = anthropic_key
133
+ st.success("API keys saved!")
134
+
135
+ def render_input_section(self, results_col):
136
+ """
137
+ Render the input section of the application.
138
+
139
+ Args:
140
+ results_col (st.delta_generator.DeltaGenerator): The results column to pass to methods.
141
+ """
142
+ st.header("Input")
143
+ uploaded_files = self.handle_file_upload()
144
+ goal_text, eval_text, num_steps = self.handle_user_inputs()
145
+ if st.button("Run AIDE", type="primary", use_container_width=True):
146
+ with st.spinner("AIDE is running..."):
147
+ results = self.run_aide(
148
+ uploaded_files, goal_text, eval_text, num_steps, results_col
149
+ )
150
+ st.session_state.results = results
151
+
152
+ def handle_file_upload(self):
153
+ """
154
+ Handle file uploads and example file loading.
155
+
156
+ Returns:
157
+ list: List of uploaded or example files.
158
+ """
159
+ # Only show file uploader if no example files are loaded
160
+ if not st.session_state.get("example_files"):
161
+ uploaded_files = st.file_uploader(
162
+ "Upload Data Files",
163
+ accept_multiple_files=True,
164
+ type=["csv", "txt", "json", "md"],
165
+ label_visibility="collapsed",
166
+ )
167
+
168
+ if uploaded_files:
169
+ st.session_state.pop(
170
+ "example_files", None
171
+ ) # Remove example files if any
172
+ return uploaded_files
173
+
174
+ # Only show example button if no files are uploaded
175
+ if st.button(
176
+ "Load Example Experiment", type="primary", use_container_width=True
177
+ ):
178
+ st.session_state.example_files = self.load_example_files()
179
+
180
+ if st.session_state.get("example_files"):
181
+ st.info("Example files loaded! Click 'Run AIDE' to proceed.")
182
+ with st.expander("View Loaded Files", expanded=False):
183
+ for file in st.session_state.example_files:
184
+ st.text(f"📄 {file['name']}")
185
+ return st.session_state.example_files
186
+
187
+ return [] # Return empty list if no files are uploaded or loaded
188
+
189
+ def handle_user_inputs(self):
190
+ """
191
+ Handle goal, evaluation criteria, and number of steps inputs.
192
+
193
+ Returns:
194
+ tuple: Goal text, evaluation criteria text, and number of steps.
195
+ """
196
+ goal_text = st.text_area(
197
+ "Goal",
198
+ value=st.session_state.get("goal", ""),
199
+ placeholder="Example: Predict the sales price for each house",
200
+ )
201
+ eval_text = st.text_area(
202
+ "Evaluation Criteria",
203
+ value=st.session_state.get("eval", ""),
204
+ placeholder="Example: Use the RMSE metric between the logarithm of the predicted and observed values.",
205
+ )
206
+ num_steps = st.slider(
207
+ "Number of Steps",
208
+ min_value=1,
209
+ max_value=20,
210
+ value=st.session_state.get("steps", 10),
211
+ )
212
+ return goal_text, eval_text, num_steps
213
+
214
+ @staticmethod
215
+ def load_example_files():
216
+ """
217
+ Load example files from the 'example_tasks/house_prices' directory.
218
+
219
+ Returns:
220
+ list: List of example files with their paths.
221
+ """
222
+ package_root = Path(__file__).parent.parent
223
+ example_dir = package_root / "example_tasks" / "house_prices"
224
+
225
+ if not example_dir.exists():
226
+ st.error(f"Example directory not found at: {example_dir}")
227
+ return []
228
+
229
+ example_files = []
230
+
231
+ for file_path in example_dir.glob("*"):
232
+ if file_path.suffix.lower() in [".csv", ".txt", ".json", ".md"]:
233
+ with tempfile.NamedTemporaryFile(
234
+ delete=False, suffix=file_path.suffix
235
+ ) as tmp_file:
236
+ tmp_file.write(file_path.read_bytes())
237
+ example_files.append(
238
+ {"name": file_path.name, "path": tmp_file.name}
239
+ )
240
+
241
+ if not example_files:
242
+ st.warning("No example files found in the example directory")
243
+
244
+ st.session_state["goal"] = "Predict the sales price for each house"
245
+ st.session_state["eval"] = (
246
+ "Use the RMSE metric between the logarithm of the predicted and observed values."
247
+ )
248
+
249
+ return example_files
250
+
251
+ def run_aide(self, files, goal_text, eval_text, num_steps, results_col):
252
+ """
253
+ Run the AIDE experiment with the provided inputs.
254
+
255
+ Args:
256
+ files (list): List of uploaded or example files.
257
+ goal_text (str): The goal of the experiment.
258
+ eval_text (str): The evaluation criteria.
259
+ num_steps (int): Number of steps to run.
260
+ results_col (st.delta_generator.DeltaGenerator): Results column for displaying progress.
261
+
262
+ Returns:
263
+ dict: Dictionary containing the results of the experiment.
264
+ """
265
+ try:
266
+ self.initialize_run_state(num_steps)
267
+ self.set_api_keys()
268
+
269
+ input_dir = self.prepare_input_directory(files)
270
+ if not input_dir:
271
+ return None
272
+
273
+ experiment = self.initialize_experiment(input_dir, goal_text, eval_text)
274
+
275
+ # Create separate placeholders for progress and config
276
+ progress_placeholder = results_col.empty()
277
+ config_placeholder = results_col.empty()
278
+ results_placeholder = results_col.empty()
279
+
280
+ for step in range(num_steps):
281
+ st.session_state.current_step = step + 1
282
+ progress = (step + 1) / num_steps
283
+
284
+ # Update progress
285
+ with progress_placeholder.container():
286
+ st.markdown(
287
+ f"### 🔥 Running Step {st.session_state.current_step}/{st.session_state.total_steps}"
288
+ )
289
+ st.progress(progress)
290
+
291
+ # Show config only for first step
292
+ if step == 0:
293
+ with config_placeholder.container():
294
+ st.markdown("### 📋 Configuration")
295
+ st.code(OmegaConf.to_yaml(experiment.cfg), language="yaml")
296
+
297
+ experiment.run(steps=1)
298
+
299
+ # Show results
300
+ with results_placeholder.container():
301
+ self.render_live_results(experiment)
302
+
303
+ # Clear config after first step
304
+ if step == 0:
305
+ config_placeholder.empty()
306
+
307
+ # Clear progress after all steps
308
+ progress_placeholder.empty()
309
+
310
+ # Update session state
311
+ st.session_state.is_running = False
312
+ st.session_state.results = self.collect_results(experiment)
313
+ return st.session_state.results
314
+
315
+ except Exception as e:
316
+ st.session_state.is_running = False
317
+ console.print_exception()
318
+ st.error(f"Error occurred: {str(e)}")
319
+ return None
320
+
321
+ @staticmethod
322
+ def initialize_run_state(num_steps):
323
+ """
324
+ Initialize the running state for the experiment.
325
+
326
+ Args:
327
+ num_steps (int): Total number of steps in the experiment.
328
+ """
329
+ st.session_state.is_running = True
330
+ st.session_state.current_step = 0
331
+ st.session_state.total_steps = num_steps
332
+ st.session_state.progress = 0
333
+
334
+ @staticmethod
335
+ def set_api_keys():
336
+ """
337
+ Set the API keys in the environment variables from the session state.
338
+ """
339
+ if st.session_state.get("openai_key"):
340
+ os.environ["OPENAI_API_KEY"] = st.session_state.openai_key
341
+ if st.session_state.get("anthropic_key"):
342
+ os.environ["ANTHROPIC_API_KEY"] = st.session_state.anthropic_key
343
+
344
+ def prepare_input_directory(self, files):
345
+ """
346
+ Prepare the input directory and handle uploaded files.
347
+
348
+ Args:
349
+ files (list): List of uploaded or example files.
350
+
351
+ Returns:
352
+ Path: The input directory path, or None if files are missing.
353
+ """
354
+ input_dir = self.project_root / "input"
355
+ input_dir.mkdir(parents=True, exist_ok=True)
356
+
357
+ if files:
358
+ for file in files:
359
+ if isinstance(file, dict): # Example files
360
+ shutil.copy2(file["path"], input_dir / file["name"])
361
+ else: # Uploaded files
362
+ with open(input_dir / file.name, "wb") as f:
363
+ f.write(file.getbuffer())
364
+ else:
365
+ st.error("Please upload data files")
366
+ return None
367
+ return input_dir
368
+
369
+ @staticmethod
370
+ def initialize_experiment(input_dir, goal_text, eval_text):
371
+ """
372
+ Initialize the AIDE Experiment.
373
+
374
+ Args:
375
+ input_dir (Path): Path to the input directory.
376
+ goal_text (str): The goal of the experiment.
377
+ eval_text (str): The evaluation criteria.
378
+
379
+ Returns:
380
+ Experiment: The initialized Experiment object.
381
+ """
382
+ experiment = Experiment(data_dir=str(input_dir), goal=goal_text, eval=eval_text)
383
+ return experiment
384
+
385
+ @staticmethod
386
+ def collect_results(experiment):
387
+ """
388
+ Collect the results from the experiment.
389
+
390
+ Args:
391
+ experiment (Experiment): The Experiment object.
392
+
393
+ Returns:
394
+ dict: Dictionary containing the collected results.
395
+ """
396
+ solution_path = experiment.cfg.log_dir / "best_solution.py"
397
+ if solution_path.exists():
398
+ solution = solution_path.read_text()
399
+ else:
400
+ solution = "No solution found"
401
+
402
+ journal_data = [
403
+ {
404
+ "step": node.step,
405
+ "code": str(node.code),
406
+ "metric": str(node.metric.value) if node.metric else None,
407
+ "is_buggy": node.is_buggy,
408
+ }
409
+ for node in experiment.journal.nodes
410
+ ]
411
+
412
+ results = {
413
+ "solution": solution,
414
+ "config": OmegaConf.to_yaml(experiment.cfg),
415
+ "journal": json.dumps(journal_data, indent=2, default=str),
416
+ "tree_path": str(experiment.cfg.log_dir / "tree_plot.html"),
417
+ }
418
+ return results
419
+
420
+ @staticmethod
421
+ def render_tree_visualization(results):
422
+ """
423
+ Render the tree visualization from the experiment results.
424
+
425
+ Args:
426
+ results (dict): The results dictionary containing paths and data.
427
+ """
428
+ if "tree_path" in results:
429
+ tree_path = Path(results["tree_path"])
430
+ logger.info(f"Loading tree visualization from: {tree_path}")
431
+ if tree_path.exists():
432
+ with open(tree_path, "r", encoding="utf-8") as f:
433
+ html_content = f.read()
434
+ components.html(html_content, height=600, scrolling=True)
435
+ else:
436
+ st.error(f"Tree visualization file not found at: {tree_path}")
437
+ logger.error(f"Tree file not found at: {tree_path}")
438
+ else:
439
+ st.info("No tree visualization available for this run.")
440
+
441
+ @staticmethod
442
+ def render_best_solution(results):
443
+ """
444
+ Display the best solution code.
445
+
446
+ Args:
447
+ results (dict): The results dictionary containing the solution.
448
+ """
449
+ if "solution" in results:
450
+ solution_code = results["solution"]
451
+ st.code(solution_code, language="python")
452
+ else:
453
+ st.info("No solution available.")
454
+
455
+ @staticmethod
456
+ def render_config(results):
457
+ """
458
+ Display the configuration used in the experiment.
459
+
460
+ Args:
461
+ results (dict): The results dictionary containing the config.
462
+ """
463
+ if "config" in results:
464
+ st.code(results["config"], language="yaml")
465
+ else:
466
+ st.info("No configuration available.")
467
+
468
+ @staticmethod
469
+ def render_journal(results):
470
+ """
471
+ Display the experiment journal as JSON.
472
+
473
+ Args:
474
+ results (dict): The results dictionary containing the journal.
475
+ """
476
+ if "journal" in results:
477
+ try:
478
+ journal_data = json.loads(results["journal"])
479
+ formatted_journal = json.dumps(journal_data, indent=2)
480
+ st.code(formatted_journal, language="json")
481
+ except json.JSONDecodeError:
482
+ st.code(results["journal"], language="json")
483
+ else:
484
+ st.info("No journal available.")
485
+
486
+ @staticmethod
487
+ def get_best_metric(results):
488
+ """
489
+ Extract the best validation metric from results.
490
+ """
491
+ try:
492
+ journal_data = json.loads(results["journal"])
493
+ metrics = []
494
+ for node in journal_data:
495
+ if node["metric"] is not None:
496
+ try:
497
+ # Convert string metric to float
498
+ metric_value = float(node["metric"])
499
+ metrics.append(metric_value)
500
+ except (ValueError, TypeError):
501
+ continue
502
+ return max(metrics) if metrics else None
503
+ except (json.JSONDecodeError, KeyError):
504
+ return None
505
+
506
+ @staticmethod
507
+ def render_validation_plot(results, step):
508
+ """
509
+ Render the validation score plot.
510
+
511
+ Args:
512
+ results (dict): The results dictionary
513
+ step (int): Current step number for unique key generation
514
+ """
515
+ try:
516
+ journal_data = json.loads(results["journal"])
517
+ steps = []
518
+ metrics = []
519
+
520
+ for node in journal_data:
521
+ if node["metric"] is not None and node["metric"].lower() != "none":
522
+ try:
523
+ metric_value = float(node["metric"])
524
+ steps.append(node["step"])
525
+ metrics.append(metric_value)
526
+ except (ValueError, TypeError):
527
+ continue
528
+
529
+ if metrics:
530
+ import plotly.graph_objects as go
531
+
532
+ fig = go.Figure()
533
+ fig.add_trace(
534
+ go.Scatter(
535
+ x=steps,
536
+ y=metrics,
537
+ mode="lines+markers",
538
+ name="Validation Score",
539
+ line=dict(color="#F04370"),
540
+ marker=dict(color="#F04370"),
541
+ )
542
+ )
543
+
544
+ fig.update_layout(
545
+ title="Validation Score Progress",
546
+ xaxis_title="Step",
547
+ yaxis_title="Validation Score",
548
+ template="plotly_white",
549
+ hovermode="x unified",
550
+ plot_bgcolor="rgba(0,0,0,0)",
551
+ paper_bgcolor="rgba(0,0,0,0)",
552
+ )
553
+
554
+ # Only keep the key for plotly_chart
555
+ st.plotly_chart(fig, use_container_width=True, key=f"plot_{step}")
556
+ else:
557
+ st.info("No validation metrics available to plot")
558
+
559
+ except (json.JSONDecodeError, KeyError):
560
+ st.error("Could not parse validation metrics data")
561
+
562
+ def render_live_results(self, experiment):
563
+ """
564
+ Render live results.
565
+
566
+ Args:
567
+ experiment (Experiment): The Experiment object
568
+ """
569
+ results = self.collect_results(experiment)
570
+
571
+ # Create tabs for different result views
572
+ tabs = st.tabs(
573
+ [
574
+ "Tree Visualization",
575
+ "Best Solution",
576
+ "Config",
577
+ "Journal",
578
+ "Validation Plot",
579
+ ]
580
+ )
581
+
582
+ with tabs[0]:
583
+ self.render_tree_visualization(results)
584
+ with tabs[1]:
585
+ self.render_best_solution(results)
586
+ with tabs[2]:
587
+ self.render_config(results)
588
+ with tabs[3]:
589
+ self.render_journal(results)
590
+ with tabs[4]:
591
+ best_metric = self.get_best_metric(results)
592
+ if best_metric is not None:
593
+ st.metric("Best Validation Score", f"{best_metric:.4f}")
594
+ self.render_validation_plot(results, step=st.session_state.current_step)
595
+
596
+
597
+ if __name__ == "__main__":
598
+ app = WebUI()
599
+ app.run()
aide/webui/style.css ADDED
@@ -0,0 +1,173 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .stVerticalBlock {
2
+ padding-top: 0rem;
3
+ padding-bottom: 0rem;
4
+ }
5
+
6
+ .block-container {
7
+ padding-top: 0rem;
8
+ padding-bottom: 0rem;
9
+ }
10
+
11
+ [data-testid="stVerticalBlock"] {
12
+ padding-top: 0rem;
13
+ padding-bottom: 0rem;
14
+ }
15
+ .st-emotion-cache-40pabj{
16
+ padding-top: 0rem;
17
+ padding-bottom: 0rem;
18
+ }
19
+ /* Make the toolbar transparent */
20
+ .st-emotion-cache-18ni7ap {
21
+ pointer-events: none;
22
+ background: rgb(255 255 255 / 0%)
23
+ }
24
+
25
+ .stAppHeader {
26
+ display: none;
27
+ }
28
+
29
+ header {visibility: hidden;}
30
+ #MainMenu {visibility: hidden;}
31
+ [data-testid="stDecoration"] {
32
+ display: none;
33
+ }
34
+ #root > div:nth-child(1) > div > div > div > div > section > div {
35
+ padding-top: 0rem;
36
+ }
37
+
38
+ section.stMain .block-container {
39
+ padding-top: 0rem;
40
+ z-index: 1;
41
+ }
42
+
43
+ /* Main container */
44
+ .stApp {
45
+ background-color: var(--background);
46
+ height: auto;
47
+ overflow: visible;
48
+ }
49
+
50
+ /* Widgets */
51
+ .stSelectbox,
52
+ .stTextInput,
53
+ .stNumberInput {
54
+ background-color: var(--card);
55
+ border: 1px solid var(--border);
56
+ border-radius: 0.4rem;
57
+ }
58
+
59
+ .stMarkdown {
60
+ color: var(--primary);
61
+ }
62
+
63
+ /* Code block styling */
64
+ .stCodeBlock {
65
+ max-height: 400px;
66
+ overflow-y: auto !important;
67
+ border: 1px solid var(--border);
68
+ border-radius: 0.4rem;
69
+ background-color: var(--background-shaded);
70
+ }
71
+
72
+ /* Custom scrollbar for code blocks */
73
+ .stCodeBlock::-webkit-scrollbar {
74
+ width: 8px;
75
+ height: 8px;
76
+ }
77
+
78
+ .stCodeBlock::-webkit-scrollbar-track {
79
+ background: var(--background-shaded);
80
+ border-radius: 4px;
81
+ }
82
+
83
+ .stCodeBlock::-webkit-scrollbar-thumb {
84
+ background: var(--accent);
85
+ border-radius: 4px;
86
+ }
87
+
88
+ .stCodeBlock::-webkit-scrollbar-thumb:hover {
89
+ background: #e13d68;
90
+ }
91
+
92
+
93
+
94
+ .scrollable-code-container {
95
+ height: 600px;
96
+ overflow-y: auto;
97
+ border: 1px solid var(--border);
98
+ padding: 15px;
99
+ border-radius: 5px;
100
+ background-color: var(--background-shaded);
101
+ }
102
+
103
+ .scrollable-code-container pre {
104
+ margin: 0;
105
+ white-space: pre;
106
+ overflow-x: auto;
107
+ font-family: monospace;
108
+ }
109
+
110
+ .scrollable-code-container code {
111
+ display: block;
112
+ min-width: 100%;
113
+ padding: 0;
114
+ tab-size: 4;
115
+ }
116
+
117
+ /* Add custom scrollbar styling for code containers */
118
+ .scrollable-code-container::-webkit-scrollbar {
119
+ width: 8px;
120
+ height: 8px;
121
+ }
122
+
123
+ .scrollable-code-container::-webkit-scrollbar-track {
124
+ background: var(--background-shaded);
125
+ border-radius: 4px;
126
+ }
127
+
128
+ .scrollable-code-container::-webkit-scrollbar-thumb {
129
+ background: var(--accent);
130
+ border-radius: 4px;
131
+ }
132
+
133
+ .scrollable-code-container::-webkit-scrollbar-thumb:hover {
134
+ background: #e13d68;
135
+ }
136
+
137
+ /* Style for expander */
138
+ .streamlit-expanderHeader {
139
+ background-color: var(--card);
140
+ border: 1px solid var(--border);
141
+ border-radius: 0.4rem;
142
+ padding: 0.5rem !important;
143
+ }
144
+
145
+ .streamlit-expanderHeader:hover {
146
+ border-color: var(--accent);
147
+ }
148
+
149
+ /* Style for expander content */
150
+ .streamlit-expanderContent {
151
+ background-color: var(--background-shaded);
152
+ border: 1px solid var(--border);
153
+ border-radius: 0 0 0.4rem 0.4rem;
154
+ margin-top: -1px;
155
+ padding: 0.5rem !important;
156
+ }
157
+
158
+ /* Style for st.code() blocks */
159
+ .stCode {
160
+ max-height: 600px;
161
+ overflow-y: auto;
162
+ background-color: var(--background-shaded) !important;
163
+ border: 1px solid var(--border) !important;
164
+ border-radius: 5px !important;
165
+ }
166
+
167
+ .stCode pre {
168
+ background-color: var(--background-shaded) !important;
169
+ }
170
+
171
+ div[data-testid="InputInstructions"] {
172
+ visibility: hidden;
173
+ }
app.py CHANGED
@@ -35,7 +35,7 @@ class WebUI:
35
  Initialize the WebUI with environment variables and session state.
36
  """
37
  self.env_vars = self.load_env_variables()
38
- self.project_root = Path(__file__).parent.parent.parent
39
  self.config_session_state()
40
  self.setup_page()
41
 
@@ -219,7 +219,7 @@ class WebUI:
219
  Returns:
220
  list: List of example files with their paths.
221
  """
222
- package_root = Path(__file__).parent.parent
223
  example_dir = package_root / "example_tasks" / "house_prices"
224
 
225
  if not example_dir.exists():
 
35
  Initialize the WebUI with environment variables and session state.
36
  """
37
  self.env_vars = self.load_env_variables()
38
+ self.project_root = Path(__file__).parent
39
  self.config_session_state()
40
  self.setup_page()
41
 
 
219
  Returns:
220
  list: List of example files with their paths.
221
  """
222
+ package_root = Path(__file__).parent / "aide"
223
  example_dir = package_root / "example_tasks" / "house_prices"
224
 
225
  if not example_dir.exists():
requirements.txt ADDED
@@ -0,0 +1,94 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # AIDE requirements
2
+ black==24.3.0
3
+ funcy==2.0
4
+ humanize==4.8.0
5
+ jsonschema==4.19.2
6
+ numpy==1.26.2
7
+ openai>=1.3.5
8
+ anthropic>=0.20.0
9
+ pandas==2.1.4
10
+ pytest==7.4.3
11
+ requests==2.32.2
12
+ scikit-learn==1.5.0
13
+ rich==13.7.0
14
+ scipy==1.11.4
15
+ dataclasses_json>=0.6.4
16
+ omegaconf>=2.3.0
17
+ loguru==0.7.2
18
+ shutup>=0.2.0
19
+ tqdm==4.66.3
20
+ coolname>=2.2.0
21
+ igraph>=0.11.3
22
+ genson>=1.2.0
23
+
24
+ # agent requirements (packages that the agent might need)
25
+ torch
26
+ torchvision
27
+ torchaudio
28
+ torchtext
29
+
30
+ lightgbm
31
+ matplotlib
32
+ seaborn
33
+
34
+ # tensorflow
35
+ # tensorflow-io
36
+ # tensorflow_hub
37
+ # tf-keras
38
+ # tensorflow_decision_forests
39
+ # keras
40
+ # keras-cv
41
+ # keras-nlp
42
+
43
+ gensim
44
+
45
+ scikit-image
46
+ opencv-python
47
+ scipy
48
+ scikit-learn
49
+ biopython
50
+ imbalanced-learn
51
+ h5py
52
+ biopython
53
+ numba
54
+ arrow
55
+ markovify
56
+ imgaug
57
+ scikit-optimize
58
+ plotly
59
+ hyperopt
60
+ bayesian-optimization
61
+ imagecodecs
62
+ hmmlearn
63
+ bayespy==0.5.1
64
+ sklearn-pandas
65
+ tensorpack
66
+ sentencepiece
67
+ librosa
68
+ ipykernel
69
+ ipython
70
+ nbformat
71
+ kornia
72
+ Pillow
73
+ pyparsing
74
+ pytz
75
+ PyYAML
76
+ tqdm
77
+ fastai
78
+ gym
79
+ optuna
80
+ transformers
81
+ datasets==2.1.0
82
+ torchmetrics
83
+ pytorch-lightning
84
+ sympy
85
+ timm
86
+ torchinfo
87
+ pdf2image
88
+ PyPDF
89
+ pyocr
90
+ pyarrow
91
+ xlrd
92
+ backoff
93
+ streamlit==1.40.2
94
+ python-dotenv
style.css ADDED
@@ -0,0 +1,173 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .stVerticalBlock {
2
+ padding-top: 0rem;
3
+ padding-bottom: 0rem;
4
+ }
5
+
6
+ .block-container {
7
+ padding-top: 0rem;
8
+ padding-bottom: 0rem;
9
+ }
10
+
11
+ [data-testid="stVerticalBlock"] {
12
+ padding-top: 0rem;
13
+ padding-bottom: 0rem;
14
+ }
15
+ .st-emotion-cache-40pabj{
16
+ padding-top: 0rem;
17
+ padding-bottom: 0rem;
18
+ }
19
+ /* Make the toolbar transparent */
20
+ .st-emotion-cache-18ni7ap {
21
+ pointer-events: none;
22
+ background: rgb(255 255 255 / 0%)
23
+ }
24
+
25
+ .stAppHeader {
26
+ display: none;
27
+ }
28
+
29
+ header {visibility: hidden;}
30
+ #MainMenu {visibility: hidden;}
31
+ [data-testid="stDecoration"] {
32
+ display: none;
33
+ }
34
+ #root > div:nth-child(1) > div > div > div > div > section > div {
35
+ padding-top: 0rem;
36
+ }
37
+
38
+ section.stMain .block-container {
39
+ padding-top: 0rem;
40
+ z-index: 1;
41
+ }
42
+
43
+ /* Main container */
44
+ .stApp {
45
+ background-color: var(--background);
46
+ height: auto;
47
+ overflow: visible;
48
+ }
49
+
50
+ /* Widgets */
51
+ .stSelectbox,
52
+ .stTextInput,
53
+ .stNumberInput {
54
+ background-color: var(--card);
55
+ border: 1px solid var(--border);
56
+ border-radius: 0.4rem;
57
+ }
58
+
59
+ .stMarkdown {
60
+ color: var(--primary);
61
+ }
62
+
63
+ /* Code block styling */
64
+ .stCodeBlock {
65
+ max-height: 400px;
66
+ overflow-y: auto !important;
67
+ border: 1px solid var(--border);
68
+ border-radius: 0.4rem;
69
+ background-color: var(--background-shaded);
70
+ }
71
+
72
+ /* Custom scrollbar for code blocks */
73
+ .stCodeBlock::-webkit-scrollbar {
74
+ width: 8px;
75
+ height: 8px;
76
+ }
77
+
78
+ .stCodeBlock::-webkit-scrollbar-track {
79
+ background: var(--background-shaded);
80
+ border-radius: 4px;
81
+ }
82
+
83
+ .stCodeBlock::-webkit-scrollbar-thumb {
84
+ background: var(--accent);
85
+ border-radius: 4px;
86
+ }
87
+
88
+ .stCodeBlock::-webkit-scrollbar-thumb:hover {
89
+ background: #e13d68;
90
+ }
91
+
92
+
93
+
94
+ .scrollable-code-container {
95
+ height: 600px;
96
+ overflow-y: auto;
97
+ border: 1px solid var(--border);
98
+ padding: 15px;
99
+ border-radius: 5px;
100
+ background-color: var(--background-shaded);
101
+ }
102
+
103
+ .scrollable-code-container pre {
104
+ margin: 0;
105
+ white-space: pre;
106
+ overflow-x: auto;
107
+ font-family: monospace;
108
+ }
109
+
110
+ .scrollable-code-container code {
111
+ display: block;
112
+ min-width: 100%;
113
+ padding: 0;
114
+ tab-size: 4;
115
+ }
116
+
117
+ /* Add custom scrollbar styling for code containers */
118
+ .scrollable-code-container::-webkit-scrollbar {
119
+ width: 8px;
120
+ height: 8px;
121
+ }
122
+
123
+ .scrollable-code-container::-webkit-scrollbar-track {
124
+ background: var(--background-shaded);
125
+ border-radius: 4px;
126
+ }
127
+
128
+ .scrollable-code-container::-webkit-scrollbar-thumb {
129
+ background: var(--accent);
130
+ border-radius: 4px;
131
+ }
132
+
133
+ .scrollable-code-container::-webkit-scrollbar-thumb:hover {
134
+ background: #e13d68;
135
+ }
136
+
137
+ /* Style for expander */
138
+ .streamlit-expanderHeader {
139
+ background-color: var(--card);
140
+ border: 1px solid var(--border);
141
+ border-radius: 0.4rem;
142
+ padding: 0.5rem !important;
143
+ }
144
+
145
+ .streamlit-expanderHeader:hover {
146
+ border-color: var(--accent);
147
+ }
148
+
149
+ /* Style for expander content */
150
+ .streamlit-expanderContent {
151
+ background-color: var(--background-shaded);
152
+ border: 1px solid var(--border);
153
+ border-radius: 0 0 0.4rem 0.4rem;
154
+ margin-top: -1px;
155
+ padding: 0.5rem !important;
156
+ }
157
+
158
+ /* Style for st.code() blocks */
159
+ .stCode {
160
+ max-height: 600px;
161
+ overflow-y: auto;
162
+ background-color: var(--background-shaded) !important;
163
+ border: 1px solid var(--border) !important;
164
+ border-radius: 5px !important;
165
+ }
166
+
167
+ .stCode pre {
168
+ background-color: var(--background-shaded) !important;
169
+ }
170
+
171
+ div[data-testid="InputInstructions"] {
172
+ visibility: hidden;
173
+ }