mamogasr commited on
Commit
5fdb69e
·
verified ·
1 Parent(s): 1200d44

Upload folder using huggingface_hub

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .gitattributes +15 -0
  2. .gitignore +184 -0
  3. LICENSE +21 -0
  4. README.md +125 -7
  5. SETUP-PC.md +200 -0
  6. SETUP-PC.pdf +3 -0
  7. SETUP-linux.md +214 -0
  8. SETUP-linux.pdf +3 -0
  9. SETUP-mac.md +196 -0
  10. SETUP-mac.pdf +3 -0
  11. business.jpg +3 -0
  12. community-contributions/playwright-bojan/Playwright_Solution_JupyterAsync.ipynb +173 -0
  13. community-contributions/playwright-bojan/Playwright_Solution_Showcase_Formatted.ipynb +69 -0
  14. community-contributions/playwright-bojan/README.md +67 -0
  15. community-contributions/playwright-bojan/openai_scraper_playwright.py +141 -0
  16. community-contributions/playwright-bojan/requirements.txt +6 -0
  17. diagnostics.ipynb +54 -0
  18. diagnostics.py +419 -0
  19. environment.yml +50 -0
  20. extras/community/prototype_signal.ipynb +413 -0
  21. extras/trading/prototype_trader.ipynb +354 -0
  22. extras/trading/trades_claude.py +725 -0
  23. extras/trading/trades_gemini.py +534 -0
  24. extras/trading/trades_gpt-4o.py +884 -0
  25. important.jpg +3 -0
  26. requirements.txt +44 -0
  27. resources.jpg +3 -0
  28. thankyou.jpg +3 -0
  29. turo_assist.py +169 -0
  30. voyage.jpg +3 -0
  31. week1/Guide to Jupyter.ipynb +380 -0
  32. week1/Intermediate Python.ipynb +486 -0
  33. week1/community-contributions/0225_day2_exercise_by_LM.ipynb +185 -0
  34. week1/community-contributions/Chat_Summary_Data/Chat_Examples/Chat1.txt +28 -0
  35. week1/community-contributions/Chat_Summary_Data/Chat_Examples/Chat2.txt +5 -0
  36. week1/community-contributions/Chat_Summary_Data/Chat_Examples/Chat3.txt +19 -0
  37. week1/community-contributions/Chat_Summary_Data/System_Prompt.txt +15 -0
  38. week1/community-contributions/CoolCodeSummarizer.ipynb +177 -0
  39. week1/community-contributions/Day-1-Text-to-sql/db.py +10 -0
  40. week1/community-contributions/Day-1-Text-to-sql/ollama-TTSQL.py +42 -0
  41. week1/community-contributions/Day2-Solution-Ollama.ipynb +123 -0
  42. week1/community-contributions/Ollama brochure.ipynb +432 -0
  43. week1/community-contributions/OllamaDay1_MailSubjectLine.ipynb +83 -0
  44. week1/community-contributions/Ollama_websummarizer_user_input.ipynb +240 -0
  45. week1/community-contributions/Text-Summarizer.ipynb +76 -0
  46. week1/community-contributions/W1D5_Code_instructor.ipynb +269 -0
  47. week1/community-contributions/Week1-Challenge-Brochure-Translation.ipynb +346 -0
  48. week1/community-contributions/Week1-Challenge-LocalGPT.ipynb +148 -0
  49. week1/community-contributions/Week1-Day2-Ollama-Exercise.ipynb +273 -0
  50. week1/community-contributions/Week1-Exercise-OllamaStream-Solution.ipynb +138 -0
.gitattributes CHANGED
@@ -33,3 +33,18 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ SETUP-PC.pdf filter=lfs diff=lfs merge=lfs -text
37
+ SETUP-linux.pdf filter=lfs diff=lfs merge=lfs -text
38
+ SETUP-mac.pdf filter=lfs diff=lfs merge=lfs -text
39
+ business.jpg filter=lfs diff=lfs merge=lfs -text
40
+ important.jpg filter=lfs diff=lfs merge=lfs -text
41
+ resources.jpg filter=lfs diff=lfs merge=lfs -text
42
+ thankyou.jpg filter=lfs diff=lfs merge=lfs -text
43
+ voyage.jpg filter=lfs diff=lfs merge=lfs -text
44
+ week2/community-contributions/chatbot_conversation_robots.jpg filter=lfs diff=lfs merge=lfs -text
45
+ week4/community-contributions/ai_code_converter/screenshots/codeXchange_3.png filter=lfs diff=lfs merge=lfs -text
46
+ week5/community-contributions/docuSeekAI/docuseek2.png filter=lfs diff=lfs merge=lfs -text
47
+ week5/community-contributions/docuSeekAI/docuseek3.png filter=lfs diff=lfs merge=lfs -text
48
+ week5/community-contributions/docuSeekAI/docuseek4.png filter=lfs diff=lfs merge=lfs -text
49
+ week8/community_contributions/images/gui.png filter=lfs diff=lfs merge=lfs -text
50
+ week8/community_contributions/images/metrics.png filter=lfs diff=lfs merge=lfs -text
.gitignore ADDED
@@ -0,0 +1,184 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Github's default gitignore for Python
2
+
3
+ # Byte-compiled / optimized / DLL files
4
+ __pycache__/
5
+ *.py[cod]
6
+ *$py.class
7
+
8
+ # C extensions
9
+ *.so
10
+
11
+ # Distribution / packaging
12
+ .Python
13
+ build/
14
+ develop-eggs/
15
+ dist/
16
+ downloads/
17
+ eggs/
18
+ .eggs/
19
+ lib/
20
+ lib64/
21
+ parts/
22
+ sdist/
23
+ var/
24
+ wheels/
25
+ share/python-wheels/
26
+ *.egg-info/
27
+ .installed.cfg
28
+ *.egg
29
+ MANIFEST
30
+
31
+ # PyInstaller
32
+ # Usually these files are written by a python script from a template
33
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
34
+ *.manifest
35
+ *.spec
36
+
37
+ # Installer logs
38
+ pip-log.txt
39
+ pip-delete-this-directory.txt
40
+
41
+ # Unit test / coverage reports
42
+ htmlcov/
43
+ .tox/
44
+ .nox/
45
+ .coverage
46
+ .coverage.*
47
+ .cache
48
+ nosetests.xml
49
+ coverage.xml
50
+ *.cover
51
+ *.py,cover
52
+ .hypothesis/
53
+ .pytest_cache/
54
+ cover/
55
+
56
+ # Translations
57
+ *.mo
58
+ *.pot
59
+
60
+ # Django stuff:
61
+ *.log
62
+ local_settings.py
63
+ db.sqlite3
64
+ db.sqlite3-journal
65
+
66
+ # Flask stuff:
67
+ instance/
68
+ .webassets-cache
69
+
70
+ # Scrapy stuff:
71
+ .scrapy
72
+
73
+ # Sphinx documentation
74
+ docs/_build/
75
+
76
+ # PyBuilder
77
+ .pybuilder/
78
+ target/
79
+
80
+ # Jupyter Notebook
81
+ .ipynb_checkpoints
82
+
83
+ # IPython
84
+ profile_default/
85
+ ipython_config.py
86
+
87
+ # pyenv
88
+ # For a library or package, you might want to ignore these files since the code is
89
+ # intended to run in multiple environments; otherwise, check them in:
90
+ # .python-version
91
+
92
+ # pipenv
93
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
94
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
95
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
96
+ # install all needed dependencies.
97
+ #Pipfile.lock
98
+
99
+ # poetry
100
+ # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
101
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
102
+ # commonly ignored for libraries.
103
+ # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
104
+ #poetry.lock
105
+
106
+ # pdm
107
+ # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
108
+ #pdm.lock
109
+ # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
110
+ # in version control.
111
+ # https://pdm.fming.dev/#use-with-ide
112
+ .pdm.toml
113
+
114
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
115
+ __pypackages__/
116
+
117
+ # Celery stuff
118
+ celerybeat-schedule
119
+ celerybeat.pid
120
+
121
+ # SageMath parsed files
122
+ *.sage.py
123
+
124
+ # Environments
125
+ .env
126
+ .venv
127
+ env/
128
+ venv/
129
+ ENV/
130
+ env.bak/
131
+ venv.bak/
132
+ llms/
133
+ llms.bak/
134
+
135
+ # Spyder project settings
136
+ .spyderproject
137
+ .spyproject
138
+
139
+ # Rope project settings
140
+ .ropeproject
141
+
142
+ # mkdocs documentation
143
+ /site
144
+
145
+ # mypy
146
+ .mypy_cache/
147
+ .dmypy.json
148
+ dmypy.json
149
+
150
+ # Pyre type checker
151
+ .pyre/
152
+
153
+ # pytype static type analyzer
154
+ .pytype/
155
+
156
+ # Cython debug symbols
157
+ cython_debug/
158
+
159
+ # PyCharm
160
+ .idea/
161
+
162
+ # Added this to ignore models downloaded from HF
163
+ model_cache/
164
+ # Ignore finder files
165
+ .DS_Store
166
+ /.DS_Store
167
+
168
+ # Ignore Chroma vector database
169
+ vector_db/
170
+ products_vectorstore/
171
+
172
+ # And ignore any pickle files made during the course
173
+ *.pkl
174
+
175
+ # ignore gradio private files
176
+ .gradio
177
+ /.gradio
178
+
179
+ # ignore diagnostics reports
180
+ **/report.txt
181
+
182
+ # ignore optimized C++ code from being checked into repo
183
+ week4/optimized
184
+ week4/simple
LICENSE ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Ed Donner
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.
README.md CHANGED
@@ -1,12 +1,130 @@
1
  ---
2
- title: Llm Engineering
3
- emoji: 😻
4
- colorFrom: purple
5
- colorTo: red
6
  sdk: gradio
7
  sdk_version: 5.29.0
8
- app_file: app.py
9
- pinned: false
10
  ---
 
11
 
12
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ---
2
+ title: llm_engineering
3
+ app_file: turo_assist.py
 
 
4
  sdk: gradio
5
  sdk_version: 5.29.0
 
 
6
  ---
7
+ # LLM Engineering - Master AI and LLMs
8
 
9
+ ## Your 8 week journey to proficiency starts today
10
+
11
+ ![Voyage](voyage.jpg)
12
+
13
+ I'm so happy you're joining me on this path. We'll be building immensely satisfying projects in the coming weeks. Some will be easy, some will be challenging, many will ASTOUND you! The projects build on each other so you develop deeper and deeper expertise each week. One thing's for sure: you're going to have a lot of fun along the way.
14
+
15
+ ### Before you begin
16
+
17
+ I'm here to help you be most successful with your learning! If you hit any snafus, or if you have any ideas on how I can improve the course, please do reach out in the platform or by emailing me direct ([email protected]). It's always great to connect with people on LinkedIn to build up the community - you'll find me here:
18
+ https://www.linkedin.com/in/eddonner/
19
+ And this is new to me, but I'm also trying out X/Twitter at [@edwarddonner](https://x.com/edwarddonner) - if you're on X, please show me how it's done 😂
20
+
21
+ Resources to accompany the course, including the slides and useful links, are here:
22
+ https://edwarddonner.com/2024/11/13/llm-engineering-resources/
23
+
24
+ ## Instant Gratification instructions for Week 1, Day 1 - with Llama 3.2 **not** Llama 3.3!
25
+
26
+ ### Important note: see my warning about Llama3.3 below - it's too large for home computers! Stick with llama3.2! Several students have missed this warning...
27
+
28
+ We will start the course by installing Ollama so you can see results immediately!
29
+ 1. Download and install Ollama from https://ollama.com noting that on a PC you might need to have administrator permissions for the install to work properly
30
+ 2. On a PC, start a Command prompt / Powershell (Press Win + R, type `cmd`, and press Enter). On a Mac, start a Terminal (Applications > Utilities > Terminal).
31
+ 3. Run `ollama run llama3.2` or for smaller machines try `ollama run llama3.2:1b` - **please note** steer clear of Meta's latest model llama3.3 because at 70B parameters that's way too large for most home computers!
32
+ 4. If this doesn't work: you may need to run `ollama serve` in another Powershell (Windows) or Terminal (Mac), and try step 3 again. On a PC, you may need to be running in an Admin instance of Powershell.
33
+ 5. And if that doesn't work on your box, I've set up this on the cloud. This is on Google Colab, which will need you to have a Google account to sign in, but is free: https://colab.research.google.com/drive/1-_f5XZPsChvfU1sJ0QqCePtIuc55LSdu?usp=sharing
34
+
35
+ Any problems, please contact me!
36
+
37
+ ## Then, Setup instructions
38
+
39
+ After we do the Ollama quick project, and after I introduce myself and the course, we get to work with the full environment setup.
40
+
41
+ Hopefully I've done a decent job of making these guides bulletproof - but please contact me right away if you hit roadblocks:
42
+
43
+ - PC people please follow the instructions in [SETUP-PC.md](SETUP-PC.md)
44
+ - Mac people please follow the instructions in [SETUP-mac.md](SETUP-mac.md)
45
+ - Linux people please follow the instructions in [SETUP-linux.md](SETUP-linux.md)
46
+
47
+ The are also PDF versions of the setup instructions in this folder if you'd prefer.
48
+
49
+ ### An important point on API costs (which are optional! No need to spend if you don't wish)
50
+
51
+ During the course, I'll suggest you try out the leading models at the forefront of progress, known as the Frontier models. I'll also suggest you run open-source models using Google Colab. These services have some charges, but I'll keep cost minimal - like, a few cents at a time. And I'll provide alternatives if you'd prefer not to use them.
52
+
53
+ Please do monitor your API usage to ensure you're comfortable with spend; I've included links below. There's no need to spend anything more than a couple of dollars for the entire course. Some AI providers such as OpenAI require a minimum credit like \$5 or local equivalent; we should only spend a fraction of it, and you'll have plenty of opportunity to put it to good use in your own projects. During Week 7 you have an option to spend a bit more if you're enjoying the process - I spend about \$10 myself and the results make me very happy indeed! But it's not necessary in the least; the important part is that you focus on learning.
54
+
55
+ ### Free alternative to Paid APIs
56
+
57
+ Early in the course, I show you an alternative if you'd rather not spend anything on APIs:
58
+ Any time that we have code like:
59
+ `openai = OpenAI()`
60
+ You can use this as a direct replacement:
61
+ `openai = OpenAI(base_url='http://localhost:11434/v1', api_key='ollama')`
62
+ And also replace model names like **gpt-4o-mini** with **llama3.2**.
63
+ For week 1 day 1, you can find this in week1/solutions/day1_with_ollama.ipynb.
64
+
65
+ Below is a full example:
66
+
67
+ ```
68
+ # You need to do this one time on your computer
69
+ !ollama pull llama3.2
70
+
71
+ from openai import OpenAI
72
+ MODEL = "llama3.2"
73
+ openai = OpenAI(base_url="http://localhost:11434/v1", api_key="ollama")
74
+
75
+ response = openai.chat.completions.create(
76
+ model=MODEL,
77
+ messages=[{"role": "user", "content": "What is 2 + 2?"}]
78
+ )
79
+
80
+ print(response.choices[0].message.content)
81
+ ```
82
+
83
+ ### How this Repo is organized
84
+
85
+ There are folders for each of the "weeks", representing modules of the class, culminating in a powerful autonomous Agentic AI solution in Week 8 that draws on many of the prior weeks.
86
+ Follow the setup instructions above, then open the Week 1 folder and prepare for joy.
87
+
88
+ ### The most important part
89
+
90
+ The mantra of the course is: the best way to learn is by **DOING**. I don't type all the code during the course; I execute it for you to see the results. You should work along with me or after each lecture, running each cell, inspecting the objects to get a detailed understanding of what's happening. Then tweak the code and make it your own. There are juicy challenges for you throughout the course. I'd love it if you wanted to submit a Pull Request for your code (instructions [here](https://chatgpt.com/share/677a9cb5-c64c-8012-99e0-e06e88afd293)) and I can make your solutions available to others so we share in your progress; as an added benefit, you'll be recognized in GitHub for your contribution to the repo. While the projects are enjoyable, they are first and foremost designed to be _educational_, teaching you business skills that can be put into practice in your work.
91
+
92
+ ## Starting in Week 3, we'll also be using Google Colab for running with GPUs
93
+
94
+ You should be able to use the free tier or minimal spend to complete all the projects in the class. I personally signed up for Colab Pro+ and I'm loving it - but it's not required.
95
+
96
+ Learn about Google Colab and set up a Google account (if you don't already have one) [here](https://colab.research.google.com/)
97
+
98
+ The colab links are in the Week folders and also here:
99
+ - For week 3 day 1, this Google Colab shows what [colab can do](https://colab.research.google.com/drive/1DjcrYDZldAXKJ08x1uYIVCtItoLPk1Wr?usp=sharing)
100
+ - For week 3 day 2, here is a colab for the HuggingFace [pipelines API](https://colab.research.google.com/drive/1aMaEw8A56xs0bRM4lu8z7ou18jqyybGm?usp=sharing)
101
+ - For week 3 day 3, here's the colab on [Tokenizers](https://colab.research.google.com/drive/1WD6Y2N7ctQi1X9wa6rpkg8UfyA4iSVuz?usp=sharing)
102
+ - For week 3 day 4, we go to a colab with HuggingFace [models](https://colab.research.google.com/drive/1hhR9Z-yiqjUe7pJjVQw4c74z_V3VchLy?usp=sharing)
103
+ - For week 3 day 5, we return to colab to make our [Meeting Minutes product](https://colab.research.google.com/drive/1KSMxOCprsl1QRpt_Rq0UqCAyMtPqDQYx?usp=sharing)
104
+ - For week 7, we will use these Colab books: [Day 1](https://colab.research.google.com/drive/15rqdMTJwK76icPBxNoqhI7Ww8UM-Y7ni?usp=sharing) | [Day 2](https://colab.research.google.com/drive/1T72pbfZw32fq-clQEp-p8YQ4_qFKv4TP?usp=sharing) | [Days 3 and 4](https://colab.research.google.com/drive/1csEdaECRtjV_1p9zMkaKKjCpYnltlN3M?usp=sharing) | [Day 5](https://colab.research.google.com/drive/1igA0HF0gvQqbdBD4GkcK3GpHtuDLijYn?usp=sharing)
105
+
106
+ ### Monitoring API charges
107
+
108
+ You can keep your API spend very low throughout this course; you can monitor spend at the dashboards: [here](https://platform.openai.com/usage) for OpenAI, [here](https://console.anthropic.com/settings/cost) for Anthropic and [here](https://console.cloud.google.com/apis/api/generativelanguage.googleapis.com/cost) for Google Gemini.
109
+
110
+ The charges for the exercsies in this course should always be quite low, but if you'd prefer to keep them minimal, then be sure to always choose the cheapest versions of models:
111
+ 1. For OpenAI: Always use model `gpt-4o-mini` in the code instead of `gpt-4o`
112
+ 2. For Anthropic: Always use model `claude-3-haiku-20240307` in the code instead of the other Claude models
113
+ 3. During week 7, look out for my instructions for using the cheaper dataset
114
+
115
+ Please do message me or email me at [email protected] if this doesn't work or if I can help with anything. I can't wait to hear how you get on.
116
+
117
+ <table style="margin: 0; text-align: left;">
118
+ <tr>
119
+ <td style="width: 150px; height: 150px; vertical-align: middle;">
120
+ <img src="resources.jpg" width="150" height="150" style="display: block;" />
121
+ </td>
122
+ <td>
123
+ <h2 style="color:#f71;">Other resources</h2>
124
+ <span style="color:#f71;">I've put together this webpage with useful resources for the course. This includes links to all the slides.<br/>
125
+ <a href="https://edwarddonner.com/2024/11/13/llm-engineering-resources/">https://edwarddonner.com/2024/11/13/llm-engineering-resources/</a><br/>
126
+ Please keep this bookmarked, and I'll continue to add more useful links there over time.
127
+ </span>
128
+ </td>
129
+ </tr>
130
+ </table>
SETUP-PC.md ADDED
@@ -0,0 +1,200 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # LLM Engineering - Master AI and LLMs
2
+
3
+ ## Setup instructions for Windows
4
+
5
+ Welcome, PC people!
6
+
7
+ I should confess up-front: setting up a powerful environment to work at the forefront of AI is not as simple as I'd like. For most people these instructions will go great; but in some cases, for whatever reason, you'll hit a problem. Please don't hesitate to reach out - I am here to get you up and running quickly. There's nothing worse than feeling _stuck_. Message me, email me or LinkedIn message me and I will unstick you quickly!
8
+
9
10
+ LinkedIn: https://www.linkedin.com/in/eddonner/
11
+
12
+ I use a platform called Anaconda to set up your environment. It's a powerful tool that builds a complete science environment. Anaconda ensures that you're working with the right version of Python and all your packages are compatible with mine, even if our systems are completely different. It takes more time to set up, and it uses more hard drive space (5+ GB) but it's very reliable once its working.
13
+
14
+ Having said that: if you have any problems with Anaconda, I've provided an alternative approach. It's faster and simpler and should have you running quickly, with less of a guarantee around compatibility.
15
+
16
+ ### Before we begin - Heads up! Please do check these Windows "gotchas":
17
+
18
+ If you are relatively new to using the Command Prompt, here is an excellent [guide](https://chatgpt.com/share/67b0acea-ba38-8012-9c34-7a2541052665) with instructions and exercises. I'd suggest you work through this first to build some confidence.
19
+
20
+ There are 4 common gotchas to developing on Windows to be aware of:
21
+
22
+ 1. Permissions. Please take a look at this [tutorial](https://chatgpt.com/share/67b0ae58-d1a8-8012-82ca-74762b0408b0) on permissions on Windows
23
+ 2. Anti-virus, Firewall, VPN. These can interfere with installations and network access; try temporarily disabling them as needed
24
+ 3. The evil Windows 260 character limit to filenames - here is a full [explanation and fix](https://chatgpt.com/share/67b0afb9-1b60-8012-a9f7-f968a5a910c7)!
25
+ 4. If you've not worked with Data Science packages on your computer before, you might need to install Microsoft Build Tools. Here are [instructions](https://chatgpt.com/share/67b0b762-327c-8012-b809-b4ec3b9e7be0). A student also mentioned that [these instructions](https://github.com/bycloudai/InstallVSBuildToolsWindows) might be helpful for people on Windows 11.
26
+
27
+ ### Part 1: Clone the Repo
28
+
29
+ This gets you a local copy of the code on your box.
30
+
31
+ 1. **Install Git** (if not already installed):
32
+
33
+ - Download Git from https://git-scm.com/download/win
34
+ - Run the installer and follow the prompts, using default options (press OK lots of times!).
35
+ - After the installation, you may need to open a new Powershell window to use it (or you might even need to restart)
36
+
37
+ 2. **Open Command Prompt:**
38
+
39
+ - Press Win + R, type `cmd`, and press Enter
40
+
41
+ 3. **Navigate to your projects folder:**
42
+
43
+ If you have a specific folder for projects, navigate to it using the cd command. For example:
44
+ `cd C:\Users\YourUsername\Documents\Projects`
45
+ Replacing YourUsername with your actual Windows user
46
+
47
+ If you don't have a projects folder, you can create one:
48
+ ```
49
+ mkdir C:\Users\YourUsername\Documents\Projects
50
+ cd C:\Users\YourUsername\Documents\Projects
51
+ ```
52
+
53
+ 4. **Clone the repository:**
54
+
55
+ Enter this in the command prompt in the Projects folder:
56
+
57
+ `git clone https://github.com/ed-donner/llm_engineering.git`
58
+
59
+ This creates a new directory `llm_engineering` within your Projects folder and downloads the code for the class. Do `cd llm_engineering` to go into it. This `llm_engineering` directory is known as the "project root directory".
60
+
61
+ ### Part 2: Install Anaconda environment
62
+
63
+ If this Part 2 gives you any problems, there is an alternative Part 2B below that can be used instead.
64
+
65
+ 1. **Install Anaconda:**
66
+
67
+ - Download Anaconda from https://docs.anaconda.com/anaconda/install/windows/
68
+ - Run the installer and follow the prompts. Note that it takes up several GB and take a while to install, but it will be a powerful platform for you to use in the future.
69
+
70
+ 2. **Set up the environment:**
71
+
72
+ - Open **Anaconda Prompt** (search for it in the Start menu)
73
+ - Navigate to the "project root directory" by entering something like `cd C:\Users\YourUsername\Documents\Projects\llm_engineering` using the actual path to your llm_engineering project root directory. Do a `dir` and check you can see subdirectories for each week of the course.
74
+ - Create the environment: `conda env create -f environment.yml`
75
+ - **If you get an ArchiveError issue, then this is caused by the Windows 260 character limit - see gotcha number 3 at the top**
76
+ - Wait for a few minutes for all packages to be installed - in some cases, this can literally take 30 minutes if you've not used Anaconda before, and even longer depending on your internet connection. Important stuff is happening! If this runs for more than 1 hour 15 mins, or gives you other problems, please go to Part 2B instead.
77
+ - You have now built an isolated, dedicated AI environment for engineering LLMs, running vector datastores, and so much more! You now need to **activate** it using this command: `conda activate llms`
78
+
79
+ You should see `(llms)` in your prompt, which indicates you've activated your new environment.
80
+
81
+ 3. **Start Jupyter Lab:**
82
+
83
+ - In the Anaconda Prompt, from within the `llm_engineering` folder, type: `jupyter lab`
84
+
85
+ ...and Jupyter Lab should open up in a browser. If you've not seen Jupyter Lab before, I'll explain it in a moment! Now close the jupyter lab browser tab, and close the Anaconda prompt, and move on to Part 3.
86
+
87
+ ### Part 2B - Alternative to Part 2 if Anaconda gives you trouble
88
+
89
+ 1. **Open Command Prompt**
90
+
91
+ Press Win + R, type `cmd`, and press Enter
92
+
93
+ Run `python --version` to find out which python you're on.
94
+ Ideally you'd be using a version of Python 3.11, so we're completely in sync.
95
+ I believe Python 3.12 works also, but (as of Feb 2025) Python 3.13 does **not** yet work as several Data Science dependencies are not yet ready for Python 3.13.
96
+ If you need to install Python or install another version, you can download it here:
97
+ https://www.python.org/downloads/
98
+
99
+ 2. Navigate to the "project root directory" by entering something like `cd C:\Users\YourUsername\Documents\Projects\llm_engineering` using the actual path to your llm_engineering project root directory. Do a `dir` and check you can see subdirectories for each week of the course.
100
+
101
+ Then, create a new virtual environment with this command:
102
+ `python -m venv llms`
103
+
104
+ 3. Activate the virtual environment with
105
+ `llms\Scripts\activate`
106
+ You should see (llms) in your command prompt, which is your sign that things are going well.
107
+
108
+ 4. Run `python -m pip install --upgrade pip` followed by `pip install -r requirements.txt`
109
+ This may take a few minutes to install.
110
+ If you see an error like this:
111
+
112
+ > Microsoft Visual C++ 14.0 or greater is required. Get it with "Microsoft C++ Build Tools": [https://visualstudio.microsoft.com/visual-cpp-build-tools/](https://visualstudio.microsoft.com/visual-cpp-build-tools/)
113
+
114
+ Then please follow the link and install Microsoft C++ Build Tools. A student also mentioned that [these instructions](https://github.com/bycloudai/InstallVSBuildToolsWindows) might be helpful for people on Windows 11.
115
+
116
+ In the very unlikely event that this step doesn't go well, you should try the bullet-proof (but slower) version:
117
+ `pip install --retries 5 --timeout 15 --no-cache-dir --force-reinstall -r requirements.txt`
118
+
119
+ 6. **Start Jupyter Lab:**
120
+
121
+ From within the `llm_engineering` folder, type: `jupyter lab`
122
+ ...and Jupyter Lab should open up, ready for you to get started. Open the `week1` folder and double click on `day1.ipynb`. Success! Now close down jupyter lab and move on to Part 3.
123
+
124
+ If there are any problems, contact me!
125
+
126
+ ### Part 3 - OpenAI key (OPTIONAL but recommended)
127
+
128
+ Particularly during weeks 1 and 2 of the course, you'll be writing code to call the APIs of Frontier models (models at the forefront of AI).
129
+
130
+ For week 1, you'll only need OpenAI, and you can add the others if you wish later on.
131
+
132
+ 1. Create an OpenAI account if you don't have one by visiting:
133
+ https://platform.openai.com/
134
+
135
+ 2. OpenAI asks for a minimum credit to use the API. For me in the US, it's \$5. The API calls will spend against this \$5. On this course, we'll only use a small portion of this. I do recommend you make the investment as you'll be able to put it to excellent use. But if you'd prefer not to pay for the API, I give you an alternative in the course using Ollama.
136
+
137
+ You can add your credit balance to OpenAI at Settings > Billing:
138
+ https://platform.openai.com/settings/organization/billing/overview
139
+
140
+ I recommend you disable the automatic recharge!
141
+
142
+ 3. Create your API key
143
+
144
+ The webpage where you set up your OpenAI key is at https://platform.openai.com/api-keys - press the green 'Create new secret key' button and press 'Create secret key'. Keep a record of the API key somewhere private; you won't be able to retrieve it from the OpenAI screens in the future. It should start `sk-proj-`.
145
+
146
+ In week 2 we will also set up keys for Anthropic and Google, which you can do here when we get there.
147
+ - Claude API at https://console.anthropic.com/ from Anthropic
148
+ - Gemini API at https://ai.google.dev/gemini-api from Google
149
+
150
+ Later in the course you'll be using the fabulous HuggingFace platform; an account is available for free at https://huggingface.co - you can create an API token from the Avatar menu >> Settings >> Access Tokens.
151
+
152
+ And in Week 6/7 you'll be using the terrific Weights & Biases at https://wandb.ai to watch over your training batches. Accounts are also free, and you can set up a token in a similar way.
153
+
154
+ ### PART 4 - .env file
155
+
156
+ When you have these keys, please create a new file called `.env` in your project root directory. The filename needs to be exactly the four characters ".env" rather than "my-keys.env" or ".env.txt". Here's how to do it:
157
+
158
+ 1. Open the Notepad (Windows + R to open the Run box, enter `notepad`)
159
+
160
+ 2. In the Notepad, type this, replacing xxxx with your API key (starting `sk-proj-`).
161
+
162
+ ```
163
+ OPENAI_API_KEY=xxxx
164
+ ```
165
+
166
+ If you have other keys, you can add them too, or come back to this in future weeks:
167
+ ```
168
+ GOOGLE_API_KEY=xxxx
169
+ ANTHROPIC_API_KEY=xxxx
170
+ DEEPSEEK_API_KEY=xxxx
171
+ HF_TOKEN=xxxx
172
+ ```
173
+
174
+ Double check there are no spaces before or after the `=` sign, and no spaces at the end of the key.
175
+
176
+ 3. Go to File > Save As. In the "Save as type" dropdown, select All Files. In the "File name" field, type exactly **.env** as the filename. Choose to save this in the project root directory (the folder called `llm_engineering`) and click Save.
177
+
178
+ 4. Navigate to the folder where you saved the file in Explorer and ensure it was saved as ".env" not ".env.txt" - if necessary rename it to ".env" - you might need to ensure that "Show file extensions" is set to "On" so that you see the file extensions. Message or email me if that doesn't make sense!
179
+
180
+ This file won't appear in Jupyter Lab because jupyter hides files starting with a dot. This file is listed in the `.gitignore` file, so it won't get checked in and your keys stay safe.
181
+
182
+ ### Part 5 - Showtime!!
183
+
184
+ - Open **Anaconda Prompt** (search for it in the Start menu) if you used Anaconda, otherwise open a Powershell if you used the alternative approach in Part 2B
185
+
186
+ - Navigate to the "project root directory" by entering something like `cd C:\Users\YourUsername\Documents\Projects\llm_engineering` using the actual path to your llm_engineering project root directory. Do a `dir` and check you can see subdirectories for each week of the course.
187
+
188
+ - Activate your environment with `conda activate llms` if you used Anaconda or `llms\Scripts\activate` if you used the alternative approach in Part 2B
189
+
190
+ - You should see (llms) in your prompt which is your sign that all is well. And now, type: `jupyter lab` and Jupyter Lab should open up, ready for you to get started. Open the `week1` folder and double click on `day1.ipynb`.
191
+
192
+ And you're off to the races!
193
+
194
+ Note that any time you start jupyter lab in the future, you'll need to follow these Part 5 instructions to start it from within the `llm_engineering` directory with the `llms` environment activated.
195
+
196
+ For those new to Jupyter Lab / Jupyter Notebook, it's a delightful Data Science environment where you can simply hit shift+return in any cell to run it; start at the top and work your way down! There's a notebook in the week1 folder with a [Guide to Jupyter Lab](week1/Guide%20to%20Jupyter.ipynb), and an [Intermediate Python](week1/Intermediate%20Python.ipynb) tutorial, if that would be helpful. When we move to Google Colab in Week 3, you'll experience the same interface for Python runtimes in the cloud.
197
+
198
+ If you have any problems, I've included a notebook in week1 called [troubleshooting.ipynb](week1/troubleshooting.ipynb) to figure it out.
199
+
200
+ Please do message me or email me at [email protected] if this doesn't work or if I can help with anything. I can't wait to hear how you get on.
SETUP-PC.pdf ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:7d6e2f14564cb5b7fbbbe23125e737047b8a6732627957a08b4400fe18f306da
3
+ size 149380
SETUP-linux.md ADDED
@@ -0,0 +1,214 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # LLM Engineering - Master AI and LLMs
2
+
3
+ ## Setup instructions for Linux
4
+
5
+ Welcome, Linux people!
6
+
7
+ I should reveal that I had ChatGPT make this document based on the Mac instructions, but then I went through and checked and tweaked some sections. If any of these instructions don't work for your distro, please do reach out and let me know - we'll figure it out, then I'll update the instructions for the future.
8
+
9
+ ___
10
+
11
+ Setting up a powerful environment to work at the forefront of AI requires some effort, but these instructions should guide you smoothly. If you encounter any issues, don't hesitate to reach out to me. I'm here to ensure you get set up without hassle.
12
+
13
14
+ LinkedIn: https://www.linkedin.com/in/eddonner/
15
+
16
+ For this setup, we'll use Anaconda to create a reliable environment for your AI work. Alternatively, I've provided a lighter option if you prefer to avoid Anaconda. Let's get started!
17
+
18
+ ### Part 1: Clone the Repo
19
+
20
+ This gets you a local copy of the code on your machine.
21
+
22
+ 1. **Install Git** if not already installed:
23
+
24
+ - Open your terminal.
25
+ - Run `git --version`. If Git isn't installed, follow the instructions for your distribution:
26
+ - Debian/Ubuntu: `sudo apt update && sudo apt install git`
27
+ - Fedora: `sudo dnf install git`
28
+ - Arch: `sudo pacman -S git`
29
+
30
+ 2. **Navigate to your projects folder:**
31
+
32
+ If you have a specific folder for projects, navigate to it using the `cd` command. For example:
33
+ `cd ~/Projects`
34
+
35
+ If you don't have a projects folder, you can create one:
36
+ ```
37
+ mkdir ~/Projects
38
+ cd ~/Projects
39
+ ```
40
+
41
+ 3. **Clone the repository:**
42
+
43
+ Run the following command in your terminal:
44
+ `git clone https://github.com/ed-donner/llm_engineering.git`
45
+
46
+ This creates a new directory `llm_engineering` within your Projects folder and downloads the course code. Use `cd llm_engineering` to enter the directory. This is your "project root directory."
47
+
48
+ ### Part 2: Install Anaconda environment
49
+
50
+ If this Part 2 gives you any trouble, refer to the alternative Part 2B below.
51
+
52
+ 1. **Install Anaconda:**
53
+
54
+ - Download the Linux installer from https://www.anaconda.com/download.
55
+ - Open a terminal and navigate to the folder containing the downloaded `.sh` file.
56
+ - Run the installer: `bash Anaconda3*.sh` and follow the prompts. Note: This requires about 5+ GB of disk space.
57
+
58
+ 2. **Set up the environment:**
59
+
60
+ - Open a terminal and navigate to the "project root directory" using:
61
+ `cd ~/Projects/llm_engineering` (adjust the path as necessary).
62
+ - Run `ls` to confirm the presence of subdirectories for each week of the course.
63
+ - Create the environment: `conda env create -f environment.yml`
64
+
65
+ This may take several minutes (even up to an hour for new Anaconda users). If it takes longer or errors occur, proceed to Part 2B.
66
+
67
+ - Activate the environment: `conda activate llms`.
68
+
69
+ You should see `(llms)` in your prompt, indicating successful activation.
70
+
71
+ In some distributions this may be required so that the llms environment is visible in jupyter lab:
72
+
73
+ `conda install ipykernel`
74
+ `python -m ipykernel install --user --name=llmenv`
75
+
76
+ 3. **Start Jupyter Lab:**
77
+
78
+ From the `llm_engineering` folder, run: `jupyter lab`.
79
+
80
+ Jupyter Lab should open in your browser. Close it after confirming it works, and proceed to Part 3.
81
+
82
+ ### Part 2B - Alternative to Part 2 if Anaconda gives you trouble
83
+
84
+ 1. **Install Python 3.11 (if not already installed):**
85
+
86
+ - Debian/Ubuntu: `sudo apt update && sudo apt install python3.11`
87
+ - Fedora: `sudo dnf install python3.11`
88
+ - Arch: `sudo pacman -S python`
89
+
90
+ 2. **Navigate to the project root directory:**
91
+
92
+ Use `cd ~/Projects/llm_engineering` and verify the folder contents with `ls`.
93
+
94
+ 3. **Create a virtual environment:**
95
+
96
+ Run: `python3.11 -m venv llms`
97
+
98
+ 4. **Activate the virtual environment:**
99
+
100
+ Use: `source llms/bin/activate`
101
+
102
+ Your prompt should now display `(llms)`, indicating the environment is active.
103
+
104
+ 5. **Install required packages:**
105
+
106
+ Run: `python -m pip install --upgrade pip` followed by `pip install -r requirements.txt`.
107
+
108
+ If issues occur, try the fallback:
109
+ `pip install --retries 5 --timeout 15 --no-cache-dir --force-reinstall -r requirements.txt`
110
+
111
+ ###### Arch users:
112
+
113
+ Some updates break dependencies. Most notably, numpy, scipy and gensim. To troubleshoot this, you can try many commands:
114
+
115
+ `sudo pacman -S python-numpy python-pandas python-scipy` This is not recommended, as pacman has no integration with pip (as far as I know)
116
+
117
+ Another possible solution if having build conflicts, is to update:
118
+
119
+ `sudo pacman -S gcc gcc-fortran python-setuptools python-wheel`
120
+
121
+ *Note:* gensim is broken if you have an updated version of scipy. You can either pin scipy to an older version, or
122
+ erase gensim from the requirements.txt for the moment. (See: https://aur.archlinux.org/packages/python-gensim)
123
+
124
+ Lastly, so that the kernel is visible after step (6) in jupyter lab :
125
+ `python -m ipykernel install --user --name=llmenv`
126
+ `ipython kernel install --user --name=llmenv`
127
+
128
+
129
+ 6. **Start Jupyter Lab:**
130
+
131
+ From the `llm_engineering` folder, run: `jupyter lab`.
132
+
133
+
134
+ ### Part 3 - OpenAI key (OPTIONAL but recommended)
135
+
136
+ Particularly during weeks 1 and 2 of the course, you'll be writing code to call the APIs of Frontier models (models at the forefront of AI).
137
+
138
+ For week 1, you'll only need OpenAI, and you can add the others if you wish later on.
139
+
140
+ 1. Create an OpenAI account if you don't have one by visiting:
141
+ https://platform.openai.com/
142
+
143
+ 2. OpenAI asks for a minimum credit to use the API. For me in the US, it's \$5. The API calls will spend against this \$5. On this course, we'll only use a small portion of this. I do recommend you make the investment as you'll be able to put it to excellent use. But if you'd prefer not to pay for the API, I give you an alternative in the course using Ollama.
144
+
145
+ You can add your credit balance to OpenAI at Settings > Billing:
146
+ https://platform.openai.com/settings/organization/billing/overview
147
+
148
+ I recommend you disable the automatic recharge!
149
+
150
+ 3. Create your API key
151
+
152
+ The webpage where you set up your OpenAI key is at https://platform.openai.com/api-keys - press the green 'Create new secret key' button and press 'Create secret key'. Keep a record of the API key somewhere private; you won't be able to retrieve it from the OpenAI screens in the future. It should start `sk-proj-`.
153
+
154
+ In week 2 we will also set up keys for Anthropic and Google, which you can do here when we get there.
155
+ - Claude API at https://console.anthropic.com/ from Anthropic
156
+ - Gemini API at https://ai.google.dev/gemini-api from Google
157
+
158
+ Later in the course you'll be using the fabulous HuggingFace platform; an account is available for free at https://huggingface.co - you can create an API token from the Avatar menu >> Settings >> Access Tokens.
159
+
160
+ And in Week 6/7 you'll be using the terrific Weights & Biases at https://wandb.ai to watch over your training batches. Accounts are also free, and you can set up a token in a similar way.
161
+
162
+ ### PART 4 - .env file
163
+
164
+ When you have these keys, please create a new file called `.env` in your project root directory. The filename needs to be exactly the four characters ".env" rather than "my-keys.env" or ".env.txt". Here's how to do it:
165
+
166
+ 1. Open Terminal (Applications > Utilities > Terminal)
167
+
168
+ 2. Navigate to the "project root directory" using `cd ~/Documents/Projects/llm_engineering` (replace this path with the actual path to the llm_engineering directory, your locally cloned version of the repo).
169
+
170
+ 3. Create the .env file with
171
+
172
+ nano .env
173
+
174
+ 4. Then type your API keys into nano, replacing xxxx with your API key (starting `sk-proj-`).
175
+
176
+ ```
177
+ OPENAI_API_KEY=xxxx
178
+ ```
179
+
180
+ If you have other keys, you can add them too, or come back to this in future weeks:
181
+ ```
182
+ GOOGLE_API_KEY=xxxx
183
+ ANTHROPIC_API_KEY=xxxx
184
+ DEEPSEEK_API_KEY=xxxx
185
+ HF_TOKEN=xxxx
186
+ ```
187
+
188
+ 5. Save the file:
189
+
190
+ Control + O
191
+ Enter (to confirm save the file)
192
+ Control + X to exit the editor
193
+
194
+ 6. Use this command to list files in your project root directory:
195
+
196
+ `ls -a`
197
+
198
+ And confirm that the `.env` file is there.
199
+
200
+ This file won't appear in Jupyter Lab because jupyter hides files starting with a dot. This file is listed in the `.gitignore` file, so it won't get checked in and your keys stay safe.
201
+
202
+ ### Part 5 - Showtime!!
203
+
204
+ 1. Open a terminal.
205
+ 2. Navigate to the "project root directory" using:
206
+ `cd ~/Projects/llm_engineering`.
207
+ 3. Activate your environment:
208
+ - If you used Anaconda: `conda activate llms`
209
+ - If you used the alternative: `source llms/bin/activate`
210
+
211
+ You should see `(llms)` in your prompt. Run: `jupyter lab` to get started.
212
+
213
+ Enjoy your journey into mastering AI and LLMs!
214
+
SETUP-linux.pdf ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:4c52d2037db403d46c3d8b8ad667d26889de95c0221a5c0ac5031914ff4a21ad
3
+ size 134097
SETUP-mac.md ADDED
@@ -0,0 +1,196 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # LLM Engineering - Master AI and LLMs
2
+
3
+ ## Setup instructions for Mac
4
+
5
+ Welcome, Mac people!
6
+
7
+ I should confess up-front: setting up a powerful environment to work at the forefront of AI is not as simple as I'd like. For most people these instructions will go great; but in some cases, for whatever reason, you'll hit a problem. Please don't hesitate to reach out - I am here to get you up and running quickly. There's nothing worse than feeling _stuck_. Message me, email me or LinkedIn message me and I will unstick you quickly!
8
+
9
10
+ LinkedIn: https://www.linkedin.com/in/eddonner/
11
+
12
+ I use a platform called Anaconda to set up your environment. It's a powerful tool that builds a complete science environment. Anaconda ensures that you're working with the right version of Python and all your packages are compatible with mine, even if our systems are completely different. It takes more time to set up, and it uses more hard drive space (5+ GB) but it's very reliable once its working.
13
+
14
+ Having said that: if you have any problems with Anaconda, I've provided an alternative approach. It's faster and simpler and should have you running quickly, with less of a guarantee around compatibility.
15
+
16
+ ### Before we begin
17
+
18
+ If you're less familiar with using the Terminal, please review this excellent [guide](https://chatgpt.com/canvas/shared/67b0b10c93a081918210723867525d2b) for some details and exercises.
19
+
20
+ If you're new to developing on your Mac, you may need to install XCode developer tools. Here are [instructions](https://chatgpt.com/share/67b0b8d7-8eec-8012-9a37-6973b9db11f5).
21
+
22
+ One "gotcha" to keep in mind: if you run anti-virus software, VPN or a Firewall, it might interfere with installations or network access. Please temporarily disable if you have problems.
23
+
24
+ ### Part 1: Clone the Repo
25
+
26
+ This gets you a local copy of the code on your box.
27
+
28
+ 1. **Install Git** if not already installed (it will be in most cases)
29
+
30
+ - Open Terminal (Applications > Utilities > Terminal)
31
+ - Type `git --version` If not installed, you'll be prompted to install it
32
+ - After the installation, you may need to open a new Terminal window to use it (or you might even need to restart)
33
+
34
+ 2. **Navigate to your projects folder:**
35
+
36
+ If you have a specific folder for projects, navigate to it using the cd command. For example:
37
+ `cd ~/Documents/Projects`
38
+
39
+ If you don't have a projects folder, you can create one:
40
+ ```
41
+ mkdir ~/Documents/Projects
42
+ cd ~/Documents/Projects
43
+ ```
44
+
45
+ 3. **Clone the repository:**
46
+
47
+ Enter this in the terminal in the Projects folder:
48
+
49
+ `git clone https://github.com/ed-donner/llm_engineering.git`
50
+
51
+ This creates a new directory `llm_engineering` within your Projects folder and downloads the code for the class. Do `cd llm_engineering` to go into it. This `llm_engineering` directory is known as the "project root directory".
52
+
53
+ ### Part 2: Install Anaconda environment
54
+
55
+ If this Part 2 gives you any problems, there is an alternative Part 2B below that can be used instead.
56
+
57
+ 1. **Install Anaconda:**
58
+
59
+ - Download Anaconda from https://docs.anaconda.com/anaconda/install/mac-os/
60
+ - Double-click the downloaded file and follow the installation prompts. Note that it takes up several GB and take a while to install, but it will be a powerful platform for you to use in the future.
61
+ - After installing, you'll need to open a fresh, new Terminal to be able to use it (and you might even need to restart).
62
+
63
+ 2. **Set up the environment:**
64
+
65
+ - Open a **new** Terminal (Applications > Utilities > Terminal)
66
+ - Navigate to the "project root directory" using `cd ~/Documents/Projects/llm_engineering` (replace this path as needed with the actual path to the llm_engineering directory, your locally cloned version of the repo). Do `ls` and check you can see subdirectories for each week of the course.
67
+ - Create the environment: `conda env create -f environment.yml`
68
+ - Wait for a few minutes for all packages to be installed - in some cases, this can literally take 20-30 minutes if you've not used Anaconda before, and even longer depending on your internet connection. Important stuff is happening! If this runs for more than 1 hour 15 mins, or gives you other problems, please go to Part 2B instead.
69
+ - You have now built an isolated, dedicated AI environment for engineering LLMs, running vector datastores, and so much more! You now need to **activate** it using this command: `conda activate llms`
70
+
71
+ You should see `(llms)` in your prompt, which indicates you've activated your new environment.
72
+
73
+ 3. **Start Jupyter Lab:**
74
+
75
+ - In the Terminal window, from within the `llm_engineering` folder, type: `jupyter lab`
76
+
77
+ ...and Jupyter Lab should open up in a browser. If you've not seen Jupyter Lab before, I'll explain it in a moment! Now close the jupyter lab browser tab, and close the Terminal, and move on to Part 3.
78
+
79
+ ### Part 2B - Alternative to Part 2 if Anaconda gives you trouble
80
+
81
+ 1. **Open a new Terminal** (Applications > Utilities > Terminal)
82
+
83
+ Run `python --version` to find out which python you're on.
84
+ Ideally you'd be using a version of Python 3.11, so we're completely in sync.
85
+ I believe Python 3.12 works also, but (as of Feb 2025) Python 3.13 does **not** yet work as several Data Science dependencies are not yet ready for Python 3.13.
86
+ If you need to install Python or install another version, you can download it here:
87
+ https://www.python.org/downloads/
88
+
89
+ 2. Navigate to the "project root directory" using `cd ~/Documents/Projects/llm_engineering` (replace this path with the actual path to the llm_engineering directory, your locally cloned version of the repo). Do `ls` and check you can see subdirectories for each week of the course.
90
+
91
+ Then, create a new virtual environment with this command:
92
+ `python -m venv llms`
93
+
94
+ 3. Activate the virtual environment with
95
+ `source llms/bin/activate`
96
+ You should see (llms) in your command prompt, which is your sign that things are going well.
97
+
98
+ 4. Run `python -m pip install --upgrade pip` followed by `pip install -r requirements.txt`
99
+ This may take a few minutes to install.
100
+ In the very unlikely event that this doesn't go well, you should try the bullet-proof (but slower) version:
101
+ `pip install --retries 5 --timeout 15 --no-cache-dir --force-reinstall -r requirements.txt`
102
+
103
+ 5. **Start Jupyter Lab:**
104
+
105
+ From within the `llm_engineering` folder, type: `jupyter lab`
106
+ ...and Jupyter Lab should open up, ready for you to get started. Open the `week1` folder and double click on `day1.ipynb`. Success! Now close down jupyter lab and move on to Part 3.
107
+
108
+ If there are any problems, contact me!
109
+
110
+ ### Part 3 - OpenAI key (OPTIONAL but recommended)
111
+
112
+ Particularly during weeks 1 and 2 of the course, you'll be writing code to call the APIs of Frontier models (models at the forefront of AI).
113
+
114
+ For week 1, you'll only need OpenAI, and you can add the others if you wish later on.
115
+
116
+ 1. Create an OpenAI account if you don't have one by visiting:
117
+ https://platform.openai.com/
118
+
119
+ 2. OpenAI asks for a minimum credit to use the API. For me in the US, it's \$5. The API calls will spend against this \$5. On this course, we'll only use a small portion of this. I do recommend you make the investment as you'll be able to put it to excellent use. But if you'd prefer not to pay for the API, I give you an alternative in the course using Ollama.
120
+
121
+ You can add your credit balance to OpenAI at Settings > Billing:
122
+ https://platform.openai.com/settings/organization/billing/overview
123
+
124
+ I recommend you disable the automatic recharge!
125
+
126
+ 3. Create your API key
127
+
128
+ The webpage where you set up your OpenAI key is at https://platform.openai.com/api-keys - press the green 'Create new secret key' button and press 'Create secret key'. Keep a record of the API key somewhere private; you won't be able to retrieve it from the OpenAI screens in the future. It should start `sk-proj-`.
129
+
130
+ In week 2 we will also set up keys for Anthropic and Google, which you can do here when we get there.
131
+ - Claude API at https://console.anthropic.com/ from Anthropic
132
+ - Gemini API at https://ai.google.dev/gemini-api from Google
133
+
134
+ Later in the course you'll be using the fabulous HuggingFace platform; an account is available for free at https://huggingface.co - you can create an API token from the Avatar menu >> Settings >> Access Tokens.
135
+
136
+ And in Week 6/7 you'll be using the terrific Weights & Biases at https://wandb.ai to watch over your training batches. Accounts are also free, and you can set up a token in a similar way.
137
+
138
+ ### PART 4 - .env file
139
+
140
+ When you have these keys, please create a new file called `.env` in your project root directory. The filename needs to be exactly the four characters ".env" rather than "my-keys.env" or ".env.txt". Here's how to do it:
141
+
142
+ 1. Open Terminal (Applications > Utilities > Terminal)
143
+
144
+ 2. Navigate to the "project root directory" using `cd ~/Documents/Projects/llm_engineering` (replace this path with the actual path to the llm_engineering directory, your locally cloned version of the repo).
145
+
146
+ 3. Create the .env file with
147
+
148
+ nano .env
149
+
150
+ 4. Then type your API keys into nano, replacing xxxx with your API key (starting `sk-proj-`).
151
+
152
+ ```
153
+ OPENAI_API_KEY=xxxx
154
+ ```
155
+
156
+ If you have other keys, you can add them too, or come back to this in future weeks:
157
+ ```
158
+ GOOGLE_API_KEY=xxxx
159
+ ANTHROPIC_API_KEY=xxxx
160
+ DEEPSEEK_API_KEY=xxxx
161
+ HF_TOKEN=xxxx
162
+ ```
163
+
164
+ 5. Save the file:
165
+
166
+ Control + O
167
+ Enter (to confirm save the file)
168
+ Control + X to exit the editor
169
+
170
+ 6. Use this command to list files in your project root directory:
171
+
172
+ `ls -a`
173
+
174
+ And confirm that the `.env` file is there.
175
+
176
+ This file won't appear in Jupyter Lab because jupyter hides files starting with a dot. This file is listed in the `.gitignore` file, so it won't get checked in and your keys stay safe.
177
+
178
+ ### Part 5 - Showtime!!
179
+
180
+ - Open Terminal (Applications > Utilities > Terminal)
181
+
182
+ - Navigate to the "project root directory" using `cd ~/Documents/Projects/llm_engineering` (replace this path with the actual path to the llm_engineering directory, your locally cloned version of the repo). Do `ls` and check you can see subdirectories for each week of the course.
183
+
184
+ - Activate your environment with `conda activate llms` (or `source llms/bin/activate` if you used the alternative approach in Part 2B)
185
+
186
+ - You should see (llms) in your prompt which is your sign that all is well. And now, type: `jupyter lab` and Jupyter Lab should open up, ready for you to get started. Open the `week1` folder and double click on `day1.ipynb`.
187
+
188
+ And you're off to the races!
189
+
190
+ Note that any time you start jupyter lab in the future, you'll need to follow these Part 5 instructions to start it from within the `llm_engineering` directory with the `llms` environment activated.
191
+
192
+ For those new to Jupyter Lab / Jupyter Notebook, it's a delightful Data Science environment where you can simply hit shift+return in any cell to run it; start at the top and work your way down! I've included a notebook called 'Guide to Jupyter' that shows you more features. When we move to Google Colab in Week 3, you'll experience the same interface for Python runtimes in the cloud.
193
+
194
+ If you have any problems, I've included a notebook in week1 called [troubleshooting.ipynb](week1/troubleshooting.ipynb) to figure it out.
195
+
196
+ Please do message me or email me at [email protected] if this doesn't work or if I can help with anything. I can't wait to hear how you get on.
SETUP-mac.pdf ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:024c05d8f578d1098029760053fc5dcd29d92ee8b1f4b4950dd0f9cf41e6156c
3
+ size 147551
business.jpg ADDED

Git LFS Details

  • SHA256: 630153df7afd567ed77983b67d83d2dce67d7c339e23bbc9631a740daeef9958
  • Pointer size: 131 Bytes
  • Size of remote file: 376 kB
community-contributions/playwright-bojan/Playwright_Solution_JupyterAsync.ipynb ADDED
@@ -0,0 +1,173 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "markdown",
5
+ "id": "aa629e55-8f41-41ab-b319-b55dd1cfc76b",
6
+ "metadata": {},
7
+ "source": [
8
+ "# Playwright Scraper Showcase (Async in Jupyter)\n",
9
+ "\n",
10
+ "This notebook demonstrates how to run async Playwright-based scraping code inside JupyterLab using `nest_asyncio`.\n",
11
+ "\n",
12
+ "**Note:** Requires `openai_scraper_playwright.py` to be in the same directory."
13
+ ]
14
+ },
15
+ {
16
+ "cell_type": "code",
17
+ "execution_count": 1,
18
+ "id": "97469777",
19
+ "metadata": {},
20
+ "outputs": [],
21
+ "source": [
22
+ "import nest_asyncio\n",
23
+ "import asyncio\n",
24
+ "nest_asyncio.apply()"
25
+ ]
26
+ },
27
+ {
28
+ "cell_type": "code",
29
+ "execution_count": 2,
30
+ "id": "6254fa89",
31
+ "metadata": {},
32
+ "outputs": [],
33
+ "source": [
34
+ "from openai_scraper_playwright import EnhancedOpenAIScraper, analyze_content"
35
+ ]
36
+ },
37
+ {
38
+ "cell_type": "code",
39
+ "execution_count": 3,
40
+ "id": "33d2737b",
41
+ "metadata": {},
42
+ "outputs": [
43
+ {
44
+ "name": "stdout",
45
+ "output_type": "stream",
46
+ "text": [
47
+ "### 1. Overall Summary of the Website:\n",
48
+ "The website appears to be a hub for various applications of AI technology, particularly focusing on the capabilities of ChatGPT and other AI models developed by OpenAI. It offers a range of services from answering queries, assisting in planning trips, explaining technical topics, helping with language translation, and providing educational content. The site also features updates on new AI models, research publications, and business solutions integrating AI.\n",
49
+ "\n",
50
+ "### 2. Key Individuals or Entities:\n",
51
+ "- **OpenAI**: Mentioned as the organization behind the development of AI models and technologies such as ChatGPT, GPT-4.1, and image generation models. OpenAI seems to be focused on advancing and applying AI in various fields.\n",
52
+ "- **Lyndon Barrois & Sora**: Featured in a story, possibly highlighting individual experiences or contributions within the OpenAI ecosystem.\n",
53
+ "\n",
54
+ "### 3. Recent Announcements or Updates:\n",
55
+ "- **Introducing our latest image generation model in the API** (Product, Apr 23, 2025)\n",
56
+ "- **Thinking with images** (Release, Apr 16, 2025)\n",
57
+ "- **OpenAI announces nonprofit commission advisors** (Company, Apr 15, 2025)\n",
58
+ "- **Our updated Preparedness Framework** (Publication, Apr 15, 2025)\n",
59
+ "- **BrowseComp: a benchmark for browsing agents** (Publication, Apr 10, 2025)\n",
60
+ "- **OpenAI Pioneers Program** (Company, Apr 9, 2025)\n",
61
+ "\n",
62
+ "### 4. Main Topics or Themes:\n",
63
+ "- **AI Model Development and Application**: Discusses various AI models like ChatGPT, GPT-4.1, and image generation models.\n",
64
+ "- **Educational and Practical AI Uses**: Offers help in educational topics, practical tasks, and creative endeavors using AI.\n",
65
+ "- **Business Integration**: Focuses on integrating AI into business processes, automating tasks in finance, legal, and other sectors.\n",
66
+ "- **Research and Publications**: Shares updates on the latest research and publications related to AI technology.\n",
67
+ "\n",
68
+ "### 5. Any Noteworthy Features or Projects:\n",
69
+ "- **GPT-4.1 and Image Generation Models**: Introduction of new and advanced AI models for text and image processing.\n",
70
+ "- **OpenAI Pioneers Program**: A significant initiative likely aimed at fostering innovation and practical applications of AI technology.\n",
71
+ "- **BrowseComp and PaperBench**: Research projects or benchmarks designed to evaluate and improve AI capabilities in specific domains.\n"
72
+ ]
73
+ }
74
+ ],
75
+ "source": [
76
+ "result = asyncio.run(analyze_content())\n",
77
+ "print(result)"
78
+ ]
79
+ },
80
+ {
81
+ "cell_type": "markdown",
82
+ "id": "d7450ccf",
83
+ "metadata": {},
84
+ "source": [
85
+ "✅ If you see structured analysis above, the async code ran successfully in Jupyter!"
86
+ ]
87
+ },
88
+ {
89
+ "cell_type": "markdown",
90
+ "id": "9a46716c-6f77-4b2b-b423-cc9fe05014da",
91
+ "metadata": {},
92
+ "source": [
93
+ "# 🧪 Playwright Scraper Output (Formatted)\n",
94
+ "\n",
95
+ "---\n",
96
+ "\n",
97
+ "## 🧭 1. **Overall Summary of the Website**\n",
98
+ "\n",
99
+ "*The website appears to be focused on showcasing various applications and updates related to OpenAI's technology, specifically ChatGPT and other AI tools. It provides information on product releases, company updates, and educational content on how to use AI technologies in different scenarios such as planning trips, learning games, coding, and more.*\n",
100
+ "\n",
101
+ "---\n",
102
+ "\n",
103
+ "## 🧑‍💼 2. **Key Individuals or Entities**\n",
104
+ "\n",
105
+ "- **OpenAI** — Company behind the technologies and updates discussed on the website \n",
106
+ "- **Lyndon Barrois & Sora** — Featured in a story, possibly highlighting user experiences or contributions\n",
107
+ "\n",
108
+ "---\n",
109
+ "\n",
110
+ "## 📰 3. **Recent Announcements or Updates**\n",
111
+ "\n",
112
+ "- 📢 **Introducing GPT-4.1 in the API** — *(no date provided)*\n",
113
+ "- 🖼️ **Introducing 4o Image Generation** — *(no date provided)*\n",
114
+ "- 🐟 **Catching halibut with ChatGPT** — *(no date provided)*\n",
115
+ "- 🧠 **Thinking with images** — *Apr 16, 2025*\n",
116
+ "- 🧑‍⚖️ **Nonprofit commission advisors announced** — *Apr 15, 2025*\n",
117
+ "- ⚙️ **Updated Preparedness Framework** — *Apr 15, 2025*\n",
118
+ "- 🌐 **BrowseComp benchmark for browsing agents** — *Apr 10, 2025*\n",
119
+ "- 🚀 **OpenAI Pioneers Program launched** — *Apr 9, 2025*\n",
120
+ "- 📊 **PaperBench research benchmark published** — *Apr 2, 2025*\n",
121
+ "\n",
122
+ "---\n",
123
+ "\n",
124
+ "## 📚 4. **Main Topics or Themes**\n",
125
+ "\n",
126
+ "- 🤖 **AI Technology Applications** — Using AI for tasks like planning, learning, and troubleshooting \n",
127
+ "- 🧩 **Product and Feature Releases** — Updates on new capabilities \n",
128
+ "- 📘 **Educational Content** — Guides for using AI effectively \n",
129
+ "- 🧪 **Research and Development** — Publications and technical benchmarks\n",
130
+ "\n",
131
+ "---\n",
132
+ "\n",
133
+ "## ⭐ 5. **Noteworthy Features or Projects**\n",
134
+ "\n",
135
+ "- ✅ **GPT-4.1** — A new API-accessible version of the language model \n",
136
+ "- 🖼️ **4o Image Generation** — Feature focused on AI-generated images \n",
137
+ "- 🚀 **OpenAI Pioneers Program** — Initiative likely fostering innovation in AI \n",
138
+ "- 📊 **BrowseComp & PaperBench** — Benchmarks for evaluating AI agents\n",
139
+ "\n",
140
+ "---\n",
141
+ "\n",
142
+ "✅ *If you're reading this inside Jupyter and seeing clean structure — your async notebook setup is working beautifully.*\n"
143
+ ]
144
+ },
145
+ {
146
+ "cell_type": "markdown",
147
+ "id": "95c38374-5daa-487c-8bd9-919bb4037ea3",
148
+ "metadata": {},
149
+ "source": []
150
+ }
151
+ ],
152
+ "metadata": {
153
+ "kernelspec": {
154
+ "display_name": "Python 3 (ipykernel)",
155
+ "language": "python",
156
+ "name": "python3"
157
+ },
158
+ "language_info": {
159
+ "codemirror_mode": {
160
+ "name": "ipython",
161
+ "version": 3
162
+ },
163
+ "file_extension": ".py",
164
+ "mimetype": "text/x-python",
165
+ "name": "python",
166
+ "nbconvert_exporter": "python",
167
+ "pygments_lexer": "ipython3",
168
+ "version": "3.12.7"
169
+ }
170
+ },
171
+ "nbformat": 4,
172
+ "nbformat_minor": 5
173
+ }
community-contributions/playwright-bojan/Playwright_Solution_Showcase_Formatted.ipynb ADDED
@@ -0,0 +1,69 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "markdown",
5
+ "id": "3df9df94",
6
+ "metadata": {},
7
+ "source": [
8
+ "# 🧪 Playwright Scraper Output (Formatted)\n",
9
+ "\n",
10
+ "---\n",
11
+ "\n",
12
+ "## 🧭 1. **Overall Summary of the Website**\n",
13
+ "\n",
14
+ "*The website appears to be focused on showcasing various applications and updates related to OpenAI's technology, specifically ChatGPT and other AI tools. It provides information on product releases, company updates, and educational content on how to use AI technologies in different scenarios such as planning trips, learning games, coding, and more.*\n",
15
+ "\n",
16
+ "---\n",
17
+ "\n",
18
+ "## 🧑‍💼 2. **Key Individuals or Entities**\n",
19
+ "\n",
20
+ "- **OpenAI** — Company behind the technologies and updates discussed on the website \n",
21
+ "- **Lyndon Barrois & Sora** — Featured in a story, possibly highlighting user experiences or contributions\n",
22
+ "\n",
23
+ "---\n",
24
+ "\n",
25
+ "## 📰 3. **Recent Announcements or Updates**\n",
26
+ "\n",
27
+ "- 📢 **Introducing GPT-4.1 in the API** — *(no date provided)*\n",
28
+ "- 🖼️ **Introducing 4o Image Generation** — *(no date provided)*\n",
29
+ "- 🐟 **Catching halibut with ChatGPT** — *(no date provided)*\n",
30
+ "- 🧠 **Thinking with images** — *Apr 16, 2025*\n",
31
+ "- 🧑‍⚖️ **Nonprofit commission advisors announced** — *Apr 15, 2025*\n",
32
+ "- ⚙️ **Updated Preparedness Framework** — *Apr 15, 2025*\n",
33
+ "- 🌐 **BrowseComp benchmark for browsing agents** — *Apr 10, 2025*\n",
34
+ "- 🚀 **OpenAI Pioneers Program launched** — *Apr 9, 2025*\n",
35
+ "- 📊 **PaperBench research benchmark published** — *Apr 2, 2025*\n",
36
+ "\n",
37
+ "---\n",
38
+ "\n",
39
+ "## 📚 4. **Main Topics or Themes**\n",
40
+ "\n",
41
+ "- 🤖 **AI Technology Applications** — Using AI for tasks like planning, learning, and troubleshooting \n",
42
+ "- 🧩 **Product and Feature Releases** — Updates on new capabilities \n",
43
+ "- 📘 **Educational Content** — Guides for using AI effectively \n",
44
+ "- 🧪 **Research and Development** — Publications and technical benchmarks\n",
45
+ "\n",
46
+ "---\n",
47
+ "\n",
48
+ "## ⭐ 5. **Noteworthy Features or Projects**\n",
49
+ "\n",
50
+ "- ✅ **GPT-4.1** — A new API-accessible version of the language model \n",
51
+ "- 🖼️ **4o Image Generation** — Feature focused on AI-generated images \n",
52
+ "- 🚀 **OpenAI Pioneers Program** — Initiative likely fostering innovation in AI \n",
53
+ "- 📊 **BrowseComp & PaperBench** — Benchmarks for evaluating AI agents\n",
54
+ "\n",
55
+ "---\n",
56
+ "\n",
57
+ "✅ *If you're reading this inside Jupyter and seeing clean structure — your async notebook setup is working beautifully.*\n"
58
+ ]
59
+ }
60
+ ],
61
+ "metadata": {
62
+ "kernelspec": {
63
+ "display_name": "Python 3",
64
+ "name": "python3"
65
+ }
66
+ },
67
+ "nbformat": 4,
68
+ "nbformat_minor": 5
69
+ }
community-contributions/playwright-bojan/README.md ADDED
@@ -0,0 +1,67 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # 🧠 Community Contribution: Async Playwright-based OpenAI Scraper
2
+
3
+ This contribution presents a fully asynchronous, headless-browser-based scraper for [https://openai.com](https://openai.com) using **Playwright** — an alternative to Selenium.
4
+
5
+ Developed by: [lakovicb](https://github.com/lakovicb)
6
+ IDE used: WingIDE Pro (Jupyter compatibility via `nest_asyncio`)
7
+
8
+ ---
9
+
10
+ ## 📦 Features
11
+
12
+ - 🧭 Simulates human-like interactions (mouse movement, scrolling)
13
+ - 🧠 GPT-based analysis using OpenAI's API
14
+ - 🧪 Works inside **JupyterLab** using `nest_asyncio`
15
+ - 📊 Prometheus metrics for scraping observability
16
+ - ⚡ Smart content caching via `diskcache`
17
+
18
+ ---
19
+
20
+ ## 🚀 How to Run
21
+
22
+ ### 1. Install dependencies
23
+
24
+ ```bash
25
+ pip install -r requirements.txt
26
+ ```
27
+
28
+ > Ensure [Playwright is installed & browsers are downloaded](https://playwright.dev/python/docs/intro)
29
+
30
+ ```bash
31
+ playwright install
32
+ ```
33
+
34
+ ### 2. Set environment variables in `.env`
35
+
36
+ ```env
37
+ OPENAI_API_KEY=your_openai_key
38
+ BROWSER_PATH=/usr/bin/chromium-browser
39
+ ```
40
+
41
+ You can also define optional proxy/login params if needed.
42
+
43
+ ---
44
+
45
+ ## 📘 Notebooks Included
46
+
47
+ | Notebook | Description |
48
+ |----------|-------------|
49
+ | `Playwright_Solution_JupyterAsync.ipynb` | Executes async scraper directly inside Jupyter |
50
+ | `Playwright_Solution_Showcase_Formatted.ipynb` | Nicely formatted output for human reading |
51
+
52
+ ---
53
+
54
+ ## 🔁 Output Example
55
+
56
+ - GPT-generated summary
57
+ - Timeline of updates
58
+ - Entities and projects mentioned
59
+ - Structured topics & themes
60
+
61
+ ✅ *Can be extended with PDF export, LangChain pipeline, or vector store ingestion.*
62
+
63
+ ---
64
+
65
+ ## 🙏 Thanks
66
+
67
+ Huge thanks to Ed Donner for the amazing course and challenge inspiration!
community-contributions/playwright-bojan/openai_scraper_playwright.py ADDED
@@ -0,0 +1,141 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # openai_scraper_playwright.py
2
+
3
+ import asyncio
4
+ from playwright.async_api import async_playwright
5
+ from openai import OpenAI
6
+ import logging
7
+ import random
8
+ import time
9
+ import os
10
+ from prometheus_client import start_http_server, Counter, Histogram
11
+ from diskcache import Cache
12
+ from dotenv import load_dotenv
13
+
14
+ load_dotenv()
15
+
16
+ SCRAPE_ATTEMPTS = Counter('scrape_attempts', 'Total scraping attempts')
17
+ SCRAPE_DURATION = Histogram('scrape_duration', 'Scraping duration distribution')
18
+ cache = Cache('./scraper_cache')
19
+
20
+ class ScrapingError(Exception): pass
21
+ class ContentAnalysisError(Exception): pass
22
+
23
+ class EnhancedOpenAIScraper:
24
+ API_KEY = os.getenv("OPENAI_API_KEY")
25
+ BROWSER_EXECUTABLE = os.getenv("BROWSER_PATH", "/usr/bin/chromium-browser")
26
+ MAX_CONTENT_LENGTH = int(os.getenv("MAX_CONTENT_LENGTH", 30000))
27
+
28
+ def __init__(self, headless=True):
29
+ self.user_agents = [
30
+ "Mozilla/5.0 (Windows NT 10.0; Win64; x64)...",
31
+ "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)..."
32
+ ]
33
+ self.timeout = 45000
34
+ self.retry_count = int(os.getenv("RETRY_COUNT", 2))
35
+ self.headless = headless
36
+ self.proxy_servers = [x.strip() for x in os.getenv("PROXY_SERVERS", "").split(',') if x.strip()]
37
+
38
+ async def human_interaction(self, page):
39
+ for _ in range(random.randint(2, 5)):
40
+ x, y = random.randint(0, 1366), random.randint(0, 768)
41
+ await page.mouse.move(x, y, steps=random.randint(5, 20))
42
+ await page.wait_for_timeout(random.randint(50, 200))
43
+
44
+ if random.random() < 0.3:
45
+ await page.keyboard.press('Tab')
46
+ await page.keyboard.type(' ', delay=random.randint(50, 200))
47
+
48
+ await page.mouse.wheel(0, random.choice([300, 600, 900]))
49
+ await page.wait_for_timeout(random.randint(500, 2000))
50
+
51
+ async def load_page(self, page, url):
52
+ try:
53
+ await page.goto(url, wait_until="domcontentloaded", timeout=self.timeout)
54
+ selectors = ['main article', '#main-content', 'section:first-of-type', 'div[class*="content"]', 'body']
55
+ for selector in selectors:
56
+ if await page.query_selector(selector):
57
+ return True
58
+ await page.wait_for_timeout(5000)
59
+ return True
60
+ except Exception as e:
61
+ logging.error(f"Error loading page {url}: {e}")
62
+ return False
63
+
64
+ @SCRAPE_DURATION.time()
65
+ async def scrape_with_retry(self, url):
66
+ SCRAPE_ATTEMPTS.inc()
67
+ last_error = None
68
+ try:
69
+ async with async_playwright() as p:
70
+ args = {
71
+ "headless": self.headless,
72
+ "args": ["--disable-blink-features=AutomationControlled", "--no-sandbox"],
73
+ "executable_path": self.BROWSER_EXECUTABLE
74
+ }
75
+ browser = await p.chromium.launch(**args)
76
+ context = await browser.new_context(user_agent=random.choice(self.user_agents))
77
+ page = await context.new_page()
78
+ await page.add_init_script("""
79
+ Object.defineProperty(navigator, 'webdriver', { get: () => false });
80
+ """)
81
+
82
+ for attempt in range(self.retry_count):
83
+ try:
84
+ if not await self.load_page(page, url):
85
+ raise ScrapingError("Failed to load page")
86
+ await self.human_interaction(page)
87
+ content = await page.evaluate("""() => document.body.innerText""")
88
+ if not content.strip():
89
+ raise ContentAnalysisError("No content extracted")
90
+ await browser.close()
91
+ return content[:self.MAX_CONTENT_LENGTH]
92
+ except Exception as e:
93
+ last_error = e
94
+ if attempt < self.retry_count - 1:
95
+ await asyncio.sleep(5)
96
+ else:
97
+ await browser.close()
98
+ raise
99
+ except Exception as e:
100
+ raise last_error or e
101
+
102
+ async def get_cached_content(self, url):
103
+ key = 'cache_' + url.replace('https://', '').replace('/', '_')
104
+ content = cache.get(key)
105
+ if content is None:
106
+ content = await self.scrape_with_retry(url)
107
+ cache.set(key, content, expire=int(os.getenv("CACHE_EXPIRY", 3600)))
108
+ return content
109
+
110
+ async def analyze_content(url="https://openai.com", headless=True):
111
+ scraper = EnhancedOpenAIScraper(headless=headless)
112
+ content = await scraper.get_cached_content(url)
113
+ client = OpenAI(api_key=EnhancedOpenAIScraper.API_KEY)
114
+ if not client.api_key:
115
+ raise ContentAnalysisError("OpenAI API key not configured")
116
+
117
+ prompt = f"""
118
+ Analyze this page:
119
+
120
+ {content}
121
+ """
122
+ model = os.getenv("OPENAI_MODEL", "gpt-4-turbo")
123
+ temperature = float(os.getenv("MODEL_TEMPERATURE", 0.3))
124
+ max_tokens = int(os.getenv("MAX_TOKENS", 1500))
125
+ top_p = float(os.getenv("MODEL_TOP_P", 0.9))
126
+
127
+ response = client.chat.completions.create(
128
+ model=model,
129
+ messages=[
130
+ {"role": "system", "content": "You are a content analyst."},
131
+ {"role": "user", "content": prompt}
132
+ ],
133
+ temperature=temperature,
134
+ max_tokens=max_tokens,
135
+ top_p=top_p
136
+ )
137
+
138
+ if not response.choices:
139
+ raise ContentAnalysisError("Empty response from GPT")
140
+
141
+ return response.choices[0].message.content
community-contributions/playwright-bojan/requirements.txt ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ playwright>=1.43.0
2
+ openai>=1.14.2
3
+ prometheus-client>=0.19.0
4
+ diskcache>=5.6.1
5
+ python-dotenv>=1.0.1
6
+ nest_asyncio>=1.6.0
diagnostics.ipynb ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "markdown",
5
+ "id": "73287ed4-81e3-496a-9e47-f0e8c3770ce9",
6
+ "metadata": {},
7
+ "source": [
8
+ "# Gathering Essential Diagnostic information\n",
9
+ "\n",
10
+ "## Please run this next cell to gather some important data\n",
11
+ "\n",
12
+ "Please run the next cell; it should take a minute or so to run (mostly the network test).\n",
13
+ "Rhen email me the output of the last cell to [email protected]. \n",
14
+ "Alternatively: this will create a file called report.txt - just attach the file to your email."
15
+ ]
16
+ },
17
+ {
18
+ "cell_type": "code",
19
+ "execution_count": null,
20
+ "id": "ed8056e8-efa2-4b6f-a4bb-e7ceb733c517",
21
+ "metadata": {},
22
+ "outputs": [],
23
+ "source": [
24
+ "# Run my diagnostics report to collect key information for debugging\n",
25
+ "# Please email me the results. Either copy & paste the output, or attach the file report.txt\n",
26
+ "\n",
27
+ "!pip install -q requests speedtest-cli psutil setuptools\n",
28
+ "from diagnostics import Diagnostics\n",
29
+ "Diagnostics().run()"
30
+ ]
31
+ }
32
+ ],
33
+ "metadata": {
34
+ "kernelspec": {
35
+ "display_name": "Python 3 (ipykernel)",
36
+ "language": "python",
37
+ "name": "python3"
38
+ },
39
+ "language_info": {
40
+ "codemirror_mode": {
41
+ "name": "ipython",
42
+ "version": 3
43
+ },
44
+ "file_extension": ".py",
45
+ "mimetype": "text/x-python",
46
+ "name": "python",
47
+ "nbconvert_exporter": "python",
48
+ "pygments_lexer": "ipython3",
49
+ "version": "3.11.10"
50
+ }
51
+ },
52
+ "nbformat": 4,
53
+ "nbformat_minor": 5
54
+ }
diagnostics.py ADDED
@@ -0,0 +1,419 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import sys
3
+ import platform
4
+ import subprocess
5
+ import shutil
6
+ import time
7
+ import ssl
8
+ import tempfile
9
+ from pathlib import Path
10
+ from datetime import datetime
11
+
12
+ class Diagnostics:
13
+
14
+ FILENAME = 'report.txt'
15
+
16
+ def __init__(self):
17
+ self.errors = []
18
+ self.warnings = []
19
+ if os.path.exists(self.FILENAME):
20
+ os.remove(self.FILENAME)
21
+
22
+ def log(self, message):
23
+ print(message)
24
+ with open(self.FILENAME, 'a', encoding='utf-8') as f:
25
+ f.write(message + "\n")
26
+
27
+ def start(self):
28
+ now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
29
+ self.log(f"Starting diagnostics at {now}\n")
30
+
31
+ def end(self):
32
+ now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
33
+ self.log(f"\n\nCompleted diagnostics at {now}\n")
34
+ print("\nPlease send these diagnostics to me at [email protected]")
35
+ print(f"Either copy & paste the above output into an email, or attach the file {self.FILENAME} that has been created in this directory.")
36
+
37
+
38
+ def _log_error(self, message):
39
+ self.log(f"ERROR: {message}")
40
+ self.errors.append(message)
41
+
42
+ def _log_warning(self, message):
43
+ self.log(f"WARNING: {message}")
44
+ self.warnings.append(message)
45
+
46
+ def run(self):
47
+ self.start()
48
+ self._step1_system_info()
49
+ self._step2_check_files()
50
+ self._step3_git_repo()
51
+ self._step4_check_env_file()
52
+ self._step5_anaconda_check()
53
+ self._step6_virtualenv_check()
54
+ self._step7_network_connectivity()
55
+ self._step8_environment_variables()
56
+ self._step9_additional_diagnostics()
57
+
58
+ if self.warnings:
59
+ self.log("\n===== Warnings Found =====")
60
+ self.log("The following warnings were detected. They might not prevent the program from running but could cause unexpected behavior:")
61
+ for warning in self.warnings:
62
+ self.log(f"- {warning}")
63
+
64
+ if self.errors:
65
+ self.log("\n===== Errors Found =====")
66
+ self.log("The following critical issues were detected. Please address them before proceeding:")
67
+ for error in self.errors:
68
+ self.log(f"- {error}")
69
+
70
+ if not self.errors and not self.warnings:
71
+ self.log("\n✅ All diagnostics passed successfully!")
72
+
73
+ self.end()
74
+
75
+ def _step1_system_info(self):
76
+ self.log("===== System Information =====")
77
+ try:
78
+ system = platform.system()
79
+ self.log(f"Operating System: {system}")
80
+
81
+ if system == "Windows":
82
+ release, version, csd, ptype = platform.win32_ver()
83
+ self.log(f"Windows Release: {release}")
84
+ self.log(f"Windows Version: {version}")
85
+ elif system == "Darwin":
86
+ release, version, machine = platform.mac_ver()
87
+ self.log(f"MacOS Version: {release}")
88
+ else:
89
+ self.log(f"Platform: {platform.platform()}")
90
+
91
+ self.log(f"Architecture: {platform.architecture()}")
92
+ self.log(f"Machine: {platform.machine()}")
93
+ self.log(f"Processor: {platform.processor()}")
94
+
95
+ try:
96
+ import psutil
97
+ ram = psutil.virtual_memory()
98
+ total_ram_gb = ram.total / (1024 ** 3)
99
+ available_ram_gb = ram.available / (1024 ** 3)
100
+ self.log(f"Total RAM: {total_ram_gb:.2f} GB")
101
+ self.log(f"Available RAM: {available_ram_gb:.2f} GB")
102
+
103
+ if available_ram_gb < 2:
104
+ self._log_warning(f"Low available RAM: {available_ram_gb:.2f} GB")
105
+ except ImportError:
106
+ self._log_warning("psutil module not found. Cannot determine RAM information.")
107
+
108
+ total, used, free = shutil.disk_usage(os.path.expanduser("~"))
109
+ free_gb = free / (1024 ** 3)
110
+ self.log(f"Free Disk Space: {free_gb:.2f} GB")
111
+
112
+ if free_gb < 5:
113
+ self._log_warning(f"Low disk space: {free_gb:.2f} GB free")
114
+
115
+ except Exception as e:
116
+ self._log_error(f"System information check failed: {e}")
117
+
118
+ def _step2_check_files(self):
119
+ self.log("\n===== File System Information =====")
120
+ try:
121
+ current_dir = os.getcwd()
122
+ self.log(f"Current Directory: {current_dir}")
123
+
124
+ # Check write permissions
125
+ test_file = Path(current_dir) / ".test_write_permission"
126
+ try:
127
+ test_file.touch(exist_ok=True)
128
+ test_file.unlink()
129
+ self.log("Write permission: OK")
130
+ except Exception as e:
131
+ self._log_error(f"No write permission in current directory: {e}")
132
+
133
+ self.log("\nFiles in Current Directory:")
134
+ try:
135
+ for item in sorted(os.listdir(current_dir)):
136
+ self.log(f" - {item}")
137
+ except Exception as e:
138
+ self._log_error(f"Cannot list directory contents: {e}")
139
+
140
+ except Exception as e:
141
+ self._log_error(f"File system check failed: {e}")
142
+
143
+ def _step3_git_repo(self):
144
+ self.log("\n===== Git Repository Information =====")
145
+ try:
146
+ result = subprocess.run(['git', 'rev-parse', '--show-toplevel'],
147
+ stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
148
+ if result.returncode == 0:
149
+ git_root = result.stdout.strip()
150
+ self.log(f"Git Repository Root: {git_root}")
151
+
152
+ result = subprocess.run(['git', 'rev-parse', 'HEAD'],
153
+ stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
154
+ if result.returncode == 0:
155
+ self.log(f"Current Commit: {result.stdout.strip()}")
156
+ else:
157
+ self._log_warning(f"Could not get current commit: {result.stderr.strip()}")
158
+
159
+ result = subprocess.run(['git', 'remote', 'get-url', 'origin'],
160
+ stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
161
+ if result.returncode == 0:
162
+ self.log(f"Remote Origin: {result.stdout.strip()}")
163
+ else:
164
+ self._log_warning("No remote 'origin' configured")
165
+ else:
166
+ self._log_warning("Not a git repository")
167
+ except FileNotFoundError:
168
+ self._log_warning("Git is not installed or not in PATH")
169
+ except Exception as e:
170
+ self._log_error(f"Git check failed: {e}")
171
+
172
+ def _step4_check_env_file(self):
173
+ self.log("\n===== Environment File Check =====")
174
+ try:
175
+ result = subprocess.run(['git', 'rev-parse', '--show-toplevel'],
176
+ stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
177
+ if result.returncode == 0:
178
+ git_root = result.stdout.strip()
179
+ env_path = os.path.join(git_root, '.env')
180
+
181
+ if os.path.isfile(env_path):
182
+ self.log(f".env file exists at: {env_path}")
183
+ try:
184
+ with open(env_path, 'r') as f:
185
+ has_api_key = any(line.strip().startswith('OPENAI_API_KEY=') for line in f)
186
+ if has_api_key:
187
+ self.log("OPENAI_API_KEY found in .env file")
188
+ else:
189
+ self._log_warning("OPENAI_API_KEY not found in .env file")
190
+ except Exception as e:
191
+ self._log_error(f"Cannot read .env file: {e}")
192
+ else:
193
+ self._log_warning(".env file not found in project root")
194
+
195
+ # Check for additional .env files
196
+ for root, _, files in os.walk(git_root):
197
+ if '.env' in files and os.path.join(root, '.env') != env_path:
198
+ self._log_warning(f"Additional .env file found at: {os.path.join(root, '.env')}")
199
+ else:
200
+ self._log_warning("Git root directory not found. Cannot perform .env file check.")
201
+ except FileNotFoundError:
202
+ self._log_warning("Git is not installed or not in PATH")
203
+ except Exception as e:
204
+ self._log_error(f"Environment file check failed: {e}")
205
+
206
+ def _step5_anaconda_check(self):
207
+ self.log("\n===== Anaconda Environment Check =====")
208
+ try:
209
+ conda_prefix = os.environ.get('CONDA_PREFIX')
210
+ if conda_prefix:
211
+ self.log("Anaconda environment is active:")
212
+ self.log(f"Environment Path: {conda_prefix}")
213
+ self.log(f"Environment Name: {os.path.basename(conda_prefix)}")
214
+
215
+ conda_exe = os.environ.get('CONDA_EXE', 'conda')
216
+ result = subprocess.run([conda_exe, '--version'],
217
+ stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
218
+ if result.returncode == 0:
219
+ self.log(f"Conda Version: {result.stdout.strip()}")
220
+ else:
221
+ self._log_warning("Could not determine Conda version")
222
+
223
+ self._check_python_packages()
224
+ else:
225
+ self.log("No active Anaconda environment detected")
226
+ except Exception as e:
227
+ self._log_error(f"Anaconda environment check failed: {e}")
228
+
229
+ def _step6_virtualenv_check(self):
230
+ self.log("\n===== Virtualenv Check =====")
231
+ try:
232
+ virtual_env = os.environ.get('VIRTUAL_ENV')
233
+ if virtual_env:
234
+ self.log("Virtualenv is active:")
235
+ self.log(f"Environment Path: {virtual_env}")
236
+ self.log(f"Environment Name: {os.path.basename(virtual_env)}")
237
+
238
+ self._check_python_packages()
239
+ else:
240
+ self.log("No active virtualenv detected")
241
+
242
+ if not virtual_env and not os.environ.get('CONDA_PREFIX'):
243
+ self._log_warning("Neither virtualenv nor Anaconda environment is active")
244
+ except Exception as e:
245
+ self._log_error(f"Virtualenv check failed: {e}")
246
+
247
+ def _check_python_packages(self):
248
+ self.log("\nPython Environment:")
249
+ self.log(f"Python Version: {sys.version}")
250
+ self.log(f"Python Executable: {sys.executable}")
251
+
252
+ required_packages = ['openai', 'python-dotenv', 'requests', 'gradio', 'transformers']
253
+
254
+ try:
255
+ import pkg_resources
256
+ installed = {pkg.key: pkg.version for pkg in pkg_resources.working_set}
257
+
258
+ self.log("\nRequired Package Versions:")
259
+ for package in required_packages:
260
+ if package in installed:
261
+ self.log(f"{package}: {installed[package]}")
262
+ else:
263
+ self._log_error(f"Required package '{package}' is not installed")
264
+
265
+ # Check for potentially conflicting packages
266
+ problem_pairs = [
267
+ ('openai', 'openai-python'),
268
+ ('python-dotenv', 'dotenv')
269
+ ]
270
+
271
+ for pkg1, pkg2 in problem_pairs:
272
+ if pkg1 in installed and pkg2 in installed:
273
+ self._log_warning(f"Potentially conflicting packages: {pkg1} and {pkg2}")
274
+ except ImportError:
275
+ self._log_error("Could not import 'pkg_resources' to check installed packages")
276
+ except Exception as e:
277
+ self._log_error(f"Package check failed: {e}")
278
+
279
+ def _step7_network_connectivity(self):
280
+ self.log("\n===== Network Connectivity Check =====")
281
+ try:
282
+ self.log(f"SSL Version: {ssl.OPENSSL_VERSION}")
283
+
284
+ import requests
285
+ import speedtest # Importing the speedtest-cli library
286
+
287
+ # Basic connectivity check
288
+ urls = [
289
+ 'https://www.google.com',
290
+ 'https://www.cloudflare.com'
291
+ ]
292
+
293
+ connected = False
294
+ for url in urls:
295
+ try:
296
+ start_time = time.time()
297
+ response = requests.get(url, timeout=10)
298
+ elapsed_time = time.time() - start_time
299
+ response.raise_for_status()
300
+ self.log(f"✓ Connected to {url}")
301
+ self.log(f" Response time: {elapsed_time:.2f}s")
302
+
303
+ if elapsed_time > 2:
304
+ self._log_warning(f"Slow response from {url}: {elapsed_time:.2f}s")
305
+ connected = True
306
+ break
307
+ except requests.exceptions.RequestException as e:
308
+ self._log_warning(f"Failed to connect to {url}: {e}")
309
+ else:
310
+ self.log("Basic connectivity OK")
311
+
312
+ if not connected:
313
+ self._log_error("Failed to connect to any test URLs")
314
+ return
315
+
316
+ # Bandwidth test using speedtest-cli
317
+ self.log("\nPerforming bandwidth test using speedtest-cli...")
318
+ try:
319
+ st = speedtest.Speedtest()
320
+ st.get_best_server()
321
+ download_speed = st.download() # Bits per second
322
+ upload_speed = st.upload() # Bits per second
323
+
324
+ download_mbps = download_speed / 1e6 # Convert to Mbps
325
+ upload_mbps = upload_speed / 1e6
326
+
327
+ self.log(f"Download speed: {download_mbps:.2f} Mbps")
328
+ self.log(f"Upload speed: {upload_mbps:.2f} Mbps")
329
+
330
+ if download_mbps < 1:
331
+ self._log_warning("Download speed is low")
332
+ if upload_mbps < 0.5:
333
+ self._log_warning("Upload speed is low")
334
+ except speedtest.ConfigRetrievalError:
335
+ self._log_error("Failed to retrieve speedtest configuration")
336
+ except Exception as e:
337
+ self._log_warning(f"Bandwidth test failed: {e}")
338
+
339
+ except ImportError:
340
+ self._log_error("Required packages are not installed. Please install them using 'pip install requests speedtest-cli'")
341
+ except Exception as e:
342
+ self._log_error(f"Network connectivity check failed: {e}")
343
+
344
+
345
+ def _step8_environment_variables(self):
346
+ self.log("\n===== Environment Variables Check =====")
347
+ try:
348
+ # Check Python paths
349
+ pythonpath = os.environ.get('PYTHONPATH')
350
+ if pythonpath:
351
+ self.log("\nPYTHONPATH:")
352
+ for path in pythonpath.split(os.pathsep):
353
+ self.log(f" - {path}")
354
+ else:
355
+ self.log("\nPYTHONPATH is not set.")
356
+
357
+ self.log("\nPython sys.path:")
358
+ for path in sys.path:
359
+ self.log(f" - {path}")
360
+
361
+ # Check OPENAI_API_KEY
362
+ from dotenv import load_dotenv
363
+ load_dotenv()
364
+ api_key = os.environ.get('OPENAI_API_KEY')
365
+ if api_key:
366
+ self.log("OPENAI_API_KEY is set after calling load_dotenv()")
367
+ if not api_key.startswith('sk-proj-') or len(api_key)<12:
368
+ self._log_warning("OPENAI_API_KEY format looks incorrect after calling load_dotenv()")
369
+ else:
370
+ self._log_warning("OPENAI_API_KEY environment variable is not set after calling load_dotenv()")
371
+ except Exception as e:
372
+ self._log_error(f"Environment variables check failed: {e}")
373
+
374
+ def _step9_additional_diagnostics(self):
375
+ self.log("\n===== Additional Diagnostics =====")
376
+ try:
377
+ # Get the site-packages directory paths
378
+ import site
379
+ site_packages_paths = site.getsitepackages()
380
+ if hasattr(site, 'getusersitepackages'):
381
+ site_packages_paths.append(site.getusersitepackages())
382
+
383
+ # Function to check if a path is within site-packages
384
+ def is_in_site_packages(path):
385
+ return any(os.path.commonpath([path, sp]) == sp for sp in site_packages_paths)
386
+
387
+ # Check for potential name conflicts in the current directory and sys.path
388
+ conflict_names = ['openai.py', 'dotenv.py']
389
+
390
+ # Check current directory
391
+ current_dir = os.getcwd()
392
+ for name in conflict_names:
393
+ conflict_path = os.path.join(current_dir, name)
394
+ if os.path.isfile(conflict_path):
395
+ self._log_warning(f"Found '{name}' in the current directory, which may cause import conflicts: {conflict_path}")
396
+
397
+ # Check sys.path directories
398
+ for path in sys.path:
399
+ if not path or is_in_site_packages(path):
400
+ continue # Skip site-packages and empty paths
401
+ for name in conflict_names:
402
+ conflict_file = os.path.join(path, name)
403
+ if os.path.isfile(conflict_file):
404
+ self._log_warning(f"Potential naming conflict: {conflict_file}")
405
+
406
+ # Check temp directory
407
+ try:
408
+ with tempfile.NamedTemporaryFile() as tmp:
409
+ self.log(f"Temp directory is writable: {os.path.dirname(tmp.name)}")
410
+ except Exception as e:
411
+ self._log_error(f"Cannot write to temp directory: {e}")
412
+
413
+ except Exception as e:
414
+ self._log_error(f"Additional diagnostics failed: {e}")
415
+
416
+
417
+ if __name__ == "__main__":
418
+ diagnostics = Diagnostics()
419
+ diagnostics.run()
environment.yml ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ name: llms
2
+ channels:
3
+ - conda-forge
4
+ - defaults
5
+ dependencies:
6
+ - python=3.11
7
+ - pip
8
+ - python-dotenv
9
+ - requests
10
+ - numpy
11
+ - pandas
12
+ - scipy
13
+ - pytorch
14
+ - jupyterlab
15
+ - ipywidgets
16
+ - matplotlib
17
+ - scikit-learn
18
+ - chromadb
19
+ - jupyter-dash
20
+ - sentencepiece
21
+ - pyarrow
22
+ - faiss-cpu
23
+ - pip:
24
+ - beautifulsoup4
25
+ - plotly
26
+ - bitsandbytes
27
+ - transformers
28
+ - sentence-transformers
29
+ - datasets
30
+ - accelerate
31
+ - openai
32
+ - anthropic
33
+ - google-generativeai
34
+ - gradio
35
+ - gensim
36
+ - modal
37
+ - ollama
38
+ - psutil
39
+ - setuptools
40
+ - speedtest-cli
41
+ - langchain
42
+ - langchain-core
43
+ - langchain-text-splitters
44
+ - langchain-openai
45
+ - langchain-chroma
46
+ - langchain-community
47
+ - faiss-cpu
48
+ - feedparser
49
+ - twilio
50
+ - pydub
extras/community/prototype_signal.ipynb ADDED
@@ -0,0 +1,413 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "markdown",
5
+ "id": "7e2c4bbb-5e8b-4d84-9997-ecb2c349cf54",
6
+ "metadata": {},
7
+ "source": [
8
+ "## First step - generate training data from examples"
9
+ ]
10
+ },
11
+ {
12
+ "cell_type": "code",
13
+ "execution_count": 105,
14
+ "id": "16cf3aa2-f407-4b95-8b9e-c3c586f67835",
15
+ "metadata": {},
16
+ "outputs": [],
17
+ "source": [
18
+ "import requests\n",
19
+ "import pandas as pd\n",
20
+ "from datetime import datetime, timedelta,timezone\n",
21
+ "from datasets import load_dataset, Dataset\n",
22
+ "from dotenv import load_dotenv\n",
23
+ "import os\n",
24
+ "from openai import OpenAI\n",
25
+ "import json\n",
26
+ "import tiktoken\n",
27
+ "from IPython.display import display, Markdown\n",
28
+ "\n"
29
+ ]
30
+ },
31
+ {
32
+ "cell_type": "code",
33
+ "execution_count": 96,
34
+ "id": "375302b6-b6a7-46ea-a74c-c2400dbd8bbe",
35
+ "metadata": {},
36
+ "outputs": [],
37
+ "source": [
38
+ "# Load environment variables in a file called .env\n",
39
+ "load_dotenv()\n",
40
+ "\n",
41
+ "# Replace with your CoinAPI key\n",
42
+ "API_KEY = os.getenv('YOUR_COINAPI_KEY')\n",
43
+ "\n",
44
+ "# Define the base URL for CoinAPI\n",
45
+ "BASE_URL = 'https://rest.coinapi.io/v1/ohlcv/'\n",
46
+ "OLLAMA_URL = \"http://localhost:11434/v1\"\n",
47
+ "\n",
48
+ "os.environ['OPENAI_API_KEY'] = os.getenv('OPENAI_API_KEY', 'your-key-if-not-using-env')\n",
49
+ "# URL to fetch the OHLCV data\n"
50
+ ]
51
+ },
52
+ {
53
+ "cell_type": "code",
54
+ "execution_count": 98,
55
+ "id": "d0cc964d",
56
+ "metadata": {},
57
+ "outputs": [],
58
+ "source": [
59
+ "openai = OpenAI()\n",
60
+ "\n",
61
+ "ollama = OpenAI(\n",
62
+ " base_url=OLLAMA_URL,\n",
63
+ " api_key='OLAMMA'\n",
64
+ ")\n"
65
+ ]
66
+ },
67
+ {
68
+ "cell_type": "code",
69
+ "execution_count": 104,
70
+ "id": "8a0c9fff-9eff-42fd-971b-403c99d9b726",
71
+ "metadata": {},
72
+ "outputs": [],
73
+ "source": [
74
+ "# Define the symbol and timeframe\n",
75
+ "base_data = {\n",
76
+ " 'name': 'Cardano',\n",
77
+ " 'symbol': f'BINANCE_SPOT_ADA_USDT',\n",
78
+ " 'timeframe': '1DAY',\n",
79
+ " 'time_range': 365 * 2\n",
80
+ "}\n",
81
+ "\n",
82
+ "\n",
83
+ "# Calculate the start date for one year ago\n",
84
+ "end_date = datetime.now(tz=timezone.utc)\n",
85
+ "\n",
86
+ "start_date = end_date - timedelta(days=base_data['time_range'])\n",
87
+ "\n",
88
+ "# Format the dates in the required format (ISO 8601)\n",
89
+ "start_date_str = start_date.strftime('%Y-%m-%dT%H:%M:%S')\n",
90
+ "end_date_str = end_date.strftime('%Y-%m-%dT%H:%M:%S')\n",
91
+ "\n",
92
+ "# Headers for authentication\n",
93
+ "headers = {\n",
94
+ " 'X-CoinAPI-Key': API_KEY\n",
95
+ "}\n",
96
+ "\n",
97
+ "# URL to fetch the OHLCV base_data\n",
98
+ "url = f'{BASE_URL}{base_data['symbol']}/history'\n",
99
+ "\n",
100
+ "# Request parameters\n",
101
+ "params = {\n",
102
+ " 'period_id': base_data['timeframe'],\n",
103
+ " 'time_start': start_date_str,\n",
104
+ " 'time_end': end_date_str,\n",
105
+ " 'limit': 1000 # Maximum number of records per request\n",
106
+ "}"
107
+ ]
108
+ },
109
+ {
110
+ "cell_type": "code",
111
+ "execution_count": 91,
112
+ "id": "586b07ba-5396-4c34-a696-01c8bc3597a0",
113
+ "metadata": {},
114
+ "outputs": [
115
+ {
116
+ "data": {
117
+ "text/plain": [
118
+ "729"
119
+ ]
120
+ },
121
+ "execution_count": 91,
122
+ "metadata": {},
123
+ "output_type": "execute_result"
124
+ }
125
+ ],
126
+ "source": [
127
+ "# Fetch the data\n",
128
+ "response = requests.get(url, headers=headers, params=params) \n",
129
+ "len(response.json())"
130
+ ]
131
+ },
132
+ {
133
+ "cell_type": "code",
134
+ "execution_count": 76,
135
+ "id": "953422d0-2e75-4d01-862e-6383df54d9e5",
136
+ "metadata": {},
137
+ "outputs": [
138
+ {
139
+ "name": "stdout",
140
+ "output_type": "stream",
141
+ "text": [
142
+ " Timestamp Open High Low Close\n",
143
+ "724 2025-02-06 0.7325 0.7660 0.6978 0.7052\n",
144
+ "725 2025-02-07 0.7052 0.7532 0.6902 0.7072\n",
145
+ "726 2025-02-08 0.7072 0.7180 0.6815 0.7005\n",
146
+ "727 2025-02-09 0.7006 0.7160 0.6503 0.6814\n",
147
+ "728 2025-02-10 0.6815 0.7177 0.6632 0.7037\n"
148
+ ]
149
+ }
150
+ ],
151
+ "source": [
152
+ "# Check for successful response\n",
153
+ "if response.status_code == 200:\n",
154
+ " data = response.json()\n",
155
+ "\n",
156
+ " if data:\n",
157
+ " # Convert to DataFrame for better readability\n",
158
+ " df = pd.DataFrame(data)\n",
159
+ "\n",
160
+ " df = df[[\"time_period_start\", \"price_open\", \"price_high\", \"price_low\", \"price_close\"]]\n",
161
+ " df.columns = [\"Timestamp\", \"Open\", \"High\", \"Low\", \"Close\"]\n",
162
+ "\n",
163
+ " # Convert timestamp to readable format\n",
164
+ " df[\"Timestamp\"] = pd.to_datetime(df[\"Timestamp\"]).dt.strftime(\"%Y-%m-%d\")\n",
165
+ "\n",
166
+ " # Display the first few rows of the data\n",
167
+ " print(df.tail())\n",
168
+ " \n",
169
+ " # Convert last 365 days of data into JSON format\n",
170
+ " price_history = df.to_dict(orient=\"records\")\n",
171
+ " \n",
172
+ " else:\n",
173
+ " print('No data found for the given period.')\n",
174
+ "else:\n",
175
+ " print(f'Error fetching data: {response.status_code}, {response.text}')"
176
+ ]
177
+ },
178
+ {
179
+ "cell_type": "code",
180
+ "execution_count": 47,
181
+ "id": "ada5ed4f",
182
+ "metadata": {},
183
+ "outputs": [],
184
+ "source": [
185
+ "def count_tokens(text, model=\"gpt-4o\"):\n",
186
+ " encoding = tiktoken.encoding_for_model(model)\n",
187
+ " return len(encoding.encode(text))\n"
188
+ ]
189
+ },
190
+ {
191
+ "cell_type": "code",
192
+ "execution_count": null,
193
+ "id": "ab47d974",
194
+ "metadata": {},
195
+ "outputs": [],
196
+ "source": [
197
+ " # Construct prompt \n",
198
+ "\n",
199
+ "prompt = f\"\"\"\n",
200
+ " Given the last 365 days of ${base_data['name']} OHLC data:\n",
201
+ "\n",
202
+ " {json.dumps(price_history, indent=2)}\n",
203
+ "\n",
204
+ " Analyze this data and provide a trading signal (Buy, Sell, or Hold) for today based on the trend and the price action.\n",
205
+ " Note that today is {end_date.strftime('%Y-%m-%d')}\n",
206
+ " Also, provide short term ,mid term and long term signals.\n",
207
+ " \"\"\"\n",
208
+ "num_tokens = count_tokens(prompt)\n",
209
+ "print(f\"Estimated Tokens: {num_tokens}\")\n",
210
+ "\n",
211
+ "print(prompt)"
212
+ ]
213
+ },
214
+ {
215
+ "cell_type": "code",
216
+ "execution_count": null,
217
+ "id": "b40fec12",
218
+ "metadata": {},
219
+ "outputs": [
220
+ {
221
+ "data": {
222
+ "text/markdown": [
223
+ "To analyze this data, I'll use a combination of moving averages, relative strength index (RSI), and other technical indicators. Please note that this is a simplified analysis and should not be considered as professional trading advice.\n",
224
+ "\n",
225
+ "**Current Data**\n",
226
+ "\n",
227
+ "For 2025-02-10, the opening price is not available. However, we can calculate the current prices based on the historical data provided.\n",
228
+ "\n",
229
+ "Let's assume the last known close price for 2025-02-09 was $0.6815. For simplicity, let's use this as the opening price for today (2025-02-10).\n",
230
+ "\n",
231
+ "**Short-Term Signal**\n",
232
+ "\n",
233
+ "For a short-term signal, I'll use a simple moving average crossover system.\n",
234
+ "\n",
235
+ "* Short-Term Moving Average (20 days): $0.6922\n",
236
+ "* Short-Term Moving Average (10 days): $0.6747\n",
237
+ "\n",
238
+ "Since the 20-day MA ($0.6922) is above the 10-day MA ($0.6747), we can conclude that **Buy** in this timeframe.\n",
239
+ "\n",
240
+ "**Mid-Term Signal**\n",
241
+ "\n",
242
+ "For a mid-term signal, I'll use RSI.\n",
243
+ "\n",
244
+ "* Current Price: $0.6815\n",
245
+ "* Overbought Region: 70-80\n",
246
+ "* Oversold Region: 20-50\n",
247
+ "\n",
248
+ "The current price ($0.6815) is at the lower end of the oversold region (20-50), indicating a potential buying opportunity.\n",
249
+ "\n",
250
+ "Since RSI values are not provided for the entire dataset, we'll use an RSI value of 30 (midpoint of the low and high values). At $0.6815, RSI is approximately 34.\n",
251
+ "\n",
252
+ "* Mid-Term Moving Average: Not available\n",
253
+ "* Mid-Term Momentum: Rising\n",
254
+ "\n",
255
+ "Considering the oversold region and rising momentum, **Hold** is a reasonable mid-term strategy for today.\n",
256
+ "\n",
257
+ "**Long-Term Signal**\n",
258
+ "\n",
259
+ "For a long-term signal, I'll use the overall trend direction based on historical data.\n",
260
+ "\n",
261
+ "The dataset shows an upward trend (average True Range, AtR, value has been increasing). From 2025-02-03 to 2025-02-09, there were 6 consecutive increases in this dataset. That's a strong positive trend.\n",
262
+ "\n",
263
+ "Since there are no obvious signs of weakness in the long-term data or divergence with other trends (like 50-day MA), I recommend **Hold** for an extended holding period, keeping an eye on RSI values and adjusting positions as needed to stay ahead of potential price drops.\n",
264
+ "\n",
265
+ "**Summary**\n",
266
+ "\n",
267
+ "* Short-Term: **Buy**\n",
268
+ "* Mid-Term: **Hold**\n",
269
+ "* Long-Term: **Hold**"
270
+ ],
271
+ "text/plain": [
272
+ "<IPython.core.display.Markdown object>"
273
+ ]
274
+ },
275
+ "metadata": {},
276
+ "output_type": "display_data"
277
+ }
278
+ ],
279
+ "source": [
280
+ "def get_response(prompt):\n",
281
+ " new_response = ollama.chat.completions.create(model=\"llama3.2\",\n",
282
+ " messages=[\n",
283
+ " {\"role\": \"system\", \"content\": f\"You are a trading analyst providing Buy/Sell/Hold signals based on ${base_data['name']} price history.Note that today is {end_date.strftime('%Y-%m-%d')}\"},\n",
284
+ " {\"role\": \"user\", \"content\": prompt}\n",
285
+ " ],\n",
286
+ " stream=True,\n",
287
+ " max_tokens=5500\n",
288
+ " )\n",
289
+ " markdown_content = \"\"\n",
290
+ " \n",
291
+ " # Stream response and accumulate markdown content\n",
292
+ " for chunk in new_response:\n",
293
+ " content = chunk.choices[0].delta.content or ''\n",
294
+ " markdown_content += content\n",
295
+ " \n",
296
+ " # Clear output and display updated markdown\n",
297
+ " display(Markdown(markdown_content), clear=True)\n",
298
+ " \n",
299
+ " yield content\n",
300
+ "\n",
301
+ "# Call the function and consume the generator to start streaming\n",
302
+ "for _ in get_response(prompt):\n",
303
+ " pass"
304
+ ]
305
+ },
306
+ {
307
+ "cell_type": "code",
308
+ "execution_count": 88,
309
+ "id": "ba09436c",
310
+ "metadata": {},
311
+ "outputs": [
312
+ {
313
+ "data": {
314
+ "text/markdown": [
315
+ "# $Cardano Trading Analysis for 2025-02-10\n",
316
+ "\n",
317
+ "### **Current Price Analysis**\n",
318
+ "- **Open:** 0.6815\n",
319
+ "- **High:** 0.7177\n",
320
+ "- **Low:** 0.6632\n",
321
+ "- **Close:** 0.7037\n",
322
+ "\n",
323
+ "The price of $Cardano closed 3.59% higher than the previous day's close. This suggests a potential bullish reversal following a downward trend observed over the last few days. However, the volatility in the high-low range reflects uncertainty in the market.\n",
324
+ "\n",
325
+ "### **Trend Overview**\n",
326
+ "- **Short-term:** \n",
327
+ " - The recent price action indicates a possible recovery as we see an upward close. The price is currently attempting to break resistance, but the last few days exhibited mixed movements (e.g., a decrease before the recent increase). \n",
328
+ "- **Mid-term:**\n",
329
+ " - Over the past month, $Cardano has experienced significant volatility. While it reached its peak at around 1.079 earlier in January, the subsequent decline indicates selling pressure in the mid-term. A consolidation phase appears as buyers are trying to push the price back up.\n",
330
+ "- **Long-term:**\n",
331
+ " - Over the past year, $Cardano has shown high volatility and a fluctuating price range, but it has generally been trending downwards since its recent highs. \n",
332
+ "\n",
333
+ "### **Trading Signals**\n",
334
+ "- **Short-term Signal:** **Buy**\n",
335
+ " - The recent upward price movement along with a closing above 0.7000 indicates potential upward momentum. Short-term traders may consider buying into this recovery signal.\n",
336
+ "\n",
337
+ "- **Mid-term Signal:** **Hold**\n",
338
+ " - Within the last month, while recovery is in place, it is prudent to wait for confirmation of sustained upward movement before committing larger positions. A hold is advised to monitor the situation.\n",
339
+ "\n",
340
+ "- **Long-term Signal:** **Sell**\n",
341
+ " - Given that the longer-term trends show a downward trajectory since peaking at higher prices, long-term holders might consider selling or reducing positions, especially if the price fails to stay above recent resistance levels.\n",
342
+ "\n",
343
+ "### **Conclusion**\n",
344
+ "Today’s price action indicates a bullish sentiment in the short term but still reflects uncertainty in the mid and long-term periods. It would be wise for traders to remain cautious and adjust positions as the market dynamics evolve further. Always consider your risk management strategies when deciding to enter or exit positions."
345
+ ],
346
+ "text/plain": [
347
+ "<IPython.core.display.Markdown object>"
348
+ ]
349
+ },
350
+ "metadata": {},
351
+ "output_type": "display_data"
352
+ }
353
+ ],
354
+ "source": [
355
+ "def get_response(prompt):\n",
356
+ " new_response = openai.chat.completions.create(model=\"gpt-4o-mini\",\n",
357
+ " messages=[\n",
358
+ " {\"role\": \"system\", \"content\": f\"You are a trading analyst providing Buy/Sell/Hold signals based on ${base_data['name']} price history. Format your response in markdown.Note that today is {end_date.strftime('%Y-%m-%d')}\"},\n",
359
+ " {\"role\": \"user\", \"content\": prompt}\n",
360
+ " ],\n",
361
+ " stream=True,\n",
362
+ " max_tokens=5500\n",
363
+ " )\n",
364
+ " \n",
365
+ " # Initialize markdown cell output\n",
366
+ " markdown_content = \"\"\n",
367
+ " \n",
368
+ " # Stream response and accumulate markdown content\n",
369
+ " for chunk in new_response:\n",
370
+ " content = chunk.choices[0].delta.content or ''\n",
371
+ " markdown_content += content\n",
372
+ " \n",
373
+ " # Clear output and display updated markdown\n",
374
+ " display(Markdown(markdown_content), clear=True)\n",
375
+ " \n",
376
+ " yield content\n",
377
+ "\n",
378
+ "# Call the function and consume the generator to start streaming\n",
379
+ "for _ in get_response(prompt):\n",
380
+ " pass"
381
+ ]
382
+ },
383
+ {
384
+ "cell_type": "code",
385
+ "execution_count": null,
386
+ "id": "f52bcc0a",
387
+ "metadata": {},
388
+ "outputs": [],
389
+ "source": []
390
+ }
391
+ ],
392
+ "metadata": {
393
+ "kernelspec": {
394
+ "display_name": "venv",
395
+ "language": "python",
396
+ "name": "python3"
397
+ },
398
+ "language_info": {
399
+ "codemirror_mode": {
400
+ "name": "ipython",
401
+ "version": 3
402
+ },
403
+ "file_extension": ".py",
404
+ "mimetype": "text/x-python",
405
+ "name": "python",
406
+ "nbconvert_exporter": "python",
407
+ "pygments_lexer": "ipython3",
408
+ "version": "3.12.7"
409
+ }
410
+ },
411
+ "nbformat": 4,
412
+ "nbformat_minor": 5
413
+ }
extras/trading/prototype_trader.ipynb ADDED
@@ -0,0 +1,354 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "markdown",
5
+ "id": "46d90d45-2d19-49c7-b853-6809dc417ea7",
6
+ "metadata": {},
7
+ "source": [
8
+ "# Extra Project - Trading Code Generator\n",
9
+ "\n",
10
+ "This is an example extra project to show fine-tuning in action, and applied to code generation.\n",
11
+ "\n",
12
+ "## Project Brief\n",
13
+ "\n",
14
+ "Build a prototype LLM that can generate example code to suggest trading decisions to buy or sell stocks!\n",
15
+ "\n",
16
+ "I generated test data using frontier models, in the other files in this directory. Use this to train an open source code model.\n",
17
+ "\n",
18
+ "In this notebook we generate the dataset; then we move over to Google Colab for the fine-tuning.\n",
19
+ "\n",
20
+ "<table style=\"margin: 0; text-align: left;\">\n",
21
+ " <tr>\n",
22
+ " <td style=\"width: 150px; height: 150px; vertical-align: middle;\">\n",
23
+ " <img src=\"../../resources.jpg\" width=\"150\" height=\"150\" style=\"display: block;\" />\n",
24
+ " </td>\n",
25
+ " <td>\n",
26
+ " <h2 style=\"color:#f71;\">This project is provided as an extra resource</h2>\n",
27
+ " <span style=\"color:#f71;\">It will make most sense after completing Week 7, and might trigger some ideas for your own projects.<br/><br/>\n",
28
+ " This is provided without a detailed walk-through; the output from the colab has been saved (see last cell) so you can review the results if you have any problems running yourself.\n",
29
+ " </span>\n",
30
+ " </td>\n",
31
+ " </tr>\n",
32
+ "</table>\n",
33
+ "<table style=\"margin: 0; text-align: left;\">\n",
34
+ " <tr>\n",
35
+ " <td style=\"width: 150px; height: 150px; vertical-align: middle;\">\n",
36
+ " <img src=\"../../important.jpg\" width=\"150\" height=\"150\" style=\"display: block;\" />\n",
37
+ " </td>\n",
38
+ " <td>\n",
39
+ " <h2 style=\"color:#900;\">Do not use for actual trading decisions!!</h2>\n",
40
+ " <span style=\"color:#900;\">It hopefully goes without saying: this project will generate toy trading code that is over-simplified and untrusted.<br/><br/>Please do not make actual trading decisions based on this!</span>\n",
41
+ " </td>\n",
42
+ " </tr>\n",
43
+ "</table>"
44
+ ]
45
+ },
46
+ {
47
+ "cell_type": "markdown",
48
+ "id": "7e2c4bbb-5e8b-4d84-9997-ecb2c349cf54",
49
+ "metadata": {},
50
+ "source": [
51
+ "## First step - generate training data from examples\n",
52
+ "\n",
53
+ "There are 3 sample python files generated (via multiple queries) by GPT-4o, Claude 3 Opus and Gemini 1.5 Pro. \n",
54
+ "\n",
55
+ "This notebook creates training data from these files, then converts to the HuggingFace format and uploads to the hub.\n",
56
+ "\n",
57
+ "Afterwards, we will move to Google Colab to fine-tune."
58
+ ]
59
+ },
60
+ {
61
+ "cell_type": "code",
62
+ "execution_count": null,
63
+ "id": "16cf3aa2-f407-4b95-8b9e-c3c586f67835",
64
+ "metadata": {},
65
+ "outputs": [],
66
+ "source": [
67
+ "import os\n",
68
+ "import glob\n",
69
+ "import matplotlib.pyplot as plt\n",
70
+ "import random\n",
71
+ "from datasets import Dataset\n",
72
+ "from dotenv import load_dotenv\n",
73
+ "from huggingface_hub import login\n",
74
+ "import transformers\n",
75
+ "from transformers import AutoTokenizer"
76
+ ]
77
+ },
78
+ {
79
+ "cell_type": "code",
80
+ "execution_count": null,
81
+ "id": "375302b6-b6a7-46ea-a74c-c2400dbd8bbe",
82
+ "metadata": {},
83
+ "outputs": [],
84
+ "source": [
85
+ "# Load environment variables in a file called .env\n",
86
+ "from datasets import load_dataset, Dataset\n",
87
+ "load_dotenv()\n",
88
+ "hf_token = os.getenv('HF_TOKEN')\n",
89
+ "if hf_token and hf_token.startswith(\"hf_\") and len(hf_token)>5:\n",
90
+ " print(\"HuggingFace Token looks good so far\")\n",
91
+ "else:\n",
92
+ " print(\"Potential problem with HuggingFace token - please check your .env file, and see the Troubleshooting notebook for more\")"
93
+ ]
94
+ },
95
+ {
96
+ "cell_type": "code",
97
+ "execution_count": null,
98
+ "id": "8a0c9fff-9eff-42fd-971b-403c99d9b726",
99
+ "metadata": {},
100
+ "outputs": [],
101
+ "source": [
102
+ "# Constants\n",
103
+ "\n",
104
+ "DATASET_NAME = \"trade_code_data\"\n",
105
+ "BASE_MODEL = \"Qwen/CodeQwen1.5-7B\""
106
+ ]
107
+ },
108
+ {
109
+ "cell_type": "code",
110
+ "execution_count": null,
111
+ "id": "586b07ba-5396-4c34-a696-01c8bc3597a0",
112
+ "metadata": {},
113
+ "outputs": [],
114
+ "source": [
115
+ "# A utility method to convert the text contents of a file into a list of methods\n",
116
+ "\n",
117
+ "def extract_method_bodies(text):\n",
118
+ " chunks = text.split('def trade')[1:]\n",
119
+ " results = []\n",
120
+ " for chunk in chunks:\n",
121
+ " lines = chunk.split('\\n')[1:]\n",
122
+ " body = '\\n'.join(line for line in lines if line!='\\n')\n",
123
+ " results.append(body)\n",
124
+ " return results "
125
+ ]
126
+ },
127
+ {
128
+ "cell_type": "code",
129
+ "execution_count": null,
130
+ "id": "953422d0-2e75-4d01-862e-6383df54d9e5",
131
+ "metadata": {},
132
+ "outputs": [],
133
+ "source": [
134
+ "# Read all .py files and convert into training data\n",
135
+ "\n",
136
+ "bodies = []\n",
137
+ "for filename in glob.glob(\"*.py\"):\n",
138
+ " with open(filename, 'r', encoding='utf-8') as file:\n",
139
+ " content = file.read()\n",
140
+ " extracted = extract_method_bodies(content)\n",
141
+ " bodies += extracted\n",
142
+ "\n",
143
+ "print(f\"Extracted {len(bodies)} trade method bodies\")"
144
+ ]
145
+ },
146
+ {
147
+ "cell_type": "code",
148
+ "execution_count": null,
149
+ "id": "836480e9-ba23-4aa3-a7e2-2666884e9a06",
150
+ "metadata": {},
151
+ "outputs": [],
152
+ "source": [
153
+ "# Let's look at one\n",
154
+ "\n",
155
+ "print(random.choice(bodies))"
156
+ ]
157
+ },
158
+ {
159
+ "cell_type": "code",
160
+ "execution_count": null,
161
+ "id": "47b10e7e-a562-4968-af3f-254a9b424ac8",
162
+ "metadata": {},
163
+ "outputs": [],
164
+ "source": [
165
+ "# To visualize the lines of code in each \n",
166
+ "\n",
167
+ "%matplotlib inline\n",
168
+ "fig, ax = plt.subplots(1, 1)\n",
169
+ "lengths = [len(body.split('\\n')) for body in bodies]\n",
170
+ "ax.set_xlabel('Lines of code')\n",
171
+ "ax.set_ylabel('Count of training samples');\n",
172
+ "_ = ax.hist(lengths, rwidth=0.7, color=\"green\", bins=range(0, max(lengths)))"
173
+ ]
174
+ },
175
+ {
176
+ "cell_type": "code",
177
+ "execution_count": null,
178
+ "id": "03b37f62-679e-4c3d-9e5b-5878a82696e6",
179
+ "metadata": {},
180
+ "outputs": [],
181
+ "source": [
182
+ "# Add the prompt to the start of every training example\n",
183
+ "\n",
184
+ "prompt = \"\"\"\n",
185
+ "# tickers is a list of stock tickers\n",
186
+ "import tickers\n",
187
+ "\n",
188
+ "# prices is a dict; the key is a ticker and the value is a list of historic prices, today first\n",
189
+ "import prices\n",
190
+ "\n",
191
+ "# Trade represents a decision to buy or sell a quantity of a ticker\n",
192
+ "import Trade\n",
193
+ "\n",
194
+ "import random\n",
195
+ "import numpy as np\n",
196
+ "\n",
197
+ "def trade():\n",
198
+ "\"\"\"\n",
199
+ "\n",
200
+ "data = [prompt + body for body in bodies]\n",
201
+ "print(random.choice(data))"
202
+ ]
203
+ },
204
+ {
205
+ "cell_type": "code",
206
+ "execution_count": null,
207
+ "id": "28fdb82f-3864-4023-8263-547d17571a5c",
208
+ "metadata": {},
209
+ "outputs": [],
210
+ "source": [
211
+ "# Distribution of tokens in our dataset\n",
212
+ "\n",
213
+ "tokenizer = AutoTokenizer.from_pretrained(BASE_MODEL, trust_remote_code=True)\n",
214
+ "tokenized_data = [tokenizer.encode(each) for each in data]\n",
215
+ "token_counts = [len(tokens) for tokens in tokenized_data]\n",
216
+ "\n",
217
+ "%matplotlib inline\n",
218
+ "fig, ax = plt.subplots(1, 1)\n",
219
+ "ax.set_xlabel('Number of tokens')\n",
220
+ "ax.set_ylabel('Count of training samples');\n",
221
+ "_ = ax.hist(token_counts, rwidth=0.7, color=\"purple\", bins=range(0, max(token_counts), 20))"
222
+ ]
223
+ },
224
+ {
225
+ "cell_type": "markdown",
226
+ "id": "b4eb73b0-88ef-4aeb-8e5b-fe7050109ba0",
227
+ "metadata": {},
228
+ "source": [
229
+ "# Enforcing a maximum token length\n",
230
+ "\n",
231
+ "We need to specify a maximum number of tokens when we fine-tune.\n",
232
+ "\n",
233
+ "Let's pick a cut-off, and only keep training data points that fit within this number of tokens,"
234
+ ]
235
+ },
236
+ {
237
+ "cell_type": "code",
238
+ "execution_count": null,
239
+ "id": "ffb0d55c-5602-4518-b811-fa385c0959a7",
240
+ "metadata": {},
241
+ "outputs": [],
242
+ "source": [
243
+ "CUTOFF = 320\n",
244
+ "truncated = len([tokens for tokens in tokenized_data if len(tokens) > CUTOFF])\n",
245
+ "percentage = truncated/len(tokenized_data)*100\n",
246
+ "print(f\"With cutoff at {CUTOFF}, we truncate {truncated} datapoints which is {percentage:.1f}% of the dataset\")"
247
+ ]
248
+ },
249
+ {
250
+ "cell_type": "code",
251
+ "execution_count": null,
252
+ "id": "7064ef0a-7b07-4f24-a580-cbef2c5e1f2f",
253
+ "metadata": {},
254
+ "outputs": [],
255
+ "source": [
256
+ "# Let's only keep datapoints that wouldn't get truncated\n",
257
+ "\n",
258
+ "filtered_data = [datapoint for datapoint in data if len(tokenizer.encode(datapoint))<=CUTOFF]\n",
259
+ "print(f\"After e now have {len(filtered_data)} datapoints\")"
260
+ ]
261
+ },
262
+ {
263
+ "cell_type": "code",
264
+ "execution_count": null,
265
+ "id": "fb2bb067-2bd3-498b-9fc8-5e8186afbe27",
266
+ "metadata": {},
267
+ "outputs": [],
268
+ "source": [
269
+ "# Mix up the data\n",
270
+ "\n",
271
+ "random.seed(42)\n",
272
+ "random.shuffle(filtered_data)"
273
+ ]
274
+ },
275
+ {
276
+ "cell_type": "code",
277
+ "execution_count": null,
278
+ "id": "26713fb9-765f-4524-b9db-447e97686d1a",
279
+ "metadata": {},
280
+ "outputs": [],
281
+ "source": [
282
+ "# I don't make a Training / Test split - if we had more training data, we would!\n",
283
+ "\n",
284
+ "dataset = Dataset.from_dict({'text':filtered_data})"
285
+ ]
286
+ },
287
+ {
288
+ "cell_type": "code",
289
+ "execution_count": null,
290
+ "id": "bfabba27-ef47-46a8-a26b-4d650ae3b193",
291
+ "metadata": {},
292
+ "outputs": [],
293
+ "source": [
294
+ "login(hf_token)"
295
+ ]
296
+ },
297
+ {
298
+ "cell_type": "code",
299
+ "execution_count": null,
300
+ "id": "55b595cd-2df7-4be4-aec1-0667b17d36f1",
301
+ "metadata": {},
302
+ "outputs": [],
303
+ "source": [
304
+ "# Push your dataset to your hub\n",
305
+ "# I've also pushed the data to my account and made it public, which you can use from the colab below\n",
306
+ "\n",
307
+ "dataset.push_to_hub(DATASET_NAME, private=True)"
308
+ ]
309
+ },
310
+ {
311
+ "cell_type": "markdown",
312
+ "id": "4691a025-9800-4e97-a20f-a65f102401f1",
313
+ "metadata": {},
314
+ "source": [
315
+ "## And now to head over to a Google Colab for fine-tuning in the cloud\n",
316
+ "\n",
317
+ "Follow this link for the Colab:\n",
318
+ "\n",
319
+ "https://colab.research.google.com/drive/1wry2-4AGw-U7K0LQ_jEgduoTQqVIvo1x?usp=sharing\n",
320
+ "\n",
321
+ "I've also saved this Colab with output included, so you can see the results without needing to train if you'd prefer.\n"
322
+ ]
323
+ },
324
+ {
325
+ "cell_type": "code",
326
+ "execution_count": null,
327
+ "id": "04a6c3e0-a2e6-4115-a01a-45e79dfdb730",
328
+ "metadata": {},
329
+ "outputs": [],
330
+ "source": []
331
+ }
332
+ ],
333
+ "metadata": {
334
+ "kernelspec": {
335
+ "display_name": "Python 3 (ipykernel)",
336
+ "language": "python",
337
+ "name": "python3"
338
+ },
339
+ "language_info": {
340
+ "codemirror_mode": {
341
+ "name": "ipython",
342
+ "version": 3
343
+ },
344
+ "file_extension": ".py",
345
+ "mimetype": "text/x-python",
346
+ "name": "python",
347
+ "nbconvert_exporter": "python",
348
+ "pygments_lexer": "ipython3",
349
+ "version": "3.11.11"
350
+ }
351
+ },
352
+ "nbformat": 4,
353
+ "nbformat_minor": 5
354
+ }
extras/trading/trades_claude.py ADDED
@@ -0,0 +1,725 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # tickers is a list of stock tickers
2
+ import tickers
3
+
4
+ # prices is a dict; the key is a ticker and the value is a list of historic prices, today first
5
+ import prices
6
+
7
+ # Trade represents a decision to buy or sell a quantity of a ticker
8
+ import Trade
9
+
10
+ import random
11
+ import numpy as np
12
+
13
+ def trade2():
14
+ # Buy if the current price is lower than the average of the last 5 days
15
+ trades = []
16
+ for ticker in tickers:
17
+ if prices[ticker][0] < np.mean(prices[ticker][1:6]):
18
+ quantity = random.randrange(1, 100)
19
+ trades.append(Trade(ticker, quantity))
20
+ return trades
21
+
22
+ def trade3():
23
+ # Sell if the current price is higher than the average of the last 10 days
24
+ trades = []
25
+ for ticker in tickers:
26
+ if prices[ticker][0] > np.mean(prices[ticker][1:11]):
27
+ quantity = random.randrange(-100, -1)
28
+ trades.append(Trade(ticker, quantity))
29
+ return trades
30
+
31
+ def trade4():
32
+ # Buy if the current price is the lowest in the last 3 days
33
+ trades = []
34
+ for ticker in tickers:
35
+ if prices[ticker][0] == min(prices[ticker][:3]):
36
+ quantity = random.randrange(1, 100)
37
+ trades.append(Trade(ticker, quantity))
38
+ return trades
39
+
40
+ def trade5():
41
+ # Sell if the current price is the highest in the last 3 days
42
+ trades = []
43
+ for ticker in tickers:
44
+ if prices[ticker][0] == max(prices[ticker][:3]):
45
+ quantity = random.randrange(-100, -1)
46
+ trades.append(Trade(ticker, quantity))
47
+ return trades
48
+
49
+ def trade6():
50
+ # Buy if the current price is higher than the previous day's price
51
+ trades = []
52
+ for ticker in tickers:
53
+ if prices[ticker][0] > prices[ticker][1]:
54
+ quantity = random.randrange(1, 100)
55
+ trades.append(Trade(ticker, quantity))
56
+ return trades
57
+
58
+ def trade7():
59
+ # Sell if the current price is lower than the previous day's price
60
+ trades = []
61
+ for ticker in tickers:
62
+ if prices[ticker][0] < prices[ticker][1]:
63
+ quantity = random.randrange(-100, -1)
64
+ trades.append(Trade(ticker, quantity))
65
+ return trades
66
+
67
+ def trade8():
68
+ # Buy if the current price is higher than the average of the last 20 days
69
+ trades = []
70
+ for ticker in tickers:
71
+ if prices[ticker][0] > np.mean(prices[ticker][1:21]):
72
+ quantity = random.randrange(1, 100)
73
+ trades.append(Trade(ticker, quantity))
74
+ return trades
75
+
76
+ def trade9():
77
+ # Sell if the current price is lower than the average of the last 20 days
78
+ trades = []
79
+ for ticker in tickers:
80
+ if prices[ticker][0] < np.mean(prices[ticker][1:21]):
81
+ quantity = random.randrange(-100, -1)
82
+ trades.append(Trade(ticker, quantity))
83
+ return trades
84
+
85
+ def trade10():
86
+ # Buy if the current price is higher than the highest price in the last 5 days
87
+ trades = []
88
+ for ticker in tickers:
89
+ if prices[ticker][0] > max(prices[ticker][1:6]):
90
+ quantity = random.randrange(1, 100)
91
+ trades.append(Trade(ticker, quantity))
92
+ return trades
93
+
94
+ def trade11():
95
+ # Sell if the current price is lower than the lowest price in the last 5 days
96
+ trades = []
97
+ for ticker in tickers:
98
+ if prices[ticker][0] < min(prices[ticker][1:6]):
99
+ quantity = random.randrange(-100, -1)
100
+ trades.append(Trade(ticker, quantity))
101
+ return trades
102
+
103
+ def trade12():
104
+ # Long/Short: Buy the best-performing stock and sell the worst-performing stock in the last 10 days
105
+ best_ticker = max(tickers, key=lambda x: (prices[x][0] - prices[x][9]) / prices[x][9])
106
+ worst_ticker = min(tickers, key=lambda x: (prices[x][0] - prices[x][9]) / prices[x][9])
107
+ return [Trade(best_ticker, 100), Trade(worst_ticker, -100)]
108
+
109
+ def trade13():
110
+ # Buy if the 5-day moving average crosses above the 20-day moving average
111
+ trades = []
112
+ for ticker in tickers:
113
+ if np.mean(prices[ticker][:5]) > np.mean(prices[ticker][:20]) and np.mean(prices[ticker][1:6]) <= np.mean(prices[ticker][1:21]):
114
+ quantity = random.randrange(1, 100)
115
+ trades.append(Trade(ticker, quantity))
116
+ return trades
117
+
118
+ def trade14():
119
+ # Sell if the 5-day moving average crosses below the 20-day moving average
120
+ trades = []
121
+ for ticker in tickers:
122
+ if np.mean(prices[ticker][:5]) < np.mean(prices[ticker][:20]) and np.mean(prices[ticker][1:6]) >= np.mean(prices[ticker][1:21]):
123
+ quantity = random.randrange(-100, -1)
124
+ trades.append(Trade(ticker, quantity))
125
+ return trades
126
+
127
+ def trade15():
128
+ # Buy if the current volume is higher than the average volume of the last 10 days
129
+ trades = []
130
+ for ticker in tickers:
131
+ if volumes[ticker][0] > np.mean(volumes[ticker][1:11]):
132
+ quantity = random.randrange(1, 100)
133
+ trades.append(Trade(ticker, quantity))
134
+ return trades
135
+
136
+ def trade16():
137
+ # Sell if the current volume is lower than the average volume of the last 10 days
138
+ trades = []
139
+ for ticker in tickers:
140
+ if volumes[ticker][0] < np.mean(volumes[ticker][1:11]):
141
+ quantity = random.randrange(-100, -1)
142
+ trades.append(Trade(ticker, quantity))
143
+ return trades
144
+
145
+ def trade17():
146
+ # Long/Short: Buy the stock with the highest relative strength index (RSI) and sell the stock with the lowest RSI
147
+ rsi = {}
148
+ for ticker in tickers:
149
+ gains = [max(prices[ticker][i] - prices[ticker][i+1], 0) for i in range(13)]
150
+ losses = [max(prices[ticker][i+1] - prices[ticker][i], 0) for i in range(13)]
151
+ avg_gain = sum(gains) / 14
152
+ avg_loss = sum(losses) / 14
153
+ rs = avg_gain / avg_loss if avg_loss > 0 else 100
154
+ rsi[ticker] = 100 - (100 / (1 + rs))
155
+ best_ticker = max(tickers, key=lambda x: rsi[x])
156
+ worst_ticker = min(tickers, key=lambda x: rsi[x])
157
+ return [Trade(best_ticker, 100), Trade(worst_ticker, -100)]
158
+
159
+ def trade18():
160
+ # Buy if the current price is higher than the 50-day moving average and the 50-day moving average is higher than the 200-day moving average
161
+ trades = []
162
+ for ticker in tickers:
163
+ if prices[ticker][0] > np.mean(prices[ticker][:50]) > np.mean(prices[ticker][:200]):
164
+ quantity = random.randrange(1, 100)
165
+ trades.append(Trade(ticker, quantity))
166
+ return trades
167
+
168
+ def trade19():
169
+ # Sell if the current price is lower than the 50-day moving average and the 50-day moving average is lower than the 200-day moving average
170
+ trades = []
171
+ for ticker in tickers:
172
+ if prices[ticker][0] < np.mean(prices[ticker][:50]) < np.mean(prices[ticker][:200]):
173
+ quantity = random.randrange(-100, -1)
174
+ trades.append(Trade(ticker, quantity))
175
+ return trades
176
+
177
+ def trade20():
178
+ # Long/Short: Buy the stock with the highest momentum and sell the stock with the lowest momentum
179
+ momentums = {}
180
+ for ticker in tickers:
181
+ momentums[ticker] = prices[ticker][0] - prices[ticker][19]
182
+ best_ticker = max(tickers, key=lambda x: momentums[x])
183
+ worst_ticker = min(tickers, key=lambda x: momentums[x])
184
+ return [Trade(best_ticker, 100), Trade(worst_ticker, -100)]
185
+
186
+ def trade21():
187
+ # Buy if the current price is higher than the upper Bollinger Band
188
+ trades = []
189
+ for ticker in tickers:
190
+ sma = np.mean(prices[ticker][:20])
191
+ std = np.std(prices[ticker][:20])
192
+ upper_band = sma + 2 * std
193
+ if prices[ticker][0] > upper_band:
194
+ quantity = random.randrange(1, 100)
195
+ trades.append(Trade(ticker, quantity))
196
+ return trades
197
+
198
+ def trade22():
199
+ # Sell if the current price is lower than the lower Bollinger Band
200
+ trades = []
201
+ for ticker in tickers:
202
+ sma = np.mean(prices[ticker][:20])
203
+ std = np.std(prices[ticker][:20])
204
+ lower_band = sma - 2 * std
205
+ if prices[ticker][0] < lower_band:
206
+ quantity = random.randrange(-100, -1)
207
+ trades.append(Trade(ticker, quantity))
208
+ return trades
209
+
210
+ def trade23():
211
+ # Buy if the current volatility is higher than the average volatility of the last 10 days
212
+ trades = []
213
+ for ticker in tickers:
214
+ volatility = np.std(prices[ticker][:10])
215
+ avg_volatility = np.mean([np.std(prices[ticker][i:i+10]) for i in range(10)])
216
+ if volatility > avg_volatility:
217
+ quantity = random.randrange(1, 100)
218
+ trades.append(Trade(ticker, quantity))
219
+ return trades
220
+
221
+ def trade24():
222
+ # Sell if the current volatility is lower than the average volatility of the last 10 days
223
+ trades = []
224
+ for ticker in tickers:
225
+ volatility = np.std(prices[ticker][:10])
226
+ avg_volatility = np.mean([np.std(prices[ticker][i:i+10]) for i in range(10)])
227
+ if volatility < avg_volatility:
228
+ quantity = random.randrange(-100, -1)
229
+ trades.append(Trade(ticker, quantity))
230
+ return trades
231
+
232
+ def trade25():
233
+ # Long/Short: Buy the stock with the lowest volatility and sell the stock with the highest volatility
234
+ volatilities = {}
235
+ for ticker in tickers:
236
+ volatilities[ticker] = np.std(prices[ticker][:10])
237
+ best_ticker = min(tickers, key=lambda x: volatilities[x])
238
+ worst_ticker = max(tickers, key=lambda x: volatilities[x])
239
+ return [Trade(best_ticker, 100), Trade(worst_ticker, -100)]
240
+
241
+ def trade26():
242
+ # Buy if the current price is higher than the 20-day exponential moving average (EMA)
243
+ trades = []
244
+ for ticker in tickers:
245
+ ema = prices[ticker][0]
246
+ multiplier = 2 / (20 + 1)
247
+ for i in range(1, 20):
248
+ ema = (prices[ticker][i] - ema) * multiplier + ema
249
+ if prices[ticker][0] > ema:
250
+ quantity = random.randrange(1, 100)
251
+ trades.append(Trade(ticker, quantity))
252
+ return trades
253
+
254
+ def trade27():
255
+ # Sell if the current price is lower than the 20-day exponential moving average (EMA)
256
+ trades = []
257
+ for ticker in tickers:
258
+ ema = prices[ticker][0]
259
+ multiplier = 2 / (20 + 1)
260
+ for i in range(1, 20):
261
+ ema = (prices[ticker][i] - ema) * multiplier + ema
262
+ if prices[ticker][0] < ema:
263
+ quantity = random.randrange(-100, -1)
264
+ trades.append(Trade(ticker, quantity))
265
+ return trades
266
+
267
+ def trade28():
268
+ # Buy if the current price is higher than the upper Keltner Channel
269
+ trades = []
270
+ for ticker in tickers:
271
+ ema = prices[ticker][0]
272
+ multiplier = 2 / (20 + 1)
273
+ for i in range(1, 20):
274
+ ema = (prices[ticker][i] - ema) * multiplier + ema
275
+ atr = np.mean([np.max(prices[ticker][i:i+10]) - np.min(prices[ticker][i:i+10]) for i in range(10)])
276
+ upper_channel = ema + 2 * atr
277
+ if prices[ticker][0] > upper_channel:
278
+ quantity = random.randrange(1, 100)
279
+ trades.append(Trade(ticker, quantity))
280
+ return trades
281
+
282
+ def trade29():
283
+ # Sell if the current price is lower than the lower Keltner Channel
284
+ trades = []
285
+ for ticker in tickers:
286
+ ema = prices[ticker][0]
287
+ multiplier = 2 / (20 + 1)
288
+ for i in range(1, 20):
289
+ ema = (prices[ticker][i] - ema) * multiplier + ema
290
+ atr = np.mean([np.max(prices[ticker][i:i+10]) - np.min(prices[ticker][i:i+10]) for i in range(10)])
291
+ lower_channel = ema - 2 * atr
292
+ if prices[ticker][0] < lower_channel:
293
+ quantity = random.randrange(-100, -1)
294
+ trades.append(Trade(ticker, quantity))
295
+ return trades
296
+
297
+ def trade30():
298
+ # Long/Short: Buy the stock with the highest Sharpe ratio and sell the stock with the lowest Sharpe ratio
299
+ sharpe_ratios = {}
300
+ for ticker in tickers:
301
+ returns = [prices[ticker][i] / prices[ticker][i+1] - 1 for i in range(19)]
302
+ sharpe_ratios[ticker] = np.mean(returns) / np.std(returns)
303
+ best_ticker = max(tickers, key=lambda x: sharpe_ratios[x])
304
+ worst_ticker = min(tickers, key=lambda x: sharpe_ratios[x])
305
+ return [Trade(best_ticker, 100), Trade(worst_ticker, -100)]
306
+
307
+ def trade31():
308
+ # Buy if the current price is higher than the Ichimoku Cloud conversion line
309
+ trades = []
310
+ for ticker in tickers:
311
+ conversion_line = (np.max(prices[ticker][:9]) + np.min(prices[ticker][:9])) / 2
312
+ if prices[ticker][0] > conversion_line:
313
+ quantity = random.randrange(1, 100)
314
+ trades.append(Trade(ticker, quantity))
315
+ return trades
316
+
317
+ def trade32():
318
+ # Buy if the current price is higher than the price 5 days ago
319
+ trades = []
320
+ for ticker in tickers:
321
+ if prices[ticker][0] > prices[ticker][4]:
322
+ quantity = random.randrange(1, 100)
323
+ trades.append(Trade(ticker, quantity))
324
+ return trades
325
+
326
+ def trade33():
327
+ # Sell if the current price is lower than the price 5 days ago
328
+ trades = []
329
+ for ticker in tickers:
330
+ if prices[ticker][0] < prices[ticker][4]:
331
+ quantity = random.randrange(-100, -1)
332
+ trades.append(Trade(ticker, quantity))
333
+ return trades
334
+
335
+ def trade34():
336
+ # Buy if the current price is the highest in the last 15 days
337
+ trades = []
338
+ for ticker in tickers:
339
+ if prices[ticker][0] == max(prices[ticker][:15]):
340
+ quantity = random.randrange(1, 100)
341
+ trades.append(Trade(ticker, quantity))
342
+ return trades
343
+
344
+ def trade35():
345
+ # Sell if the current price is the lowest in the last 15 days
346
+ trades = []
347
+ for ticker in tickers:
348
+ if prices[ticker][0] == min(prices[ticker][:15]):
349
+ quantity = random.randrange(-100, -1)
350
+ trades.append(Trade(ticker, quantity))
351
+ return trades
352
+
353
+ def trade36():
354
+ # Buy if the current price is higher than the 10-day simple moving average (SMA)
355
+ trades = []
356
+ for ticker in tickers:
357
+ sma = np.mean(prices[ticker][:10])
358
+ if prices[ticker][0] > sma:
359
+ quantity = random.randrange(1, 100)
360
+ trades.append(Trade(ticker, quantity))
361
+ return trades
362
+
363
+ def trade37():
364
+ # Sell if the current price is lower than the 10-day simple moving average (SMA)
365
+ trades = []
366
+ for ticker in tickers:
367
+ sma = np.mean(prices[ticker][:10])
368
+ if prices[ticker][0] < sma:
369
+ quantity = random.randrange(-100, -1)
370
+ trades.append(Trade(ticker, quantity))
371
+ return trades
372
+
373
+ def trade38():
374
+ # Buy if the current price is higher than the highest price in the last 20 days
375
+ trades = []
376
+ for ticker in tickers:
377
+ if prices[ticker][0] > max(prices[ticker][:20]):
378
+ quantity = random.randrange(1, 100)
379
+ trades.append(Trade(ticker, quantity))
380
+ return trades
381
+
382
+ def trade39():
383
+ # Sell if the current price is lower than the lowest price in the last 20 days
384
+ trades = []
385
+ for ticker in tickers:
386
+ if prices[ticker][0] < min(prices[ticker][:20]):
387
+ quantity = random.randrange(-100, -1)
388
+ trades.append(Trade(ticker, quantity))
389
+ return trades
390
+
391
+ def trade40():
392
+ # Buy if the current price is higher than the 50-day SMA
393
+ trades = []
394
+ for ticker in tickers:
395
+ sma = np.mean(prices[ticker][:50])
396
+ if prices[ticker][0] > sma:
397
+ quantity = random.randrange(1, 100)
398
+ trades.append(Trade(ticker, quantity))
399
+ return trades
400
+
401
+ def trade41():
402
+ # Sell if the current price is lower than the 50-day SMA
403
+ trades = []
404
+ for ticker in tickers:
405
+ sma = np.mean(prices[ticker][:50])
406
+ if prices[ticker][0] < sma:
407
+ quantity = random.randrange(-100, -1)
408
+ trades.append(Trade(ticker, quantity))
409
+ return trades
410
+
411
+ def trade42():
412
+ # Buy if the current price is higher than the previous 2 days (a simple uptrend)
413
+ trades = []
414
+ for ticker in tickers:
415
+ if prices[ticker][0] > prices[ticker][1] > prices[ticker][2]:
416
+ quantity = random.randrange(1, 100)
417
+ trades.append(Trade(ticker, quantity))
418
+ return trades
419
+
420
+ def trade43():
421
+ # Sell if the current price is lower than the previous 2 days (a simple downtrend)
422
+ trades = []
423
+ for ticker in tickers:
424
+ if prices[ticker][0] < prices[ticker][1] < prices[ticker][2]:
425
+ quantity = random.randrange(-100, -1)
426
+ trades.append(Trade(ticker, quantity))
427
+ return trades
428
+
429
+ def trade44():
430
+ # Buy if the current price is higher than the previous day's high (a breakout)
431
+ trades = []
432
+ for ticker in tickers:
433
+ if prices[ticker][0] > max(prices[ticker][1:2]):
434
+ quantity = random.randrange(1, 100)
435
+ trades.append(Trade(ticker, quantity))
436
+ return trades
437
+
438
+ def trade45():
439
+ # Sell if the current price is lower than the previous day's low (a breakdown)
440
+ trades = []
441
+ for ticker in tickers:
442
+ if prices[ticker][0] < min(prices[ticker][1:2]):
443
+ quantity = random.randrange(-100, -1)
444
+ trades.append(Trade(ticker, quantity))
445
+ return trades
446
+
447
+ def trade46():
448
+ # Buy if the current price is above the previous day's high and the previous day was a down day (a potential reversal)
449
+ trades = []
450
+ for ticker in tickers:
451
+ if prices[ticker][0] > max(prices[ticker][1:2]) and prices[ticker][1] < prices[ticker][2]:
452
+ quantity = random.randrange(1, 100)
453
+ trades.append(Trade(ticker, quantity))
454
+ return trades
455
+
456
+ def trade47():
457
+ # Sell if the current price is below the previous day's low and the previous day was an up day (a potential reversal)
458
+ trades = []
459
+ for ticker in tickers:
460
+ if prices[ticker][0] < min(prices[ticker][1:2]) and prices[ticker][1] > prices[ticker][2]:
461
+ quantity = random.randrange(-100, -1)
462
+ trades.append(Trade(ticker, quantity))
463
+ return trades
464
+
465
+ def trade48():
466
+ # Buy if the current price is above the 5-day SMA and the 5-day SMA is above the 10-day SMA (a bullish crossover)
467
+ trades = []
468
+ for ticker in tickers:
469
+ sma5 = np.mean(prices[ticker][:5])
470
+ sma10 = np.mean(prices[ticker][:10])
471
+ if prices[ticker][0] > sma5 > sma10:
472
+ quantity = random.randrange(1, 100)
473
+ trades.append(Trade(ticker, quantity))
474
+ return trades
475
+
476
+ def trade49():
477
+ # Sell if the current price is below the 5-day SMA and the 5-day SMA is below the 10-day SMA (a bearish crossover)
478
+ trades = []
479
+ for ticker in tickers:
480
+ sma5 = np.mean(prices[ticker][:5])
481
+ sma10 = np.mean(prices[ticker][:10])
482
+ if prices[ticker][0] < sma5 < sma10:
483
+ quantity = random.randrange(-100, -1)
484
+ trades.append(Trade(ticker, quantity))
485
+ return trades
486
+
487
+ def trade50():
488
+ # Buy if the current price is above the 50-day SMA and the previous price was below the 50-day SMA (a bullish breakthrough)
489
+ trades = []
490
+ for ticker in tickers:
491
+ sma50 = np.mean(prices[ticker][:50])
492
+ if prices[ticker][0] > sma50 and prices[ticker][1] < sma50:
493
+ quantity = random.randrange(1, 100)
494
+ trades.append(Trade(ticker, quantity))
495
+ return trades
496
+
497
+ def trade51():
498
+ # Sell if the current price is below the 50-day SMA and the previous price was above the 50-day SMA (a bearish breakthrough)
499
+ trades = []
500
+ for ticker in tickers:
501
+ sma50 = np.mean(prices[ticker][:50])
502
+ if prices[ticker][0] < sma50 and prices[ticker][1] > sma50:
503
+ quantity = random.randrange(-100, -1)
504
+ trades.append(Trade(ticker, quantity))
505
+ return trades
506
+
507
+ def trade52():
508
+ # Buy if the current price is more than 2 standard deviations below the 20-day mean (a potential oversold condition)
509
+ trades = []
510
+ for ticker in tickers:
511
+ mean20 = np.mean(prices[ticker][:20])
512
+ std20 = np.std(prices[ticker][:20])
513
+ if prices[ticker][0] < mean20 - 2 * std20:
514
+ quantity = random.randrange(1, 100)
515
+ trades.append(Trade(ticker, quantity))
516
+ return trades
517
+
518
+ def trade53():
519
+ # Sell if the current price is more than 2 standard deviations above the 20-day mean (a potential overbought condition)
520
+ trades = []
521
+ for ticker in tickers:
522
+ mean20 = np.mean(prices[ticker][:20])
523
+ std20 = np.std(prices[ticker][:20])
524
+ if prices[ticker][0] > mean20 + 2 * std20:
525
+ quantity = random.randrange(-100, -1)
526
+ trades.append(Trade(ticker, quantity))
527
+ return trades
528
+
529
+ def trade54():
530
+ # Buy if the current price is below the 50-day mean and the 50-day mean is increasing (a potential uptrend)
531
+ trades = []
532
+ for ticker in tickers:
533
+ mean50 = np.mean(prices[ticker][:50])
534
+ prev_mean50 = np.mean(prices[ticker][1:51])
535
+ if prices[ticker][0] < mean50 and mean50 > prev_mean50:
536
+ quantity = random.randrange(1, 100)
537
+ trades.append(Trade(ticker, quantity))
538
+ return trades
539
+
540
+ def trade55():
541
+ # Sell if the current price is above the 50-day mean and the 50-day mean is decreasing (a potential downtrend)
542
+ trades = []
543
+ for ticker in tickers:
544
+ mean50 = np.mean(prices[ticker][:50])
545
+ prev_mean50 = np.mean(prices[ticker][1:51])
546
+ if prices[ticker][0] > mean50 and mean50 < prev_mean50:
547
+ quantity = random.randrange(-100, -1)
548
+ trades.append(Trade(ticker, quantity))
549
+ return trades
550
+
551
+ def trade56():
552
+ # Buy if the 5-day mean is above the 50-day mean and the 5-day mean was previously below the 50-day mean (a potential trend change)
553
+ trades = []
554
+ for ticker in tickers:
555
+ mean5 = np.mean(prices[ticker][:5])
556
+ mean50 = np.mean(prices[ticker][:50])
557
+ prev_mean5 = np.mean(prices[ticker][1:6])
558
+ if mean5 > mean50 and prev_mean5 < mean50:
559
+ quantity = random.randrange(1, 100)
560
+ trades.append(Trade(ticker, quantity))
561
+ return trades
562
+
563
+ def trade57():
564
+ # Sell if the 5-day mean is below the 50-day mean and the 5-day mean was previously above the 50-day mean (a potential trend change)
565
+ trades = []
566
+ for ticker in tickers:
567
+ mean5 = np.mean(prices[ticker][:5])
568
+ mean50 = np.mean(prices[ticker][:50])
569
+ prev_mean5 = np.mean(prices[ticker][1:6])
570
+ if mean5 < mean50 and prev_mean5 > mean50:
571
+ quantity = random.randrange(-100, -1)
572
+ trades.append(Trade(ticker, quantity))
573
+ return trades
574
+
575
+ def trade58():
576
+ # Buy the ticker that has had the largest percent decrease over the last 10 days (a potential mean reversion play)
577
+ percent_changes = {}
578
+ for ticker in tickers:
579
+ percent_changes[ticker] = (prices[ticker][0] - prices[ticker][9]) / prices[ticker][9] * 100
580
+ worst_ticker = min(tickers, key=lambda x: percent_changes[x])
581
+ return [Trade(worst_ticker, 100)]
582
+
583
+ def trade59():
584
+ # Sell the ticker that has had the largest percent increase over the last 10 days (a potential mean reversion play)
585
+ percent_changes = {}
586
+ for ticker in tickers:
587
+ percent_changes[ticker] = (prices[ticker][0] - prices[ticker][9]) / prices[ticker][9] * 100
588
+ best_ticker = max(tickers, key=lambda x: percent_changes[x])
589
+ return [Trade(best_ticker, -100)]
590
+
591
+ def trade60():
592
+ # Buy if the current price is above the 200-day mean and the 200-day mean is increasing (a potential long-term uptrend)
593
+ trades = []
594
+ for ticker in tickers:
595
+ mean200 = np.mean(prices[ticker][:200])
596
+ prev_mean200 = np.mean(prices[ticker][1:201])
597
+ if prices[ticker][0] > mean200 and mean200 > prev_mean200:
598
+ quantity = random.randrange(1, 100)
599
+ trades.append(Trade(ticker, quantity))
600
+ return trades
601
+
602
+ def trade61():
603
+ # Sell if the current price is below the 200-day mean and the 200-day mean is decreasing (a potential long-term downtrend)
604
+ trades = []
605
+ for ticker in tickers:
606
+ mean200 = np.mean(prices[ticker][:200])
607
+ prev_mean200 = np.mean(prices[ticker][1:201])
608
+ if prices[ticker][0] < mean200 and mean200 < prev_mean200:
609
+ quantity = random.randrange(-100, -1)
610
+ trades.append(Trade(ticker, quantity))
611
+ return trades
612
+
613
+ def trade62():
614
+ # Buy if the stock's return is greater than the market's return over the last 5 days
615
+ trades = []
616
+ for ticker in tickers:
617
+ stock_return = (prices[ticker][0] - prices[ticker][4]) / prices[ticker][4]
618
+ market_return = (sum(prices[t][0] for t in tickers) - sum(prices[t][4] for t in tickers)) / sum(prices[t][4] for t in tickers)
619
+ if stock_return > market_return:
620
+ quantity = random.randrange(1, 100)
621
+ trades.append(Trade(ticker, quantity))
622
+ return trades
623
+
624
+ def trade63():
625
+ # Sell if the stock's return is less than the market's return over the last 5 days
626
+ trades = []
627
+ for ticker in tickers:
628
+ stock_return = (prices[ticker][0] - prices[ticker][4]) / prices[ticker][4]
629
+ market_return = (sum(prices[t][0] for t in tickers) - sum(prices[t][4] for t in tickers)) / sum(prices[t][4] for t in tickers)
630
+ if stock_return < market_return:
631
+ quantity = random.randrange(-100, -1)
632
+ trades.append(Trade(ticker, quantity))
633
+ return trades
634
+
635
+ def trade64():
636
+ # Buy the stock with the highest relative strength compared to the market over the last 10 days
637
+ relative_strengths = {}
638
+ for ticker in tickers:
639
+ stock_return = prices[ticker][0] / prices[ticker][9]
640
+ market_return = sum(prices[t][0] for t in tickers) / sum(prices[t][9] for t in tickers)
641
+ relative_strengths[ticker] = stock_return / market_return
642
+ best_ticker = max(tickers, key=lambda x: relative_strengths[x])
643
+ return [Trade(best_ticker, 100)]
644
+
645
+ def trade65():
646
+ # Sell the stock with the lowest relative strength compared to the market over the last 10 days
647
+ relative_strengths = {}
648
+ for ticker in tickers:
649
+ stock_return = prices[ticker][0] / prices[ticker][9]
650
+ market_return = sum(prices[t][0] for t in tickers) / sum(prices[t][9] for t in tickers)
651
+ relative_strengths[ticker] = stock_return / market_return
652
+ worst_ticker = min(tickers, key=lambda x: relative_strengths[x])
653
+ return [Trade(worst_ticker, -100)]
654
+
655
+ def trade66():
656
+ # Buy stocks that have a higher Sharpe ratio than the market over the last 20 days
657
+ trades = []
658
+ market_returns = [(sum(prices[t][i] for t in tickers) / sum(prices[t][i+1] for t in tickers)) - 1 for i in range(19)]
659
+ market_sharpe = np.mean(market_returns) / np.std(market_returns)
660
+ for ticker in tickers:
661
+ stock_returns = [(prices[ticker][i] / prices[ticker][i+1]) - 1 for i in range(19)]
662
+ stock_sharpe = np.mean(stock_returns) / np.std(stock_returns)
663
+ if stock_sharpe > market_sharpe:
664
+ quantity = random.randrange(1, 100)
665
+ trades.append(Trade(ticker, quantity))
666
+ return trades
667
+
668
+ def trade67():
669
+ # Sell stocks that have a lower Sharpe ratio than the market over the last 20 days
670
+ trades = []
671
+ market_returns = [(sum(prices[t][i] for t in tickers) / sum(prices[t][i+1] for t in tickers)) - 1 for i in range(19)]
672
+ market_sharpe = np.mean(market_returns) / np.std(market_returns)
673
+ for ticker in tickers:
674
+ stock_returns = [(prices[ticker][i] / prices[ticker][i+1]) - 1 for i in range(19)]
675
+ stock_sharpe = np.mean(stock_returns) / np.std(stock_returns)
676
+ if stock_sharpe < market_sharpe:
677
+ quantity = random.randrange(-100, -1)
678
+ trades.append(Trade(ticker, quantity))
679
+ return trades
680
+
681
+ def trade68():
682
+ # Buy stocks that have a higher beta than 1 (they move more than the market)
683
+ trades = []
684
+ market_returns = [(sum(prices[t][i] for t in tickers) / sum(prices[t][i+1] for t in tickers)) - 1 for i in range(49)]
685
+ for ticker in tickers:
686
+ stock_returns = [(prices[ticker][i] / prices[ticker][i+1]) - 1 for i in range(49)]
687
+ beta = np.cov(stock_returns, market_returns)[0, 1] / np.var(market_returns)
688
+ if beta > 1:
689
+ quantity = random.randrange(1, 100)
690
+ trades.append(Trade(ticker, quantity))
691
+ return trades
692
+
693
+ def trade69():
694
+ # Sell stocks that have a lower beta than 1 (they move less than the market)
695
+ trades = []
696
+ market_returns = [(sum(prices[t][i] for t in tickers) / sum(prices[t][i+1] for t in tickers)) - 1 for i in range(49)]
697
+ for ticker in tickers:
698
+ stock_returns = [(prices[ticker][i] / prices[ticker][i+1]) - 1 for i in range(49)]
699
+ beta = np.cov(stock_returns, market_returns)[0, 1] / np.var(market_returns)
700
+ if beta < 1:
701
+ quantity = random.randrange(-100, -1)
702
+ trades.append(Trade(ticker, quantity))
703
+ return trades
704
+
705
+ def trade70():
706
+ # Buy stocks that have a higher percentage of up days than the market over the last 50 days
707
+ trades = []
708
+ market_up_days = sum(sum(prices[t][i] for t in tickers) > sum(prices[t][i+1] for t in tickers) for i in range(49))
709
+ for ticker in tickers:
710
+ stock_up_days = sum(prices[ticker][i] > prices[ticker][i+1] for i in range(49))
711
+ if stock_up_days > market_up_days:
712
+ quantity = random.randrange(1, 100)
713
+ trades.append(Trade(ticker, quantity))
714
+ return trades
715
+
716
+ def trade71():
717
+ # Sell stocks that have a lower percentage of up days than the market over the last 50 days
718
+ trades = []
719
+ market_up_days = sum(sum(prices[t][i] for t in tickers) > sum(prices[t][i+1] for t in tickers) for i in range(49))
720
+ for ticker in tickers:
721
+ stock_up_days = sum(prices[ticker][i] > prices[ticker][i+1] for i in range(49))
722
+ if stock_up_days < market_up_days:
723
+ quantity = random.randrange(-100, -1)
724
+ trades.append(Trade(ticker, quantity))
725
+ return trades
extras/trading/trades_gemini.py ADDED
@@ -0,0 +1,534 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # tickers is a list of stock tickers
2
+ import tickers
3
+
4
+ # prices is a dict; the key is a ticker and the value is a list of historic prices, today first
5
+ import prices
6
+
7
+ # Trade represents a decision to buy or sell a quantity of a ticker
8
+ import Trade
9
+
10
+ import random
11
+ import numpy as np
12
+
13
+ def trade2():
14
+ # Buy the stock with the highest price today
15
+ ticker = max(prices, key=lambda t: prices[t][0]) # Find ticker with highest price
16
+ return [Trade(ticker, random.randrange(1, 10))] # Buy a small quantity
17
+
18
+ def trade3():
19
+ # Sell the stock with the lowest price today
20
+ ticker = min(prices, key=lambda t: prices[t][0])
21
+ return [Trade(ticker, random.randrange(-10, -1))]
22
+
23
+ def trade4():
24
+ # Buy the stock with the largest percent increase today
25
+ changes = {t: (prices[t][0] - prices[t][1]) / prices[t][1] for t in prices}
26
+ ticker = max(changes, key=changes.get)
27
+ return [Trade(ticker, random.randrange(1, 10))]
28
+
29
+ def trade5():
30
+ # Sell the stock with the largest percent decrease today
31
+ changes = {t: (prices[t][0] - prices[t][1]) / prices[t][1] for t in prices}
32
+ ticker = min(changes, key=changes.get)
33
+ return [Trade(ticker, random.randrange(-10, -1))]
34
+
35
+ def trade6():
36
+ # Buy the 3 stocks with the highest moving average over the last 5 days
37
+ mvgs = {t: np.mean(prices[t][:5]) for t in prices}
38
+ top_tickers = sorted(mvgs, key=mvgs.get, reverse=True)[:3]
39
+ return [Trade(t, random.randrange(1, 5)) for t in top_tickers]
40
+
41
+ def trade7():
42
+ # Sell the 3 stocks with the lowest moving average over the last 5 days
43
+ mvgs = {t: np.mean(prices[t][:5]) for t in prices}
44
+ bottom_tickers = sorted(mvgs, key=mvgs.get)[:3]
45
+ return [Trade(t, random.randrange(-5, -1)) for t in bottom_tickers]
46
+
47
+ def trade8():
48
+ # Randomly buy or sell a single stock based on a coin flip
49
+ ticker = random.choice(tickers)
50
+ action = random.choice([-1, 1]) # -1 for sell, 1 for buy
51
+ return [Trade(ticker, action * random.randrange(1, 10))]
52
+
53
+ def trade9():
54
+ # Diversify: Buy a small amount of 5 random stocks
55
+ chosen_tickers = random.sample(tickers, 5)
56
+ return [Trade(t, random.randrange(1, 3)) for t in chosen_tickers]
57
+
58
+ def trade10():
59
+ # Follow the trend: If the market is up today, buy, else sell
60
+ market_change = (prices[tickers[0]][0] - prices[tickers[0]][1]) / prices[tickers[0]][1]
61
+ action = 1 if market_change > 0 else -1
62
+ ticker = random.choice(tickers)
63
+ return [Trade(ticker, action * random.randrange(1, 10))]
64
+
65
+ def trade11():
66
+ # Mean Reversion: Buy the 2 stocks that fell the most yesterday, hoping they rebound
67
+ yesterday_changes = {t: (prices[t][1] - prices[t][2]) / prices[t][2] for t in prices}
68
+ bottom_tickers = sorted(yesterday_changes, key=yesterday_changes.get)[:2]
69
+ return [Trade(t, random.randrange(1, 5)) for t in bottom_tickers]
70
+
71
+ def trade12():
72
+ # Momentum: Short the 2 stocks that rose the most yesterday, expecting a pullback
73
+ yesterday_changes = {t: (prices[t][1] - prices[t][2]) / prices[t][2] for t in prices}
74
+ top_tickers = sorted(yesterday_changes, key=yesterday_changes.get, reverse=True)[:2]
75
+ return [Trade(t, random.randrange(-5, -1)) for t in top_tickers]
76
+
77
+ def trade13():
78
+ # Pairs Trading: Long one stock, short another with a similar price history
79
+ correlations = np.corrcoef([prices[t] for t in tickers])
80
+ i, j = np.unravel_index(np.argmax(correlations), correlations.shape)
81
+ return [Trade(tickers[i], 1), Trade(tickers[j], -1)]
82
+
83
+ def trade14():
84
+ # Relative Strength: Go long on the strongest stock, short the weakest
85
+ performances = {t: (prices[t][0] - prices[t][-1]) / prices[t][-1] for t in prices}
86
+ strongest = max(performances, key=performances.get)
87
+ weakest = min(performances, key=performances.get)
88
+ return [Trade(strongest, 1), Trade(weakest, -1)]
89
+
90
+ def trade15():
91
+ # Calendar Spread: Buy this month's option, sell next month's (same strike
92
+ # This is a simplified representation, as actual option trading is more complex
93
+ ticker = random.choice(tickers)
94
+ return [Trade(f"{ticker}_OPT_THIS_MONTH", 1), Trade(f"{ticker}_OPT_NEXT_MONTH", -1)]
95
+
96
+ def trade16():
97
+ # Straddle: Buy both a call and put option on the same stock (same strike
98
+ ticker = random.choice(tickers)
99
+ strike = prices[ticker][0] # Use the current price as a simple strike price
100
+ return [Trade(f"{ticker}_CALL_{strike}", 1), Trade(f"{ticker}_PUT_{strike}", 1)]
101
+
102
+ def trade17():
103
+ # Breakout: Buy if a stock breaks above its 52-week high
104
+ ticker = random.choice(tickers)
105
+ if prices[ticker][0] > max(prices[ticker]):
106
+ return [Trade(ticker, random.randrange(1, 10))]
107
+ else:
108
+ return []
109
+
110
+ def trade18():
111
+ # Volatility: If market volatility is high, sell (expecting it to decrease
112
+ market_volatility = np.std([prices[t][0] / prices[t][1] for t in tickers])
113
+ if market_volatility > 0.05: # You'd adjust this threshold based on your risk tolerance
114
+ ticker = random.choice(tickers)
115
+ return [Trade(ticker, random.randrange(-10, -1))]
116
+ else:
117
+ return []
118
+
119
+ def trade19():
120
+ # Golden Cross: Buy if the short-term moving average crosses above the long-term
121
+ ticker = random.choice(tickers)
122
+ short_ma = np.mean(prices[ticker][:5])
123
+ long_ma = np.mean(prices[ticker][:20])
124
+ if short_ma > long_ma and short_ma - long_ma < 0.01: # Small margin to avoid false signals
125
+ return [Trade(ticker, random.randrange(1, 10))]
126
+ else:
127
+ return []
128
+
129
+ def trade20():
130
+ # Death Cross: Sell if the short-term moving average crosses below the long-term
131
+ ticker = random.choice(tickers)
132
+ short_ma = np.mean(prices[ticker][:5])
133
+ long_ma = np.mean(prices[ticker][:20])
134
+ if short_ma < long_ma and long_ma - short_ma < 0.01:
135
+ return [Trade(ticker, random.randrange(-10, -1))]
136
+ else:
137
+ return []
138
+
139
+ def trade21():
140
+ # Correlated Pairs Buy: Buy a pair of stocks that have historically moved together
141
+ correlations = np.corrcoef([prices[t] for t in tickers])
142
+ i, j = np.unravel_index(np.argmax(correlations), correlations.shape)
143
+ return [Trade(tickers[i], 1), Trade(tickers[j], 1)]
144
+
145
+ def trade22():
146
+ # Correlated Pairs Sell: Sell a pair of stocks that have historically moved together
147
+ correlations = np.corrcoef([prices[t] for t in tickers])
148
+ i, j = np.unravel_index(np.argmax(correlations), correlations.shape)
149
+ return [Trade(tickers[i], -1), Trade(tickers[j], -1)]
150
+
151
+ def trade23():
152
+ # Contrarian Pairs Buy: Buy a stock that's down while its correlated pair is up
153
+ correlations = np.corrcoef([prices[t] for t in tickers])
154
+ i, j = np.unravel_index(np.argmax(correlations), correlations.shape)
155
+ if prices[tickers[i]][0] < prices[tickers[i]][1] and prices[tickers[j]][0] > prices[tickers[j]][1]:
156
+ return [Trade(tickers[i], 1)]
157
+ else:
158
+ return []
159
+
160
+ def trade24():
161
+ # Contrarian Pairs Sell: Sell a stock that's up while its correlated pair is down
162
+ correlations = np.corrcoef([prices[t] for t in tickers])
163
+ i, j = np.unravel_index(np.argmax(correlations), correlations.shape)
164
+ if prices[tickers[i]][0] > prices[tickers[i]][1] and prices[tickers[j]][0] < prices[tickers[j]][1]:
165
+ return [Trade(tickers[i], -1)]
166
+ else:
167
+ return []
168
+
169
+ def trade25():
170
+ # Correlation Reversal: Buy a stock that's recently become less correlated with the market
171
+ # This is a simplified version, you'd likely use a rolling correlation window
172
+ market_prices = [prices[t] for t in tickers]
173
+ correlations_today = np.corrcoef(market_prices)
174
+ correlations_yesterday = np.corrcoef([p[1:] for p in market_prices])
175
+ diffs = correlations_today - correlations_yesterday
176
+ i, j = np.unravel_index(np.argmin(diffs), diffs.shape)
177
+ if i != j: # Ensure we're not comparing a stock to itself
178
+ return [Trade(tickers[i], 1)]
179
+ else:
180
+ return []
181
+
182
+ def trade26():
183
+ # Sector Rotation: Buy the top 2 stocks from the sector that's most correlated with the market
184
+ # Assuming you have sector data (e.g., 'sector_map' dict: ticker -> sector)
185
+ sector_returns = {s: np.mean([(prices[t][0] - prices[t][1]) / prices[t][1] for t in tickers if sector_map[t] == s]) for s in set(sector_map.values())}
186
+ top_sector = max(sector_returns, key=sector_returns.get)
187
+ top_tickers_in_sector = sorted([(t, prices[t][0]) for t in tickers if sector_map[t] == top_sector], key=lambda x: x[1], reverse=True)[:2]
188
+ return [Trade(t, 1) for t, _ in top_tickers_in_sector]
189
+
190
+ def trade27():
191
+ # Beta-Weighted Portfolio: Allocate more to stocks with higher betas (more volatile
192
+ # You'd need historical market data to calculate betas
193
+ betas = {t: random.uniform(0.5, 2) for t in tickers} # Placeholder for actual betas
194
+ total_beta = sum(betas.values())
195
+ allocations = {t: betas[t] / total_beta * 100 for t in tickers}
196
+ return [Trade(t, int(allocations[t])) for t in tickers]
197
+
198
+ def trade28():
199
+ # Diversified Portfolio: Buy a mix of stocks with low correlations to each other
200
+ correlations = np.corrcoef([prices[t] for t in tickers])
201
+ chosen_tickers = []
202
+ while len(chosen_tickers) < 5 and len(tickers) > 0:
203
+ t = random.choice(tickers)
204
+ if all(correlations[tickers.index(t)][tickers.index(c)] < 0.5 for c in chosen_tickers):
205
+ chosen_tickers.append(t)
206
+ tickers.remove(t)
207
+ return [Trade(t, random.randrange(1, 3)) for t in chosen_tickers]
208
+
209
+ def trade29():
210
+ # Cointegration: Find a pair of stocks that are cointegrated and trade their spread
211
+ # This requires more complex analysis (e.g., using the Johansen test)
212
+ # For simplicity, we'll just pick a random pair and assume cointegration
213
+ i, j = random.sample(range(len(tickers)), 2)
214
+ spread = prices[tickers[i]][0] - prices[tickers[j]][0]
215
+ if spread > 0:
216
+ return [Trade(tickers[i], -1), Trade(tickers[j], 1)]
217
+ else:
218
+ return [Trade(tickers[i], 1), Trade(tickers[j], -1)]
219
+
220
+ def trade30():
221
+ # Basket Trading: Buy or sell a basket of stocks based on their correlation to a benchmark
222
+ # You'd need a benchmark ticker and its historical prices
223
+ benchmark = "SPY"
224
+ correlations = np.corrcoef([prices[t] for t in tickers + [benchmark]])[:-1, -1] # Correlate each stock with the benchmark
225
+ if np.mean(correlations) > 0.5:
226
+ return [Trade(t, 1) for t in tickers]
227
+ else:
228
+ return [Trade(t, -1) for t in tickers]
229
+
230
+ def trade31():
231
+ # Double Bottom: Buy when a stock forms a double bottom pattern
232
+ ticker = random.choice(tickers)
233
+ if prices[ticker][0] < prices[ticker][2] < prices[ticker][4] and prices[ticker][1] > prices[ticker][3]:
234
+ return [Trade(ticker, 1)]
235
+ else:
236
+ return []
237
+
238
+ def trade32():
239
+ # Double Top: Sell when a stock forms a double top pattern
240
+ ticker = random.choice(tickers)
241
+ if prices[ticker][0] > prices[ticker][2] > prices[ticker][4] and prices[ticker][1] < prices[ticker][3]:
242
+ return [Trade(ticker, -1)]
243
+ else:
244
+ return []
245
+
246
+ def trade33():
247
+ # Head and Shoulders: Sell when a stock forms a head and shoulders pattern
248
+ ticker = random.choice(tickers)
249
+ if prices[ticker][0] < prices[ticker][2] < prices[ticker][4] and prices[ticker][1] > prices[ticker][3] > prices[ticker][5]:
250
+ return [Trade(ticker, -1)]
251
+ else:
252
+ return []
253
+
254
+ def trade34
255
+ # Inverse Head and Shoulders: Buy when a stock forms an inverse head and shoulders pattern
256
+ ticker = random.choice(tickers)
257
+ if prices[ticker][0] > prices[ticker][2] > prices[ticker][4] and prices[ticker][1] < prices[ticker][3] < prices[ticker][5]:
258
+ return [Trade(ticker, 1)]
259
+ else:
260
+ return []
261
+
262
+ def trade35():
263
+ # Ascending Triangle: Buy when a stock forms an ascending triangle pattern
264
+ ticker = random.choice(tickers)
265
+ # Simplified logic: check for higher lows and flat highs
266
+ if prices[ticker][0] > prices[ticker][2] > prices[ticker][4] and prices[ticker][1] == prices[ticker][3] == prices[ticker][5]:
267
+ return [Trade(ticker, 1)]
268
+ else:
269
+ return []
270
+
271
+ def trade36():
272
+ # Descending Triangle: Sell when a stock forms a descending triangle pattern
273
+ ticker = random.choice(tickers)
274
+ # Simplified logic: check for lower highs and flat lows
275
+ if prices[ticker][0] < prices[ticker][2] < prices[ticker][4] and prices[ticker][1] == prices[ticker][3] == prices[ticker][5]:
276
+ return [Trade(ticker, -1)]
277
+ else:
278
+ return []
279
+
280
+ def trade37():
281
+ # Flag/Pennant: Buy or sell based on the direction of the flag/pennant pattern
282
+ ticker = random.choice(tickers)
283
+ # Simplified logic: check for a consolidation period after a strong move
284
+ if abs(prices[ticker][0] - np.mean(prices[ticker][1:5])) < 0.05 and abs(prices[ticker][5] - prices[ticker][6]) > 0.1:
285
+ # Buy if the prior move was up, sell if down
286
+ return [Trade(ticker, 1 if prices[ticker][5] > prices[ticker][6] else -1)]
287
+ else:
288
+ return []
289
+
290
+ def trade38():
291
+ # Gap Up: Buy when a stock opens significantly higher than its previous close
292
+ ticker = random.choice(tickers)
293
+ if prices[ticker][0] > prices[ticker][1] * 1.05: # 5% gap up
294
+ return [Trade(ticker, 1)]
295
+ else:
296
+ return []
297
+
298
+ def trade39():
299
+ # Gap Down: Sell when a stock opens significantly lower than its previous close
300
+ ticker = random.choice(tickers)
301
+ if prices[ticker][0] < prices[ticker][1] * 0.95: # 5% gap down
302
+ return [Trade(ticker, -1)]
303
+ else:
304
+ return []
305
+
306
+ def trade40():
307
+ # Rounding Bottom: Buy when a stock forms a rounding bottom pattern
308
+ ticker = random.choice(tickers)
309
+ # Simplified logic: check for a gradual price increase after a period of decline
310
+ if prices[ticker][0] > prices[ticker][2] > prices[ticker][4] and prices[ticker][1] < prices[ticker][3] < prices[ticker][5]:
311
+ return [Trade(ticker, 1)]
312
+ else:
313
+ return []
314
+
315
+ def trade41():
316
+ # Overbought/Oversold (RSI): Sell if RSI is above 70, buy if below 30
317
+ ticker = random.choice(tickers)
318
+ rsi = calculate_rsi(prices[ticker], 14) # Assuming you have an RSI calculation function
319
+ if rsi > 70:
320
+ return [Trade(ticker, -1)]
321
+ elif rsi < 30:
322
+ return [Trade(ticker, 1)]
323
+ else:
324
+ return []
325
+
326
+ def trade42():
327
+ # Bollinger Bands Breakout: Buy if price breaks above the upper band, sell if below lower
328
+ ticker = random.choice(tickers)
329
+ upper, middle, lower = calculate_bollinger_bands(prices[ticker], 20, 2) # Assuming you have a Bollinger Band calculation function
330
+ if prices[ticker][0] > upper:
331
+ return [Trade(ticker, 1)]
332
+ elif prices[ticker][0] < lower:
333
+ return [Trade(ticker, -1)]
334
+ else:
335
+ return []
336
+
337
+ def trade43():
338
+ # Channel Breakout: Buy or sell when price breaks out of a recent price channel
339
+ ticker = random.choice(tickers)
340
+ highs = [max(prices[ticker][i:i+5]) for i in range(len(prices[ticker]) - 5)]
341
+ lows = [min(prices[ticker][i:i+5]) for i in range(len(prices[ticker]) - 5)]
342
+ if prices[ticker][0] > highs[-1]:
343
+ return [Trade(ticker, 1)]
344
+ elif prices[ticker][0] < lows[-1]:
345
+ return [Trade(ticker, -1)]
346
+ else:
347
+ return []
348
+
349
+ def trade44():
350
+ # Trend Following: Buy if the 20-day moving average is rising, sell if falling
351
+ ticker = random.choice(tickers)
352
+ ma20_today = np.mean(prices[ticker][:20])
353
+ ma20_yesterday = np.mean(prices[ticker][1:21])
354
+ if ma20_today > ma20_yesterday:
355
+ return [Trade(ticker, 1)]
356
+ elif ma20_today < ma20_yesterday:
357
+ return [Trade(ticker, -1)]
358
+ else:
359
+ return []
360
+
361
+ def trade45():
362
+ # MACD Crossover: Buy when MACD line crosses above signal line, sell when below
363
+ ticker = random.choice(tickers)
364
+ macd_line, signal_line = calculate_macd(prices[ticker]) # Assuming you have a MACD calculation function
365
+ if macd_line[-1] > signal_line[-1] and macd_line[-2] <= signal_line[-2]:
366
+ return [Trade(ticker, 1)]
367
+ elif macd_line[-1] < signal_line[-1] and macd_line[-2] >= signal_line[-2]:
368
+ return [Trade(ticker, -1)]
369
+ else:
370
+ return []
371
+
372
+ def trade46():
373
+ # Stochastic Oscillator: Buy if %K crosses above %D in oversold zone, sell if opposite
374
+ ticker = random.choice(tickers)
375
+ k_line, d_line = calculate_stochastic(prices[ticker]) # Assuming you have a Stochastic calculation function
376
+ if k_line[-1] > d_line[-1] and k_line[-1] < 20:
377
+ return [Trade(ticker, 1)]
378
+ elif k_line[-1] < d_line[-1] and k_line[-1] > 80:
379
+ return [Trade(ticker, -1)]
380
+ else:
381
+ return []
382
+
383
+ def trade47():
384
+ # Volume Spike: Buy if today's volume is much higher than the average
385
+ # You'd need volume data for this strategy
386
+ ticker = random.choice(tickers)
387
+ avg_volume = np.mean(volumes[ticker][1:]) # Assuming you have 'volumes' data
388
+ if volumes[ticker][0] > avg_volume * 2:
389
+ return [Trade(ticker, 1)]
390
+ else:
391
+ return []
392
+
393
+ def trade48():
394
+ # Price Spike: Buy if today's price increase is much higher than average daily change
395
+ ticker = random.choice(tickers)
396
+ daily_changes = [(prices[ticker][i] - prices[ticker][i + 1]) / prices[ticker][i + 1] for i in range(len(prices[ticker]) - 1)]
397
+ avg_change = np.mean(daily_changes)
398
+ today_change = (prices[ticker][0] - prices[ticker][1]) / prices[ticker][1]
399
+ if today_change > avg_change * 2:
400
+ return [Trade(ticker, 1)]
401
+ else:
402
+ return []
403
+
404
+ def trade49():
405
+ # Mean Reversion (Long-term): Buy if the price is below its 200-day moving average
406
+ ticker = random.choice(tickers)
407
+ ma200 = np.mean(prices[ticker])
408
+ if prices[ticker][0] < ma200:
409
+ return [Trade(ticker, 1)]
410
+ else:
411
+ return []
412
+
413
+ def trade50():
414
+ # Trend Reversal (Parabolic SAR): Buy or sell based on the Parabolic SAR indicator
415
+ # Assuming you have a Parabolic SAR calculation function
416
+ ticker = random.choice(tickers)
417
+ sar = calculate_parabolic_sar(prices[ticker])
418
+ if prices[ticker][0] > sar[-1]:
419
+ return [Trade(ticker, 1)]
420
+ elif prices[ticker][0] < sar[-1]:
421
+ return [Trade(ticker, -1)]
422
+ else:
423
+ return []
424
+
425
+ def trade51():
426
+ # Market Outperformance: Buy stocks whose daily returns beat the market
427
+ total_market_values = [sum(prices[t][i] for t in tickers) for i in range(len(prices[tickers[0]]))]
428
+ market_return = (total_market_values[0] - total_market_values[1]) / total_market_values[1]
429
+ outperformers = [t for t in tickers if (prices[t][0] - prices[t][1]) / prices[t][1] > market_return]
430
+ if outperformers:
431
+ ticker = random.choice(outperformers)
432
+ return [Trade(ticker, 1)]
433
+ else:
434
+ return []
435
+
436
+ def trade52():
437
+ # Market Underperformance: Short stocks whose daily returns lag the market
438
+ total_market_values = [sum(prices[t][i] for t in tickers) for i in range(len(prices[tickers[0]]))]
439
+ market_return = (total_market_values[0] - total_market_values[1]) / total_market_values[1]
440
+ underperformers = [t for t in tickers if (prices[t][0] - prices[t][1]) / prices[t][1] < market_return]
441
+ if underperformers:
442
+ ticker = random.choice(underperformers)
443
+ return [Trade(ticker, -1)]
444
+ else:
445
+ return []
446
+
447
+ def trade53():
448
+ # Relative Strength to Market: Buy the stock with the highest relative strength to the market
449
+ total_market_values = [sum(prices[t][i] for t in tickers) for i in range(len(prices[tickers[0]]))]
450
+ market_return = (total_market_values[0] - total_market_values[1]) / total_market_values[1]
451
+ relative_strengths = {t: ((prices[t][0] - prices[t][1]) / prices[t][1]) - market_return for t in tickers}
452
+ ticker = max(relative_strengths, key=relative_strengths.get)
453
+ return [Trade(ticker, 1)]
454
+
455
+ def trade54():
456
+ # Relative Weakness to Market: Short the stock with the lowest relative strength to the market
457
+ total_market_values = [sum(prices[t][i] for t in tickers) for i in range(len(prices[tickers[0]]))]
458
+ market_return = (total_market_values[0] - total_market_values[1]) / total_market_values[1]
459
+ relative_strengths = {t: ((prices[t][0] - prices[t][1]) / prices[t][1]) - market_return for t in tickers}
460
+ ticker = min(relative_strengths, key=relative_strengths.get)
461
+ return [Trade(ticker, -1)]
462
+
463
+ def trade55():
464
+ # Sector vs. Market: Buy top stock from sector outperforming the market, short from underperforming
465
+ # Assuming you have sector data (e.g., 'sector_map' dict: ticker -> sector)
466
+ total_market_values = [sum(prices[t][i] for t in tickers) for i in range(len(prices[tickers[0]]))]
467
+ market_return = (total_market_values[0] - total_market_values[1]) / total_market_values[1]
468
+ sector_returns = {s: np.mean([(prices[t][0] - prices[t][1]) / prices[t][1] for t in tickers if sector_map[t] == s]) for s in set(sector_map.values())}
469
+ outperforming_sectors = [s for s in sector_returns if sector_returns[s] > market_return]
470
+ underperforming_sectors = [s for s in sector_returns if sector_returns[s] < market_return]
471
+ trades = []
472
+ if outperforming_sectors:
473
+ top_ticker = max([(t, prices[t][0]) for t in tickers if sector_map[t] == random.choice(outperforming_sectors)], key=lambda x: x[1])[0]
474
+ trades.append(Trade(top_ticker, 1))
475
+ if underperforming_sectors:
476
+ bottom_ticker = min([(t, prices[t][0]) for t in tickers if sector_map[t] == random.choice(underperforming_sectors)], key=lambda x: x[1])[0]
477
+ trades.append(Trade(bottom_ticker, -1))
478
+ return trades
479
+
480
+ def trade56():
481
+ # Market-Neutral Pairs: Long/short pairs of stocks with similar market betas
482
+ betas = {t: random.uniform(0.8, 1.2) for t in tickers} # Placeholder, calculate actual betas
483
+ pairs = [(t1, t2) for t1 in tickers for t2 in tickers if abs(betas[t1] - betas[t2]) < 0.1 and t1 != t2]
484
+ if pairs:
485
+ t1, t2 = random.choice(pairs)
486
+ return [Trade(t1, 1), Trade(t2, -1)]
487
+ else:
488
+ return []
489
+
490
+ def trade57():
491
+ # Beta Rotation: Buy high-beta stocks if the market is rising, low-beta if falling
492
+ total_market_values = [sum(prices[t][i] for t in tickers) for i in range(len(prices[tickers[0]]))]
493
+ market_return = (total_market_values[0] - total_market_values[1]) / total_market_values[1]
494
+ betas = {t: random.uniform(0.5, 2) for t in tickers} # Placeholder, calculate actual betas
495
+ if market_return > 0: # Market is rising
496
+ target_beta = 1.5 # Example target for high-beta
497
+ else:
498
+ target_beta = 0.8 # Example target for low-beta
499
+ closest_ticker = min(tickers, key=lambda t: abs(betas[t] - target_beta))
500
+ return [Trade(closest_ticker, 1 if market_return > 0 else -1)] # Buy if rising, short if falling
501
+
502
+ def trade58():
503
+ # Market Timing with Relative Strength: Buy strong stocks in up markets, sell in down markets
504
+ total_market_values = [sum(prices[t][i] for t in tickers) for i in range(len(prices[tickers[0]]))]
505
+ market_return = (total_market_values[0] - total_market_values[1]) / total_market_values[1]
506
+ relative_strengths = {t: ((prices[t][0] - prices[t][-1]) / prices[t][-1]) for t in tickers} # Calculate over a longer period (e.g., 20 days)
507
+ if market_return > 0:
508
+ strongest = max(relative_strengths, key=relative_strengths.get)
509
+ return [Trade(strongest, 1)]
510
+ else:
511
+ weakest = min(relative_strengths, key=relative_strengths.get)
512
+ return [Trade(weakest, -1)]
513
+
514
+ def trade59():
515
+ # Relative Value to Market: Buy stocks trading below their historical average relative to the market
516
+ # Requires historical data to calculate averages
517
+ total_market_values = [sum(prices[t][i] for t in tickers) for i in range(len(prices[tickers[0]]))]
518
+ relative_values = {t: prices[t][0] / total_market_values[0] for t in tickers} # Current relative value
519
+ historical_averages = {t: 0.05 for t in tickers} # Placeholder, calculate actual averages
520
+ undervalued = [t for t in tickers if relative_values[t] < historical_averages[t] * 0.95] # Allow some buffer
521
+ if undervalued:
522
+ ticker = random.choice(undervalued)
523
+ return [Trade(ticker, 1)]
524
+ else:
525
+ return []
526
+
527
+ def trade60():
528
+ # Market-Cap Weighted: Allocate trade amounts proportional to each stock's market cap relative to total market
529
+ total_market_value = sum(prices[t][0] for t in tickers)
530
+ market_caps = {t: prices[t][0] * 1000 for t in tickers} # Assuming 1000 shares outstanding for each stock
531
+ weights = {t: market_caps[t] / total_market_value for t in tickers}
532
+ total_trade_amount = 100 # Example
533
+ trades = [Trade(t, int(weights[t] * total_trade_amount)) for t in tickers]
534
+ return trades
extras/trading/trades_gpt-4o.py ADDED
@@ -0,0 +1,884 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # tickers is a list of stock tickers
2
+ import tickers
3
+
4
+ # prices is a dict; the key is a ticker and the value is a list of historic prices, today first
5
+ import prices
6
+
7
+ # Trade represents a decision to buy or sell a quantity of a ticker
8
+ import Trade
9
+
10
+ import random
11
+ import numpy as np
12
+
13
+ def trade2():
14
+ # Buy top performing stock in the last 5 days
15
+ avg_prices = {ticker: np.mean(prices[ticker][:5]) for ticker in tickers}
16
+ best_ticker = max(avg_prices, key=avg_prices.get)
17
+ trade = Trade(best_ticker, 100)
18
+ return [trade]
19
+
20
+ def trade3():
21
+ # Sell worst performing stock in the last 5 days
22
+ avg_prices = {ticker: np.mean(prices[ticker][:5]) for ticker in tickers}
23
+ worst_ticker = min(avg_prices, key=avg_prices.get)
24
+ trade = Trade(worst_ticker, -100)
25
+ return [trade]
26
+
27
+ def trade4():
28
+ # Buy random stock from top 5 performing in the last 10 days
29
+ avg_prices = {ticker: np.mean(prices[ticker][:10]) for ticker in tickers}
30
+ top_5_tickers = sorted(avg_prices, key=avg_prices.get, reverse=True)[:5]
31
+ ticker = random.choice(top_5_tickers)
32
+ trade = Trade(ticker, 100)
33
+ return [trade]
34
+
35
+ def trade5():
36
+ # Sell random stock from bottom 5 performing in the last 10 days
37
+ avg_prices = {ticker: np.mean(prices[ticker][:10]) for ticker in tickers}
38
+ bottom_5_tickers = sorted(avg_prices, key=avg_prices.get)[:5]
39
+ ticker = random.choice(bottom_5_tickers)
40
+ trade = Trade(ticker, -100)
41
+ return [trade]
42
+
43
+ def trade6():
44
+ # Buy stocks with a positive trend over the last 7 days
45
+ trending_up = [ticker for ticker in tickers if prices[ticker][0] > prices[ticker][6]]
46
+ ticker = random.choice(trending_up)
47
+ trade = Trade(ticker, 100)
48
+ return [trade]
49
+
50
+ def trade7():
51
+ # Sell stocks with a negative trend over the last 7 days
52
+ trending_down = [ticker for ticker in tickers if prices[ticker][0] < prices[ticker][6]]
53
+ ticker = random.choice(trending_down)
54
+ trade = Trade(ticker, -100)
55
+ return [trade]
56
+
57
+ def trade8():
58
+ # Buy stocks with the lowest volatility over the last 20 days
59
+ volatilities = {ticker: np.std(prices[ticker][:20]) for ticker in tickers}
60
+ least_volatile = min(volatilities, key=volatilities.get)
61
+ trade = Trade(least_volatile, 100)
62
+ return [trade]
63
+
64
+ def trade9():
65
+ # Sell stocks with the highest volatility over the last 20 days
66
+ volatilities = {ticker: np.std(prices[ticker][:20]) for ticker in tickers}
67
+ most_volatile = max(volatilities, key=volatilities.get)
68
+ trade = Trade(most_volatile, -100)
69
+ return [trade]
70
+
71
+ def trade10():
72
+ # Random mixed strategy: randomly buy or sell a random stock
73
+ ticker = random.choice(tickers)
74
+ quantity = random.choice([-100, 100])
75
+ trade = Trade(ticker, quantity)
76
+ return [trade]
77
+
78
+ def trade11():
79
+ # Buy the top 3 performing stocks in the last 15 days
80
+ avg_prices = {ticker: np.mean(prices[ticker][:15]) for ticker in tickers}
81
+ top_3_tickers = sorted(avg_prices, key=avg_prices.get, reverse=True)[:3]
82
+ trades = [Trade(ticker, 100) for ticker in top_3_tickers]
83
+ return trades
84
+
85
+ def trade12():
86
+ # Sell the bottom 3 performing stocks in the last 15 days
87
+ avg_prices = {ticker: np.mean(prices[ticker][:15]) for ticker in tickers}
88
+ bottom_3_tickers = sorted(avg_prices, key=avg_prices.get)[:3]
89
+ trades = [Trade(ticker, -100) for ticker in bottom_3_tickers]
90
+ return trades
91
+
92
+ def trade13():
93
+ # Buy 2 random stocks with the highest increase in price in the last 10 days
94
+ price_increases = {ticker: prices[ticker][0] - prices[ticker][9] for ticker in tickers}
95
+ top_2_increases = sorted(price_increases, key=price_increases.get, reverse=True)[:2]
96
+ trades = [Trade(ticker, 100) for ticker in top_2_increases]
97
+ return trades
98
+
99
+ def trade14():
100
+ # Sell 2 random stocks with the highest decrease in price in the last 10 days
101
+ price_decreases = {ticker: prices[ticker][0] - prices[ticker][9] for ticker in tickers}
102
+ top_2_decreases = sorted(price_decreases, key=price_decreases.get)[:2]
103
+ trades = [Trade(ticker, -100) for ticker in top_2_decreases]
104
+ return trades
105
+
106
+ def trade15():
107
+ # Buy stocks that have shown the highest volatility in the last 30 days
108
+ volatilities = {ticker: np.std(prices[ticker][:30]) for ticker in tickers}
109
+ high_volatility_tickers = sorted(volatilities, key=volatilities.get, reverse=True)[:3]
110
+ trades = [Trade(ticker, 100) for ticker in high_volatility_tickers]
111
+ return trades
112
+
113
+ def trade16():
114
+ # Sell stocks that have shown the lowest volatility in the last 30 days
115
+ volatilities = {ticker: np.std(prices[ticker][:30]) for ticker in tickers}
116
+ low_volatility_tickers = sorted(volatilities, key=volatilities.get)[:3]
117
+ trades = [Trade(ticker, -100) for ticker in low_volatility_tickers]
118
+ return trades
119
+
120
+ def trade17():
121
+ # Buy stocks with prices above their 50-day moving average
122
+ ma_50 = {ticker: np.mean(prices[ticker][:50]) for ticker in tickers}
123
+ above_ma_tickers = [ticker for ticker in tickers if prices[ticker][0] > ma_50[ticker]]
124
+ trades = [Trade(ticker, 100) for ticker in random.sample(above_ma_tickers, min(3, len(above_ma_tickers)))]
125
+ return trades
126
+
127
+ def trade18():
128
+ # Sell stocks with prices below their 50-day moving average
129
+ ma_50 = {ticker: np.mean(prices[ticker][:50]) for ticker in tickers}
130
+ below_ma_tickers = [ticker for ticker in tickers if prices[ticker][0] < ma_50[ticker]]
131
+ trades = [Trade(ticker, -100) for ticker in random.sample(below_ma_tickers, min(3, len(below_ma_tickers)))]
132
+ return trades
133
+
134
+ def trade19():
135
+ # Mixed strategy: buy 2 random stocks and sell 2 random stocks
136
+ buy_tickers = random.sample(tickers, 2)
137
+ sell_tickers = random.sample([ticker for ticker in tickers if ticker not in buy_tickers], 2)
138
+ trades = [Trade(ticker, 100) for ticker in buy_tickers] + [Trade(ticker, -100) for ticker in sell_tickers]
139
+ return trades
140
+
141
+ def trade20():
142
+ # Buy stocks that have positive return in the last 20 days and sell those with negative return
143
+ returns = {ticker: (prices[ticker][0] - prices[ticker][19]) / prices[ticker][19] for ticker in tickers}
144
+ buy_tickers = [ticker for ticker in tickers if returns[ticker] > 0]
145
+ sell_tickers = [ticker for ticker in tickers if returns[ticker] < 0]
146
+ trades = [Trade(ticker, 100) for ticker in random.sample(buy_tickers, min(2, len(buy_tickers)))] + \
147
+ [Trade(ticker, -100) for ticker in random.sample(sell_tickers, min(2, len(sell_tickers)))]
148
+ return trades
149
+
150
+ def trade21():
151
+ # Buy the top performing stock in the last 3 days
152
+ avg_prices = {ticker: np.mean(prices[ticker][:3]) for ticker in tickers}
153
+ best_ticker = max(avg_prices, key=avg_prices.get)
154
+ trade = Trade(best_ticker, 100)
155
+ return [trade]
156
+
157
+ def trade22():
158
+ # Sell the worst performing stock in the last 3 days
159
+ avg_prices = {ticker: np.mean(prices[ticker][:3]) for ticker in tickers}
160
+ worst_ticker = min(avg_prices, key=avg_prices.get)
161
+ trade = Trade(worst_ticker, -100)
162
+ return [trade]
163
+
164
+ def trade23():
165
+ # Buy stocks that have not changed price in the last 7 days
166
+ stable_tickers = [ticker for ticker in tickers if prices[ticker][0] == prices[ticker][6]]
167
+ trades = [Trade(ticker, 100) for ticker in random.sample(stable_tickers, min(3, len(stable_tickers)))]
168
+ return trades
169
+
170
+ def trade24():
171
+ # Sell stocks that have the smallest price change in the last 5 days
172
+ smallest_changes = sorted(tickers, key=lambda t: abs(prices[t][0] - prices[t][4]))[:3]
173
+ trades = [Trade(ticker, -100) for ticker in smallest_changes]
174
+ return trades
175
+
176
+ def trade25():
177
+ # Buy random stocks from the top 10 highest priced stocks
178
+ highest_priced = sorted(tickers, key=lambda t: prices[t][0], reverse=True)[:10]
179
+ ticker = random.choice(highest_priced)
180
+ trade = Trade(ticker, 100)
181
+ return [trade]
182
+
183
+ def trade26():
184
+ # Sell random stocks from the bottom 10 lowest priced stocks
185
+ lowest_priced = sorted(tickers, key=lambda t: prices[t][0])[:10]
186
+ ticker = random.choice(lowest_priced)
187
+ trade = Trade(ticker, -100)
188
+ return [trade]
189
+
190
+ def trade27():
191
+ # Buy 2 stocks with the highest momentum (last 5 days)
192
+ momentums = {ticker: prices[ticker][0] - prices[ticker][4] for ticker in tickers}
193
+ top_momentum_tickers = sorted(momentums, key=momentums.get, reverse=True)[:2]
194
+ trades = [Trade(ticker, 100) for ticker in top_momentum_tickers]
195
+ return trades
196
+
197
+ def trade28():
198
+ # Sell 2 stocks with the lowest momentum (last 5 days)
199
+ momentums = {ticker: prices[ticker][0] - prices[ticker][4] for ticker in tickers}
200
+ lowest_momentum_tickers = sorted(momentums, key=momentums.get)[:2]
201
+ trades = [Trade(ticker, -100) for ticker in lowest_momentum_tickers]
202
+ return trades
203
+
204
+ def trade29():
205
+ # Buy the stock with the highest daily price increase yesterday
206
+ yesterday_increase = {ticker: prices[ticker][1] - prices[ticker][2] for ticker in tickers}
207
+ best_yesterday_ticker = max(yesterday_increase, key=yesterday_increase.get)
208
+ trade = Trade(best_yesterday_ticker, 100)
209
+ return [trade]
210
+
211
+ def trade30():
212
+ # Sell the stock with the highest daily price decrease yesterday
213
+ yesterday_decrease = {ticker: prices[ticker][1] - prices[ticker][2] for ticker in tickers}
214
+ worst_yesterday_ticker = min(yesterday_decrease, key=yesterday_decrease.get)
215
+ trade = Trade(worst_yesterday_ticker, -100)
216
+ return [trade]
217
+
218
+ def trade31():
219
+ # Long/short strategy: Buy the top performing stock and sell the worst performing stock over the last 7 days
220
+ avg_prices = {ticker: np.mean(prices[ticker][:7]) for ticker in tickers}
221
+ best_ticker = max(avg_prices, key=avg_prices.get)
222
+ worst_ticker = min(avg_prices, key=avg_prices.get)
223
+ trades = [Trade(best_ticker, 100), Trade(worst_ticker, -100)]
224
+ return trades
225
+
226
+ def trade32():
227
+ # Buy stocks that have had a positive return in the last 5 days and sell those with a negative return
228
+ returns = {ticker: (prices[ticker][0] - prices[ticker][4]) / prices[ticker][4] for ticker in tickers}
229
+ buy_tickers = [ticker for ticker in tickers if returns[ticker] > 0]
230
+ sell_tickers = [ticker for ticker in tickers if returns[ticker] < 0]
231
+ trades = [Trade(ticker, 100) for ticker in random.sample(buy_tickers, min(2, len(buy_tickers)))] + \
232
+ [Trade(ticker, -100) for ticker in random.sample(sell_tickers, min(2, len(sell_tickers)))]
233
+ return trades
234
+
235
+ def trade33():
236
+ # Buy 2 stocks with the highest price-to-earnings ratio and sell 2 with the lowest
237
+ pe_ratios = {ticker: random.uniform(10, 30) for ticker in tickers} # Mock P/E ratios
238
+ top_pe_tickers = sorted(pe_ratios, key=pe_ratios.get, reverse=True)[:2]
239
+ low_pe_tickers = sorted(pe_ratios, key=pe_ratios.get)[:2]
240
+ trades = [Trade(ticker, 100) for ticker in top_pe_tickers] + [Trade(ticker, -100) for ticker in low_pe_tickers]
241
+ return trades
242
+
243
+ def trade34():
244
+ # Buy the stock with the highest volume and sell the one with the lowest volume
245
+ volumes = {ticker: random.randint(1000, 10000) for ticker in tickers} # Mock volumes
246
+ high_volume_ticker = max(volumes, key=volumes.get)
247
+ low_volume_ticker = min(volumes, key=volumes.get)
248
+ trades = [Trade(high_volume_ticker, 100), Trade(low_volume_ticker, -100)]
249
+ return trades
250
+
251
+ def trade35():
252
+ # Buy 3 stocks with the highest recent momentum and sell 3 with the lowest recent momentum
253
+ momentums = {ticker: prices[ticker][0] - prices[ticker][5] for ticker in tickers}
254
+ top_momentum_tickers = sorted(momentums, key=momentums.get, reverse=True)[:3]
255
+ low_momentum_tickers = sorted(momentums, key=momentums.get)[:3]
256
+ trades = [Trade(ticker, 100) for ticker in top_momentum_tickers] + [Trade(ticker, -100) for ticker in low_momentum_tickers]
257
+ return trades
258
+
259
+ def trade36():
260
+ # Buy stocks in the technology sector and sell stocks in the energy sector
261
+ tech_stocks = random.sample(tickers, 3) # Mock tech stocks
262
+ energy_stocks = random.sample(tickers, 3) # Mock energy stocks
263
+ trades = [Trade(ticker, 100) for ticker in tech_stocks] + [Trade(ticker, -100) for ticker in energy_stocks]
264
+ return trades
265
+
266
+ def trade37():
267
+ # Long/short strategy: Buy the top 2 stocks with the highest recent gains and sell the top 2 with the highest recent losses
268
+ recent_gains = {ticker: prices[ticker][0] - prices[ticker][10] for ticker in tickers}
269
+ top_gainers = sorted(recent_gains, key=recent_gains.get, reverse=True)[:2]
270
+ top_losers = sorted(recent_gains, key=recent_gains.get)[:2]
271
+ trades = [Trade(ticker, 100) for ticker in top_gainers] + [Trade(ticker, -100) for ticker in top_losers]
272
+ return trades
273
+
274
+ def trade38():
275
+ # Buy the stocks with the highest dividend yield and sell those with the lowest
276
+ dividend_yields = {ticker: random.uniform(1, 5) for ticker in tickers} # Mock dividend yields
277
+ high_yield_tickers = sorted(dividend_yields, key=dividend_yields.get, reverse=True)[:2]
278
+ low_yield_tickers = sorted(dividend_yields, key=dividend_yields.get)[:2]
279
+ trades = [Trade(ticker, 100) for ticker in high_yield_tickers] + [Trade(ticker, -100) for ticker in low_yield_tickers]
280
+ return trades
281
+
282
+ def trade39():
283
+ # Buy stocks that are trading near their 52-week highs and sell those near their 52-week lows
284
+ highs_52w = {ticker: max(prices[ticker]) for ticker in tickers}
285
+ lows_52w = {ticker: min(prices[ticker]) for ticker in tickers}
286
+ near_highs = [ticker for ticker in tickers if prices[ticker][0] >= 0.9 * highs_52w[ticker]]
287
+ near_lows = [ticker for ticker in tickers if prices[ticker][0] <= 1.1 * lows_52w[ticker]]
288
+ trades = [Trade(ticker, 100) for ticker in random.sample(near_highs, min(2, len(near_highs)))] + \
289
+ [Trade(ticker, -100) for ticker in random.sample(near_lows, min(2, len(near_lows)))]
290
+ return trades
291
+
292
+ def trade40():
293
+ # Long/short strategy: Buy 2 random stocks from the top 10 performing sectors and sell 2 from the bottom 10
294
+ sectors = {ticker: random.choice(['Tech', 'Energy', 'Health', 'Finance', 'Retail']) for ticker in tickers}
295
+ sector_performance = {sector: random.uniform(-10, 10) for sector in set(sectors.values())}
296
+ top_sectors = sorted(sector_performance, key=sector_performance.get, reverse=True)[:2]
297
+ bottom_sectors = sorted(sector_performance, key=sector_performance.get)[:2]
298
+ buy_tickers = [ticker for ticker in tickers if sectors[ticker] in top_sectors]
299
+ sell_tickers = [ticker for ticker in tickers if sectors[ticker] in bottom_sectors]
300
+ trades = [Trade(ticker, 100) for ticker in random.sample(buy_tickers, min(2, len(buy_tickers)))] + \
301
+ [Trade(ticker, -100) for ticker in random.sample(sell_tickers, min(2, len(sell_tickers)))]
302
+ return trades
303
+
304
+ def trade41():
305
+ # Buy the stock with the highest price increase today
306
+ price_increases = {ticker: prices[ticker][0] - prices[ticker][1] for ticker in tickers}
307
+ best_ticker = max(price_increases, key=price_increases.get)
308
+ trade = Trade(best_ticker, 100)
309
+ return [trade]
310
+
311
+ def trade42():
312
+ # Sell the stock with the highest price decrease today
313
+ price_decreases = {ticker: prices[ticker][0] - prices[ticker][1] for ticker in tickers}
314
+ worst_ticker = min(price_decreases, key=price_decreases.get)
315
+ trade = Trade(worst_ticker, -100)
316
+ return [trade]
317
+
318
+ def trade43():
319
+ # Buy stocks that have had a positive return in the last 3 days
320
+ returns = {ticker: (prices[ticker][0] - prices[ticker][2]) / prices[ticker][2] for ticker in tickers}
321
+ buy_tickers = [ticker for ticker in tickers if returns[ticker] > 0]
322
+ trades = [Trade(ticker, 100) for ticker in random.sample(buy_tickers, min(3, len(buy_tickers)))]
323
+ return trades
324
+
325
+ def trade44():
326
+ # Sell stocks that have had a negative return in the last 3 days
327
+ returns = {ticker: (prices[ticker][0] - prices[ticker][2]) / prices[ticker][2] for ticker in tickers}
328
+ sell_tickers = [ticker for ticker in tickers if returns[ticker] < 0]
329
+ trades = [Trade(ticker, -100) for ticker in random.sample(sell_tickers, min(3, len(sell_tickers)))]
330
+ return trades
331
+
332
+ def trade45():
333
+ # Buy the stock with the highest average return over the last 10 days
334
+ avg_returns = {ticker: np.mean([(prices[ticker][i] - prices[ticker][i+1]) / prices[ticker][i+1] for i in range(9)]) for ticker in tickers}
335
+ best_ticker = max(avg_returns, key=avg_returns.get)
336
+ trade = Trade(best_ticker, 100)
337
+ return [trade]
338
+
339
+ def trade46():
340
+ # Sell the stock with the lowest average return over the last 10 days
341
+ avg_returns = {ticker: np.mean([(prices[ticker][i] - prices[ticker][i+1]) / prices[ticker][i+1] for i in range(9)]) for ticker in tickers}
342
+ worst_ticker = min(avg_returns, key=avg_returns.get)
343
+ trade = Trade(worst_ticker, -100)
344
+ return [trade]
345
+
346
+ def trade47():
347
+ # Buy stocks that are oversold based on RSI (Randomly assigned for simplicity)
348
+ rsi = {ticker: random.uniform(0, 100) for ticker in tickers}
349
+ oversold_tickers = [ticker for ticker in tickers if rsi[ticker] < 30]
350
+ trades = [Trade(ticker, 100) for ticker in random.sample(oversold_tickers, min(3, len(oversold_tickers)))]
351
+ return trades
352
+
353
+ def trade48():
354
+ # Sell stocks that are overbought based on RSI (Randomly assigned for simplicity)
355
+ rsi = {ticker: random.uniform(0, 100) for ticker in tickers}
356
+ overbought_tickers = [ticker for ticker in tickers if rsi[ticker] > 70]
357
+ trades = [Trade(ticker, -100) for ticker in random.sample(overbought_tickers, min(3, len(overbought_tickers)))]
358
+ return trades
359
+
360
+ def trade49():
361
+ # Buy stocks with positive momentum over the last 20 days
362
+ momentums = {ticker: prices[ticker][0] - prices[ticker][19] for ticker in tickers}
363
+ positive_momentum_tickers = [ticker for ticker in momentums if momentums[ticker] > 0]
364
+ trades = [Trade(ticker, 100) for ticker in random.sample(positive_momentum_tickers, min(3, len(positive_momentum_tickers)))]
365
+ return trades
366
+
367
+ def trade50():
368
+ # Sell stocks with negative momentum over the last 20 days
369
+ momentums = {ticker: prices[ticker][0] - prices[ticker][19] for ticker in tickers}
370
+ negative_momentum_tickers = [ticker for ticker in momentums if momentums[ticker] < 0]
371
+ trades = [Trade(ticker, -100) for ticker in random.sample(negative_momentum_tickers, min(3, len(negative_momentum_tickers)))]
372
+ return trades
373
+
374
+ def trade51():
375
+ # Buy stocks that have a high positive correlation with a randomly chosen strong performer
376
+ import scipy.stats
377
+ base_ticker = random.choice(tickers)
378
+ base_prices = prices[base_ticker]
379
+ correlations = {ticker: scipy.stats.pearsonr(base_prices, prices[ticker])[0] for ticker in tickers if ticker != base_ticker}
380
+ high_corr_tickers = [ticker for ticker, corr in correlations.items() if corr > 0.8]
381
+ trades = [Trade(ticker, 100) for ticker in random.sample(high_corr_tickers, min(3, len(high_corr_tickers)))]
382
+ return trades
383
+
384
+ def trade52():
385
+ # Sell stocks that have a high negative correlation with a randomly chosen weak performer
386
+ import scipy.stats
387
+ base_ticker = random.choice(tickers)
388
+ base_prices = prices[base_ticker]
389
+ correlations = {ticker: scipy.stats.pearsonr(base_prices, prices[ticker])[0] for ticker in tickers if ticker != base_ticker}
390
+ low_corr_tickers = [ticker for ticker, corr in correlations.items() if corr < -0.8]
391
+ trades = [Trade(ticker, -100) for ticker in random.sample(low_corr_tickers, min(3, len(low_corr_tickers)))]
392
+ return trades
393
+
394
+ def trade53():
395
+ # Long/short strategy: Buy stocks with high positive correlation and sell stocks with high negative correlation to a strong performer
396
+ import scipy.stats
397
+ base_ticker = random.choice(tickers)
398
+ base_prices = prices[base_ticker]
399
+ correlations = {ticker: scipy.stats.pearsonr(base_prices, prices[ticker])[0] for ticker in tickers if ticker != base_ticker}
400
+ high_corr_tickers = [ticker for ticker, corr in correlations.items() if corr > 0.7]
401
+ low_corr_tickers = [ticker for ticker, corr in correlations.items() if corr < -0.7]
402
+ trades = [Trade(ticker, 100) for ticker in random.sample(high_corr_tickers, min(2, len(high_corr_tickers)))] + \
403
+ [Trade(ticker, -100) for ticker in random.sample(low_corr_tickers, min(2, len(low_corr_tickers)))]
404
+ return trades
405
+
406
+ def trade54():
407
+ # Buy stocks that have a high correlation with an index (e.g., S&P 500)
408
+ import scipy.stats
409
+ index_prices = [random.uniform(1000, 5000) for _ in range(len(prices[tickers[0]]))] # Mock index prices
410
+ correlations = {ticker: scipy.stats.pearsonr(index_prices, prices[ticker])[0] for ticker in tickers}
411
+ high_corr_tickers = [ticker for ticker, corr in correlations.items() if corr > 0.8]
412
+ trades = [Trade(ticker, 100) for ticker in random.sample(high_corr_tickers, min(3, len(high_corr_tickers)))]
413
+ return trades
414
+
415
+ def trade55():
416
+ # Sell stocks that have a low correlation with an index (e.g., S&P 500)
417
+ import scipy.stats
418
+ index_prices = [random.uniform(1000, 5000) for _ in range(len(prices[tickers[0]]))] # Mock index prices
419
+ correlations = {ticker: scipy.stats.pearsonr(index_prices, prices[ticker])[0] for ticker in tickers}
420
+ low_corr_tickers = [ticker for ticker, corr in correlations.items() if corr < 0.2]
421
+ trades = [Trade(ticker, -100) for ticker in random.sample(low_corr_tickers, min(3, len(low_corr_tickers)))]
422
+ return trades
423
+
424
+ def trade56():
425
+ # Long/short strategy: Buy stocks with high correlation and sell stocks with low correlation to a randomly chosen strong performer
426
+ import scipy.stats
427
+ base_ticker = random.choice(tickers)
428
+ base_prices = prices[base_ticker]
429
+ correlations = {ticker: scipy.stats.pearsonr(base_prices, prices[ticker])[0] for ticker in tickers if ticker != base_ticker}
430
+ high_corr_tickers = [ticker for ticker, corr in correlations.items() if corr > 0.7]
431
+ low_corr_tickers = [ticker for ticker, corr in correlations.items() if corr < 0.2]
432
+ trades = [Trade(ticker, 100) for ticker in random.sample(high_corr_tickers, min(2, len(high_corr_tickers)))] + \
433
+ [Trade(ticker, -100) for ticker in random.sample(low_corr_tickers, min(2, len(low_corr_tickers)))]
434
+ return trades
435
+
436
+ def trade57():
437
+ # Buy stocks that are inversely correlated with a major sector ETF (mocked data)
438
+ import scipy.stats
439
+ sector_etf_prices = [random.uniform(50, 150) for _ in range(len(prices[tickers[0]]))] # Mock sector ETF prices
440
+ correlations = {ticker: scipy.stats.pearsonr(sector_etf_prices, prices[ticker])[0] for ticker in tickers}
441
+ inverse_corr_tickers = [ticker for ticker, corr in correlations.items() if corr < -0.7]
442
+ trades = [Trade(ticker, 100) for ticker in random.sample(inverse_corr_tickers, min(3, len(inverse_corr_tickers)))]
443
+ return trades
444
+
445
+ def trade58():
446
+ # Sell stocks that are highly correlated with a volatile index
447
+ import scipy.stats
448
+ volatile_index_prices = [random.uniform(1000, 2000) for _ in range(len(prices[tickers[0]]))] # Mock volatile index prices
449
+ correlations = {ticker: scipy.stats.pearsonr(volatile_index_prices, prices[ticker])[0] for ticker in tickers}
450
+ high_corr_tickers = [ticker for ticker, corr in correlations.items() if corr > 0.8]
451
+ trades = [Trade(ticker, -100) for ticker in random.sample(high_corr_tickers, min(3, len(high_corr_tickers)))]
452
+ return trades
453
+
454
+ def trade59():
455
+ # Buy stocks that are less correlated with the overall market (S&P 500)
456
+ import scipy.stats
457
+ market_prices = [random.uniform(1000, 5000) for _ in range(len(prices[tickers[0]]))] # Mock market index prices
458
+ correlations = {ticker: scipy.stats.pearsonr(market_prices, prices[ticker])[0] for ticker in tickers}
459
+ low_corr_tickers = [ticker for ticker, corr in correlations.items() if corr < 0.3]
460
+ trades = [Trade(ticker, 100) for ticker in random.sample(low_corr_tickers, min(3, len(low_corr_tickers)))]
461
+ return trades
462
+
463
+ def trade60():
464
+ # Sell stocks that are highly correlated with a specific commodity price (e.g., oil)
465
+ import scipy.stats
466
+ commodity_prices = [random.uniform(50, 100) for _ in range(len(prices[tickers[0]]))] # Mock commodity prices
467
+ correlations = {ticker: scipy.stats.pearsonr(commodity_prices, prices[ticker])[0] for ticker in tickers}
468
+ high_corr_tickers = [ticker for ticker, corr in correlations.items() if corr > 0.7]
469
+ trades = [Trade(ticker, -100) for ticker in random.sample(high_corr_tickers, min(3, len(high_corr_tickers)))]
470
+ return trades
471
+
472
+ def trade61():
473
+ # Buy stocks forming a "double bottom" pattern (last 5 days)
474
+ double_bottom_tickers = [ticker for ticker in tickers if prices[ticker][4] < prices[ticker][2] == prices[ticker][0] < prices[ticker][1] and prices[ticker][3] > prices[ticker][2]]
475
+ trades = [Trade(ticker, 100) for ticker in random.sample(double_bottom_tickers, min(3, len(double_bottom_tickers)))]
476
+ return trades
477
+
478
+ def trade62():
479
+ # Sell stocks forming a "double top" pattern (last 5 days)
480
+ double_top_tickers = [ticker for ticker in tickers if prices[ticker][4] > prices[ticker][2] == prices[ticker][0] > prices[ticker][1] and prices[ticker][3] < prices[ticker][2]]
481
+ trades = [Trade(ticker, -100) for ticker in random.sample(double_top_tickers, min(3, len(double_top_tickers)))]
482
+ return trades
483
+
484
+ def trade63():
485
+ # Buy stocks showing a "head and shoulders" bottom pattern (last 7 days)
486
+ hs_bottom_tickers = [ticker for ticker in tickers if prices[ticker][6] > prices[ticker][5] < prices[ticker][4] > prices[ticker][3] < prices[ticker][2] and prices[ticker][1] < prices[ticker][0]]
487
+ trades = [Trade(ticker, 100) for ticker in random.sample(hs_bottom_tickers, min(3, len(hs_bottom_tickers)))]
488
+ return trades
489
+
490
+ def trade64():
491
+ # Sell stocks showing a "head and shoulders" top pattern (last 7 days)
492
+ hs_top_tickers = [ticker for ticker in tickers if prices[ticker][6] < prices[ticker][5] > prices[ticker][4] < prices[ticker][3] > prices[ticker][2] and prices[ticker][1] > prices[ticker][0]]
493
+ trades = [Trade(ticker, -100) for ticker in random.sample(hs_top_tickers, min(3, len(hs_top_tickers)))]
494
+ return trades
495
+
496
+ def trade65():
497
+ # Buy stocks forming a "bullish flag" pattern (last 10 days)
498
+ bullish_flag_tickers = [ticker for ticker in tickers if prices[ticker][9] < prices[ticker][8] and all(prices[ticker][i] < prices[ticker][i+1] for i in range(8, 4, -1)) and all(prices[ticker][i] > prices[ticker][i+1] for i in range(4, 0, -1))]
499
+ trades = [Trade(ticker, 100) for ticker in random.sample(bullish_flag_tickers, min(3, len(bullish_flag_tickers)))]
500
+ return trades
501
+
502
+ def trade66():
503
+ # Sell stocks forming a "bearish flag" pattern (last 10 days)
504
+ bearish_flag_tickers = [ticker for ticker in tickers if prices[ticker][9] > prices[ticker][8] and all(prices[ticker][i] > prices[ticker][i+1] for i in range(8, 4, -1)) and all(prices[ticker][i] < prices[ticker][i+1] for i in range(4, 0, -1))]
505
+ trades = [Trade(ticker, -100) for ticker in random.sample(bearish_flag_tickers, min(3, len(bearish_flag_tickers)))]
506
+ return trades
507
+
508
+ def trade67():
509
+ # Buy stocks forming a "ascending triangle" pattern (last 15 days)
510
+ ascending_triangle_tickers = [ticker for ticker in tickers if prices[ticker][14] < prices[ticker][13] and prices[ticker][0] > prices[ticker][7] and all(prices[ticker][i] <= prices[ticker][i+1] for i in range(13))]
511
+ trades = [Trade(ticker, 100) for ticker in random.sample(ascending_triangle_tickers, min(3, len(ascending_triangle_tickers)))]
512
+ return trades
513
+
514
+ def trade68():
515
+ # Sell stocks forming a "descending triangle" pattern (last 15 days)
516
+ descending_triangle_tickers = [ticker for ticker in tickers if prices[ticker][14] > prices[ticker][13] and prices[ticker][0] < prices[ticker][7] and all(prices[ticker][i] >= prices[ticker][i+1] for i in range(13))]
517
+ trades = [Trade(ticker, -100) for ticker in random.sample(descending_triangle_tickers, min(3, len(descending_triangle_tickers)))]
518
+ return trades
519
+
520
+ def trade69():
521
+ # Buy stocks forming a "rounding bottom" pattern (last 20 days)
522
+ rounding_bottom_tickers = [ticker for ticker in tickers if all(prices[ticker][i] >= prices[ticker][i+1] for i in range(10)) and all(prices[ticker][i] <= prices[ticker][i+1] for i in range(10, 19))]
523
+ trades = [Trade(ticker, 100) for ticker in random.sample(rounding_bottom_tickers, min(3, len(rounding_bottom_tickers)))]
524
+ return trades
525
+
526
+ def trade70():
527
+ # Sell stocks forming a "rounding top" pattern (last 20 days)
528
+ rounding_top_tickers = [ticker for ticker in tickers if all(prices[ticker][i] <= prices[ticker][i+1] for i in range(10)) and all(prices[ticker][i] >= prices[ticker][i+1] for i in range(10, 19))]
529
+ trades = [Trade(ticker, -100) for ticker in random.sample(rounding_top_tickers, min(3, len(rounding_top_tickers)))]
530
+ return trades
531
+
532
+ def trade71():
533
+ # Buy stocks showing a strong upward trend over the last 10 days
534
+ upward_trend_tickers = [ticker for ticker in tickers if prices[ticker][0] > prices[ticker][9] and all(prices[ticker][i] >= prices[ticker][i+1] for i in range(9))]
535
+ trades = [Trade(ticker, 100) for ticker in random.sample(upward_trend_tickers, min(3, len(upward_trend_tickers)))]
536
+ return trades
537
+
538
+ def trade72():
539
+ # Sell stocks showing a strong downward trend over the last 10 days
540
+ downward_trend_tickers = [ticker for ticker in tickers if prices[ticker][0] < prices[ticker][9] and all(prices[ticker][i] <= prices[ticker][i+1] for i in range(9))]
541
+ trades = [Trade(ticker, -100) for ticker in random.sample(downward_trend_tickers, min(3, len(downward_trend_tickers)))]
542
+ return trades
543
+
544
+ def trade73():
545
+ # Buy stocks that have reverted to their mean price over the last 20 days
546
+ mean_reversion_tickers = [ticker for ticker in tickers if abs(prices[ticker][0] - np.mean(prices[ticker][:20])) < np.std(prices[ticker][:20])]
547
+ trades = [Trade(ticker, 100) for ticker in random.sample(mean_reversion_tickers, min(3, len(mean_reversion_tickers)))]
548
+ return trades
549
+
550
+ def trade74():
551
+ # Sell stocks that have deviated significantly from their mean price over the last 20 days
552
+ mean_deviation_tickers = [ticker for ticker in tickers if abs(prices[ticker][0] - np.mean(prices[ticker][:20])) > 2 * np.std(prices[ticker][:20])]
553
+ trades = [Trade(ticker, -100) for ticker in random.sample(mean_deviation_tickers, min(3, len(mean_deviation_tickers)))]
554
+ return trades
555
+
556
+ def trade75():
557
+ # Buy stocks that have shown increased volatility in the last 10 days compared to the previous 20 days
558
+ increased_volatility_tickers = [ticker for ticker in tickers if np.std(prices[ticker][:10]) > 1.5 * np.std(prices[ticker][10:30])]
559
+ trades = [Trade(ticker, 100) for ticker in random.sample(increased_volatility_tickers, min(3, len(increased_volatility_tickers)))]
560
+ return trades
561
+
562
+ def trade76():
563
+ # Sell stocks that have shown decreased volatility in the last 10 days compared to the previous 20 days
564
+ decreased_volatility_tickers = [ticker for ticker in tickers if np.std(prices[ticker][:10]) < 0.5 * np.std(prices[ticker][10:30])]
565
+ trades = [Trade(ticker, -100) for ticker in random.sample(decreased_volatility_tickers, min(3, len(decreased_volatility_tickers)))]
566
+ return trades
567
+
568
+ def trade77():
569
+ # Buy stocks that have broken above their previous 50-day high
570
+ previous_50_day_highs = {ticker: max(prices[ticker][1:51]) for ticker in tickers}
571
+ breakout_tickers = [ticker for ticker in tickers if prices[ticker][0] > previous_50_day_highs[ticker]]
572
+ trades = [Trade(ticker, 100) for ticker in random.sample(breakout_tickers, min(3, len(breakout_tickers)))]
573
+ return trades
574
+
575
+ def trade78():
576
+ # Sell stocks that have broken below their previous 50-day low
577
+ previous_50_day_lows = {ticker: min(prices[ticker][1:51]) for ticker in tickers}
578
+ breakdown_tickers = [ticker for ticker in tickers if prices[ticker][0] < previous_50_day_lows[ticker]]
579
+ trades = [Trade(ticker, -100) for ticker in random.sample(breakdown_tickers, min(3, len(breakdown_tickers)))]
580
+ return trades
581
+
582
+ def trade79():
583
+ # Buy stocks that have shown a significant upward price spike in the last 3 days
584
+ price_spike_tickers = [ticker for ticker in tickers if (prices[ticker][0] - prices[ticker][2]) / prices[ticker][2] > 0.1]
585
+ trades = [Trade(ticker, 100) for ticker in random.sample(price_spike_tickers, min(3, len(price_spike_tickers)))]
586
+ return trades
587
+
588
+ def trade80():
589
+ # Sell stocks that have shown a significant downward price spike in the last 3 days
590
+ price_drop_tickers = [ticker for ticker in tickers if (prices[ticker][0] - prices[ticker][2]) / prices[ticker][2] < -0.1]
591
+ trades = [Trade(ticker, -100) for ticker in random.sample(price_drop_tickers, min(3, len(price_drop_tickers)))]
592
+ return trades
593
+
594
+ def trade81():
595
+ # Buy stocks that have formed a "golden cross" (50-day MA crosses above 200-day MA)
596
+ golden_cross_tickers = [ticker for ticker in tickers if np.mean(prices[ticker][:50]) > np.mean(prices[ticker][:200])]
597
+ trades = [Trade(ticker, 100) for ticker in random.sample(golden_cross_tickers, min(3, len(golden_cross_tickers)))]
598
+ return trades
599
+
600
+ def trade82():
601
+ # Sell stocks that have formed a "death cross" (50-day MA crosses below 200-day MA)
602
+ death_cross_tickers = [ticker for ticker in tickers if np.mean(prices[ticker][:50]) < np.mean(prices[ticker][:200])]
603
+ trades = [Trade(ticker, -100) for ticker in random.sample(death_cross_tickers, min(3, len(death_cross_tickers)))]
604
+ return trades
605
+
606
+ def trade83():
607
+ # Buy stocks that have shown an increase in trading volume in the last 5 days
608
+ volume_increase_tickers = [ticker for ticker in tickers if np.mean(prices[ticker][:5]) > 1.2 * np.mean(prices[ticker][5:10])]
609
+ trades = [Trade(ticker, 100) for ticker in random.sample(volume_increase_tickers, min(3, len(volume_increase_tickers)))]
610
+ return trades
611
+
612
+ def trade84():
613
+ # Sell stocks that have shown a decrease in trading volume in the last 5 days
614
+ volume_decrease_tickers = [ticker for ticker in tickers if np.mean(prices[ticker][:5]) < 0.8 * np.mean(prices[ticker][5:10])]
615
+ trades = [Trade(ticker, -100) for ticker in random.sample(volume_decrease_tickers, min(3, len(volume_decrease_tickers)))]
616
+ return trades
617
+
618
+ def trade85():
619
+ # Buy stocks that have shown consistent daily gains for the last 5 days
620
+ consistent_gainers = [ticker for ticker in tickers if all(prices[ticker][i] > prices[ticker][i+1] for i in range(5))]
621
+ trades = [Trade(ticker, 100) for ticker in random.sample(consistent_gainers, min(3, len(consistent_gainers)))]
622
+ return trades
623
+
624
+ def trade86():
625
+ # Sell stocks that have shown consistent daily losses for the last 5 days
626
+ consistent_losers = [ticker for ticker in tickers if all(prices[ticker][i] < prices[ticker][i+1] for i in range(5))]
627
+ trades = [Trade(ticker, -100) for ticker in random.sample(consistent_losers, min(3, len(consistent_losers)))]
628
+ return trades
629
+
630
+ def trade87():
631
+ # Buy stocks that are trading near their all-time highs
632
+ all_time_high_tickers = [ticker for ticker in tickers if prices[ticker][0] >= 0.95 * max(prices[ticker])]
633
+ trades = [Trade(ticker, 100) for ticker in random.sample(all_time_high_tickers, min(3, len(all_time_high_tickers)))]
634
+ return trades
635
+
636
+ def trade88():
637
+ # Sell stocks that are trading near their all-time lows
638
+ all_time_low_tickers = [ticker for ticker in tickers if prices[ticker][0] <= 1.05 * min(prices[ticker])]
639
+ trades = [Trade(ticker, -100) for ticker in random.sample(all_time_low_tickers, min(3, len(all_time_low_tickers)))]
640
+ return trades
641
+
642
+ def trade89():
643
+ # Buy stocks that have gapped up at market open today
644
+ gap_up_tickers = [ticker for ticker in tickers if prices[ticker][0] > 1.05 * prices[ticker][1]]
645
+ trades = [Trade(ticker, 100) for ticker in random.sample(gap_up_tickers, min(3, len(gap_up_tickers)))]
646
+ return trades
647
+
648
+ def trade90():
649
+ # Sell stocks that have gapped down at market open today
650
+ gap_down_tickers = [ticker for ticker in tickers if prices[ticker][0] < 0.95 * prices[ticker][1]]
651
+ trades = [Trade(ticker, -100) for ticker in random.sample(gap_down_tickers, min(3, len(gap_down_tickers)))]
652
+ return trades
653
+
654
+ def trade91():
655
+ # Buy stocks that have shown a steady upward trend for the last 15 days
656
+ steady_uptrend_tickers = [ticker for ticker in tickers if all(prices[ticker][i] >= prices[ticker][i+1] for i in range(15))]
657
+ trades = [Trade(ticker, 100) for ticker in random.sample(steady_uptrend_tickers, min(3, len(steady_uptrend_tickers)))]
658
+ return trades
659
+
660
+ def trade92():
661
+ # Sell stocks that have shown a steady downward trend for the last 15 days
662
+ steady_downtrend_tickers = [ticker for ticker in tickers if all(prices[ticker][i] <= prices[ticker][i+1] for i in range(15))]
663
+ trades = [Trade(ticker, -100) for ticker in random.sample(steady_downtrend_tickers, min(3, len(steady_downtrend_tickers)))]
664
+ return trades
665
+
666
+ def trade93():
667
+ # Buy stocks that have outperformed the market index by 5% in the last 30 days
668
+ market_index_return = random.uniform(-0.05, 0.05) # Mock market index return
669
+ outperforming_tickers = [ticker for ticker in tickers if (prices[ticker][0] - prices[ticker][29]) / prices[ticker][29] > market_index_return + 0.05]
670
+ trades = [Trade(ticker, 100) for ticker in random.sample(outperforming_tickers, min(3, len(outperforming_tickers)))]
671
+ return trades
672
+
673
+ def trade94():
674
+ # Sell stocks that have underperformed the market index by 5% in the last 30 days
675
+ market_index_return = random.uniform(-0.05, 0.05) # Mock market index return
676
+ underperforming_tickers = [ticker for ticker in tickers if (prices[ticker][0] - prices[ticker][29]) / prices[ticker][29] < market_index_return - 0.05]
677
+ trades = [Trade(ticker, -100) for ticker in random.sample(underperforming_tickers, min(3, len(underperforming_tickers)))]
678
+ return trades
679
+
680
+ def trade95():
681
+ # Buy stocks that have broken above their previous 10-day high
682
+ previous_10_day_highs = {ticker: max(prices[ticker][1:11]) for ticker in tickers}
683
+ breakout_tickers = [ticker for ticker in tickers if prices[ticker][0] > previous_10_day_highs[ticker]]
684
+ trades = [Trade(ticker, 100) for ticker in random.sample(breakout_tickers, min(3, len(breakout_tickers)))]
685
+ return trades
686
+
687
+ def trade96():
688
+ # Sell stocks that have broken below their previous 10-day low
689
+ previous_10_day_lows = {ticker: min(prices[ticker][1:11]) for ticker in tickers}
690
+ breakdown_tickers = [ticker for ticker in tickers if prices[ticker][0] < previous_10_day_lows[ticker]]
691
+ trades = [Trade(ticker, -100) for ticker in random.sample(breakdown_tickers, min(3, len(breakdown_tickers)))]
692
+ return trades
693
+
694
+ def trade97():
695
+ # Buy stocks with a relative strength index (RSI) below 30 (oversold)
696
+ rsi = {ticker: random.uniform(0, 100) for ticker in tickers} # Mock RSI values
697
+ oversold_tickers = [ticker for ticker in tickers if rsi[ticker] < 30]
698
+ trades = [Trade(ticker, 100) for ticker in random.sample(oversold_tickers, min(3, len(oversold_tickers)))]
699
+ return trades
700
+
701
+ def trade98():
702
+ # Sell stocks with a relative strength index (RSI) above 70 (overbought)
703
+ rsi = {ticker: random.uniform(0, 100) for ticker in tickers} # Mock RSI values
704
+ overbought_tickers = [ticker for ticker in tickers if rsi[ticker] > 70]
705
+ trades = [Trade(ticker, -100) for ticker in random.sample(overbought_tickers, min(3, len(overbought_tickers)))]
706
+ return trades
707
+
708
+ def trade99():
709
+ # Buy stocks with a price-to-earnings ratio (P/E) below the industry average (mocked data)
710
+ pe_ratios = {ticker: random.uniform(10, 30) for ticker in tickers} # Mock P/E ratios
711
+ industry_average_pe = 20 # Mock industry average P/E
712
+ undervalued_tickers = [ticker for ticker in tickers if pe_ratios[ticker] < industry_average_pe]
713
+ trades = [Trade(ticker, 100) for ticker in random.sample(undervalued_tickers, min(3, len(undervalued_tickers)))]
714
+ return trades
715
+
716
+ def trade100():
717
+ # Sell stocks with a price-to-earnings ratio (P/E) above the industry average (mocked data)
718
+ pe_ratios = {ticker: random.uniform(10, 30) for ticker in tickers} # Mock P/E ratios
719
+ industry_average_pe = 20 # Mock industry average P/E
720
+ overvalued_tickers = [ticker for ticker in tickers if pe_ratios[ticker] > industry_average_pe]
721
+ trades = [Trade(ticker, -100) for ticker in random.sample(overvalued_tickers, min(3, len(overvalued_tickers)))]
722
+ return trades
723
+
724
+ def trade101():
725
+ # Buy stocks that have outperformed the market by more than 5% in the last 10 days
726
+ market_total = [sum(prices[ticker][i] for ticker in tickers) for i in range(10)]
727
+ market_return = (market_total[0] - market_total[-1]) / market_total[-1]
728
+ outperforming_tickers = [ticker for ticker in tickers if (prices[ticker][0] - prices[ticker][9]) / prices[ticker][9] > market_return + 0.05]
729
+ trades = [Trade(ticker, 100) for ticker in random.sample(outperforming_tickers, min(3, len(outperforming_tickers)))]
730
+ return trades
731
+
732
+ def trade102():
733
+ # Sell stocks that have underperformed the market by more than 5% in the last 10 days
734
+ market_total = [sum(prices[ticker][i] for ticker in tickers) for i in range(10)]
735
+ market_return = (market_total[0] - market_total[-1]) / market_total[-1]
736
+ underperforming_tickers = [ticker for ticker in tickers if (prices[ticker][0] - prices[ticker][9]) / prices[ticker][9] < market_return - 0.05]
737
+ trades = [Trade(ticker, -100) for ticker in random.sample(underperforming_tickers, min(3, len(underperforming_tickers)))]
738
+ return trades
739
+
740
+ def trade103():
741
+ # Buy stocks that have shown a positive return while the market showed a negative return over the last 5 days
742
+ market_total = [sum(prices[ticker][i] for ticker in tickers) for i in range(5)]
743
+ market_return = (market_total[0] - market_total[-1]) / market_total[-1]
744
+ positive_tickers = [ticker for ticker in tickers if (prices[ticker][0] - prices[ticker][4]) / prices[ticker][4] > 0 and market_return < 0]
745
+ trades = [Trade(ticker, 100) for ticker in random.sample(positive_tickers, min(3, len(positive_tickers)))]
746
+ return trades
747
+
748
+ def trade104():
749
+ # Sell stocks that have shown a negative return while the market showed a positive return over the last 5 days
750
+ market_total = [sum(prices[ticker][i] for ticker in tickers) for i in range(5)]
751
+ market_return = (market_total[0] - market_total[-1]) / market_total[-1]
752
+ negative_tickers = [ticker for ticker in tickers if (prices[ticker][0] - prices[ticker][4]) / prices[ticker][4] < 0 and market_return > 0]
753
+ trades = [Trade(ticker, -100) for ticker in random.sample(negative_tickers, min(3, len(negative_tickers)))]
754
+ return trades
755
+
756
+ def trade105():
757
+ # Buy stocks that have shown less volatility compared to the market over the last 20 days
758
+ market_total = [sum(prices[ticker][i] for ticker in tickers) for i in range(20)]
759
+ market_volatility = np.std(market_total)
760
+ low_volatility_tickers = [ticker for ticker in tickers if np.std(prices[ticker][:20]) < market_volatility]
761
+ trades = [Trade(ticker, 100) for ticker in random.sample(low_volatility_tickers, min(3, len(low_volatility_tickers)))]
762
+ return trades
763
+
764
+ def trade106():
765
+ # Sell stocks that have shown more volatility compared to the market over the last 20 days
766
+ market_total = [sum(prices[ticker][i] for ticker in tickers) for i in range(20)]
767
+ market_volatility = np.std(market_total)
768
+ high_volatility_tickers = [ticker for ticker in tickers if np.std(prices[ticker][:20]) > market_volatility]
769
+ trades = [Trade(ticker, -100) for ticker in random.sample(high_volatility_tickers, min(3, len(high_volatility_tickers)))]
770
+ return trades
771
+
772
+ def trade107():
773
+ # Buy stocks that have shown an increasing trend while the market showed a decreasing trend over the last 15 days
774
+ market_total = [sum(prices[ticker][i] for ticker in tickers) for i in range(15)]
775
+ market_trend = market_total[0] > market_total[-1]
776
+ increasing_tickers = [ticker for ticker in tickers if prices[ticker][0] > prices[ticker][14] and not market_trend]
777
+ trades = [Trade(ticker, 100) for ticker in random.sample(increasing_tickers, min(3, len(increasing_tickers)))]
778
+ return trades
779
+
780
+ def trade108():
781
+ # Sell stocks that have shown a decreasing trend while the market showed an increasing trend over the last 15 days
782
+ market_total = [sum(prices[ticker][i] for ticker in tickers) for i in range(15)]
783
+ market_trend = market_total[0] < market_total[-1]
784
+ decreasing_tickers = [ticker for ticker in tickers if prices[ticker][0] < prices[ticker][14] and market_trend]
785
+ trades = [Trade(ticker, -100) for ticker in random.sample(decreasing_tickers, min(3, len(decreasing_tickers)))]
786
+ return trades
787
+
788
+ def trade109():
789
+ # Buy stocks that have broken above their previous 10-day high while the market is flat
790
+ market_total = [sum(prices[ticker][i] for ticker in tickers) for i in range(10)]
791
+ market_flat = abs((market_total[0] - market_total[-1]) / market_total[-1]) < 0.01
792
+ previous_10_day_highs = {ticker: max(prices[ticker][1:11]) for ticker in tickers}
793
+ breakout_tickers = [ticker for ticker in tickers if prices[ticker][0] > previous_10_day_highs[ticker] and market_flat]
794
+ trades = [Trade(ticker, 100) for ticker in random.sample(breakout_tickers, min(3, len(breakout_tickers)))]
795
+ return trades
796
+
797
+ def trade110():
798
+ # Sell stocks that have broken below their previous 10-day low while the market is flat
799
+ market_total = [sum(prices[ticker][i] for ticker in tickers) for i in range(10)]
800
+ market_flat = abs((market_total[0] - market_total[-1]) / market_total[-1]) < 0.01
801
+ previous_10_day_lows = {ticker: min(prices[ticker][1:11]) for ticker in tickers}
802
+ breakdown_tickers = [ticker for ticker in tickers if prices[ticker][0] < previous_10_day_lows[ticker] and market_flat]
803
+ trades = [Trade(ticker, -100) for ticker in random.sample(breakdown_tickers, min(3, len(breakdown_tickers)))]
804
+ return trades
805
+
806
+ def trade111():
807
+ # Buy stocks that have shown a higher positive return compared to the market over the last 20 days
808
+ market_total = [sum(prices[ticker][i] for ticker in tickers) for i in range(20)]
809
+ market_return = (market_total[0] - market_total[-1]) / market_total[-1]
810
+ higher_positive_tickers = [ticker for ticker in tickers if (prices[ticker][0] - prices[ticker][19]) / prices[ticker][19] > market_return]
811
+ trades = [Trade(ticker, 100) for ticker in random.sample(higher_positive_tickers, min(3, len(higher_positive_tickers)))]
812
+ return trades
813
+
814
+ def trade112():
815
+ # Sell stocks that have shown a higher negative return compared to the market over the last 20 days
816
+ market_total = [sum(prices[ticker][i] for ticker in tickers) for i in range(20)]
817
+ market_return = (market_total[0] - market_total[-1]) / market_total[-1]
818
+ higher_negative_tickers = [ticker for ticker in tickers if (prices[ticker][0] - prices[ticker][19]) / prices[ticker][19] < market_return]
819
+ trades = [Trade(ticker, -100) for ticker in random.sample(higher_negative_tickers, min(3, len(higher_negative_tickers)))]
820
+ return trades
821
+
822
+ def trade113():
823
+ # Buy stocks that have shown less drawdown compared to the market over the last 30 days
824
+ market_total = [sum(prices[ticker][i] for ticker in tickers) for i in range(30)]
825
+ market_drawdown = min(market_total) / max(market_total)
826
+ less_drawdown_tickers = [ticker for ticker in tickers if min(prices[ticker][:30]) / max(prices[ticker][:30]) > market_drawdown]
827
+ trades = [Trade(ticker, 100) for ticker in random.sample(less_drawdown_tickers, min(3, len(less_drawdown_tickers)))]
828
+ return trades
829
+
830
+ def trade114():
831
+ # Sell stocks that have shown more drawdown compared to the market over the last 30 days
832
+ market_total = [sum(prices[ticker][i] for ticker in tickers) for i in range(30)]
833
+ market_drawdown = min(market_total) / max(market_total)
834
+ more_drawdown_tickers = [ticker for ticker in tickers if min(prices[ticker][:30]) / max(prices[ticker][:30]) < market_drawdown]
835
+ trades = [Trade(ticker, -100) for ticker in random.sample(more_drawdown_tickers, min(3, len(more_drawdown_tickers)))]
836
+ return trades
837
+
838
+ def trade115():
839
+ # Buy stocks that have had a smaller price range compared to the market over the last 15 days
840
+ market_total = [sum(prices[ticker][i] for ticker in tickers) for i in range(15)]
841
+ market_range = max(market_total) - min(market_total)
842
+ small_range_tickers = [ticker for ticker in tickers if max(prices[ticker][:15]) - min(prices[ticker][:15]) < market_range]
843
+ trades = [Trade(ticker, 100) for ticker in random.sample(small_range_tickers, min(3, len(small_range_tickers)))]
844
+ return trades
845
+
846
+ def trade116():
847
+ # Sell stocks that have had a larger price range compared to the market over the last 15 days
848
+ market_total = [sum(prices[ticker][i] for ticker in tickers) for i in range(15)]
849
+ market_range = max(market_total) - min(market_total)
850
+ large_range_tickers = [ticker for ticker in tickers if max(prices[ticker][:15]) - min(prices[ticker][:15]) > market_range]
851
+ trades = [Trade(ticker, -100) for ticker in random.sample(large_range_tickers, min(3, len(large_range_tickers)))]
852
+ return trades
853
+
854
+ def trade117():
855
+ # Buy stocks that have consistently stayed above their market-relative average price in the last 10 days
856
+ market_total = [sum(prices[ticker][i] for ticker in tickers) for i in range(10)]
857
+ market_avg = sum(market_total) / len(market_total)
858
+ consistent_above_avg_tickers = [ticker for ticker in tickers if all(prices[ticker][i] > market_avg for i in range(10))]
859
+ trades = [Trade(ticker, 100) for ticker in random.sample(consistent_above_avg_tickers, min(3, len(consistent_above_avg_tickers)))]
860
+ return trades
861
+
862
+ def trade118():
863
+ # Sell stocks that have consistently stayed below their market-relative average price in the last 10 days
864
+ market_total = [sum(prices[ticker][i] for ticker in tickers) for i in range(10)]
865
+ market_avg = sum(market_total) / len(market_total)
866
+ consistent_below_avg_tickers = [ticker for ticker in tickers if all(prices[ticker][i] < market_avg for i in range(10))]
867
+ trades = [Trade(ticker, -100) for ticker in random.sample(consistent_below_avg_tickers, min(3, len(consistent_below_avg_tickers)))]
868
+ return trades
869
+
870
+ def trade119():
871
+ # Buy stocks that have shown a positive correlation with the market trend over the last 20 days
872
+ market_total = [sum(prices[ticker][i] for ticker in tickers) for i in range(20)]
873
+ market_trend = scipy.stats.linregress(range(20), market_total).slope
874
+ positive_corr_tickers = [ticker for ticker in tickers if scipy.stats.pearsonr(prices[ticker][:20], market_total)[0] > 0.5]
875
+ trades = [Trade(ticker, 100) for ticker in random.sample(positive_corr_tickers, min(3, len(positive_corr_tickers)))]
876
+ return trades
877
+
878
+ def trade120():
879
+ # Sell stocks that have shown a negative correlation with the market trend over the last 20 days
880
+ market_total = [sum(prices[ticker][i] for ticker in tickers) for i in range(20)]
881
+ market_trend = scipy.stats.linregress(range(20), market_total).slope
882
+ negative_corr_tickers = [ticker for ticker in tickers if scipy.stats.pearsonr(prices[ticker][:20], market_total)[0] < -0.5]
883
+ trades = [Trade(ticker, -100) for ticker in random.sample(negative_corr_tickers, min(3, len(negative_corr_tickers)))]
884
+ return trades
important.jpg ADDED

Git LFS Details

  • SHA256: 5f641f16b7a427f3becb73a4e68f20809dbe56912c15137bc70f106b435513c6
  • Pointer size: 131 Bytes
  • Size of remote file: 364 kB
requirements.txt ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ python-dotenv
2
+ jupyterlab
3
+ ipywidgets
4
+ requests
5
+ numpy
6
+ pandas
7
+ scipy
8
+ scikit-learn
9
+ matplotlib
10
+ gensim
11
+ torch
12
+ transformers
13
+ tqdm
14
+ openai
15
+ gradio
16
+ langchain
17
+ tiktoken
18
+ faiss-cpu
19
+ langchain-openai
20
+ langchain_experimental
21
+ langchain_chroma
22
+ langchain[docarray]
23
+ datasets
24
+ sentencepiece
25
+ matplotlib
26
+ google-generativeai
27
+ anthropic
28
+ scikit-learn
29
+ unstructured
30
+ chromadb
31
+ plotly
32
+ jupyter-dash
33
+ beautifulsoup4
34
+ pydub
35
+ modal
36
+ ollama
37
+ accelerate
38
+ sentencepiece
39
+ bitsandbytes
40
+ psutil
41
+ setuptools
42
+ speedtest-cli
43
+ sentence_transformers
44
+ feedparser
resources.jpg ADDED

Git LFS Details

  • SHA256: 45647e83cb24fefa736cc230a278347b3a7d91ec42eca67167c1bb0e6725e4f4
  • Pointer size: 131 Bytes
  • Size of remote file: 450 kB
thankyou.jpg ADDED

Git LFS Details

  • SHA256: 90f4e335d4ea8e17e0bd6895d0e0c04c934c2d99d5769591fc2ca02b27278824
  • Pointer size: 131 Bytes
  • Size of remote file: 443 kB
turo_assist.py ADDED
@@ -0,0 +1,169 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python
2
+ # coding: utf-8
3
+
4
+ # In[3]:
5
+
6
+
7
+ # imports
8
+ import os
9
+ from dotenv import load_dotenv
10
+ from openai import OpenAI
11
+ import gradio as gr
12
+ import json
13
+
14
+ # Load environment variables in a file called .env
15
+ load_dotenv(override=True)
16
+ openai_api_key = os.getenv('OPENAI_API_KEY')
17
+ anthropic_api_key = os.getenv('ANTHROPIC_API_KEY')
18
+ google_api_key = os.getenv('GOOGLE_API_KEY')
19
+
20
+ # Initialize
21
+ openai = OpenAI()
22
+ MODEL = 'gpt-4o-mini'
23
+
24
+ # Real listing-specific information
25
+ listing_info = {
26
+ "vehicles": [
27
+ {
28
+ "id": "vehicle1",
29
+ "name": "2024 Chevrolet Equinox LS FWD (Sport Edition)",
30
+ "type": "SUV",
31
+ "seats": 5,
32
+ "features": [
33
+ "Automatic transmission",
34
+ "AUX input",
35
+ "Backup camera",
36
+ "Bluetooth",
37
+ "Keyless entry",
38
+ "Toll pass (SunPass enabled)",
39
+ "USB charger",
40
+ "USB input",
41
+ "Must be 21+ to book"
42
+ ],
43
+ "daily_rate": "See Turo listing",
44
+ "mileage_limit": "Unlimited",
45
+ "fuel_type": "Gasoline",
46
+ "additional_notes": "Includes toll pass S/N 0729884410104. Please return with same fuel level or opt for prepaid refuel. No smoking, pets, or unauthorized drivers. $25 fee for unauthorized cancellation prior to start."
47
+ }
48
+ ],
49
+ "parking_locations": {
50
+ "airport": {
51
+ "address": "7640 Narcoossee Rd, Orlando, FL 32822",
52
+ "instructions": "Pickup and drop-off at OMNI Airport Parking. Use lockbox code sent via Turo app 30 minutes before pickup. Free 24/7 shuttle service to/from MCO available.",
53
+ "shuttle": "Free 24/7 shuttle runs between MCO and OMNI Parking. Details provided before trip."
54
+ }
55
+ },
56
+ "pickup_process": "Receive lockbox code via Turo app 30 minutes before pickup. Use the code to access keys. Drop off at same location.",
57
+ "license_requirements": "Only listed drivers with valid licenses may operate the vehicle. Upload your license via the Turo app at least 24 hours before your trip. International licenses require a passport.",
58
+ "contact_info": {
59
+ "host": {
60
+ "name": "MM Services",
61
+ "phone": "Not publicly shared; use Turo messaging",
62
+ "response_time": "Usually within 30 minutes"
63
+ }
64
+ },
65
+ "cancellation_policy": "$25 cancellation fee applies if canceled before trip starts. Turo cancellation rules apply after trip starts.",
66
+ "insurance_options": {
67
+ "basic": "State minimum liability coverage, physical damage up to actual cash value with $3,000 deductible",
68
+ "standard": "State minimum liability coverage, physical damage up to actual cash value with $500 deductible",
69
+ "premium": "State minimum liability coverage, physical damage up to actual cash value with $0 deductible"
70
+ },
71
+ "extras": {
72
+ "Child safety seat": "$20/trip - 2 available",
73
+ "Prepaid refuel": "$50/trip - Return at any fuel level",
74
+ "Cooler": "$20/trip - 1 available"
75
+ },
76
+ "guidelines": {
77
+ "smoking": "No smoking. Cleaning fees apply per Turo policy.",
78
+ "pets": "No pets. Cleaning fees apply per Turo policy.",
79
+ "vehicle_use": "No racing, off-roading, or reckless driving. Violations incur $150+ fee.",
80
+ "fueling": "Return with same fuel level unless prepaid refuel is selected.",
81
+ "tolls": "Toll charges billed 30-90 days post-trip using SunPass.",
82
+ "airport": "Do not use terminal parking. Use OMNI lot and shuttle."
83
+ },
84
+ "reviews": [
85
+ {"user": "Wendy", "comment": "The pick up and drop was super nice... Host is very quick to respond and easy to communicate with."},
86
+ {"user": "Ariel", "comment": "The car was clean and ready to go. Clear directions on pickup. Great host."},
87
+ {"user": "Marco", "comment": "Great host! Easy instructions. Highly recommend."}
88
+ ]
89
+ }
90
+
91
+ # Define system message
92
+ system_message = f"""You are a helpful assistant for a Turo car sharing business. Your role is to help hosts and co-hosts
93
+ communicate effectively with customers. Provide relevant information about the hosts' car listings,
94
+ address customer queries professionally, and offer guidance on important topics.
95
+
96
+ LISTING INFORMATION:
97
+ {json.dumps(listing_info, indent=2)}
98
+
99
+ Use the above listing information to answer customer questions. Be specific when referencing vehicle details,
100
+ parking locations, and policies. For example, if someone asks about airport parking, provide the exact address
101
+ and shuttle information from the listing data. If they ask about a specific vehicle, provide details for that
102
+ vehicle only. Always be helpful, courteous, and informative.
103
+
104
+ Key topics to address:
105
+ - Parking locations and directions
106
+ - Airport shuttle services and pickup procedures
107
+ - License upload requirements and verification process
108
+ - Vehicle features and specifications
109
+ - Booking policies, extensions, and modifications
110
+ - Check-in and check-out procedures
111
+ - Fueling requirements and recommendations
112
+ - Mileage limits and overage fees
113
+ - Cleaning expectations and fees
114
+ - Emergency contacts and roadside assistance"""
115
+
116
+ # Chat function
117
+ def chat(message, history):
118
+ relevant_system_message = system_message
119
+ message_lower = message.lower()
120
+
121
+ if 'insurance' in message_lower:
122
+ relevant_system_message += "\nProvide specific details about our insurance options."
123
+
124
+ elif 'cancel' in message_lower:
125
+ relevant_system_message += "\nReference the cancellation policy."
126
+
127
+ elif 'chevrolet' in message_lower or 'equinox' in message_lower:
128
+ relevant_system_message += "\nThe customer is asking about the 2024 Chevrolet Equinox. Provide specific details."
129
+
130
+ elif 'airport' in message_lower or 'parking' in message_lower:
131
+ relevant_system_message += "\nInclude specific parking location and shuttle details."
132
+
133
+ elif 'pickup' in message_lower or 'shuttle' in message_lower:
134
+ relevant_system_message += "\nProvide exact pickup process and shuttle details."
135
+
136
+ elif 'license' in message_lower or 'verification' in message_lower:
137
+ relevant_system_message += "\nExplain license requirements clearly."
138
+
139
+ elif 'contact' in message_lower or 'host' in message_lower:
140
+ relevant_system_message += "\nShare host contact details from the listing."
141
+
142
+ messages = [{"role": "system", "content": relevant_system_message}] + history + [{"role": "user", "content": message}]
143
+ stream = openai.chat.completions.create(model=MODEL, messages=messages, stream=True)
144
+
145
+ response = ""
146
+ for chunk in stream:
147
+ response += chunk.choices[0].delta.content or ''
148
+ yield response
149
+
150
+ # Launch the chat interface
151
+ if __name__ == "__main__":
152
+ gr.ChatInterface(
153
+ fn=chat,
154
+ type="messages",
155
+ title="🚗 MM Services – Turo Rental Assistant",
156
+ description="""
157
+ 👋 Welcome to MM Services!<br>
158
+ Need help with your booking, pickup, airport shuttle, or car details? Just ask me!
159
+ I’m available 24/7 to assist with anything related to your trip.
160
+ """,
161
+ theme="soft"
162
+ ).launch(share=True)
163
+
164
+
165
+ # In[ ]:
166
+
167
+
168
+
169
+
voyage.jpg ADDED

Git LFS Details

  • SHA256: 822edecb097c3f277bcd4efa2a431a63ef5e643921c2fc33cc270ec59eafe2cb
  • Pointer size: 131 Bytes
  • Size of remote file: 779 kB
week1/Guide to Jupyter.ipynb ADDED
@@ -0,0 +1,380 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "markdown",
5
+ "id": "5c291475-8c7c-461c-9b12-545a887b2432",
6
+ "metadata": {},
7
+ "source": [
8
+ "# Jupyter Lab\n",
9
+ "\n",
10
+ "## A Quick Start Guide\n",
11
+ "\n",
12
+ "Welcome to the wonderful world of Jupyter lab! \n",
13
+ "This is a Data Science playground where you can easily write code and investigate the results. It's an ideal environment for: \n",
14
+ "- Research & Development\n",
15
+ "- Prototyping\n",
16
+ "- Learning (that's us!)\n",
17
+ "\n",
18
+ "It's not typically used for shipping production code, and in Week 8 we'll explore the bridge between Jupyter and python code.\n",
19
+ "\n",
20
+ "A file in Jupyter Lab, like this one, is called a **Notebook**.\n",
21
+ "\n",
22
+ "A long time ago, Jupyter used to be called \"IPython\", and so the extensions of notebooks are \".ipynb\" which stands for \"IPython Notebook\".\n",
23
+ "\n",
24
+ "On the left is a File Browser that lets you navigate around the directories and choose different notebooks. But you probably know that already, or you wouldn't have got here!\n",
25
+ "\n",
26
+ "The notebook consists of a series of square boxes called \"cells\". Some of them contain text, like this cell, and some of them contain code, like the cell below.\n",
27
+ "\n",
28
+ "Click in a cell with code and press `Shift + Return` (or `Shift + Enter`) to run the code and print the output.\n",
29
+ "\n",
30
+ "Do that now for the cell below this:"
31
+ ]
32
+ },
33
+ {
34
+ "cell_type": "code",
35
+ "execution_count": null,
36
+ "id": "33d37cd8-55c9-4e03-868c-34aa9cab2c80",
37
+ "metadata": {},
38
+ "outputs": [],
39
+ "source": [
40
+ "# Click anywhere in this cell and press Shift + Return\n",
41
+ "\n",
42
+ "2 + 2"
43
+ ]
44
+ },
45
+ {
46
+ "cell_type": "markdown",
47
+ "id": "9e95df7b-55c6-4204-b8f9-cae83360fc23",
48
+ "metadata": {},
49
+ "source": [
50
+ "## Congrats!\n",
51
+ "\n",
52
+ "Now run the next cell which sets a value, followed by the cells after it to print the value"
53
+ ]
54
+ },
55
+ {
56
+ "cell_type": "code",
57
+ "execution_count": null,
58
+ "id": "585eb9c1-85ee-4c27-8dc2-b4d8d022eda0",
59
+ "metadata": {},
60
+ "outputs": [],
61
+ "source": [
62
+ "# Set a value for a variable\n",
63
+ "\n",
64
+ "favorite_fruit = \"bananas\""
65
+ ]
66
+ },
67
+ {
68
+ "cell_type": "code",
69
+ "execution_count": null,
70
+ "id": "07792faa-761d-46cb-b9b7-2bbf70bb1628",
71
+ "metadata": {},
72
+ "outputs": [],
73
+ "source": [
74
+ "# The result of the last statement is shown after you run it\n",
75
+ "\n",
76
+ "favorite_fruit"
77
+ ]
78
+ },
79
+ {
80
+ "cell_type": "code",
81
+ "execution_count": null,
82
+ "id": "a067d2b1-53d5-4aeb-8a3c-574d39ff654a",
83
+ "metadata": {},
84
+ "outputs": [],
85
+ "source": [
86
+ "# Use the variable\n",
87
+ "\n",
88
+ "print(f\"My favorite fruit is {favorite_fruit}\")"
89
+ ]
90
+ },
91
+ {
92
+ "cell_type": "code",
93
+ "execution_count": null,
94
+ "id": "4c5a4e60-b7f4-4953-9e80-6d84ba4664ad",
95
+ "metadata": {},
96
+ "outputs": [],
97
+ "source": [
98
+ "# Now change the variable\n",
99
+ "\n",
100
+ "favorite_fruit = f\"anything but {favorite_fruit}\""
101
+ ]
102
+ },
103
+ {
104
+ "cell_type": "markdown",
105
+ "id": "9442d5c9-f57d-4839-b0af-dce58646c04f",
106
+ "metadata": {},
107
+ "source": [
108
+ "## Now go back and rerun the cell with the print statement, two cells back\n",
109
+ "\n",
110
+ "See how it prints something different, even though favorite_fruit was changed further down in the notebook? \n",
111
+ "\n",
112
+ "The order that code appears in the notebook doesn't matter. What matters is the order that the code is **executed**. There's a python process sitting behind this notebook in which the variables are being changed.\n",
113
+ "\n",
114
+ "This catches some people out when they first use Jupyter."
115
+ ]
116
+ },
117
+ {
118
+ "cell_type": "code",
119
+ "execution_count": null,
120
+ "id": "8e5ec81d-7c5b-4025-bd2e-468d67b581b6",
121
+ "metadata": {},
122
+ "outputs": [],
123
+ "source": [
124
+ "# Then run this cell twice, and see if you understand what's going on\n",
125
+ "\n",
126
+ "print(f\"My favorite fruit is {favorite_fruit}\")\n",
127
+ "\n",
128
+ "favorite_fruit = \"apples\""
129
+ ]
130
+ },
131
+ {
132
+ "cell_type": "markdown",
133
+ "id": "a29dab2d-bab9-4a54-8504-05e62594cc6f",
134
+ "metadata": {},
135
+ "source": [
136
+ "# Explaining the 'kernel'\n",
137
+ "\n",
138
+ "Sitting behind this notebook is a Python process which executes each cell when you run it. That Python process is known as the Kernel. Each notebook has its own separate Kernel.\n",
139
+ "\n",
140
+ "You can go to the Kernel menu and select \"Restart Kernel\".\n",
141
+ "\n",
142
+ "If you then try to run the next cell, you'll get an error, because favorite_fruit is no longer defined. You'll need to run the cells from the top of the notebook again. Then the next cell should run fine."
143
+ ]
144
+ },
145
+ {
146
+ "cell_type": "code",
147
+ "execution_count": null,
148
+ "id": "84b1e410-5eda-4e2c-97ce-4eebcff816c5",
149
+ "metadata": {},
150
+ "outputs": [],
151
+ "source": [
152
+ "print(f\"My favorite fruit is {favorite_fruit}\")"
153
+ ]
154
+ },
155
+ {
156
+ "cell_type": "markdown",
157
+ "id": "4d4188fc-d9cc-42be-8b4e-ae8630456764",
158
+ "metadata": {},
159
+ "source": [
160
+ "# Adding and moving cells\n",
161
+ "\n",
162
+ "Click in this cell, then click the \\[+\\] button in the toolbar above to create a new cell immediately below this one. Copy and paste in the code in the prior cell, then run it! There are also icons in the top right of the selected cell to delete it (bin), duplicate it, and move it up and down.\n"
163
+ ]
164
+ },
165
+ {
166
+ "cell_type": "code",
167
+ "execution_count": null,
168
+ "id": "ce258424-40c3-49a7-9462-e6fa25014b03",
169
+ "metadata": {},
170
+ "outputs": [],
171
+ "source": []
172
+ },
173
+ {
174
+ "cell_type": "markdown",
175
+ "id": "30e71f50-8f01-470a-9d7a-b82a6cef4236",
176
+ "metadata": {},
177
+ "source": [
178
+ "# Cell output\n",
179
+ "\n",
180
+ "When you execute a cell, the standard output and the result of the last statement is written to the area immediately under the code, known as the 'cell output'. When you save a Notebook from the file menu (or command+S), the output is also saved, making it a useful record of what happened.\n",
181
+ "\n",
182
+ "You can clean this up by going to Edit menu >> Clear Outputs of All Cells, or Kernel menu >> Restart Kernel and Clear Outputs of All Cells."
183
+ ]
184
+ },
185
+ {
186
+ "cell_type": "code",
187
+ "execution_count": null,
188
+ "id": "a4d021e2-c284-411f-8ab1-030530cfbe72",
189
+ "metadata": {},
190
+ "outputs": [],
191
+ "source": [
192
+ "spams = [\"spam\"] * 1000\n",
193
+ "print(spams)\n",
194
+ "\n",
195
+ "# Might be worth clearing output after running this!"
196
+ ]
197
+ },
198
+ {
199
+ "cell_type": "markdown",
200
+ "id": "eac060f2-7a71-46e7-8235-b6ad0a76f5f8",
201
+ "metadata": {},
202
+ "source": [
203
+ "# Using markdown\n",
204
+ "\n",
205
+ "So what's going on with these areas with writing in them, like this one? Well, there's actually a different kind of cell called a 'Markdown' cell for adding explanations like this. Click the + button to add a cell. Then in the toolbar, click where it says 'Code' and change it to 'Markdown'.\n",
206
+ "\n",
207
+ "Add some comments using Markdown format, perhaps copying and pasting from here:\n",
208
+ "\n",
209
+ "```\n",
210
+ "# This is a heading\n",
211
+ "## This is a sub-head\n",
212
+ "### And a sub-sub-head\n",
213
+ "\n",
214
+ "I like Jupyter Lab because it's\n",
215
+ "- Easy\n",
216
+ "- Flexible\n",
217
+ "- Satisfying\n",
218
+ "```\n",
219
+ "\n",
220
+ "And to turn this into formatted text simply with Shift+Return in the cell.\n",
221
+ "Click in the cell and press the Bin icon if you want to remove it."
222
+ ]
223
+ },
224
+ {
225
+ "cell_type": "code",
226
+ "execution_count": null,
227
+ "id": "e1586320-c90f-4f22-8b39-df6865484950",
228
+ "metadata": {},
229
+ "outputs": [],
230
+ "source": []
231
+ },
232
+ {
233
+ "cell_type": "markdown",
234
+ "id": "1330c83c-67ac-4ca0-ac92-a71699e0c31b",
235
+ "metadata": {},
236
+ "source": [
237
+ "# The exclamation point\n",
238
+ "\n",
239
+ "There's a super useful feature of jupyter labs; you can type a command with a ! in front of it in a code cell, like:\n",
240
+ "\n",
241
+ "!pip install \\[some_package\\]\n",
242
+ "\n",
243
+ "And it will run it at the command line (as if in Windows Powershell or Mac Terminal) and print the result"
244
+ ]
245
+ },
246
+ {
247
+ "cell_type": "code",
248
+ "execution_count": null,
249
+ "id": "82042fc5-a907-4381-a4b8-eb9386df19cd",
250
+ "metadata": {},
251
+ "outputs": [],
252
+ "source": [
253
+ "# list the current directory\n",
254
+ "\n",
255
+ "!ls"
256
+ ]
257
+ },
258
+ {
259
+ "cell_type": "code",
260
+ "execution_count": null,
261
+ "id": "4fc3e3da-8a55-40cc-9706-48bf12a0e20e",
262
+ "metadata": {},
263
+ "outputs": [],
264
+ "source": [
265
+ "# ping cnn.com - press the stop button in the toolbar when you're bored\n",
266
+ "\n",
267
+ "!ping cnn.com"
268
+ ]
269
+ },
270
+ {
271
+ "cell_type": "code",
272
+ "execution_count": null,
273
+ "id": "a58e9462-89a2-4b4f-b4aa-51c4bd9f796b",
274
+ "metadata": {},
275
+ "outputs": [],
276
+ "source": [
277
+ "# This is a useful command that ensures your Anaconda environment \n",
278
+ "# is up to date with any new upgrades to packages;\n",
279
+ "# But it might take a minute and will print a lot to output\n",
280
+ "\n",
281
+ "!conda env update -f ../environment.yml"
282
+ ]
283
+ },
284
+ {
285
+ "cell_type": "markdown",
286
+ "id": "4688baaf-a72c-41b5-90b6-474cb24790a7",
287
+ "metadata": {},
288
+ "source": [
289
+ "# Minor things we encounter on the course\n",
290
+ "\n",
291
+ "This isn't necessarily a feature of Jupyter, but it's a nice package to know about that is useful in Jupyter Labs, and I use it in the course.\n",
292
+ "\n",
293
+ "The package `tqdm` will print a nice progress bar if you wrap any iterable."
294
+ ]
295
+ },
296
+ {
297
+ "cell_type": "code",
298
+ "execution_count": null,
299
+ "id": "2646a4e5-3c23-4aee-a34d-d623815187d2",
300
+ "metadata": {},
301
+ "outputs": [],
302
+ "source": [
303
+ "# Here's some code with no progress bar\n",
304
+ "# It will take 10 seconds while you wonder what's happpening..\n",
305
+ "\n",
306
+ "import time\n",
307
+ "\n",
308
+ "spams = [\"spam\"] * 1000\n",
309
+ "\n",
310
+ "for spam in spams:\n",
311
+ " time.sleep(0.01)"
312
+ ]
313
+ },
314
+ {
315
+ "cell_type": "code",
316
+ "execution_count": null,
317
+ "id": "6e96be3d-fa82-42a3-a8aa-b81dd20563a5",
318
+ "metadata": {},
319
+ "outputs": [],
320
+ "source": [
321
+ "# And now, with a nice little progress bar:\n",
322
+ "\n",
323
+ "import time\n",
324
+ "from tqdm import tqdm\n",
325
+ "\n",
326
+ "spams = [\"spam\"] * 1000\n",
327
+ "\n",
328
+ "for spam in tqdm(spams):\n",
329
+ " time.sleep(0.01)"
330
+ ]
331
+ },
332
+ {
333
+ "cell_type": "code",
334
+ "execution_count": null,
335
+ "id": "63c788dd-4618-4bb4-a5ce-204411a38ade",
336
+ "metadata": {},
337
+ "outputs": [],
338
+ "source": [
339
+ "# On a different topic, here's a useful way to print output in markdown\n",
340
+ "\n",
341
+ "from IPython.display import Markdown, display\n",
342
+ "\n",
343
+ "display(Markdown(\"# This is a big heading!\\n\\n- And this is a bullet-point\\n- So is this\\n- Me, too!\"))\n"
344
+ ]
345
+ },
346
+ {
347
+ "cell_type": "markdown",
348
+ "id": "9d14c1fb-3321-4387-b6ca-9af27676f980",
349
+ "metadata": {},
350
+ "source": [
351
+ "# That's it! You're up to speed on Jupyter Lab.\n",
352
+ "\n",
353
+ "## Want to be even more advanced?\n",
354
+ "\n",
355
+ "If you want to become a pro at Jupyter Lab, you can read their tutorial [here](https://jupyterlab.readthedocs.io/en/latest/). But this isn't required for our course; just a good technique for hitting Shift + Return and enjoying the result!"
356
+ ]
357
+ }
358
+ ],
359
+ "metadata": {
360
+ "kernelspec": {
361
+ "display_name": "Python 3 (ipykernel)",
362
+ "language": "python",
363
+ "name": "python3"
364
+ },
365
+ "language_info": {
366
+ "codemirror_mode": {
367
+ "name": "ipython",
368
+ "version": 3
369
+ },
370
+ "file_extension": ".py",
371
+ "mimetype": "text/x-python",
372
+ "name": "python",
373
+ "nbconvert_exporter": "python",
374
+ "pygments_lexer": "ipython3",
375
+ "version": "3.11.11"
376
+ }
377
+ },
378
+ "nbformat": 4,
379
+ "nbformat_minor": 5
380
+ }
week1/Intermediate Python.ipynb ADDED
@@ -0,0 +1,486 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "markdown",
5
+ "id": "5c291475-8c7c-461c-9b12-545a887b2432",
6
+ "metadata": {},
7
+ "source": [
8
+ "# Intermediate Level Python\n",
9
+ "\n",
10
+ "## Getting you up to speed\n",
11
+ "\n",
12
+ "This course assumes that you're at an intermediate level of python. For example, you should have a decent idea what something like this might do:\n",
13
+ "\n",
14
+ "`yield from {book.get(\"author\") for book in books if book.get(\"author\")}`\n",
15
+ "\n",
16
+ "If not - then you've come to the right place! Welcome to the crash course in intermediate level python. The best way to learn is by doing!\n"
17
+ ]
18
+ },
19
+ {
20
+ "cell_type": "markdown",
21
+ "id": "542f0577-a826-4613-a5d7-4170e9666d04",
22
+ "metadata": {},
23
+ "source": [
24
+ "## First: if you need a refresher on the foundations\n",
25
+ "\n",
26
+ "I'm going to defer to an AI friend for this, because these explanations are so well written with great examples. Copy and paste the code examples into a new cell to give them a try. Pick whichever section(s) you'd like to brush up on.\n",
27
+ "\n",
28
+ "**Python imports:** \n",
29
+ "https://chatgpt.com/share/672f9f31-8114-8012-be09-29ef0d0140fb\n",
30
+ "\n",
31
+ "**Python functions** including default arguments: \n",
32
+ "https://chatgpt.com/share/672f9f99-7060-8012-bfec-46d4cf77d672\n",
33
+ "\n",
34
+ "**Python strings**, including slicing, split/join, replace and literals: \n",
35
+ "https://chatgpt.com/share/672fb526-0aa0-8012-9e00-ad1687c04518\n",
36
+ "\n",
37
+ "**Python f-strings** including number and date formatting: \n",
38
+ "https://chatgpt.com/share/672fa125-0de0-8012-8e35-27918cbb481c\n",
39
+ "\n",
40
+ "**Python lists, dicts and sets**, including the `get()` method: \n",
41
+ "https://chatgpt.com/share/672fa225-3f04-8012-91af-f9c95287da8d\n",
42
+ "\n",
43
+ "**Python files** including modes, encoding, context managers, Path, glob.glob: \n",
44
+ "https://chatgpt.com/share/673b53b2-6d5c-8012-a344-221056c2f960\n",
45
+ "\n",
46
+ "**Python classes:** \n",
47
+ "https://chatgpt.com/share/672fa07a-1014-8012-b2ea-6dc679552715\n",
48
+ "\n",
49
+ "**Pickling Python objects and converting to JSON:** \n",
50
+ "https://chatgpt.com/share/673b553e-9d0c-8012-9919-f3bb5aa23e31"
51
+ ]
52
+ },
53
+ {
54
+ "cell_type": "markdown",
55
+ "id": "f9e0f8e1-09b3-478b-ada7-c8c35003929b",
56
+ "metadata": {},
57
+ "source": [
58
+ "## With this in mind - understanding NameErrors in Python\n",
59
+ "\n",
60
+ "It's quite common to hit a NameError in python. With foundational knowledge, you should always feel equipped to debug a NameError and get to the bottom of it.\n",
61
+ "\n",
62
+ "If you're unsure how to fix a NameError, please see this [initial guide](https://chatgpt.com/share/67958312-ada0-8012-a1d3-62b3a5fcbbfc) and this [second guide with exercises](https://chatgpt.com/share/67a57e0b-0194-8012-bb50-8ea76c5995b8), and work through them both until you have high confidence.\n",
63
+ "\n",
64
+ "There's some repetition here, so feel free to skip it if you're already confident.\n",
65
+ "\n",
66
+ "## And now, on to the code!"
67
+ ]
68
+ },
69
+ {
70
+ "cell_type": "code",
71
+ "execution_count": null,
72
+ "id": "5802e2f0-0ea0-4237-bbb7-f375a34260f0",
73
+ "metadata": {},
74
+ "outputs": [],
75
+ "source": [
76
+ "# First let's create some things:\n",
77
+ "\n",
78
+ "fruits = [\"Apples\", \"Bananas\", \"Pears\"]\n",
79
+ "\n",
80
+ "book1 = {\"title\": \"Great Expectations\", \"author\": \"Charles Dickens\"}\n",
81
+ "book2 = {\"title\": \"Bleak House\", \"author\": \"Charles Dickens\"}\n",
82
+ "book3 = {\"title\": \"An Book By No Author\"}\n",
83
+ "book4 = {\"title\": \"Moby Dick\", \"author\": \"Herman Melville\"}\n",
84
+ "\n",
85
+ "books = [book1, book2, book3, book4]"
86
+ ]
87
+ },
88
+ {
89
+ "cell_type": "markdown",
90
+ "id": "9b941e6a-3658-4144-a8d4-72f5e72f3707",
91
+ "metadata": {},
92
+ "source": [
93
+ "# Part 1: List and dict comprehensions"
94
+ ]
95
+ },
96
+ {
97
+ "cell_type": "code",
98
+ "execution_count": null,
99
+ "id": "61992bb8-735d-4dad-8747-8c10b63aec82",
100
+ "metadata": {},
101
+ "outputs": [],
102
+ "source": [
103
+ "# Simple enough to start\n",
104
+ "\n",
105
+ "for fruit in fruits:\n",
106
+ " print(fruit)"
107
+ ]
108
+ },
109
+ {
110
+ "cell_type": "code",
111
+ "execution_count": null,
112
+ "id": "c89c3842-9b74-47fa-8424-0fcb08e4177c",
113
+ "metadata": {},
114
+ "outputs": [],
115
+ "source": [
116
+ "# Let's make a new version of fruits\n",
117
+ "\n",
118
+ "fruits_shouted = []\n",
119
+ "for fruit in fruits:\n",
120
+ " fruits_shouted.append(fruit.upper())\n",
121
+ "\n",
122
+ "fruits_shouted"
123
+ ]
124
+ },
125
+ {
126
+ "cell_type": "code",
127
+ "execution_count": null,
128
+ "id": "4ec13b3a-9545-44f1-874a-2910a0663560",
129
+ "metadata": {},
130
+ "outputs": [],
131
+ "source": [
132
+ "# You probably already know this\n",
133
+ "# There's a nice Python construct called \"list comprehension\" that does this:\n",
134
+ "\n",
135
+ "fruits_shouted2 = [fruit.upper() for fruit in fruits]\n",
136
+ "fruits_shouted2"
137
+ ]
138
+ },
139
+ {
140
+ "cell_type": "code",
141
+ "execution_count": null,
142
+ "id": "ecc08c3c-181d-4b64-a3e1-b0ccffc6c0cd",
143
+ "metadata": {},
144
+ "outputs": [],
145
+ "source": [
146
+ "# But you may not know that you can do this to create dictionaries, too:\n",
147
+ "\n",
148
+ "fruit_mapping = {fruit: fruit.upper() for fruit in fruits}\n",
149
+ "fruit_mapping"
150
+ ]
151
+ },
152
+ {
153
+ "cell_type": "code",
154
+ "execution_count": null,
155
+ "id": "500c2406-00d2-4793-b57b-f49b612760c8",
156
+ "metadata": {},
157
+ "outputs": [],
158
+ "source": [
159
+ "# you can also use the if statement to filter the results\n",
160
+ "\n",
161
+ "fruits_with_longer_names_shouted = [fruit.upper() for fruit in fruits if len(fruit)>5]\n",
162
+ "fruits_with_longer_names_shouted"
163
+ ]
164
+ },
165
+ {
166
+ "cell_type": "code",
167
+ "execution_count": null,
168
+ "id": "38c11c34-d71e-45ba-945b-a3d37dc29793",
169
+ "metadata": {},
170
+ "outputs": [],
171
+ "source": [
172
+ "fruit_mapping_unless_starts_with_a = {fruit: fruit.upper() for fruit in fruits if not fruit.startswith('A')}\n",
173
+ "fruit_mapping_unless_starts_with_a"
174
+ ]
175
+ },
176
+ {
177
+ "cell_type": "code",
178
+ "execution_count": null,
179
+ "id": "5c97d8e8-31de-4afa-973e-28d8e5cab749",
180
+ "metadata": {},
181
+ "outputs": [],
182
+ "source": [
183
+ "# Another comprehension\n",
184
+ "\n",
185
+ "[book['title'] for book in books]"
186
+ ]
187
+ },
188
+ {
189
+ "cell_type": "code",
190
+ "execution_count": null,
191
+ "id": "50be0edc-a4cd-493f-a680-06080bb497b4",
192
+ "metadata": {},
193
+ "outputs": [],
194
+ "source": [
195
+ "# This code will fail with an error because one of our books doesn't have an author\n",
196
+ "\n",
197
+ "[book['author'] for book in books]"
198
+ ]
199
+ },
200
+ {
201
+ "cell_type": "code",
202
+ "execution_count": null,
203
+ "id": "53794083-cc09-4edb-b448-2ffb7e8495c2",
204
+ "metadata": {},
205
+ "outputs": [],
206
+ "source": [
207
+ "# But this will work, because get() returns None\n",
208
+ "\n",
209
+ "[book.get('author') for book in books]"
210
+ ]
211
+ },
212
+ {
213
+ "cell_type": "code",
214
+ "execution_count": null,
215
+ "id": "b8e4b859-24f8-4016-8d74-c2cef226d049",
216
+ "metadata": {},
217
+ "outputs": [],
218
+ "source": [
219
+ "# And this variation will filter out the None\n",
220
+ "\n",
221
+ "[book.get('author') for book in books if book.get('author')]"
222
+ ]
223
+ },
224
+ {
225
+ "cell_type": "code",
226
+ "execution_count": null,
227
+ "id": "c44bb999-52b4-4dee-810b-8a400db8f25f",
228
+ "metadata": {},
229
+ "outputs": [],
230
+ "source": [
231
+ "# And this version will convert it into a set, removing duplicates\n",
232
+ "\n",
233
+ "set([book.get('author') for book in books if book.get('author')])"
234
+ ]
235
+ },
236
+ {
237
+ "cell_type": "code",
238
+ "execution_count": null,
239
+ "id": "80a65156-6192-4bb4-b4e6-df3fdc933891",
240
+ "metadata": {},
241
+ "outputs": [],
242
+ "source": [
243
+ "# And finally, this version is even nicer\n",
244
+ "# curly braces creates a set, so this is a set comprehension\n",
245
+ "\n",
246
+ "{book.get('author') for book in books if book.get('author')}"
247
+ ]
248
+ },
249
+ {
250
+ "cell_type": "markdown",
251
+ "id": "c100e5db-5438-4715-921c-3f7152f83f4a",
252
+ "metadata": {},
253
+ "source": [
254
+ "# Part 2: Generators\n",
255
+ "\n",
256
+ "We use Generators in the course because AI models can stream back results.\n",
257
+ "\n",
258
+ "If you've not used Generators before, please start with this excellent intro from ChatGPT:\n",
259
+ "\n",
260
+ "https://chatgpt.com/share/672faa6e-7dd0-8012-aae5-44fc0d0ec218\n",
261
+ "\n",
262
+ "Try pasting some of its examples into a cell."
263
+ ]
264
+ },
265
+ {
266
+ "cell_type": "code",
267
+ "execution_count": null,
268
+ "id": "1efc26fa-9144-4352-9a17-dfec1d246aad",
269
+ "metadata": {},
270
+ "outputs": [],
271
+ "source": [
272
+ "# First define a generator; it looks like a function, but it has yield instead of return\n",
273
+ "\n",
274
+ "import time\n",
275
+ "\n",
276
+ "def come_up_with_fruit_names():\n",
277
+ " for fruit in fruits:\n",
278
+ " time.sleep(1) # thinking of a fruit\n",
279
+ " yield fruit"
280
+ ]
281
+ },
282
+ {
283
+ "cell_type": "code",
284
+ "execution_count": null,
285
+ "id": "eac338bb-285c-45c8-8a3e-dbfc41409ca3",
286
+ "metadata": {},
287
+ "outputs": [],
288
+ "source": [
289
+ "# Then use it\n",
290
+ "\n",
291
+ "for fruit in come_up_with_fruit_names():\n",
292
+ " print(fruit)"
293
+ ]
294
+ },
295
+ {
296
+ "cell_type": "code",
297
+ "execution_count": null,
298
+ "id": "f6880578-a3de-4502-952a-4572b95eb9ff",
299
+ "metadata": {},
300
+ "outputs": [],
301
+ "source": [
302
+ "# Here's another one\n",
303
+ "\n",
304
+ "def authors_generator():\n",
305
+ " for book in books:\n",
306
+ " if book.get(\"author\"):\n",
307
+ " yield book.get(\"author\")"
308
+ ]
309
+ },
310
+ {
311
+ "cell_type": "code",
312
+ "execution_count": null,
313
+ "id": "9e316f02-f87f-441d-a01f-024ade949607",
314
+ "metadata": {},
315
+ "outputs": [],
316
+ "source": [
317
+ "# Use it\n",
318
+ "\n",
319
+ "for author in authors_generator():\n",
320
+ " print(author)"
321
+ ]
322
+ },
323
+ {
324
+ "cell_type": "code",
325
+ "execution_count": null,
326
+ "id": "7535c9d0-410e-4e56-a86c-ae6c0e16053f",
327
+ "metadata": {},
328
+ "outputs": [],
329
+ "source": [
330
+ "# Here's the same thing written with list comprehension\n",
331
+ "\n",
332
+ "def authors_generator():\n",
333
+ " for author in [book.get(\"author\") for book in books if book.get(\"author\")]:\n",
334
+ " yield author"
335
+ ]
336
+ },
337
+ {
338
+ "cell_type": "code",
339
+ "execution_count": null,
340
+ "id": "dad34494-0f6c-4edb-b03f-b8d49ee186f2",
341
+ "metadata": {},
342
+ "outputs": [],
343
+ "source": [
344
+ "# Use it\n",
345
+ "\n",
346
+ "for author in authors_generator():\n",
347
+ " print(author)"
348
+ ]
349
+ },
350
+ {
351
+ "cell_type": "code",
352
+ "execution_count": null,
353
+ "id": "abeb7e61-d8aa-4af0-b05a-ae17323e678c",
354
+ "metadata": {},
355
+ "outputs": [],
356
+ "source": [
357
+ "# Here's a nice shortcut\n",
358
+ "# You can use \"yield from\" to yield each item of an iterable\n",
359
+ "\n",
360
+ "def authors_generator():\n",
361
+ " yield from [book.get(\"author\") for book in books if book.get(\"author\")]"
362
+ ]
363
+ },
364
+ {
365
+ "cell_type": "code",
366
+ "execution_count": null,
367
+ "id": "05b0cb43-aa83-4762-a797-d3beb0f22c44",
368
+ "metadata": {},
369
+ "outputs": [],
370
+ "source": [
371
+ "# Use it\n",
372
+ "\n",
373
+ "for author in authors_generator():\n",
374
+ " print(author)"
375
+ ]
376
+ },
377
+ {
378
+ "cell_type": "code",
379
+ "execution_count": null,
380
+ "id": "fdfea58e-d809-4dd4-b7b0-c26427f8be55",
381
+ "metadata": {},
382
+ "outputs": [],
383
+ "source": [
384
+ "# And finally - we can replace the list comprehension with a set comprehension\n",
385
+ "\n",
386
+ "def unique_authors_generator():\n",
387
+ " yield from {book.get(\"author\") for book in books if book.get(\"author\")}"
388
+ ]
389
+ },
390
+ {
391
+ "cell_type": "code",
392
+ "execution_count": null,
393
+ "id": "3e821d08-97be-4db9-9a5b-ce5dced3eff8",
394
+ "metadata": {},
395
+ "outputs": [],
396
+ "source": [
397
+ "# Use it\n",
398
+ "\n",
399
+ "for author in unique_authors_generator():\n",
400
+ " print(author)"
401
+ ]
402
+ },
403
+ {
404
+ "cell_type": "code",
405
+ "execution_count": null,
406
+ "id": "905ba603-15d8-4d01-9a79-60ec293d7ca1",
407
+ "metadata": {},
408
+ "outputs": [],
409
+ "source": [
410
+ "# And for some fun - press the stop button in the toolbar when bored!\n",
411
+ "# It's like we've made our own Large Language Model... although not particularly large..\n",
412
+ "# See if you understand why it prints a letter at a time, instead of a word at a time. If you're unsure, try removing the keyword \"from\" everywhere in the code.\n",
413
+ "\n",
414
+ "import random\n",
415
+ "import time\n",
416
+ "\n",
417
+ "pronouns = [\"I\", \"You\", \"We\", \"They\"]\n",
418
+ "verbs = [\"eat\", \"detest\", \"bathe in\", \"deny the existence of\", \"resent\", \"pontificate about\", \"juggle\", \"impersonate\", \"worship\", \"misplace\", \"conspire with\", \"philosophize about\", \"tap dance on\", \"dramatically renounce\", \"secretly collect\"]\n",
419
+ "adjectives = [\"turqoise\", \"smelly\", \"arrogant\", \"festering\", \"pleasing\", \"whimsical\", \"disheveled\", \"pretentious\", \"wobbly\", \"melodramatic\", \"pompous\", \"fluorescent\", \"bewildered\", \"suspicious\", \"overripe\"]\n",
420
+ "nouns = [\"turnips\", \"rodents\", \"eels\", \"walruses\", \"kumquats\", \"monocles\", \"spreadsheets\", \"bagpipes\", \"wombats\", \"accordions\", \"mustaches\", \"calculators\", \"jellyfish\", \"thermostats\"]\n",
421
+ "\n",
422
+ "def infinite_random_sentences():\n",
423
+ " while True:\n",
424
+ " yield from random.choice(pronouns)\n",
425
+ " yield \" \"\n",
426
+ " yield from random.choice(verbs)\n",
427
+ " yield \" \"\n",
428
+ " yield from random.choice(adjectives)\n",
429
+ " yield \" \"\n",
430
+ " yield from random.choice(nouns)\n",
431
+ " yield \". \"\n",
432
+ "\n",
433
+ "for letter in infinite_random_sentences():\n",
434
+ " print(letter, end=\"\", flush=True)\n",
435
+ " time.sleep(0.02)"
436
+ ]
437
+ },
438
+ {
439
+ "cell_type": "markdown",
440
+ "id": "04832ea2-2447-4473-a449-104f80e24d85",
441
+ "metadata": {},
442
+ "source": [
443
+ "# Exercise\n",
444
+ "\n",
445
+ "Write some python classes for the books example.\n",
446
+ "\n",
447
+ "Write a Book class with a title and author. Include a method has_author()\n",
448
+ "\n",
449
+ "Write a BookShelf class with a list of books. Include a generator method unique_authors()"
450
+ ]
451
+ },
452
+ {
453
+ "cell_type": "markdown",
454
+ "id": "35760406-fe6c-41f9-b0c0-3e8cf73aafd0",
455
+ "metadata": {},
456
+ "source": [
457
+ "# Finally\n",
458
+ "\n",
459
+ "Here are some intermediate level details of Classes from our AI friend, including use of type hints, inheritance and class methods. This includes a Book example.\n",
460
+ "\n",
461
+ "https://chatgpt.com/share/67348aca-65fc-8012-a4a9-fd1b8f04ba59"
462
+ ]
463
+ }
464
+ ],
465
+ "metadata": {
466
+ "kernelspec": {
467
+ "display_name": "Python 3 (ipykernel)",
468
+ "language": "python",
469
+ "name": "python3"
470
+ },
471
+ "language_info": {
472
+ "codemirror_mode": {
473
+ "name": "ipython",
474
+ "version": 3
475
+ },
476
+ "file_extension": ".py",
477
+ "mimetype": "text/x-python",
478
+ "name": "python",
479
+ "nbconvert_exporter": "python",
480
+ "pygments_lexer": "ipython3",
481
+ "version": "3.11.11"
482
+ }
483
+ },
484
+ "nbformat": 4,
485
+ "nbformat_minor": 5
486
+ }
week1/community-contributions/0225_day2_exercise_by_LM.ipynb ADDED
@@ -0,0 +1,185 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "markdown",
5
+ "id": "fef36918-109d-41e3-8603-75ff81b42379",
6
+ "metadata": {},
7
+ "source": [
8
+ "# Solution for exercise day 2 - slight modification: model is a parameter also - display_summary(\"deepseek-r1:1.5b\",\"https://yoururl\")\n",
9
+ "\n"
10
+ ]
11
+ },
12
+ {
13
+ "cell_type": "code",
14
+ "execution_count": null,
15
+ "id": "b50349ac-93ea-496b-ae20-bd72a93bb138",
16
+ "metadata": {},
17
+ "outputs": [],
18
+ "source": [
19
+ "# imports\n",
20
+ "\n",
21
+ "import requests\n",
22
+ "from bs4 import BeautifulSoup\n",
23
+ "from IPython.display import Markdown, display"
24
+ ]
25
+ },
26
+ {
27
+ "cell_type": "code",
28
+ "execution_count": null,
29
+ "id": "edd073c7-8444-4a0d-b84e-4b2ed0ee7f35",
30
+ "metadata": {},
31
+ "outputs": [],
32
+ "source": [
33
+ "# Constants\n",
34
+ "OLLAMA_API = \"http://localhost:11434/api/chat\"\n",
35
+ "HEADERS = {\"Content-Type\": \"application/json\"}\n",
36
+ "#MODEL = \"llama3.2\""
37
+ ]
38
+ },
39
+ {
40
+ "cell_type": "code",
41
+ "execution_count": null,
42
+ "id": "2e3a6e1a-e4c7-4448-9852-1b6ba2bd8d66",
43
+ "metadata": {},
44
+ "outputs": [],
45
+ "source": [
46
+ "# A class to represent a Webpage\n",
47
+ "# Some websites need you to use proper headers when fetching them:\n",
48
+ "headers = {\n",
49
+ " \"User-Agent\": \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36\"\n",
50
+ "}\n",
51
+ "\n",
52
+ "class Website:\n",
53
+ "\n",
54
+ " def __init__(self, url):\n",
55
+ " \"\"\"\n",
56
+ " Create this Website object from the given url using the BeautifulSoup library\n",
57
+ " \"\"\"\n",
58
+ " self.url = url\n",
59
+ " response = requests.get(url, headers=headers)\n",
60
+ " soup = BeautifulSoup(response.content, 'html.parser')\n",
61
+ " self.title = soup.title.string if soup.title else \"No title found\"\n",
62
+ " for irrelevant in soup.body([\"script\", \"style\", \"img\", \"input\"]):\n",
63
+ " irrelevant.decompose()\n",
64
+ " self.text = soup.body.get_text(separator=\"\\n\", strip=True)"
65
+ ]
66
+ },
67
+ {
68
+ "cell_type": "code",
69
+ "execution_count": null,
70
+ "id": "ae3752ca-3a97-4d6a-ac84-5b75ebfb50ed",
71
+ "metadata": {},
72
+ "outputs": [],
73
+ "source": [
74
+ "# Define the system prompt \n",
75
+ "system_prompt = \"You are an assistant that analyzes the contents of a website \\\n",
76
+ "and provides a short summary, ignoring text that might be navigation related. \\\n",
77
+ "Respond in markdown.\""
78
+ ]
79
+ },
80
+ {
81
+ "cell_type": "code",
82
+ "execution_count": null,
83
+ "id": "48b5240f-7617-4e51-a320-cba9650bec84",
84
+ "metadata": {},
85
+ "outputs": [],
86
+ "source": [
87
+ "# A function that writes a User Prompt that asks for summaries of websites:\n",
88
+ "\n",
89
+ "def user_prompt_for(website):\n",
90
+ " user_prompt = f\"You are looking at a website titled {website.title}\"\n",
91
+ " user_prompt += \"\\nThe contents of this website is as follows; \\\n",
92
+ "please provide a short summary of this website in markdown. \\\n",
93
+ "If it includes news or announcements, then summarize these too.\\n\\n\"\n",
94
+ " user_prompt += website.text\n",
95
+ " return user_prompt"
96
+ ]
97
+ },
98
+ {
99
+ "cell_type": "code",
100
+ "execution_count": null,
101
+ "id": "6f7d84f0-60f2-4cbf-b4d1-173a79fe3380",
102
+ "metadata": {},
103
+ "outputs": [],
104
+ "source": [
105
+ "def messages_for(website):\n",
106
+ " return [\n",
107
+ " {\"role\": \"system\", \"content\": system_prompt},\n",
108
+ " {\"role\": \"user\", \"content\": user_prompt_for(website)}\n",
109
+ " ]"
110
+ ]
111
+ },
112
+ {
113
+ "cell_type": "code",
114
+ "execution_count": null,
115
+ "id": "25520a31-c857-4ed5-86da-50dfe5fab7bb",
116
+ "metadata": {},
117
+ "outputs": [],
118
+ "source": [
119
+ "def summarize(model,url):\n",
120
+ " website = Website(url)\n",
121
+ " payload = {\n",
122
+ " \"model\": model,\n",
123
+ " \"messages\": messages_for(website),\n",
124
+ " \"stream\": False\n",
125
+ " }\n",
126
+ " response = requests.post(OLLAMA_API, json=payload, headers=HEADERS)\n",
127
+ " return response.json()['message']['content']"
128
+ ]
129
+ },
130
+ {
131
+ "cell_type": "code",
132
+ "execution_count": null,
133
+ "id": "430776ed-8516-43a9-8a22-618d9080f2e1",
134
+ "metadata": {},
135
+ "outputs": [],
136
+ "source": [
137
+ "# A function to display this nicely in the Jupyter output, using markdown\n",
138
+ "def display_summary(model,url):\n",
139
+ " summary = summarize(model,url)\n",
140
+ " display(Markdown(summary))"
141
+ ]
142
+ },
143
+ {
144
+ "cell_type": "code",
145
+ "execution_count": null,
146
+ "id": "b2b05c1f-e4a2-4f65-bd6d-634d72e38b6e",
147
+ "metadata": {},
148
+ "outputs": [],
149
+ "source": [
150
+ "#!ollama pull deepseek-r1:1.5b"
151
+ ]
152
+ },
153
+ {
154
+ "cell_type": "code",
155
+ "execution_count": null,
156
+ "id": "01513f8a-15b7-4053-bfe4-44b36e5494d1",
157
+ "metadata": {},
158
+ "outputs": [],
159
+ "source": [
160
+ "display_summary(\"deepseek-r1:1.5b\",\"https://www.ipma.pt\")"
161
+ ]
162
+ }
163
+ ],
164
+ "metadata": {
165
+ "kernelspec": {
166
+ "display_name": "Python 3 (ipykernel)",
167
+ "language": "python",
168
+ "name": "python3"
169
+ },
170
+ "language_info": {
171
+ "codemirror_mode": {
172
+ "name": "ipython",
173
+ "version": 3
174
+ },
175
+ "file_extension": ".py",
176
+ "mimetype": "text/x-python",
177
+ "name": "python",
178
+ "nbconvert_exporter": "python",
179
+ "pygments_lexer": "ipython3",
180
+ "version": "3.12.9"
181
+ }
182
+ },
183
+ "nbformat": 4,
184
+ "nbformat_minor": 5
185
+ }
week1/community-contributions/Chat_Summary_Data/Chat_Examples/Chat1.txt ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Client: Hello I would like to order a pizza
2
+ Restaurant: Sure. What pizza would you like to order from our menu?
3
+ Client: Chicken Ranch
4
+ Restaurant: I am so sorry, but chicken ranch is currently unavailable on our menu
5
+ Client: AHHHHH. Do you have chicken BBQ?
6
+ Restaurant: Yes! Do you want it small, medium, or large?
7
+ Client: Medium
8
+ Restaurant: Ok. This will be 180 LE
9
+ Client: Thanks
10
+ Restaurant: Anytime.
11
+ Client: AHHHH I forgot. I want to add a new chicken BBQ pizza
12
+ Restaurant: No problem. Do you also want it medium?
13
+ Client: Yes
14
+ Restaurant: Okay this will be 380 LE
15
+ Client: Okay Thanks
16
+ Client: Wait a minute. Isn't 180 * 2 = 360?
17
+ Restaurant: It seems that there might be a misunderstanding. We add an extra 20 LE for every extra pizza ordered.
18
+ Client: NOBODY TOLD ME THAT.. AND WHY ON EARTH WOULD YOU DO SOMETHING LIKE THAT?
19
+ Restaurant: We are sorry but this is our policy.
20
+ Client: Okay then I don't want your pizza.
21
+ Restaurant: We are so sorry to hear that. We can make a 10% discount on the total price so it would be 342 LE
22
+ Client: Fine
23
+ Restaurant: Thank you for ordering
24
+ Restaurant: Pizza is delivered. How is your experience?
25
+ Client: Your pizza doesn't taste good
26
+ Restaurant: We are so sorry to hear that. Do you have any suggestions you would like to make?
27
+ Client: Make good pizza
28
+ Restaurant: Thanks for your review. We will make sure to improve our pizza in the future. Your opinion really matters.
week1/community-contributions/Chat_Summary_Data/Chat_Examples/Chat2.txt ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ Client: Hello I would like to order a chicken ranch pizza
2
+ Restaurant: I am so sorry, but chicken ranch is currently unavailable on our menu
3
+ Client: Okay thanks
4
+ Restaurant: Would you like to order something else?
5
+ Client: No thank you
week1/community-contributions/Chat_Summary_Data/Chat_Examples/Chat3.txt ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Client: Hello. What is the most selling pizza on your menu?
2
+ Restaurant: Hello! Chicken Ranch pizza is our most selling pizza. Also our special pepperoni pizza got some amazing reviews
3
+ Client: Okay. I want to order a pepperoni pizza
4
+ Restaurant: Sure. Do you want it small, medium, or large?
5
+ Client: Large
6
+ Restaurant: Okay. This will be 210 LE. Would you like to order something else?
7
+ Client: Yes. Do you have onion rings?
8
+ Restaurant: Yes
9
+ Client: Okay I would like to add onion rings.
10
+ Restaurant: Sure. This will be 250 LE
11
+ Client: Thanks
12
+ Restaurant: Anytime
13
+ Client: I have been waiting for too long and the order hasn't arrived yet
14
+ Restaurant: Sorry to hear that. But it appears that the order is on its way to you.
15
+ Restaurant: The order is supposed to be arrived by now.
16
+ Client: Yes it is arrived.
17
+ Restaurant: How is your experience?
18
+ Client: Your pizza tastes soooooo good. The order took too long to arrive but when I tasted the pizza, I was really enjoying it and forgot everything about the delay.
19
+ Restaurant: We are so glad to hear that
week1/community-contributions/Chat_Summary_Data/System_Prompt.txt ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ You are an assistant working for the customer service department in a pizza restaurant.
2
+ You are to receive a chat between a client and the restaurant's customer service.
3
+ You should generate your responses based on the following criteria:
4
+ - What did the client order?
5
+ - How much did it cost?
6
+ - If the client changed their mind just keep their final order and the final cost
7
+ - Mention the client's experience only if they ordered anything as follows: (Positive/Negative/Neutral/Unknown)
8
+ - If the client did not order anything do not mention their sentiment or experience
9
+ - If the client's experience is positive or negative only, provide a brief summary about their sentiment
10
+ - Do not provide brief summary about their sentiment if their experience was neutral or unknown.
11
+ - Your answers should be clear, straight to the point, and do not use long sentences
12
+ - Your answers should be displayed in bullet points
13
+ - Your answers should be displayed in markdown
14
+ - If the client did not order anything provide a brief summary why that might happened
15
+ - Do not mention cost if the client did not order anything
week1/community-contributions/CoolCodeSummarizer.ipynb ADDED
@@ -0,0 +1,177 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "markdown",
5
+ "id": "0b15b939-593a-4ccc-89bd-0cee09fe2f12",
6
+ "metadata": {},
7
+ "source": [
8
+ "# Python Code Summarizer\n",
9
+ "\n",
10
+ "The Below code will summarize the python code and example it in details which can help codes better understand a forigen code."
11
+ ]
12
+ },
13
+ {
14
+ "cell_type": "code",
15
+ "execution_count": null,
16
+ "id": "8dcf353c-e4f2-4ce7-a3b5-71b29700a148",
17
+ "metadata": {},
18
+ "outputs": [],
19
+ "source": [
20
+ "# Imports\n",
21
+ "from IPython.display import Markdown, display\n",
22
+ "import os\n",
23
+ "import openai\n",
24
+ "from dotenv import load_dotenv"
25
+ ]
26
+ },
27
+ {
28
+ "cell_type": "code",
29
+ "execution_count": null,
30
+ "id": "111cf632-08e8-4246-a5bb-b56942789242",
31
+ "metadata": {},
32
+ "outputs": [],
33
+ "source": [
34
+ "load_dotenv(override=True)\n",
35
+ "api_key = os.getenv('OPENAI_API_KEY')"
36
+ ]
37
+ },
38
+ {
39
+ "cell_type": "code",
40
+ "execution_count": null,
41
+ "id": "e4f5376f-5e6f-4d75-81bf-222e34bfe828",
42
+ "metadata": {},
43
+ "outputs": [],
44
+ "source": [
45
+ "def read_code(**kwargs):\n",
46
+ " \"\"\"\n",
47
+ " You can pass two types of key word arguments to this function.\n",
48
+ " code_path= Path to your complex python code.\n",
49
+ " code= Passing raw python code.\n",
50
+ " \"\"\"\n",
51
+ " code_path = kwargs.get('code_path',None)\n",
52
+ " code_raw = kwargs.get('code',None)\n",
53
+ " \n",
54
+ " if code_path:\n",
55
+ " with open(code_path, 'r') as code_file:\n",
56
+ " code = code_file.read()\n",
57
+ " return (True, code)\n",
58
+ "\n",
59
+ " if code_raw:\n",
60
+ " return (True, code_raw)\n",
61
+ "\n",
62
+ " return (False, None)"
63
+ ]
64
+ },
65
+ {
66
+ "cell_type": "code",
67
+ "execution_count": null,
68
+ "id": "00743dac-0e70-45b7-879a-d7293a6f68a6",
69
+ "metadata": {},
70
+ "outputs": [],
71
+ "source": [
72
+ "# Model Prompt\n",
73
+ "system_prompt = (\n",
74
+ " \"You are a helpful assistant. The following input will be a Python code snippet. \"\n",
75
+ " \"Your task is to:\\n\\n\"\n",
76
+ " \"1. Summarize the overall purpose of the code.\\n\"\n",
77
+ " \"2. Explain the code line by line, describing what each line does and why it's written that way.\\n\"\n",
78
+ " \"3. Provide reasoning behind the code structure and logic to help novice Python developers understand the concepts better.\\n\\n\"\n",
79
+ " \"Use Markdown format in your response. Make the explanation beginner-friendly, using code blocks, bullet points, and headings where helpful.\"\n",
80
+ " ) \n",
81
+ "# In a plot twist worthy of sci-fi, this prompt was written by ChatGPT...\n",
82
+ "# to tell ChatGPT how to respond. We’ve officially entered the Matrix. 🤖🌀"
83
+ ]
84
+ },
85
+ {
86
+ "cell_type": "code",
87
+ "execution_count": null,
88
+ "id": "ed7d2447-32a9-4761-8b0a-b31814bee7e5",
89
+ "metadata": {},
90
+ "outputs": [],
91
+ "source": [
92
+ "\n",
93
+ "# Guess where I got this code from :)\n",
94
+ "code_line = \"\"\"yeild from set(book.get(\"author)) for book in books if book.get(\"author\"))\"\"\"\n",
95
+ "is_code, raw_code = read_code(code=code_line)\n",
96
+ "\n",
97
+ "if is_code:\n",
98
+ " user_prompt = raw_code\n",
99
+ "else:\n",
100
+ " print(\"Invalid Arguments\")"
101
+ ]
102
+ },
103
+ {
104
+ "cell_type": "code",
105
+ "execution_count": null,
106
+ "id": "d74a1a39-1c24-4d4b-bd49-0ca416377a93",
107
+ "metadata": {},
108
+ "outputs": [],
109
+ "source": [
110
+ "def messages_for():\n",
111
+ " return [\n",
112
+ " {\"role\": \"system\", \"content\": system_prompt},\n",
113
+ " {\"role\": \"user\", \"content\": user_prompt}\n",
114
+ " ]"
115
+ ]
116
+ },
117
+ {
118
+ "cell_type": "code",
119
+ "execution_count": null,
120
+ "id": "df6c2726-d0fb-4ab6-b13b-d047e8807558",
121
+ "metadata": {},
122
+ "outputs": [],
123
+ "source": [
124
+ "def summarize():\n",
125
+ " \n",
126
+ " response = openai.chat.completions.create(\n",
127
+ " model = \"gpt-4o-mini\",\n",
128
+ " messages = messages_for()\n",
129
+ " )\n",
130
+ " return response.choices[0].message.content"
131
+ ]
132
+ },
133
+ {
134
+ "cell_type": "code",
135
+ "execution_count": null,
136
+ "id": "8425144c-595e-4ad6-9801-3e8778d285c4",
137
+ "metadata": {},
138
+ "outputs": [],
139
+ "source": [
140
+ "def display_summary():\n",
141
+ " summary = summarize()\n",
142
+ " display(Markdown(summary))"
143
+ ]
144
+ },
145
+ {
146
+ "cell_type": "code",
147
+ "execution_count": null,
148
+ "id": "744bffdd-ec3c-4b27-b126-81bf3e8c8295",
149
+ "metadata": {},
150
+ "outputs": [],
151
+ "source": [
152
+ "display_summary()"
153
+ ]
154
+ }
155
+ ],
156
+ "metadata": {
157
+ "kernelspec": {
158
+ "display_name": "Python 3 (ipykernel)",
159
+ "language": "python",
160
+ "name": "python3"
161
+ },
162
+ "language_info": {
163
+ "codemirror_mode": {
164
+ "name": "ipython",
165
+ "version": 3
166
+ },
167
+ "file_extension": ".py",
168
+ "mimetype": "text/x-python",
169
+ "name": "python",
170
+ "nbconvert_exporter": "python",
171
+ "pygments_lexer": "ipython3",
172
+ "version": "3.11.12"
173
+ }
174
+ },
175
+ "nbformat": 4,
176
+ "nbformat_minor": 5
177
+ }
week1/community-contributions/Day-1-Text-to-sql/db.py ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ import mysql.connector
2
+
3
+ def get_connection():
4
+ conn = mysql.connector.connect(
5
+ host="127.0.0.1",
6
+ user="root",
7
+ password="xyz",
8
+ database="your_database"
9
+ )
10
+ return conn
week1/community-contributions/Day-1-Text-to-sql/ollama-TTSQL.py ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import ollama
2
+ from db import get_connection
3
+ import mysql.connector
4
+
5
+ def text_to_sql(user_query):
6
+ prompt = f"""
7
+ Convert the following natural language query into an SQL statement for MySQL:
8
+
9
+ Query: "{user_query}"
10
+
11
+ Ensure the query is syntactically correct and does not contain harmful operations.
12
+ Only return the SQL query without any explanation.
13
+ """
14
+
15
+ # Update the model name to 'llama3.2:latest'
16
+ response = ollama.chat(model="llama3.2:latest", messages=[{"role": "user", "content": prompt}])
17
+ sql_query = response['message']['content'].strip()
18
+ return sql_query
19
+
20
+
21
+ # Uncomment this section if you wish to connect with mysql and fill out your credentials in db.py
22
+ '''def execute_sql_query(user_query):
23
+ sql_query = text_to_sql(user_query)
24
+
25
+ try:
26
+ conn = get_connection()
27
+ cursor = conn.cursor()
28
+ cursor.execute(sql_query)
29
+ result = cursor.fetchall()
30
+ except mysql.connector.Error as e:
31
+ return {"error": f"MySQL Error: {e}"}
32
+ except Exception as e:
33
+ return {"error": str(e)}
34
+ finally:
35
+ conn.close() # Ensure connection is closed even if an error occurs
36
+
37
+ return result'''
38
+
39
+ # Example usage
40
+ if __name__ == "__main__":
41
+ user_input = "Show me all users whose first name starts with the letter j in the first_name column."
42
+ print(text_to_sql(user_input))
week1/community-contributions/Day2-Solution-Ollama.ipynb ADDED
@@ -0,0 +1,123 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "markdown",
5
+ "id": "6e9fa1fc-eac5-4d1d-9be4-541b3f2b3458",
6
+ "metadata": {},
7
+ "source": [
8
+ "# Day 2 EXERCISE Solution:\n",
9
+ "\n",
10
+ "Upgraded day 1 project that scrapes and summarizes any webpage using an Open Source model running locally via Ollama instead of OpenAI\n",
11
+ "\n",
12
+ "## Note:-\n",
13
+ "If Ollama is slow on your machine, try using `llama3.2:1b` as an alternative: \n",
14
+ "1. Run `ollama pull llama3.2:1b` from a Terminal or Powershell\n",
15
+ "2. **Ctrl + /** to comment this code line below: `MODEL = \"llama3.2\"`\n",
16
+ "3. same **Ctrl + /** to uncomment: `MODEL = \"llama3.2:1b\"`"
17
+ ]
18
+ },
19
+ {
20
+ "cell_type": "code",
21
+ "execution_count": null,
22
+ "id": "4e2a9393-7767-488e-a8bf-27c12dca35bd",
23
+ "metadata": {},
24
+ "outputs": [],
25
+ "source": [
26
+ "# imports:-\n",
27
+ "\n",
28
+ "import requests\n",
29
+ "from bs4 import BeautifulSoup\n",
30
+ "from IPython.display import Markdown, display\n",
31
+ "import ollama"
32
+ ]
33
+ },
34
+ {
35
+ "cell_type": "code",
36
+ "execution_count": null,
37
+ "id": "29ddd15d-a3c5-4f4e-a678-873f56162724",
38
+ "metadata": {},
39
+ "outputs": [],
40
+ "source": [
41
+ "# Constants:-\n",
42
+ "\n",
43
+ "# MODEL = \"llama3.2\"\n",
44
+ "MODEL = \"llama3.2:1b\"\n",
45
+ "# MODEL = \"deepseek-r1:1.5b\""
46
+ ]
47
+ },
48
+ {
49
+ "cell_type": "code",
50
+ "execution_count": null,
51
+ "id": "6de38216-6d1c-48c4-877b-86d403f4e0f8",
52
+ "metadata": {},
53
+ "outputs": [],
54
+ "source": [
55
+ "class Website:\n",
56
+ " def __init__(self, url):\n",
57
+ " self.url = url\n",
58
+ " response = requests.get(url)\n",
59
+ " soup = BeautifulSoup(response.content, 'html.parser')\n",
60
+ " self.title = soup.title.string if soup.title else \"No title found\"\n",
61
+ " for irrelevant in soup.body([\"script\", \"style\", \"img\", \"input\"]):\n",
62
+ " irrelevant.decompose()\n",
63
+ " self.text = soup.body.get_text(separator=\"\\n\", strip=True)\n",
64
+ "\n",
65
+ "\n",
66
+ "system_prompt = \"You are an assistant that analyzes the contents of a website \\\n",
67
+ " and provides a short summary, ignoring text that might be navigation related. \\\n",
68
+ " Respond in markdown.\"\n",
69
+ "\n",
70
+ "\n",
71
+ "def user_prompt_for(website):\n",
72
+ " user_prompt = f\"You are looking at a website titled {website.title}\"\n",
73
+ " user_prompt += \"\\nThe contents of this website is as follows; \\\n",
74
+ " please provide a short summary of this website in markdown. \\\n",
75
+ " If it includes news or announcements, then summarize these too.\\n\\n\"\n",
76
+ " user_prompt += website.text\n",
77
+ " return user_prompt\n",
78
+ "\n",
79
+ "\n",
80
+ "def messages_for(website):\n",
81
+ " return [\n",
82
+ " {\"role\": \"system\", \"content\": system_prompt},\n",
83
+ " {\"role\": \"user\", \"content\": user_prompt_for(website)}\n",
84
+ " ]\n",
85
+ "\n",
86
+ "\n",
87
+ "def summary(url):\n",
88
+ " website = Website(url)\n",
89
+ " response = ollama.chat(\n",
90
+ " model = MODEL,\n",
91
+ " messages = messages_for(website)\n",
92
+ " )\n",
93
+ " return display(Markdown(response['message']['content']))\n",
94
+ "\n",
95
+ "\n",
96
+ "summary(\"https://edwarddonner.com\")\n",
97
+ "# summary(\"https://cnn.com\")\n",
98
+ "# summary(\"https://anthropic.com\")"
99
+ ]
100
+ }
101
+ ],
102
+ "metadata": {
103
+ "kernelspec": {
104
+ "display_name": "Python 3 (ipykernel)",
105
+ "language": "python",
106
+ "name": "python3"
107
+ },
108
+ "language_info": {
109
+ "codemirror_mode": {
110
+ "name": "ipython",
111
+ "version": 3
112
+ },
113
+ "file_extension": ".py",
114
+ "mimetype": "text/x-python",
115
+ "name": "python",
116
+ "nbconvert_exporter": "python",
117
+ "pygments_lexer": "ipython3",
118
+ "version": "3.10.7"
119
+ }
120
+ },
121
+ "nbformat": 4,
122
+ "nbformat_minor": 5
123
+ }
week1/community-contributions/Ollama brochure.ipynb ADDED
@@ -0,0 +1,432 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "code",
5
+ "execution_count": 52,
6
+ "id": "b56a950c-db41-4575-bef9-0fa651dea363",
7
+ "metadata": {},
8
+ "outputs": [],
9
+ "source": [
10
+ "import os\n",
11
+ "import requests\n",
12
+ "import json\n",
13
+ "import ollama\n",
14
+ "from typing import List\n",
15
+ "from bs4 import BeautifulSoup\n",
16
+ "from IPython.display import Markdown, display, update_display,clear_output\n",
17
+ "\n",
18
+ "\n"
19
+ ]
20
+ },
21
+ {
22
+ "cell_type": "code",
23
+ "execution_count": null,
24
+ "id": "0ec875db-0f6a-4eec-a3b6-eae4b71a4b89",
25
+ "metadata": {},
26
+ "outputs": [],
27
+ "source": [
28
+ "# Constants\n",
29
+ "\n",
30
+ "MODEL = \"llama3.2\""
31
+ ]
32
+ },
33
+ {
34
+ "cell_type": "code",
35
+ "execution_count": null,
36
+ "id": "227cd07c-98a4-463b-94ad-94e33d04944b",
37
+ "metadata": {},
38
+ "outputs": [],
39
+ "source": [
40
+ "# A class to represent a Webpage\n",
41
+ "\n",
42
+ "# Some websites need you to use proper headers when fetching them:\n",
43
+ "headers = {\n",
44
+ " \"User-Agent\": \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36\"\n",
45
+ "}\n",
46
+ "\n",
47
+ "class Website:\n",
48
+ " \"\"\"\n",
49
+ " A utility class to represent a Website that we have scraped, now with links\n",
50
+ " \"\"\"\n",
51
+ "\n",
52
+ " def __init__(self, url):\n",
53
+ " self.url = url\n",
54
+ " response = requests.get(url, headers=headers)\n",
55
+ " self.body = response.content\n",
56
+ " soup = BeautifulSoup(self.body, 'html.parser')\n",
57
+ " self.title = soup.title.string if soup.title else \"No title found\"\n",
58
+ " if soup.body:\n",
59
+ " for irrelevant in soup.body([\"script\", \"style\", \"img\", \"input\"]):\n",
60
+ " irrelevant.decompose()\n",
61
+ " self.text = soup.body.get_text(separator=\"\\n\", strip=True)\n",
62
+ " else:\n",
63
+ " self.text = \"\"\n",
64
+ " links = [link.get('href') for link in soup.find_all('a')]\n",
65
+ " self.links = [link for link in links if link]\n",
66
+ "\n",
67
+ " def get_contents(self):\n",
68
+ " return f\"Webpage Title:\\n{self.title}\\nWebpage Contents:\\n{self.text}\\n\\n\""
69
+ ]
70
+ },
71
+ {
72
+ "cell_type": "code",
73
+ "execution_count": null,
74
+ "id": "4d5c5e40-c010-4102-8359-899f988185fb",
75
+ "metadata": {},
76
+ "outputs": [],
77
+ "source": [
78
+ "ed = Website(\"https://edwarddonner.com\")\n",
79
+ "ed.links"
80
+ ]
81
+ },
82
+ {
83
+ "cell_type": "code",
84
+ "execution_count": null,
85
+ "id": "5f0b5d71-487c-47a5-ace6-8e02465ed452",
86
+ "metadata": {},
87
+ "outputs": [],
88
+ "source": [
89
+ "link_system_prompt = \"You are provided with a list of links found on a webpage. \\\n",
90
+ "You are able to decide which of the links would be most relevant to include in a brochure about the company, \\\n",
91
+ "such as links to an About page, or a Company page, or Careers/Jobs pages.\\n\"\n",
92
+ "link_system_prompt += \"You should respond in JSON as in this example:\"\n",
93
+ "link_system_prompt += \"\"\"\n",
94
+ "{\n",
95
+ " \"links\": [\n",
96
+ " {\"type\": \"about page\", \"url\": \"https://full.url/goes/here/about\"},\n",
97
+ " {\"type\": \"careers page\": \"url\": \"https://another.full.url/careers\"}\n",
98
+ " ]\n",
99
+ "}\n",
100
+ "\"\"\""
101
+ ]
102
+ },
103
+ {
104
+ "cell_type": "code",
105
+ "execution_count": null,
106
+ "id": "c6550325-5160-42c9-b7e7-980b504cd096",
107
+ "metadata": {},
108
+ "outputs": [],
109
+ "source": [
110
+ "print(link_system_prompt)"
111
+ ]
112
+ },
113
+ {
114
+ "cell_type": "code",
115
+ "execution_count": null,
116
+ "id": "2db4ccc6-5c35-4775-a5b2-4b86e4c73808",
117
+ "metadata": {},
118
+ "outputs": [],
119
+ "source": [
120
+ "def get_links_user_prompt(website):\n",
121
+ " user_prompt = f\"Here is the list of links on the website of {website.url} - \"\n",
122
+ " user_prompt += \"please decide which of these are relevant web links for a brochure about the company, respond with the full https URL in JSON format. \\\n",
123
+ "Do not include Terms of Service, Privacy, email links.\\n\"\n",
124
+ " user_prompt += \"Links (some might be relative links):\\n\"\n",
125
+ " user_prompt += \"\\n\".join(website.links)\n",
126
+ " return user_prompt"
127
+ ]
128
+ },
129
+ {
130
+ "cell_type": "code",
131
+ "execution_count": null,
132
+ "id": "8af511c7-5a74-4d1a-b763-b31370e70cff",
133
+ "metadata": {},
134
+ "outputs": [],
135
+ "source": [
136
+ "print(get_links_user_prompt(ed))"
137
+ ]
138
+ },
139
+ {
140
+ "cell_type": "code",
141
+ "execution_count": null,
142
+ "id": "a3b7fb61-ca15-4eab-b017-b0fe5cce46fd",
143
+ "metadata": {},
144
+ "outputs": [],
145
+ "source": [
146
+ "def get_links(url):\n",
147
+ " website = Website(url)\n",
148
+ " response = ollama.chat(\n",
149
+ " model=MODEL,\n",
150
+ " messages=[\n",
151
+ " {\"role\": \"system\", \"content\": link_system_prompt},\n",
152
+ " {\"role\": \"user\", \"content\": get_links_user_prompt(website)}\n",
153
+ " ], format = \"json\" #Define format as json!\n",
154
+ " )\n",
155
+ " result = response['message']['content']\n",
156
+ "\n",
157
+ " return json.loads(result)\n"
158
+ ]
159
+ },
160
+ {
161
+ "cell_type": "code",
162
+ "execution_count": null,
163
+ "id": "7816d393-620d-4c53-913e-4ec130b2baba",
164
+ "metadata": {},
165
+ "outputs": [],
166
+ "source": [
167
+ "# Anthropic has made their site harder to scrape, so I'm using HuggingFace..\n",
168
+ "\n",
169
+ "anthropic = Website(\"https://anthropic.com\")\n",
170
+ "anthropic.links"
171
+ ]
172
+ },
173
+ {
174
+ "cell_type": "code",
175
+ "execution_count": null,
176
+ "id": "f32ceccb-1d45-41a3-a5c1-fb2e6cd76afe",
177
+ "metadata": {},
178
+ "outputs": [],
179
+ "source": [
180
+ "get_links(\"https://anthropic.com\")"
181
+ ]
182
+ },
183
+ {
184
+ "cell_type": "code",
185
+ "execution_count": null,
186
+ "id": "a7ec4727-e897-473c-a657-e74f6999c974",
187
+ "metadata": {},
188
+ "outputs": [],
189
+ "source": [
190
+ "def get_all_details(url):\n",
191
+ " result = \"Landing page:\\n\"\n",
192
+ " result += Website(url).get_contents()\n",
193
+ " links = get_links(url)\n",
194
+ " print(\"Found links:\", links)\n",
195
+ " for link in links[\"links\"]:\n",
196
+ " result += f\"\\n\\n{link['type']}\\n\"\n",
197
+ " result += Website(link[\"url\"]).get_contents()\n",
198
+ " return result"
199
+ ]
200
+ },
201
+ {
202
+ "cell_type": "code",
203
+ "execution_count": null,
204
+ "id": "7acde0c5-1af2-4e8e-9303-e2a98ec9cdbb",
205
+ "metadata": {
206
+ "scrolled": true
207
+ },
208
+ "outputs": [],
209
+ "source": [
210
+ "print(get_all_details(\"https://anthropic.com\"))"
211
+ ]
212
+ },
213
+ {
214
+ "cell_type": "code",
215
+ "execution_count": null,
216
+ "id": "5a2e2b1d-eb55-4bfb-bf55-5e8c87db0d96",
217
+ "metadata": {},
218
+ "outputs": [],
219
+ "source": [
220
+ "system_prompt = \"You are an assistant that analyzes the contents of several relevant pages from a company website \\\n",
221
+ "and creates a short brochure about the company for prospective customers, investors and recruits. Respond in markdown.\\\n",
222
+ "Include details of company culture, customers and careers/jobs if you have the information.\"\n",
223
+ "\n",
224
+ "# Or uncomment the lines below for a more humorous brochure - this demonstrates how easy it is to incorporate 'tone':\n",
225
+ "\n",
226
+ "# system_prompt = \"You are an assistant that analyzes the contents of several relevant pages from a company website \\\n",
227
+ "# and creates a short humorous, entertaining, jokey brochure about the company for prospective customers, investors and recruits. Respond in markdown.\\\n",
228
+ "# Include details of company culture, customers and careers/jobs if you have the information.\""
229
+ ]
230
+ },
231
+ {
232
+ "cell_type": "code",
233
+ "execution_count": null,
234
+ "id": "8eac1719-7f94-4460-bc4a-0c9c93bb17a5",
235
+ "metadata": {},
236
+ "outputs": [],
237
+ "source": [
238
+ "def get_brochure_user_prompt(company_name, url):\n",
239
+ " user_prompt = f\"You are looking at a company called: {company_name}\\n\"\n",
240
+ " user_prompt += f\"Here are the contents of its landing page and other relevant pages; use this information to build a short brochure of the company in markdown.\\n\"\n",
241
+ " user_prompt += get_all_details(url)\n",
242
+ " user_prompt = user_prompt[:5_000] # Truncate if more than 5,000 characters\n",
243
+ " return user_prompt"
244
+ ]
245
+ },
246
+ {
247
+ "cell_type": "code",
248
+ "execution_count": null,
249
+ "id": "e2e312f6-01c5-4e57-9134-fb4aa447d155",
250
+ "metadata": {},
251
+ "outputs": [],
252
+ "source": [
253
+ "get_brochure_user_prompt(\"Anthropic\", \"https://anthropic.com\")"
254
+ ]
255
+ },
256
+ {
257
+ "cell_type": "code",
258
+ "execution_count": null,
259
+ "id": "8b05cbab-f0d2-4a9e-8b8c-c868a036e9cd",
260
+ "metadata": {},
261
+ "outputs": [],
262
+ "source": [
263
+ "def create_brochure(company_name, url):\n",
264
+ " response = ollama.chat(\n",
265
+ " model=MODEL,\n",
266
+ " messages=[\n",
267
+ " {\"role\": \"system\", \"content\": system_prompt},\n",
268
+ " {\"role\": \"user\", \"content\": get_brochure_user_prompt(company_name, url)}\n",
269
+ " ]\n",
270
+ " )\n",
271
+ " result = response[\"message\"][\"content\"]\n",
272
+ " display(Markdown(result))\n"
273
+ ]
274
+ },
275
+ {
276
+ "cell_type": "code",
277
+ "execution_count": null,
278
+ "id": "91ede0c0-daf2-42ef-9d31-749afb9d5352",
279
+ "metadata": {},
280
+ "outputs": [],
281
+ "source": [
282
+ "create_brochure(\"Anthropic\", \"https://anthropic.com\")"
283
+ ]
284
+ },
285
+ {
286
+ "cell_type": "markdown",
287
+ "id": "afb4aeee-5108-42a7-a1c1-5bad254b7e8b",
288
+ "metadata": {},
289
+ "source": [
290
+ "# Final omprovement\n",
291
+ "\n",
292
+ "getting a typewriter animation"
293
+ ]
294
+ },
295
+ {
296
+ "cell_type": "code",
297
+ "execution_count": 50,
298
+ "id": "177de611-1cb1-49e2-b7ea-8d01191af3ee",
299
+ "metadata": {},
300
+ "outputs": [],
301
+ "source": [
302
+ "def create_brochure(company_name, url):\n",
303
+ " messages = [\n",
304
+ " {\"role\": \"system\", \"content\": system_prompt},\n",
305
+ " {\"role\": \"user\", \"content\": get_brochure_user_prompt(company_name, url)}\n",
306
+ " ]\n",
307
+ "\n",
308
+ " display_markdown = display(Markdown(\"\"), display_id=True) # Initialize Markdown display\n",
309
+ " response_text = \"\"\n",
310
+ "\n",
311
+ " for chunk in ollama.chat(model=MODEL, messages=messages, stream=True): # Ensure stream=True (not a string)\n",
312
+ " response_text += chunk['message']['content']\n",
313
+ " clear_output(wait=True) # Clear previous output to create a streaming effect\n",
314
+ " display_markdown.update(Markdown(response_text)) # Update Markdown dynamically\n"
315
+ ]
316
+ },
317
+ {
318
+ "cell_type": "code",
319
+ "execution_count": 53,
320
+ "id": "a1971d81-fc7f-4ed1-97a0-7ef5e8ed332a",
321
+ "metadata": {},
322
+ "outputs": [
323
+ {
324
+ "name": "stdout",
325
+ "output_type": "stream",
326
+ "text": [
327
+ "Found links: {'links': [{'type': 'About page', 'url': 'https://www.anthropic.com/company'}, {'type': 'Careers page', 'url': 'https://www.anthropic.com/careers'}, {'type': 'Company page', 'url': 'https://www.anthropic.com/'}, {'type': 'Research page', 'url': 'https://www.anthropic.com/research'}, {'type': 'Twitter profile', 'url': 'https://twitter.com/AnthropicAI'}, {'type': 'LinkedIn company page', 'url': 'https://www.linkedin.com/company/anthropicresearch'}, {'type': 'YouTube channel', 'url': 'https://www.youtube.com/@anthropic-ai'}]}\n"
328
+ ]
329
+ },
330
+ {
331
+ "data": {
332
+ "text/markdown": [
333
+ "**Anthropic Brochure**\n",
334
+ "======================\n",
335
+ "\n",
336
+ "**Mission Statement**\n",
337
+ "-------------------\n",
338
+ "\n",
339
+ "Anthropic is an AI safety and research company dedicated to building reliable, interpretable, and steerable AI systems that benefit humanity in the long run.\n",
340
+ "\n",
341
+ "**Company Overview**\n",
342
+ "--------------------\n",
343
+ "\n",
344
+ "Anthropic is headquartered in San Francisco and brings together a diverse team of researchers, engineers, policy experts, and business leaders with experience spanning various disciplines. Our mission is to conduct frontier AI research, develop and apply safety techniques, and deploy the resulting systems via partnerships and products.\n",
345
+ "\n",
346
+ "**Research Focus**\n",
347
+ "-----------------\n",
348
+ "\n",
349
+ "Anthropic conducts cutting-edge AI research across various modalities, exploring novel and emerging safety research areas such as interpretability, RL from human feedback, policy, and societal impacts analysis. Our research aims to advance the field of AI safety and inform our product development.\n",
350
+ "\n",
351
+ "**Product Portfolio**\n",
352
+ "---------------------\n",
353
+ "\n",
354
+ "Our flagship product is Claude, a highly intelligent AI model that enables customers to build custom applications and experiences using our API. We also offer various enterprise solutions, including Claude for Enterprise, designed to meet the needs of large organizations.\n",
355
+ "\n",
356
+ "**Customer Base**\n",
357
+ "-----------------\n",
358
+ "\n",
359
+ "Anthropic serves a diverse range of customers, including businesses, nonprofits, civil society groups, and their clients around the globe. Our commitment to safety and reliability has earned us a reputation as a trusted partner in the AI industry.\n",
360
+ "\n",
361
+ "**Values and Culture**\n",
362
+ "----------------------\n",
363
+ "\n",
364
+ "At Anthropic, we value:\n",
365
+ "\n",
366
+ "* **Acting for the global good**: We strive to make decisions that maximize positive outcomes for humanity in the long run.\n",
367
+ "* **Holding light and shade**: We acknowledge the potential risks of AI and approach our work with caution and transparency.\n",
368
+ "\n",
369
+ "**Join Our Team**\n",
370
+ "-----------------\n",
371
+ "\n",
372
+ "We're a collaborative team of researchers, engineers, policy experts, and business leaders passionate about building safer AI systems. Join us to be part of this exciting journey and contribute your skills and expertise to shaping the future of AI.\n",
373
+ "\n",
374
+ "**Careers**\n",
375
+ "------------\n",
376
+ "\n",
377
+ "Check our website for open roles and learn more about our company culture, benefits, and career opportunities.\n",
378
+ "\n",
379
+ "[Learn More](link)\n",
380
+ "\n",
381
+ "**Get in Touch**\n",
382
+ "-----------------\n",
383
+ "\n",
384
+ "Stay up-to-date with the latest news and announcements from Anthropic. Follow us on Twitter, LinkedIn, or YouTube to join the conversation and stay informed.\n",
385
+ "\n",
386
+ "[Twitter](link)\n",
387
+ "[LinkedIn](link)\n",
388
+ "[YouTube](link)"
389
+ ],
390
+ "text/plain": [
391
+ "<IPython.core.display.Markdown object>"
392
+ ]
393
+ },
394
+ "metadata": {},
395
+ "output_type": "display_data"
396
+ }
397
+ ],
398
+ "source": [
399
+ "create_brochure(\"Anthropic\", \"https://anthropic.com\")"
400
+ ]
401
+ },
402
+ {
403
+ "cell_type": "code",
404
+ "execution_count": null,
405
+ "id": "c33277a4-84f1-447c-a66e-eb7e2af42d2a",
406
+ "metadata": {},
407
+ "outputs": [],
408
+ "source": []
409
+ }
410
+ ],
411
+ "metadata": {
412
+ "kernelspec": {
413
+ "display_name": "Python 3 (ipykernel)",
414
+ "language": "python",
415
+ "name": "python3"
416
+ },
417
+ "language_info": {
418
+ "codemirror_mode": {
419
+ "name": "ipython",
420
+ "version": 3
421
+ },
422
+ "file_extension": ".py",
423
+ "mimetype": "text/x-python",
424
+ "name": "python",
425
+ "nbconvert_exporter": "python",
426
+ "pygments_lexer": "ipython3",
427
+ "version": "3.11.11"
428
+ }
429
+ },
430
+ "nbformat": 4,
431
+ "nbformat_minor": 5
432
+ }
week1/community-contributions/OllamaDay1_MailSubjectLine.ipynb ADDED
@@ -0,0 +1,83 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "code",
5
+ "execution_count": null,
6
+ "id": "ce3db287-8661-4649-a599-cba0edd115b1",
7
+ "metadata": {},
8
+ "outputs": [],
9
+ "source": [
10
+ "\n",
11
+ "import os\n",
12
+ "import requests\n",
13
+ "from dotenv import load_dotenv\n",
14
+ "from bs4 import BeautifulSoup\n",
15
+ "from IPython.display import Markdown, display\n",
16
+ "from openai import OpenAI\n",
17
+ "\n",
18
+ "openai = OpenAI(base_url='http://localhost:11434/v1', api_key='ollama')\n",
19
+ "system_prompt = \"You are an assistant that analyzes the contents of an email\"\n",
20
+ "user_prompt = \"Provide a short subject line which aligns with the body of the email\"\n",
21
+ "email_content = \"\"\"\n",
22
+ "From: [email protected]\n",
23
+ "To: [email protected]\n",
24
+ "Subject: \n",
25
+ "\n",
26
+ "Hi Team,\n",
27
+ "\n",
28
+ "This email provides an update on Project Alpha. We've successfully completed Phase 1, which involved, and would like to thank all the \n",
29
+ "team for the great work, and looking forward to the same energy and rigor for Phase 2 too. \n",
30
+ "\n",
31
+ "Keep up the good work!! \n",
32
+ "\n",
33
+ "Thanks,\n",
34
+ "James\n",
35
+ "\"\"\"\n",
36
+ "\n",
37
+ "# Step 2: Make the messages list\n",
38
+ "\n",
39
+ "messages = [\n",
40
+ " {\"role\": \"system\", \"content\": system_prompt},\n",
41
+ " {\"role\": \"user\", \"content\": user_prompt+email_content}\n",
42
+ "]\n",
43
+ "\n",
44
+ "# Step 3: Call OpenAI\n",
45
+ "\n",
46
+ "#response =\n",
47
+ "response = openai.chat.completions.create(model=\"llama3.2\", messages=messages)\n",
48
+ "\n",
49
+ "# Step 4: print the result\n",
50
+ "print(response.choices[0].message.content)\n"
51
+ ]
52
+ },
53
+ {
54
+ "cell_type": "code",
55
+ "execution_count": null,
56
+ "id": "526b87f1-aa38-44d4-9609-292a4f4d72a9",
57
+ "metadata": {},
58
+ "outputs": [],
59
+ "source": []
60
+ }
61
+ ],
62
+ "metadata": {
63
+ "kernelspec": {
64
+ "display_name": "Python 3 (ipykernel)",
65
+ "language": "python",
66
+ "name": "python3"
67
+ },
68
+ "language_info": {
69
+ "codemirror_mode": {
70
+ "name": "ipython",
71
+ "version": 3
72
+ },
73
+ "file_extension": ".py",
74
+ "mimetype": "text/x-python",
75
+ "name": "python",
76
+ "nbconvert_exporter": "python",
77
+ "pygments_lexer": "ipython3",
78
+ "version": "3.11.12"
79
+ }
80
+ },
81
+ "nbformat": 4,
82
+ "nbformat_minor": 5
83
+ }
week1/community-contributions/Ollama_websummarizer_user_input.ipynb ADDED
@@ -0,0 +1,240 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "markdown",
5
+ "id": "9964872b-225d-4ced-93e4-fc5b279ec2ed",
6
+ "metadata": {},
7
+ "source": [
8
+ "# Webpage English summarizer with user inputs (url, ollama-based LLM) "
9
+ ]
10
+ },
11
+ {
12
+ "cell_type": "code",
13
+ "execution_count": null,
14
+ "id": "4e49d399-d18c-4c91-8abc-cf3289e11e2f",
15
+ "metadata": {},
16
+ "outputs": [],
17
+ "source": [
18
+ "# imports\n",
19
+ "\n",
20
+ "import os\n",
21
+ "import requests\n",
22
+ "# from dotenv import load_dotenv\n",
23
+ "from bs4 import BeautifulSoup\n",
24
+ "from IPython.display import Markdown, display\n",
25
+ "from openai import OpenAI\n",
26
+ "import ollama, time\n",
27
+ "from tqdm import tqdm"
28
+ ]
29
+ },
30
+ {
31
+ "cell_type": "code",
32
+ "execution_count": null,
33
+ "id": "46e7d809-248d-41b8-80e1-36b210041581",
34
+ "metadata": {},
35
+ "outputs": [],
36
+ "source": [
37
+ "# Define system prompt.\n",
38
+ "\n",
39
+ "system_prompt = \"You are an assistant that analyzes the contents of a website \\\n",
40
+ "and provides a detailed summary, ignoring text that might be navigation related. \\\n",
41
+ "Respond in markdown, in English.\""
42
+ ]
43
+ },
44
+ {
45
+ "cell_type": "code",
46
+ "execution_count": null,
47
+ "id": "e8bf237f-591f-4c32-9415-5d5d4e2522b8",
48
+ "metadata": {},
49
+ "outputs": [],
50
+ "source": [
51
+ "# A function that writes a User Prompt that asks for summaries of websites:\n",
52
+ "\n",
53
+ "def user_prompt_for(website):\n",
54
+ " user_prompt = f\"You are looking at a website titled {website.title}\"\n",
55
+ " user_prompt += \"\\nThe contents of this website is as follows; \\\n",
56
+ "please provide a detailed summary of this website in markdown. \\\n",
57
+ "If it includes news or announcements, then summarize these too.\\n\\n\"\n",
58
+ " user_prompt += website.text\n",
59
+ " return user_prompt"
60
+ ]
61
+ },
62
+ {
63
+ "cell_type": "code",
64
+ "execution_count": null,
65
+ "id": "7d39ee6d-c670-41ba-a0b8-debd55bda8e3",
66
+ "metadata": {},
67
+ "outputs": [],
68
+ "source": [
69
+ "# See how this function creates exactly the format above\n",
70
+ "\n",
71
+ "def messages_for(website):\n",
72
+ " return [\n",
73
+ " {\"role\": \"system\", \"content\": system_prompt},\n",
74
+ " {\"role\": \"user\", \"content\": user_prompt_for(website)}\n",
75
+ " ]"
76
+ ]
77
+ },
78
+ {
79
+ "cell_type": "code",
80
+ "execution_count": null,
81
+ "id": "43e28ff5-2def-4a47-acdd-2e06c0666956",
82
+ "metadata": {},
83
+ "outputs": [],
84
+ "source": [
85
+ "# Constants\n",
86
+ "\n",
87
+ "OLLAMA_API = \"http://localhost:11434/api/chat\"\n",
88
+ "HEADERS = {\"Content-Type\": \"application/json\"}"
89
+ ]
90
+ },
91
+ {
92
+ "cell_type": "code",
93
+ "execution_count": null,
94
+ "id": "32f4f481-81a3-479d-817b-4e754d9af46d",
95
+ "metadata": {},
96
+ "outputs": [],
97
+ "source": [
98
+ "# A class to represent a Webpage\n",
99
+ "# If you're not familiar with Classes, check out the \"Intermediate Python\" notebook\n",
100
+ "\n",
101
+ "# Some websites need you to use proper headers when fetching them:\n",
102
+ "headers = HEADERS\n",
103
+ "\n",
104
+ "class Website:\n",
105
+ "\n",
106
+ " def __init__(self, url):\n",
107
+ " \"\"\"\n",
108
+ " Create this Website object from the given url using the BeautifulSoup library\n",
109
+ " \"\"\"\n",
110
+ " self.url = url\n",
111
+ " response = requests.get(url, headers=headers)\n",
112
+ " soup = BeautifulSoup(response.content, 'html.parser')\n",
113
+ " self.title = soup.title.string if soup.title else \"No title found\"\n",
114
+ " for irrelevant in soup.body([\"script\", \"style\", \"img\", \"input\"]):\n",
115
+ " irrelevant.decompose()\n",
116
+ " self.text = soup.body.get_text(separator=\"\\n\", strip=True)"
117
+ ]
118
+ },
119
+ {
120
+ "cell_type": "code",
121
+ "execution_count": null,
122
+ "id": "f81cfd17-8208-4192-a59f-485ff3ea74e4",
123
+ "metadata": {},
124
+ "outputs": [],
125
+ "source": [
126
+ "# And now: call the ollama API wrapper and return the relevant component of the response\n",
127
+ "\n",
128
+ "def summarize(url):\n",
129
+ " website = Website(url)\n",
130
+ " response = ollama.chat(\n",
131
+ " model=MODEL,\n",
132
+ " messages = messages_for(website)\n",
133
+ " )\n",
134
+ " return response['message']['content']"
135
+ ]
136
+ },
137
+ {
138
+ "cell_type": "code",
139
+ "execution_count": null,
140
+ "id": "7a9eedc6-2183-473d-84ca-b10d40e2a1e6",
141
+ "metadata": {},
142
+ "outputs": [],
143
+ "source": [
144
+ "# Ask the user the name of the url address\n",
145
+ "\n",
146
+ "url= str(input(\"\"\"\n",
147
+ "Please provide a valid url address:\n",
148
+ "https://\"\"\"))"
149
+ ]
150
+ },
151
+ {
152
+ "cell_type": "code",
153
+ "execution_count": null,
154
+ "id": "5d012de2-0ef2-43db-9f51-fc7f989c3642",
155
+ "metadata": {},
156
+ "outputs": [],
157
+ "source": [
158
+ "# Ask the user to select a valid model\n",
159
+ "\n",
160
+ "MODEL= str(input(\"\"\"\n",
161
+ "Please select a LLM:\n",
162
+ "(examples: llama3.2, deepseek-r1:1.5b)\n",
163
+ "\"\"\"))"
164
+ ]
165
+ },
166
+ {
167
+ "cell_type": "code",
168
+ "execution_count": null,
169
+ "id": "1ac8c02e-4a62-448b-a231-8c6f65891811",
170
+ "metadata": {},
171
+ "outputs": [],
172
+ "source": [
173
+ "# Let's just make sure the model is loaded\n",
174
+ "\n",
175
+ "!ollama pull {MODEL}"
176
+ ]
177
+ },
178
+ {
179
+ "cell_type": "code",
180
+ "execution_count": null,
181
+ "id": "0544541f-11a8-4eb7-8eb6-bc032ed6d0d1",
182
+ "metadata": {},
183
+ "outputs": [],
184
+ "source": [
185
+ "print('url: https://{0}\\nModel= {1}'.format(url, MODEL))"
186
+ ]
187
+ },
188
+ {
189
+ "cell_type": "code",
190
+ "execution_count": null,
191
+ "id": "45518950-f2c9-43af-b897-4fe8fe48dfd8",
192
+ "metadata": {},
193
+ "outputs": [],
194
+ "source": [
195
+ "summary = summarize('https://'+ url)\n",
196
+ "for summ in tqdm(summary):\n",
197
+ " time.sleep(0.01)"
198
+ ]
199
+ },
200
+ {
201
+ "cell_type": "code",
202
+ "execution_count": null,
203
+ "id": "02c0c15e-216d-47c7-843d-ac27af02820b",
204
+ "metadata": {},
205
+ "outputs": [],
206
+ "source": [
207
+ "display(Markdown(summary))"
208
+ ]
209
+ },
210
+ {
211
+ "cell_type": "code",
212
+ "execution_count": null,
213
+ "id": "985a3689-5827-4b15-b8d5-276f9b292afd",
214
+ "metadata": {},
215
+ "outputs": [],
216
+ "source": []
217
+ }
218
+ ],
219
+ "metadata": {
220
+ "kernelspec": {
221
+ "display_name": "Python 3 (ipykernel)",
222
+ "language": "python",
223
+ "name": "python3"
224
+ },
225
+ "language_info": {
226
+ "codemirror_mode": {
227
+ "name": "ipython",
228
+ "version": 3
229
+ },
230
+ "file_extension": ".py",
231
+ "mimetype": "text/x-python",
232
+ "name": "python",
233
+ "nbconvert_exporter": "python",
234
+ "pygments_lexer": "ipython3",
235
+ "version": "3.11.11"
236
+ }
237
+ },
238
+ "nbformat": 4,
239
+ "nbformat_minor": 5
240
+ }
week1/community-contributions/Text-Summarizer.ipynb ADDED
@@ -0,0 +1,76 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "code",
5
+ "execution_count": null,
6
+ "metadata": {},
7
+ "outputs": [],
8
+ "source": [
9
+ "# 1) Import Required Libraries \n",
10
+ "\n",
11
+ "import requests\n",
12
+ "import gradio as gr\n",
13
+ "\n",
14
+ "# Deepseek only uses abstract summarization\n",
15
+ "# This tool use DeepSeek API Endpoint\n",
16
+ "\n",
17
+ "# 2) Define the DeepSeek API Endpoint\n",
18
+ "\n",
19
+ "OLLAMA_URL = \"http://localhost:11434/api/generate\"\n",
20
+ "\n",
21
+ "# 3) Define the Summarization Function which can retrieve Information\n",
22
+ "\n",
23
+ "def summarize_text(text):\n",
24
+ " payload = {\n",
25
+ " \"model\": \"deepseek-r1\", #Here you can load whatever the model you have in your ollama(ex:deepseek-r1:1.5b,7b,8b,14b) I used 7b model here \n",
26
+ " \"prompt\": f\"Summarize the following text in **5 bullet points**:\\n\\n{text}\", #The prompt is here for tell commands for the llm to act \n",
27
+ " \"stream\": False # Ensures the response is returned as a whole, not streamed\n",
28
+ " }\n",
29
+ "\n",
30
+ " response = requests.post(OLLAMA_URL, json=payload) #Send Requests to deepseekAPI\n",
31
+ "\n",
32
+ " if response.status_code == 200: #if server run correctly it return the result or it will give error\n",
33
+ " return response.json().get(\"response\", \"No summary generated.\")\n",
34
+ " else:\n",
35
+ " return f\"Error: {response.text}\"\n",
36
+ "\n",
37
+ "# 4) Create Gradio interface to design \n",
38
+ "interface = gr.Interface(\n",
39
+ " fn=summarize_text,\n",
40
+ " inputs=gr.Textbox(lines=10, placeholder=\"Enter text to summarize\"),\n",
41
+ " outputs=gr.Textbox(label=\"Summarized Text\"),\n",
42
+ " #theme='NoCrypt/miku', #Theme for the Interface I used Hatsune Miku from HF \n",
43
+ " title=\"AI-Powered Text Summarizer\",\n",
44
+ " description=\"Enter a long text and DeepSeek AI will generate a concise summary.\"\n",
45
+ ")\n",
46
+ "\n",
47
+ "# Launch the web app\n",
48
+ "if __name__ == \"__main__\":\n",
49
+ " interface.launch()\n",
50
+ "\n",
51
+ "\n"
52
+ ]
53
+ }
54
+ ],
55
+ "metadata": {
56
+ "kernelspec": {
57
+ "display_name": "base",
58
+ "language": "python",
59
+ "name": "python3"
60
+ },
61
+ "language_info": {
62
+ "codemirror_mode": {
63
+ "name": "ipython",
64
+ "version": 3
65
+ },
66
+ "file_extension": ".py",
67
+ "mimetype": "text/x-python",
68
+ "name": "python",
69
+ "nbconvert_exporter": "python",
70
+ "pygments_lexer": "ipython3",
71
+ "version": "3.12.4"
72
+ }
73
+ },
74
+ "nbformat": 4,
75
+ "nbformat_minor": 2
76
+ }
week1/community-contributions/W1D5_Code_instructor.ipynb ADDED
@@ -0,0 +1,269 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "markdown",
5
+ "id": "0e5dc476-e3c9-49bd-934a-35dbe0d55b13",
6
+ "metadata": {},
7
+ "source": [
8
+ "# End of week 1 exercise (with user input(question, model)"
9
+ ]
10
+ },
11
+ {
12
+ "cell_type": "code",
13
+ "execution_count": null,
14
+ "id": "353fba18-a9b4-4ba8-be7e-f3e3c37521ff",
15
+ "metadata": {},
16
+ "outputs": [],
17
+ "source": [
18
+ "# imports\n",
19
+ "\n",
20
+ "import os\n",
21
+ "import requests\n",
22
+ "from dotenv import load_dotenv\n",
23
+ "from bs4 import BeautifulSoup\n",
24
+ "from IPython.display import Markdown, display, update_display\n",
25
+ "from openai import OpenAI\n",
26
+ "import ollama"
27
+ ]
28
+ },
29
+ {
30
+ "cell_type": "code",
31
+ "execution_count": null,
32
+ "id": "be2b859d-b3d2-41f7-8666-28ecde26e3b8",
33
+ "metadata": {},
34
+ "outputs": [],
35
+ "source": [
36
+ "# set up environment and constants\n",
37
+ "load_dotenv(override=True)\n",
38
+ "api_key = os.getenv('OPENAI_API_KEY')\n",
39
+ "\n",
40
+ "if api_key and api_key.startswith('sk-proj-') and len(api_key)>10:\n",
41
+ " print(\"API key looks good so far\")\n",
42
+ "else:\n",
43
+ " print(\"There might be a problem with your API key? Please visit the troubleshooting notebook!\")"
44
+ ]
45
+ },
46
+ {
47
+ "cell_type": "code",
48
+ "execution_count": null,
49
+ "id": "c1b2b694-11a1-4d2a-8e34-d1fb02617fa3",
50
+ "metadata": {},
51
+ "outputs": [],
52
+ "source": [
53
+ "system_prompt = \"You are an expert coder with educational skills for beginners. \\\n",
54
+ "You are able to explain, debbug or generate code in Python, R or bash, and to provide examples of use case if applicable. \\\n",
55
+ "Please add references to relevant sources if available. If not, do not invent.\\n\"\n",
56
+ "system_prompt += \"this is an example of a response:\"\n",
57
+ "system_prompt += \"\"\"\n",
58
+ "Sure! Here’s the explanation in plain text format, suitable for Markdown:\n",
59
+ "\n",
60
+ "# Explanation of the Code\n",
61
+ "\n",
62
+ "### Code:\n",
63
+ "```python\n",
64
+ "full_name = lambda first, last: f'Full name: {first.title()} {last.title()}'\n",
65
+ "```\n",
66
+ "\n",
67
+ "### Explanation:\n",
68
+ "\n",
69
+ "1. **Lambda Function:**\n",
70
+ " - The keyword `lambda` is used to create a small, one-line anonymous function (a function without a name).\n",
71
+ " - It takes two parameters: `first` (for the first name) and `last` (for the last name).\n",
72
+ "\n",
73
+ "2. **String Formatting (`f-string`):**\n",
74
+ " - `f'Full name: {first.title()} {last.title()}'` is a formatted string (f-string).\n",
75
+ " - It inserts the values of `first` and `last` into the string while applying `.title()` to capitalize the first letter of each name.\n",
76
+ "\n",
77
+ "3. **Assigning the Function:**\n",
78
+ " - The lambda function is assigned to the variable `full_name`, so we can use `full_name()` like a regular function.\n",
79
+ "\n",
80
+ "### How to Use It:\n",
81
+ "Now, let’s call this function and see what it does.\n",
82
+ "\n",
83
+ "```python\n",
84
+ "print(full_name(\"john\", \"doe\"))\n",
85
+ "```\n",
86
+ "\n",
87
+ "#### Output:\n",
88
+ "```\n",
89
+ "Full name: John Doe\n",
90
+ "```\n",
91
+ "\n",
92
+ "### What Happens:\n",
93
+ "- `\"john\"` becomes `\"John\"` (because `.title()` capitalizes the first letter).\n",
94
+ "- `\"doe\"` becomes `\"Doe\"`.\n",
95
+ "- The output is `\"Full name: John Doe\"`.\n",
96
+ "\n",
97
+ "### Summary:\n",
98
+ "This is a simple way to create a function that formats a full name while ensuring proper capitalization. You could write the same function using `def` like this:\n",
99
+ "\n",
100
+ "```python\n",
101
+ "def full_name(first, last):\n",
102
+ " return f'Full name: {first.title()} {last.title()}'\n",
103
+ "```\n",
104
+ "\n",
105
+ "Both versions work the same way, but the `lambda` version is more compact.\n",
106
+ "\n",
107
+ "### Reference(s):\n",
108
+ "To deepen your understanding of the code snippet involving Python's lambda functions here is a resource you might find helpful:\n",
109
+ "\n",
110
+ "Ref. **Python Lambda Functions:**\n",
111
+ " - The official Python documentation provides an in-depth explanation of lambda expressions, including their syntax and use cases.\n",
112
+ " - [Lambda Expressions](https://docs.python.org/3/tutorial/controlflow.html#lambda-expressions)\n",
113
+ "\n",
114
+ "```\n",
115
+ "You can copy and paste this into any Markdown file or viewer. Let me know if you need further modifications! 😊\n",
116
+ "\"\"\""
117
+ ]
118
+ },
119
+ {
120
+ "cell_type": "code",
121
+ "execution_count": null,
122
+ "id": "f7225ab0-5ade-4c93-839c-3c80b0b23c37",
123
+ "metadata": {},
124
+ "outputs": [],
125
+ "source": [
126
+ "# display(Markdown(system_prompt))"
127
+ ]
128
+ },
129
+ {
130
+ "cell_type": "code",
131
+ "execution_count": null,
132
+ "id": "07fa2506-4b24-4a53-9f3f-500b4cbcb10a",
133
+ "metadata": {},
134
+ "outputs": [],
135
+ "source": [
136
+ "# user question\n",
137
+ "default_question= \"\"\"\n",
138
+ "Please explain what this code does and why:\n",
139
+ "yield from {book.get('author') from book in books if book.get('author')}\n",
140
+ "\"\"\"\n",
141
+ "user_question= str(input(\"What code do you want me to explain?/n(Press 'Enter' for an example)\"))\n",
142
+ "\n",
143
+ "if user_question== '':\n",
144
+ " question= default_question\n",
145
+ " print(default_question)\n",
146
+ "else:\n",
147
+ " question= \"Please explain what this code does and why:\\n\" + user_question"
148
+ ]
149
+ },
150
+ {
151
+ "cell_type": "code",
152
+ "execution_count": null,
153
+ "id": "a6749065-fb8a-4f9f-8297-3cd33abd97bd",
154
+ "metadata": {},
155
+ "outputs": [],
156
+ "source": [
157
+ "print(question)"
158
+ ]
159
+ },
160
+ {
161
+ "cell_type": "code",
162
+ "execution_count": null,
163
+ "id": "f48df06c-edb7-4a05-9e56-910854dad0c7",
164
+ "metadata": {},
165
+ "outputs": [],
166
+ "source": [
167
+ "# user model\n",
168
+ "model_number= input(\"\"\"\n",
169
+ "Please enter the number of the model you want to use from the list below:\n",
170
+ "1 GPT-4o Mini\n",
171
+ "2 Llama 3.2\n",
172
+ "3 DeepSeek R1\n",
173
+ "4 Qwen 2.5\n",
174
+ "\"\"\")\n",
175
+ "try:\n",
176
+ " if int(model_number)==1:\n",
177
+ " model= 'gpt-4o-mini'\n",
178
+ " elif int(model_number)==2:\n",
179
+ " model= 'llama3.2'\n",
180
+ " elif int(model_number)==3:\n",
181
+ " model= 'deepseek-r1:1.5b'\n",
182
+ " elif int(model_number)==4:\n",
183
+ " model= 'qwen2.5:3b'\n",
184
+ " else:\n",
185
+ " model= ''\n",
186
+ " print(\"please provide only a number from the list\")\n",
187
+ "except:\n",
188
+ " model=''\n",
189
+ " print(\"Please provide a number or press 'Enter' to finish\")"
190
+ ]
191
+ },
192
+ {
193
+ "cell_type": "code",
194
+ "execution_count": null,
195
+ "id": "aeb6e4e5-fb63-4192-bb74-0b015dfedfb7",
196
+ "metadata": {},
197
+ "outputs": [],
198
+ "source": [
199
+ "# print(model)"
200
+ ]
201
+ },
202
+ {
203
+ "cell_type": "code",
204
+ "execution_count": null,
205
+ "id": "fffa6021-d3f8-4855-a694-bed6d651791f",
206
+ "metadata": {},
207
+ "outputs": [],
208
+ "source": [
209
+ "messages=[\n",
210
+ " {\"role\": \"system\", \"content\": system_prompt},\n",
211
+ " {\"role\": \"user\", \"content\": question}\n",
212
+ " ]"
213
+ ]
214
+ },
215
+ {
216
+ "cell_type": "code",
217
+ "execution_count": null,
218
+ "id": "835374a4-3df5-4f28-82e3-6bc70514df16",
219
+ "metadata": {},
220
+ "outputs": [],
221
+ "source": [
222
+ "if int(model_number)==1:\n",
223
+ " openai= OpenAI()\n",
224
+ " stream = openai.chat.completions.create(\n",
225
+ " model=model,\n",
226
+ " messages=messages,\n",
227
+ " stream= True\n",
228
+ " )\n",
229
+ "\n",
230
+ " response = \"\"\n",
231
+ " print(\"The following answer will be generated by {0} LLM\".format(model))\n",
232
+ " display_handle = display(Markdown(\"\"), display_id=True)\n",
233
+ " for chunk in stream:\n",
234
+ " response += chunk.choices[0].delta.content or ''\n",
235
+ " response = response.replace(\"```\",\"\").replace(\"markdown\", \"\")\n",
236
+ " update_display(Markdown(response), display_id=display_handle.display_id)\n",
237
+ "elif int(model_number)==2 or 3 or 4:\n",
238
+ " !ollama pull {model}\n",
239
+ " print(\"\\n\\nThe following answer will be generated by {0} LLM\\n\\n\".format(model))\n",
240
+ " response = ollama.chat(\n",
241
+ " model=model,\n",
242
+ " messages = messages)\n",
243
+ " result= response['message']['content']\n",
244
+ " display(Markdown(result))"
245
+ ]
246
+ }
247
+ ],
248
+ "metadata": {
249
+ "kernelspec": {
250
+ "display_name": "Python 3 (ipykernel)",
251
+ "language": "python",
252
+ "name": "python3"
253
+ },
254
+ "language_info": {
255
+ "codemirror_mode": {
256
+ "name": "ipython",
257
+ "version": 3
258
+ },
259
+ "file_extension": ".py",
260
+ "mimetype": "text/x-python",
261
+ "name": "python",
262
+ "nbconvert_exporter": "python",
263
+ "pygments_lexer": "ipython3",
264
+ "version": "3.11.11"
265
+ }
266
+ },
267
+ "nbformat": 4,
268
+ "nbformat_minor": 5
269
+ }
week1/community-contributions/Week1-Challenge-Brochure-Translation.ipynb ADDED
@@ -0,0 +1,346 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "markdown",
5
+ "id": "5787d599-798e-4161-a473-970e8d948db3",
6
+ "metadata": {},
7
+ "source": [
8
+ "# Community contribution\n",
9
+ "\n",
10
+ "Generating a sports brochure - and then in Spanish! Many thanks for the contribution."
11
+ ]
12
+ },
13
+ {
14
+ "cell_type": "code",
15
+ "execution_count": null,
16
+ "id": "4ed9b1c0-50dc-48ea-b1b6-6be3264255b6",
17
+ "metadata": {},
18
+ "outputs": [],
19
+ "source": [
20
+ "# imports\n",
21
+ "\n",
22
+ "import os\n",
23
+ "import requests\n",
24
+ "import json\n",
25
+ "from typing import List\n",
26
+ "from dotenv import load_dotenv\n",
27
+ "from bs4 import BeautifulSoup\n",
28
+ "from IPython.display import Markdown, display, update_display\n",
29
+ "from openai import OpenAI"
30
+ ]
31
+ },
32
+ {
33
+ "cell_type": "code",
34
+ "execution_count": null,
35
+ "id": "23cc579a-43eb-44b5-8105-8ec3d46ec029",
36
+ "metadata": {},
37
+ "outputs": [],
38
+ "source": [
39
+ "# Initialize and constants\n",
40
+ "\n",
41
+ "load_dotenv()\n",
42
+ "os.environ['OPENAI_API_KEY'] = os.getenv('OPENAI_API_KEY', 'your-key-if-not-using-env')\n",
43
+ "MODEL = 'gpt-4o-mini'\n",
44
+ "openai = OpenAI()"
45
+ ]
46
+ },
47
+ {
48
+ "cell_type": "code",
49
+ "execution_count": null,
50
+ "id": "0206cf1d-00c5-401d-8aa0-88a83aeb8c83",
51
+ "metadata": {},
52
+ "outputs": [],
53
+ "source": [
54
+ "# A class to represent a Webpage\n",
55
+ "\n",
56
+ "class Website:\n",
57
+ " url: str\n",
58
+ " title: str\n",
59
+ " body: str\n",
60
+ " links: List[str]\n",
61
+ "\n",
62
+ " def __init__(self, url):\n",
63
+ " self.url = url\n",
64
+ " response = requests.get(url)\n",
65
+ " self.body = response.content\n",
66
+ " soup = BeautifulSoup(self.body, 'html.parser')\n",
67
+ " self.title = soup.title.string if soup.title else \"No title found\"\n",
68
+ " if soup.body:\n",
69
+ " for irrelevant in soup.body([\"script\", \"style\", \"img\", \"input\"]):\n",
70
+ " irrelevant.decompose()\n",
71
+ " self.text = soup.body.get_text(separator=\"\\n\", strip=True)\n",
72
+ " else:\n",
73
+ " self.text = \"\"\n",
74
+ " links = [link.get('href') for link in soup.find_all('a')]\n",
75
+ " self.links = [link for link in links if link]\n",
76
+ "\n",
77
+ " def get_contents(self):\n",
78
+ " return f\"Webpage Title:\\n{self.title}\\nWebpage Contents:\\n{self.text}\\n\\n\""
79
+ ]
80
+ },
81
+ {
82
+ "cell_type": "code",
83
+ "execution_count": null,
84
+ "id": "e1ab939b-0a81-4301-8820-abdc1b740a86",
85
+ "metadata": {},
86
+ "outputs": [],
87
+ "source": [
88
+ "caps = Website(\"https://www.nhl.com/capitals/\")\n",
89
+ "print(caps.get_contents())"
90
+ ]
91
+ },
92
+ {
93
+ "cell_type": "code",
94
+ "execution_count": null,
95
+ "id": "6bc9763c-e8cb-47f4-a5f0-fccbdb34f5f9",
96
+ "metadata": {},
97
+ "outputs": [],
98
+ "source": [
99
+ "print(caps.links)"
100
+ ]
101
+ },
102
+ {
103
+ "cell_type": "code",
104
+ "execution_count": null,
105
+ "id": "11a407e0-6d23-4199-bb58-344352178978",
106
+ "metadata": {},
107
+ "outputs": [],
108
+ "source": [
109
+ "link_system_prompt = \"You are provided with a list of links found on a webpage. \\\n",
110
+ "You are able to decide which of the links would be most relevant to include in a brochure about the team, \\\n",
111
+ "such as links to an About page, Team, News, Schedule, History, Stats pages.\\n\"\n",
112
+ "link_system_prompt += \"You should respond in JSON as in this example:\"\n",
113
+ "link_system_prompt += \"\"\"\n",
114
+ "{\n",
115
+ " \"links\": [\n",
116
+ " {\"type\": \"about page\", \"url\": \"https://full.url/goes/here/about\"},\n",
117
+ " {\"type\": \"team page\", \"url\": \"https://full.url/goes/here/team\"},\n",
118
+ " {\"type\": \"news page\": \"url\": \"https://another.full.url/news\"},\n",
119
+ " {\"type\": \"schedule page\": \"url\": \"https://another.full.url/schedule\"},\n",
120
+ " {\"type\": \"history page\": \"url\": \"https://another.full.url/history\"},\n",
121
+ " {\"type\": \"stats page\": \"url\": \"https://another.full.url/stats\"},\n",
122
+ " {\"type\": \"standings page\": \"url\": \"https://another.full.url/standings\"},\n",
123
+ " ]\n",
124
+ "}\n",
125
+ "\"\"\""
126
+ ]
127
+ },
128
+ {
129
+ "cell_type": "code",
130
+ "execution_count": null,
131
+ "id": "b45c01f5-e27d-47d6-b9e7-7500940da3c0",
132
+ "metadata": {},
133
+ "outputs": [],
134
+ "source": [
135
+ "def get_links_user_prompt(website):\n",
136
+ " user_prompt = f\"Here is the list of links on the website of {website.url} - \"\n",
137
+ " user_prompt += \"please decide which of these are relevant web links for a brochure about the team, respond with the full https URL in JSON format. \\\n",
138
+ "Do not include Terms of Service, Privacy, Tickets, Video, Listen, Community, Fans, Youth Hockey, Shop, League, email links.\\n\"\n",
139
+ " user_prompt += \"Links (some might be relative links):\\n\"\n",
140
+ " user_prompt += \"\\n\".join(website.links)\n",
141
+ " return user_prompt"
142
+ ]
143
+ },
144
+ {
145
+ "cell_type": "code",
146
+ "execution_count": null,
147
+ "id": "9dbfc365-b3c7-45d2-bd6d-79efb2372f43",
148
+ "metadata": {},
149
+ "outputs": [],
150
+ "source": [
151
+ "print(get_links_user_prompt(caps))"
152
+ ]
153
+ },
154
+ {
155
+ "cell_type": "code",
156
+ "execution_count": null,
157
+ "id": "410c113b-a5b2-4639-aace-2203a8631dbc",
158
+ "metadata": {},
159
+ "outputs": [],
160
+ "source": [
161
+ "def get_links(url):\n",
162
+ " website = Website(url)\n",
163
+ " completion = openai.chat.completions.create(\n",
164
+ " model=MODEL,\n",
165
+ " messages=[\n",
166
+ " {\"role\": \"system\", \"content\": link_system_prompt},\n",
167
+ " {\"role\": \"user\", \"content\": get_links_user_prompt(website)}\n",
168
+ " ],\n",
169
+ " response_format={\"type\": \"json_object\"}\n",
170
+ " )\n",
171
+ " result = completion.choices[0].message.content\n",
172
+ " return json.loads(result)"
173
+ ]
174
+ },
175
+ {
176
+ "cell_type": "code",
177
+ "execution_count": null,
178
+ "id": "b8a5d809-c85e-4a97-9a81-61114b635027",
179
+ "metadata": {},
180
+ "outputs": [],
181
+ "source": [
182
+ "get_links(\"https://www.nhl.com/capitals/\")"
183
+ ]
184
+ },
185
+ {
186
+ "cell_type": "code",
187
+ "execution_count": null,
188
+ "id": "ffb4dbdf-758c-4180-aa4f-3c18899493eb",
189
+ "metadata": {},
190
+ "outputs": [],
191
+ "source": [
192
+ "def get_all_details(url):\n",
193
+ " result = \"Landing page:\\n\"\n",
194
+ " result += Website(url).get_contents()\n",
195
+ " links = get_links(url)\n",
196
+ " print(\"Found links:\", links)\n",
197
+ " for link in links[\"links\"]:\n",
198
+ " result += f\"\\n\\n{link['type']}\\n\"\n",
199
+ " result += Website(link[\"url\"]).get_contents()\n",
200
+ " return result"
201
+ ]
202
+ },
203
+ {
204
+ "cell_type": "code",
205
+ "execution_count": null,
206
+ "id": "b7546e12-c819-4092-a783-7be23d4d7b8c",
207
+ "metadata": {},
208
+ "outputs": [],
209
+ "source": [
210
+ "print(get_all_details(\"https://www.nhl.com/capitals/\"))"
211
+ ]
212
+ },
213
+ {
214
+ "cell_type": "code",
215
+ "execution_count": null,
216
+ "id": "3d9aa466-e68d-4119-95e4-10893d774ebf",
217
+ "metadata": {},
218
+ "outputs": [],
219
+ "source": [
220
+ "system_prompt = \"You are a sports marketing analyst that analyzes the contents of several relevant pages from a sports team website \\\n",
221
+ "and creates a short brochure about the team for prospective fans and players to recruit. Respond in markdown.\\\n",
222
+ "Include details of team history, team culture, team news, and team stats if you have the information.\"\n",
223
+ "\n",
224
+ "# Or uncomment the lines below for a more humorous brochure - this demonstrates how easy it is to incorporate 'tone':\n",
225
+ "\n",
226
+ "# system_prompt = \"You are an assistant that analyzes the contents of several relevant pages from a company website \\\n",
227
+ "# and creates a short humorous, entertaining, jokey brochure about the company for prospective customers, investors and recruits. Respond in markdown.\\\n",
228
+ "# Include details of company culture, customers and careers/jobs if you have the information.\""
229
+ ]
230
+ },
231
+ {
232
+ "cell_type": "code",
233
+ "execution_count": null,
234
+ "id": "07097603-5196-47cc-9e61-b412c14b62c6",
235
+ "metadata": {},
236
+ "outputs": [],
237
+ "source": [
238
+ "def get_brochure_user_prompt(company_name, url):\n",
239
+ " user_prompt = f\"You are looking at a company called: {company_name}\\n\"\n",
240
+ " user_prompt += f\"Here are the contents of its landing page and other relevant pages; use this information to build a short brochure of the team in markdown.\\n\"\n",
241
+ " user_prompt += get_all_details(url)\n",
242
+ " user_prompt = user_prompt[:40_000] # Truncate if more than 40,000 characters\n",
243
+ " return user_prompt"
244
+ ]
245
+ },
246
+ {
247
+ "cell_type": "code",
248
+ "execution_count": null,
249
+ "id": "36d42b59-0a96-41b7-b9fc-02ae37659f7a",
250
+ "metadata": {},
251
+ "outputs": [],
252
+ "source": [
253
+ "def create_brochure(company_name, url):\n",
254
+ " response = openai.chat.completions.create(\n",
255
+ " model=MODEL,\n",
256
+ " messages=[\n",
257
+ " {\"role\": \"system\", \"content\": system_prompt},\n",
258
+ " {\"role\": \"user\", \"content\": get_brochure_user_prompt(company_name, url)}\n",
259
+ " ],\n",
260
+ " )\n",
261
+ " result = response.choices[0].message.content\n",
262
+ " display(Markdown(result))"
263
+ ]
264
+ },
265
+ {
266
+ "cell_type": "code",
267
+ "execution_count": null,
268
+ "id": "6e642228-092a-4bf5-a3c2-1ab78822453a",
269
+ "metadata": {},
270
+ "outputs": [],
271
+ "source": [
272
+ "create_brochure(\"Washington Capitals\", \"https://www.nhl.com/capitals\")"
273
+ ]
274
+ },
275
+ {
276
+ "cell_type": "code",
277
+ "execution_count": null,
278
+ "id": "1ccee810-3a11-48ec-8a69-d12efcbeb1cd",
279
+ "metadata": {},
280
+ "outputs": [],
281
+ "source": []
282
+ },
283
+ {
284
+ "cell_type": "markdown",
285
+ "id": "d392b8a2-9d1a-40bb-a8c1-5b88ad7e463d",
286
+ "metadata": {},
287
+ "source": [
288
+ "# Translate to Spanish"
289
+ ]
290
+ },
291
+ {
292
+ "cell_type": "code",
293
+ "execution_count": null,
294
+ "id": "7bc08bb5-c02e-4685-bbd1-5afa084b7f18",
295
+ "metadata": {},
296
+ "outputs": [],
297
+ "source": [
298
+ "def get_brochure_user_prompt(company_name, url):\n",
299
+ " user_prompt = f\"You are looking at a company called: {company_name}\\n\"\n",
300
+ " user_prompt += f\"Here are the contents of its landing page and other relevant pages; use this information to build a short brochure in spanish of the team in markdown.\\n\"\n",
301
+ " user_prompt += get_all_details(url)\n",
302
+ " user_prompt = user_prompt[:40_000] # Truncate if more than 40,000 characters\n",
303
+ " return user_prompt"
304
+ ]
305
+ },
306
+ {
307
+ "cell_type": "code",
308
+ "execution_count": null,
309
+ "id": "a40a2437-499a-4665-8d45-8241705477d6",
310
+ "metadata": {},
311
+ "outputs": [],
312
+ "source": [
313
+ "create_brochure(\"Washington Capitals\", \"https://www.nhl.com/capitals\")"
314
+ ]
315
+ },
316
+ {
317
+ "cell_type": "code",
318
+ "execution_count": null,
319
+ "id": "36f5d6d7-952c-4d50-894c-9b01e29cebc8",
320
+ "metadata": {},
321
+ "outputs": [],
322
+ "source": []
323
+ }
324
+ ],
325
+ "metadata": {
326
+ "kernelspec": {
327
+ "display_name": "Python 3 (ipykernel)",
328
+ "language": "python",
329
+ "name": "python3"
330
+ },
331
+ "language_info": {
332
+ "codemirror_mode": {
333
+ "name": "ipython",
334
+ "version": 3
335
+ },
336
+ "file_extension": ".py",
337
+ "mimetype": "text/x-python",
338
+ "name": "python",
339
+ "nbconvert_exporter": "python",
340
+ "pygments_lexer": "ipython3",
341
+ "version": "3.11.11"
342
+ }
343
+ },
344
+ "nbformat": 4,
345
+ "nbformat_minor": 5
346
+ }
week1/community-contributions/Week1-Challenge-LocalGPT.ipynb ADDED
@@ -0,0 +1,148 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "markdown",
5
+ "id": "87c2da09-bd0c-4683-828b-4f7643018795",
6
+ "metadata": {},
7
+ "source": [
8
+ "# Community contribution\n",
9
+ "\n",
10
+ "Implementing simple ChatGPT interface to maintain conversation and context with sleected model"
11
+ ]
12
+ },
13
+ {
14
+ "cell_type": "code",
15
+ "execution_count": 26,
16
+ "id": "77a850ed-61f8-4a0d-9c41-45781eb60bc9",
17
+ "metadata": {},
18
+ "outputs": [
19
+ {
20
+ "name": "stdout",
21
+ "output_type": "stream",
22
+ "text": [
23
+ "API key looks good so far\n"
24
+ ]
25
+ }
26
+ ],
27
+ "source": [
28
+ "import os\n",
29
+ "from dotenv import load_dotenv\n",
30
+ "import ipywidgets as widgets\n",
31
+ "from IPython.display import Markdown, display, update_display, clear_output\n",
32
+ "from openai import OpenAI\n",
33
+ "\n",
34
+ "load_dotenv()\n",
35
+ "api_key = os.getenv('OPENAI_API_KEY')\n",
36
+ "\n",
37
+ "if api_key and api_key.startswith('sk-proj-') and len(api_key)>10:\n",
38
+ " print(\"API key looks good so far\")\n",
39
+ "else:\n",
40
+ " print(\"There might be a problem with your API key? Please visit the troubleshooting notebook!\")\n",
41
+ " \n",
42
+ "MODEL = 'gpt-4o-mini'\n"
43
+ ]
44
+ },
45
+ {
46
+ "cell_type": "code",
47
+ "execution_count": null,
48
+ "id": "1f7f16f0-6fec-4190-882a-3fe1f0e9704a",
49
+ "metadata": {},
50
+ "outputs": [],
51
+ "source": [
52
+ "class ChatGPTInterface:\n",
53
+ " def __init__(self, api_key, model, system_message=\"You are a helpful assistant. You can format your responses using Markdown.\"):\n",
54
+ " self.openai = OpenAI(api_key=api_key)\n",
55
+ " self.model = model\n",
56
+ " self.conversation_history = [{\"role\": \"system\", \"content\": system_message}]\n",
57
+ "\n",
58
+ " self.chat_area = widgets.Output()\n",
59
+ " self.input_box = widgets.Text(placeholder=\"Enter your message here...\")\n",
60
+ " self.send_button = widgets.Button(description=\"Send\")\n",
61
+ " self.clear_button = widgets.Button(description=\"Clear\")\n",
62
+ "\n",
63
+ " self.send_button.on_click(self.send_message)\n",
64
+ " self.clear_button.on_click(self.clear_chat)\n",
65
+ "\n",
66
+ " self.layout = widgets.VBox([\n",
67
+ " self.chat_area,\n",
68
+ " widgets.HBox([self.input_box, self.send_button, self.clear_button])\n",
69
+ " ])\n",
70
+ "\n",
71
+ " def display(self):\n",
72
+ " display(self.layout)\n",
73
+ "\n",
74
+ " def send_message(self, _):\n",
75
+ " user_message = self.input_box.value.strip()\n",
76
+ " if user_message:\n",
77
+ " self.conversation_history.append({\"role\": \"user\", \"content\": user_message})\n",
78
+ " self.display_message(\"You\", user_message)\n",
79
+ " self.input_box.value = \"\"\n",
80
+ "\n",
81
+ " try:\n",
82
+ " response = self.openai.chat.completions.create(\n",
83
+ " model=self.model,\n",
84
+ " messages=self.conversation_history\n",
85
+ " )\n",
86
+ " assistant_message = response.choices[0].message.content.strip()\n",
87
+ " self.conversation_history.append({\"role\": \"assistant\", \"content\": assistant_message})\n",
88
+ " self.display_message(\"ChatGPT\", assistant_message)\n",
89
+ " except Exception as e:\n",
90
+ " self.display_message(\"Error\", str(e))\n",
91
+ "\n",
92
+ " def clear_chat(self, _):\n",
93
+ " self.conversation_history = [{\"role\": \"system\", \"content\": self.conversation_history[0][\"content\"]}]\n",
94
+ " self.chat_area.clear_output(wait=True)\n",
95
+ "\n",
96
+ " def display_message(self, sender, message):\n",
97
+ " self.chat_area.append_display_data(Markdown(f\"**{sender}:**\\n{message}\"))\n"
98
+ ]
99
+ },
100
+ {
101
+ "cell_type": "code",
102
+ "execution_count": 28,
103
+ "id": "78287e42-8964-4da6-bd48-a7dffd0ce7dd",
104
+ "metadata": {},
105
+ "outputs": [
106
+ {
107
+ "data": {
108
+ "application/vnd.jupyter.widget-view+json": {
109
+ "model_id": "54956535cb32419bbe38d2bee125992d",
110
+ "version_major": 2,
111
+ "version_minor": 0
112
+ },
113
+ "text/plain": [
114
+ "VBox(children=(Output(), HBox(children=(Text(value='', placeholder='Enter your message here...'), Button(descr…"
115
+ ]
116
+ },
117
+ "metadata": {},
118
+ "output_type": "display_data"
119
+ }
120
+ ],
121
+ "source": [
122
+ "chat_interface = ChatGPTInterface(api_key,MODEL)\n",
123
+ "chat_interface.display()"
124
+ ]
125
+ }
126
+ ],
127
+ "metadata": {
128
+ "kernelspec": {
129
+ "display_name": "Python 3 (ipykernel)",
130
+ "language": "python",
131
+ "name": "python3"
132
+ },
133
+ "language_info": {
134
+ "codemirror_mode": {
135
+ "name": "ipython",
136
+ "version": 3
137
+ },
138
+ "file_extension": ".py",
139
+ "mimetype": "text/x-python",
140
+ "name": "python",
141
+ "nbconvert_exporter": "python",
142
+ "pygments_lexer": "ipython3",
143
+ "version": "3.11.11"
144
+ }
145
+ },
146
+ "nbformat": 4,
147
+ "nbformat_minor": 5
148
+ }
week1/community-contributions/Week1-Day2-Ollama-Exercise.ipynb ADDED
@@ -0,0 +1,273 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "markdown",
5
+ "id": "fad31e32-2e42-42ae-ae63-c15d90292839",
6
+ "metadata": {},
7
+ "source": [
8
+ "# First Project\n",
9
+ "Ollama -> Summary\n",
10
+ "huggingface_hub -> \"facebook/m2m100_418M\" for translation"
11
+ ]
12
+ },
13
+ {
14
+ "cell_type": "code",
15
+ "execution_count": null,
16
+ "id": "5fb79a20-a455-4d27-91a1-91958af786c1",
17
+ "metadata": {},
18
+ "outputs": [],
19
+ "source": [
20
+ "!pip install transformers datasets torch\n",
21
+ "!pip install huggingface_hub"
22
+ ]
23
+ },
24
+ {
25
+ "cell_type": "code",
26
+ "execution_count": null,
27
+ "id": "e95ac7f2-5192-4f83-acf3-61df30cd3109",
28
+ "metadata": {},
29
+ "outputs": [],
30
+ "source": [
31
+ "# imports\n",
32
+ "import requests\n",
33
+ "from bs4 import BeautifulSoup\n",
34
+ "import json\n",
35
+ "import ollama"
36
+ ]
37
+ },
38
+ {
39
+ "cell_type": "code",
40
+ "execution_count": null,
41
+ "id": "12276d74-0e79-4e66-9135-1c9d1a80b943",
42
+ "metadata": {},
43
+ "outputs": [],
44
+ "source": [
45
+ "class Website:\n",
46
+ " def __init__(self, url):\n",
47
+ " self.url = url\n",
48
+ " response = requests.get(url)\n",
49
+ " soup = BeautifulSoup(response.content, 'html.parser')\n",
50
+ " self.title = soup.title.string if soup.title else \"No title found\"\n",
51
+ " for irrelevant in soup.body([\"script\", \"style\", \"img\", \"input\"]):\n",
52
+ " irrelevant.decompose()\n",
53
+ " self.text = soup.body.get_text(separator=\"\\n\", strip=True)\n",
54
+ "\n",
55
+ "huggingface_url = \"https://huggingface.co/learn/ml-for-3d-course\"\n",
56
+ "huggingface_website = Website(huggingface_url)\n",
57
+ "\n",
58
+ "huggingface_data = {\n",
59
+ " \"title\": huggingface_website.title,\n",
60
+ " \"text\": huggingface_website.text\n",
61
+ "}\n",
62
+ "print(huggingface_data)\n",
63
+ "\n",
64
+ "with open('ml_for_3d_course_data.json', 'w') as f:\n",
65
+ " json.dump(huggingface_data, f)\n"
66
+ ]
67
+ },
68
+ {
69
+ "cell_type": "code",
70
+ "execution_count": null,
71
+ "id": "7d74c85c-3e09-4514-bde4-4cafc4910c52",
72
+ "metadata": {},
73
+ "outputs": [],
74
+ "source": [
75
+ "# huggingface_data 'text' value\n",
76
+ "huggingface_text = huggingface_data['text']\n",
77
+ "\n",
78
+ "# Summary\n",
79
+ "response_summary = ollama.chat(model=\"llama3.2:latest\", messages=[{\"role\": \"user\", \"content\": f\"Summarize the following text: {huggingface_text}\"}])\n",
80
+ "print(response_summary)\n",
81
+ "\n",
82
+ "# print summary\n",
83
+ "summary_huggingface_text = response_summary.message['content']\n",
84
+ "print(\"Summary Text:\", summary_huggingface_text)\n",
85
+ "\n"
86
+ ]
87
+ },
88
+ {
89
+ "cell_type": "code",
90
+ "execution_count": null,
91
+ "id": "d13764d5-cb76-46c5-bbe6-d132b31a9ea6",
92
+ "metadata": {},
93
+ "outputs": [],
94
+ "source": [
95
+ "# HuggingFace Translation"
96
+ ]
97
+ },
98
+ {
99
+ "cell_type": "code",
100
+ "execution_count": null,
101
+ "id": "08405038-4115-487f-9efc-de58572453c1",
102
+ "metadata": {},
103
+ "outputs": [],
104
+ "source": [
105
+ "class Website:\n",
106
+ " url: str\n",
107
+ " title: str\n",
108
+ " text: str\n",
109
+ "\n",
110
+ " def __init__(self, url):\n",
111
+ " self.url = url\n",
112
+ " response = requests.get(url)\n",
113
+ " soup = BeautifulSoup(response.content, 'html.parser')\n",
114
+ " self.title = soup.title.string if soup.title else \"No title found\"\n",
115
+ " for irrelevant in soup.body([\"script\", \"style\", \"img\", \"input\"]):\n",
116
+ " irrelevant.decompose()\n",
117
+ " self.text = soup.body.get_text(separator=\"\\n\", strip=True)\n",
118
+ "\n",
119
+ "url = \"https://huggingface.co/learn/ml-for-3d-course\"\n",
120
+ "website = Website(url)\n",
121
+ "print(website.title) \n",
122
+ "print(website.text[:1000])\n",
123
+ "\n",
124
+ "data = {\n",
125
+ " \"title\": website.title,\n",
126
+ " \"text\": website.text\n",
127
+ "}\n",
128
+ "\n",
129
+ "with open('ml_for_3d_course_data.json', 'w') as f:\n",
130
+ " json.dump(data, f)\n"
131
+ ]
132
+ },
133
+ {
134
+ "cell_type": "code",
135
+ "execution_count": null,
136
+ "id": "0632352f-4b16-4125-83bf-f3cc3aabd659",
137
+ "metadata": {},
138
+ "outputs": [],
139
+ "source": [
140
+ "print(data)"
141
+ ]
142
+ },
143
+ {
144
+ "cell_type": "code",
145
+ "execution_count": null,
146
+ "id": "a85f8625-725d-4d7f-8cb7-8da4276f81cf",
147
+ "metadata": {},
148
+ "outputs": [],
149
+ "source": [
150
+ "!pip install sacremoses"
151
+ ]
152
+ },
153
+ {
154
+ "cell_type": "code",
155
+ "execution_count": null,
156
+ "id": "c800cea4-f4a4-4e41-9637-31ff11afb256",
157
+ "metadata": {},
158
+ "outputs": [],
159
+ "source": [
160
+ "import json\n",
161
+ "from transformers import M2M100ForConditionalGeneration, M2M100Tokenizer\n",
162
+ "\n",
163
+ "# Load the M2M100 model and tokenizer\n",
164
+ "model_name = \"facebook/m2m100_418M\"\n",
165
+ "model = M2M100ForConditionalGeneration.from_pretrained(model_name)\n",
166
+ "tokenizer = M2M100Tokenizer.from_pretrained(model_name)\n",
167
+ "\n",
168
+ "# Load the saved JSON file\n",
169
+ "with open('ml_for_3d_course_data.json', 'r') as f:\n",
170
+ " data = json.load(f)\n",
171
+ "\n",
172
+ "# Extract text from the loaded data\n",
173
+ "text = data[\"text\"]\n",
174
+ "\n",
175
+ "# Set the source language to English and target language to Korean\n",
176
+ "source_lang = \"en\"\n",
177
+ "target_lang = \"ko\"\n",
178
+ "\n",
179
+ "# Set the language for tokenizer (important for M2M100)\n",
180
+ "tokenizer.src_lang = source_lang\n",
181
+ "tokenizer.tgt_lang = target_lang\n",
182
+ "\n",
183
+ "# Split text into smaller chunks if it's too large\n",
184
+ "# This step ensures we don't exceed the model's maximum length (512 tokens)\n",
185
+ "max_input_length = 512\n",
186
+ "chunks = [text[i:i+max_input_length] for i in range(0, len(text), max_input_length)]\n",
187
+ "\n",
188
+ "print(chunks)\n",
189
+ "# Initialize a list to hold the translated text\n",
190
+ "translated_chunks = []\n",
191
+ "\n",
192
+ "# Iterate through each chunk and translate it\n",
193
+ "for chunk in chunks:\n",
194
+ " # Tokenize the chunk\n",
195
+ " encoded = tokenizer(chunk, return_tensors=\"pt\", padding=True, truncation=True, max_length=512)\n",
196
+ "\n",
197
+ " # Generate translation from the model, forcing the output to be in Korean\n",
198
+ " generated_tokens = model.generate(**encoded, forced_bos_token_id=tokenizer.get_lang_id(target_lang), max_length=512)\n",
199
+ "\n",
200
+ " # Decode the translated tokens to text\n",
201
+ " translated_text = tokenizer.batch_decode(generated_tokens, skip_special_tokens=True)[0]\n",
202
+ " translated_chunks.append(translated_text)\n",
203
+ "\n",
204
+ "# Combine all translated chunks back together\n",
205
+ "final_translated_text = ' '.join(translated_chunks)\n",
206
+ "print(\"Translated Text:\", final_translated_text)\n"
207
+ ]
208
+ },
209
+ {
210
+ "cell_type": "code",
211
+ "execution_count": null,
212
+ "id": "ffe0f264-a588-422f-a6e1-b60504d1e02c",
213
+ "metadata": {},
214
+ "outputs": [],
215
+ "source": [
216
+ "import json\n",
217
+ "import requests\n",
218
+ "\n",
219
+ "# Ollama API URL 설정\n",
220
+ "ollama_url = \"http://localhost:11411/v1/models/facebook/m2m100_418M/generate\"\n",
221
+ "\n",
222
+ "# 저장된 JSON 파일 로드\n",
223
+ "with open('ml_for_3d_course_data.json', 'r') as f:\n",
224
+ " data = json.load(f)\n",
225
+ "\n",
226
+ "# 텍스트 추출\n",
227
+ "course_text = data[\"text\"]\n",
228
+ "\n",
229
+ "# 번역할 소스 언어 및 타겟 언어 설정\n",
230
+ "source_language = \"en\"\n",
231
+ "target_language = \"ko\"\n",
232
+ "\n",
233
+ "# 데이터 준비\n",
234
+ "payload = {\n",
235
+ " \"input_text\": course_text,\n",
236
+ " \"src_lang\": source_language,\n",
237
+ " \"tgt_lang\": target_language\n",
238
+ "}\n",
239
+ "\n",
240
+ "# API 호출\n",
241
+ "response = requests.post(ollama_url, json=payload)\n",
242
+ "\n",
243
+ "# 응답 확인\n",
244
+ "if response.status_code == 200:\n",
245
+ " translated_course_text = response.json().get(\"translated_text\", \"Translation failed\")\n",
246
+ " print(\"Translated Course Text:\", translated_course_text)\n",
247
+ "else:\n",
248
+ " print(f\"Error {response.status_code}: {response.text}\")\n"
249
+ ]
250
+ }
251
+ ],
252
+ "metadata": {
253
+ "kernelspec": {
254
+ "display_name": "Python 3 (ipykernel)",
255
+ "language": "python",
256
+ "name": "python3"
257
+ },
258
+ "language_info": {
259
+ "codemirror_mode": {
260
+ "name": "ipython",
261
+ "version": 3
262
+ },
263
+ "file_extension": ".py",
264
+ "mimetype": "text/x-python",
265
+ "name": "python",
266
+ "nbconvert_exporter": "python",
267
+ "pygments_lexer": "ipython3",
268
+ "version": "3.11.11"
269
+ }
270
+ },
271
+ "nbformat": 4,
272
+ "nbformat_minor": 5
273
+ }
week1/community-contributions/Week1-Exercise-OllamaStream-Solution.ipynb ADDED
@@ -0,0 +1,138 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "markdown",
5
+ "id": "fe12c203-e6a6-452c-a655-afb8a03a4ff5",
6
+ "metadata": {},
7
+ "source": [
8
+ "# End of week 1 exercise Solution Ollama with streaming\n",
9
+ "\n",
10
+ "A tool that takes a technical question, and responds with an explanation."
11
+ ]
12
+ },
13
+ {
14
+ "cell_type": "code",
15
+ "execution_count": null,
16
+ "id": "c1070317-3ed9-4659-abe3-828943230e03",
17
+ "metadata": {},
18
+ "outputs": [],
19
+ "source": [
20
+ "# Imports\n",
21
+ "\n",
22
+ "import ollama\n",
23
+ "import requests\n",
24
+ "from IPython.display import Markdown, display"
25
+ ]
26
+ },
27
+ {
28
+ "cell_type": "code",
29
+ "execution_count": null,
30
+ "id": "4a456906-915a-4bfd-bb9d-57e505c5093f",
31
+ "metadata": {},
32
+ "outputs": [],
33
+ "source": [
34
+ "# Constants\n",
35
+ "\n",
36
+ "MODEL_LLAMA = 'llama3.2'\n",
37
+ "MODEL_LLAMA1b = \"llama3.2:1b\""
38
+ ]
39
+ },
40
+ {
41
+ "cell_type": "code",
42
+ "execution_count": null,
43
+ "id": "3f0d0137-52b0-47a8-81a8-11a90a010798",
44
+ "metadata": {},
45
+ "outputs": [],
46
+ "source": [
47
+ "# Environment\n",
48
+ "\n",
49
+ "system_prompt = \"\"\"\n",
50
+ "You are an assistant that takes a technical question and respond with an explanation.\n",
51
+ "\"\"\"\n",
52
+ "\n",
53
+ "question = \"\"\"\n",
54
+ "Please explain what this code does and why:\n",
55
+ "yield from {book.get(\"author\") for book in books if book.get(\"author\")}\n",
56
+ "\"\"\"\n",
57
+ "\n",
58
+ "question2 = \"\"\"\n",
59
+ "What is the purpose of using yield from in the following code, and how does it differ from a standard for loop with yield?\n",
60
+ "yield from {book.get(\"author\") for book in books if book.get(\"author\")}\n",
61
+ "\"\"\"\n",
62
+ "\n",
63
+ "user_prompt = \"Answer these two questions in detail please, Question1:\" + question + \"Question2:\" + question2\n",
64
+ "\n",
65
+ "def message():\n",
66
+ " return [\n",
67
+ " {\"role\": \"system\", \"content\": system_prompt},\n",
68
+ " {\"role\": \"user\", \"content\": user_prompt}\n",
69
+ " ]"
70
+ ]
71
+ },
72
+ {
73
+ "cell_type": "code",
74
+ "execution_count": null,
75
+ "id": "8f7c8ea8-4082-4ad0-8751-3301adcf6538",
76
+ "metadata": {},
77
+ "outputs": [],
78
+ "source": [
79
+ "# Llama 3.2 answer, with streaming\n",
80
+ "\n",
81
+ "def llama():\n",
82
+ " response = ollama.chat(\n",
83
+ " model = MODEL_LLAMA,\n",
84
+ " messages = message(),\n",
85
+ " stream =True\n",
86
+ " )\n",
87
+ " full_response = \"\"\n",
88
+ " display_handle = display(Markdown(\"\"), display_id=True)\n",
89
+ " for chunk in response:\n",
90
+ " content = chunk.get(\"message\", {}).get(\"content\", \"\")\n",
91
+ " if content:\n",
92
+ " full_response += content\n",
93
+ " display_handle.update(Markdown(full_response))\n",
94
+ "llama()"
95
+ ]
96
+ },
97
+ {
98
+ "cell_type": "code",
99
+ "execution_count": null,
100
+ "id": "342a470c-9aab-4051-ad21-514dceec76eb",
101
+ "metadata": {},
102
+ "outputs": [],
103
+ "source": [
104
+ "# Llama 3.2:1b answer\n",
105
+ "\n",
106
+ "def llama():\n",
107
+ " response = ollama.chat(\n",
108
+ " model = MODEL_LLAMA1b,\n",
109
+ " messages = message()\n",
110
+ " )\n",
111
+ " return display(Markdown(response['message']['content']))\n",
112
+ "\n",
113
+ "llama()"
114
+ ]
115
+ }
116
+ ],
117
+ "metadata": {
118
+ "kernelspec": {
119
+ "display_name": "Python 3 (ipykernel)",
120
+ "language": "python",
121
+ "name": "python3"
122
+ },
123
+ "language_info": {
124
+ "codemirror_mode": {
125
+ "name": "ipython",
126
+ "version": 3
127
+ },
128
+ "file_extension": ".py",
129
+ "mimetype": "text/x-python",
130
+ "name": "python",
131
+ "nbconvert_exporter": "python",
132
+ "pygments_lexer": "ipython3",
133
+ "version": "3.10.7"
134
+ }
135
+ },
136
+ "nbformat": 4,
137
+ "nbformat_minor": 5
138
+ }