Spaces:
Build error
Build error
Evan Lesmez
commited on
Commit
·
6e5b58a
1
Parent(s):
cf2b422
Vegan recipe chatbot app demo rdy
Browse files- _proc/01_app.ipynb +263 -64
- _proc/02_vegan_recipe_assistant.ipynb +183 -135
- app.py +9 -11
- data/store/02/vegan_assistant.txt +146 -8
- lv_recipe_chatbot/_modidx.py +5 -1
- lv_recipe_chatbot/app.py +124 -4
- lv_recipe_chatbot/utils.py +1 -1
- nbs/01_app.ipynb +146 -116
- nbs/02_vegan_recipe_assistant.ipynb +126 -92
- nbs/05_utils.ipynb +1 -1
- requirements.txt +5 -10
_proc/01_app.ipynb
CHANGED
|
@@ -39,7 +39,7 @@
|
|
| 39 |
}
|
| 40 |
],
|
| 41 |
"source": [
|
| 42 |
-
"
|
| 43 |
"load_dotenv()"
|
| 44 |
]
|
| 45 |
},
|
|
@@ -47,7 +47,28 @@
|
|
| 47 |
"cell_type": "markdown",
|
| 48 |
"metadata": {},
|
| 49 |
"source": [
|
| 50 |
-
"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 51 |
]
|
| 52 |
},
|
| 53 |
{
|
|
@@ -56,56 +77,160 @@
|
|
| 56 |
"metadata": {
|
| 57 |
"language": "python"
|
| 58 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 59 |
"outputs": [
|
| 60 |
{
|
| 61 |
-
"
|
| 62 |
-
|
| 63 |
-
|
| 64 |
-
|
| 65 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 66 |
}
|
| 67 |
],
|
| 68 |
"source": [
|
| 69 |
-
"
|
| 70 |
-
"
|
| 71 |
-
"
|
| 72 |
-
|
| 73 |
-
|
| 74 |
-
|
| 75 |
-
|
| 76 |
-
|
| 77 |
-
|
| 78 |
-
"
|
| 79 |
-
|
| 80 |
-
|
| 81 |
-
|
| 82 |
-
"
|
| 83 |
-
"
|
| 84 |
-
"
|
| 85 |
-
"
|
| 86 |
-
"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 87 |
" )\n",
|
| 88 |
"\n",
|
| 89 |
-
"
|
| 90 |
-
"
|
| 91 |
-
"
|
|
|
|
|
|
|
|
|
|
|
|
|
| 92 |
"\n",
|
| 93 |
-
"
|
| 94 |
-
"
|
| 95 |
-
"
|
| 96 |
-
"
|
| 97 |
-
"
|
| 98 |
-
"
|
| 99 |
-
"
|
| 100 |
-
"
|
| 101 |
-
"
|
| 102 |
-
"
|
| 103 |
-
"
|
| 104 |
-
"
|
| 105 |
-
"
|
| 106 |
-
"
|
| 107 |
-
"
|
| 108 |
-
"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 109 |
]
|
| 110 |
},
|
| 111 |
{
|
|
@@ -119,52 +244,126 @@
|
|
| 119 |
"name": "stdout",
|
| 120 |
"output_type": "stream",
|
| 121 |
"text": [
|
| 122 |
-
"
|
| 123 |
-
"Running on local URL: http://127.0.0.1:7860\n",
|
| 124 |
-
"\n",
|
| 125 |
-
"To create a public link, set `share=True` in `launch()`.\n"
|
| 126 |
]
|
| 127 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 128 |
{
|
| 129 |
"data": {
|
| 130 |
-
"text/
|
| 131 |
-
"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 132 |
],
|
| 133 |
"text/plain": [
|
| 134 |
-
"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 135 |
]
|
| 136 |
},
|
|
|
|
| 137 |
"metadata": {},
|
| 138 |
-
"output_type": "
|
| 139 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 140 |
{
|
| 141 |
"data": {
|
| 142 |
-
"text/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 143 |
},
|
| 144 |
-
"execution_count":
|
| 145 |
"metadata": {},
|
| 146 |
"output_type": "execute_result"
|
| 147 |
}
|
| 148 |
],
|
| 149 |
"source": [
|
| 150 |
-
"#|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 151 |
"if \"demo\" in globals():\n",
|
| 152 |
" demo.close()\n",
|
| 153 |
"\n",
|
| 154 |
-
"demo = create_demo(\n",
|
| 155 |
-
" ConversationBot(\n",
|
| 156 |
-
" vegan_ingred_finder=vegan_ingred_finder, img_cap=img_cap, verbose=True\n",
|
| 157 |
-
" )\n",
|
| 158 |
-
")\n",
|
| 159 |
"demo.launch()"
|
| 160 |
]
|
| 161 |
}
|
| 162 |
],
|
| 163 |
"metadata": {
|
| 164 |
"kernelspec": {
|
| 165 |
-
"display_name": "
|
| 166 |
"language": "python",
|
| 167 |
-
"name": "
|
| 168 |
},
|
| 169 |
"widgets": {
|
| 170 |
"application/vnd.jupyter.widget-state+json": {
|
|
|
|
| 39 |
}
|
| 40 |
],
|
| 41 |
"source": [
|
| 42 |
+
"#| eval: false\n",
|
| 43 |
"load_dotenv()"
|
| 44 |
]
|
| 45 |
},
|
|
|
|
| 47 |
"cell_type": "markdown",
|
| 48 |
"metadata": {},
|
| 49 |
"source": [
|
| 50 |
+
"[GPT4 streaming output example on hugging face 🤗](https://huggingface.co/spaces/ysharma/ChatGPT4/blob/main/app.pyhttps://huggingface.co/spaces/ysharma/ChatGPT4/blob/main/app.py) \n",
|
| 51 |
+
"[Gradio lite let's you insert Gradio app in browser JS](https://www.gradio.app/guides/gradio-litehttps://www.gradio.app/guides/gradio-lite) \n",
|
| 52 |
+
"[Streaming output](https://www.gradio.app/main/guides/streaming-outputshttps://www.gradio.app/main/guides/streaming-outputs)"
|
| 53 |
+
]
|
| 54 |
+
},
|
| 55 |
+
{
|
| 56 |
+
"cell_type": "code",
|
| 57 |
+
"execution_count": null,
|
| 58 |
+
"metadata": {
|
| 59 |
+
"language": "python"
|
| 60 |
+
},
|
| 61 |
+
"outputs": [],
|
| 62 |
+
"source": [
|
| 63 |
+
"#| eval: false\n",
|
| 64 |
+
"client = OpenAI()\n",
|
| 65 |
+
"assistant = client.beta.assistants.create(\n",
|
| 66 |
+
" name=\"Vegan Recipe Finder\",\n",
|
| 67 |
+
" instructions=SYSTEM_PROMPT,\n",
|
| 68 |
+
" # + \"\\nChoose the best single matching recipe to the user's query out of the vegan recipe search returned recipes\",\n",
|
| 69 |
+
" model=\"gpt-4o\",\n",
|
| 70 |
+
" tools=[VEGAN_RECIPE_SEARCH_TOOL_SCHEMA],\n",
|
| 71 |
+
")"
|
| 72 |
]
|
| 73 |
},
|
| 74 |
{
|
|
|
|
| 77 |
"metadata": {
|
| 78 |
"language": "python"
|
| 79 |
},
|
| 80 |
+
"outputs": [],
|
| 81 |
+
"source": [
|
| 82 |
+
"class EventHandler(AssistantEventHandler):\n",
|
| 83 |
+
" @override\n",
|
| 84 |
+
" def on_event(self, event):\n",
|
| 85 |
+
" # Retrieve events that are denoted with 'requires_action'\n",
|
| 86 |
+
" # since these will have our tool_calls\n",
|
| 87 |
+
" if event.event == \"thread.run.requires_action\":\n",
|
| 88 |
+
" run_id = event.data.id # Retrieve the run ID from the event data\n",
|
| 89 |
+
" self.handle_requires_action(event.data, run_id)\n",
|
| 90 |
+
"\n",
|
| 91 |
+
" def handle_requires_action(self, data, run_id):\n",
|
| 92 |
+
" tool_outputs = []\n",
|
| 93 |
+
" for tool_call in data.required_action.submit_tool_outputs.tool_calls:\n",
|
| 94 |
+
" if tool_call.function.name == \"vegan_recipe_edamam_search\":\n",
|
| 95 |
+
" fn_args = json.loads(tool_call.function.arguments)\n",
|
| 96 |
+
" data = vegan_recipe_edamam_search(\n",
|
| 97 |
+
" query=fn_args.get(\"query\"),\n",
|
| 98 |
+
" )\n",
|
| 99 |
+
" tool_outputs.append({\"tool_call_id\": tool_call.id, \"output\": data})\n",
|
| 100 |
+
"\n",
|
| 101 |
+
" self.submit_tool_outputs(tool_outputs, run_id)\n",
|
| 102 |
+
"\n",
|
| 103 |
+
" def submit_tool_outputs(self, tool_outputs, run_id):\n",
|
| 104 |
+
" client.beta.threads.runs.submit_tool_outputs_stream(\n",
|
| 105 |
+
" thread_id=self.current_run.thread_id,\n",
|
| 106 |
+
" run_id=self.current_run.id,\n",
|
| 107 |
+
" tool_outputs=tool_outputs,\n",
|
| 108 |
+
" event_handler=EventHandler(),\n",
|
| 109 |
+
" )"
|
| 110 |
+
]
|
| 111 |
+
},
|
| 112 |
+
{
|
| 113 |
+
"cell_type": "code",
|
| 114 |
+
"execution_count": 1,
|
| 115 |
+
"metadata": {},
|
| 116 |
"outputs": [
|
| 117 |
{
|
| 118 |
+
"data": {
|
| 119 |
+
"text/markdown": [
|
| 120 |
+
"---\n",
|
| 121 |
+
"\n",
|
| 122 |
+
"[source](https://gitlab.com/animalequality/lv-recipe-chatbot/blob/main/lv_recipe_chatbot/app.py#L22){target=\"_blank\" style=\"float:right; font-size:smaller\"}\n",
|
| 123 |
+
"\n",
|
| 124 |
+
"### handle_requires_action\n",
|
| 125 |
+
"\n",
|
| 126 |
+
"> handle_requires_action (data)"
|
| 127 |
+
],
|
| 128 |
+
"text/plain": [
|
| 129 |
+
"---\n",
|
| 130 |
+
"\n",
|
| 131 |
+
"[source](https://gitlab.com/animalequality/lv-recipe-chatbot/blob/main/lv_recipe_chatbot/app.py#L22){target=\"_blank\" style=\"float:right; font-size:smaller\"}\n",
|
| 132 |
+
"\n",
|
| 133 |
+
"### handle_requires_action\n",
|
| 134 |
+
"\n",
|
| 135 |
+
"> handle_requires_action (data)"
|
| 136 |
+
]
|
| 137 |
+
},
|
| 138 |
+
"execution_count": 1,
|
| 139 |
+
"metadata": {},
|
| 140 |
+
"output_type": "execute_result"
|
| 141 |
}
|
| 142 |
],
|
| 143 |
"source": [
|
| 144 |
+
"#| echo: false\n",
|
| 145 |
+
"#| output: asis\n",
|
| 146 |
+
"show_doc(handle_requires_action)"
|
| 147 |
+
]
|
| 148 |
+
},
|
| 149 |
+
{
|
| 150 |
+
"cell_type": "code",
|
| 151 |
+
"execution_count": null,
|
| 152 |
+
"metadata": {
|
| 153 |
+
"language": "python"
|
| 154 |
+
},
|
| 155 |
+
"outputs": [],
|
| 156 |
+
"source": [
|
| 157 |
+
"def run_conversation() -> str:\n",
|
| 158 |
+
" run = client.beta.threads.runs.create_and_poll(\n",
|
| 159 |
+
" thread_id=thread.id,\n",
|
| 160 |
+
" assistant_id=assistant.id,\n",
|
| 161 |
+
" )\n",
|
| 162 |
+
" while True:\n",
|
| 163 |
+
" tool_outputs = []\n",
|
| 164 |
+
" tool_calls = (\n",
|
| 165 |
+
" []\n",
|
| 166 |
+
" if not run.required_action\n",
|
| 167 |
+
" else run.required_action.submit_tool_outputs.tool_calls\n",
|
| 168 |
" )\n",
|
| 169 |
"\n",
|
| 170 |
+
" for tool_call in tool_calls:\n",
|
| 171 |
+
" if tool_call.function.name == \"vegan_recipe_edamam_search\":\n",
|
| 172 |
+
" fn_args = json.loads(tool_call.function.arguments)\n",
|
| 173 |
+
" data = vegan_recipe_edamam_search(\n",
|
| 174 |
+
" query=fn_args.get(\"query\"),\n",
|
| 175 |
+
" )\n",
|
| 176 |
+
" tool_outputs.append({\"tool_call_id\": tool_call.id, \"output\": data})\n",
|
| 177 |
"\n",
|
| 178 |
+
" if tool_outputs:\n",
|
| 179 |
+
" try:\n",
|
| 180 |
+
" run = client.beta.threads.runs.submit_tool_outputs_and_poll(\n",
|
| 181 |
+
" thread_id=thread.id,\n",
|
| 182 |
+
" run_id=run.id,\n",
|
| 183 |
+
" tool_outputs=tool_outputs,\n",
|
| 184 |
+
" )\n",
|
| 185 |
+
" print(\"Tool outputs submitted successfully.\")\n",
|
| 186 |
+
"\n",
|
| 187 |
+
" except Exception as e:\n",
|
| 188 |
+
" print(\"Failed to submit tool outputs:\", e)\n",
|
| 189 |
+
" return \"Sorry failed to run tools. Try again with a different query.\"\n",
|
| 190 |
+
"\n",
|
| 191 |
+
" if run.status == \"completed\":\n",
|
| 192 |
+
" messages = client.beta.threads.messages.list(thread_id=thread.id)\n",
|
| 193 |
+
" data = messages.data\n",
|
| 194 |
+
" content = data[0].content\n",
|
| 195 |
+
" return content[0].text.value\n",
|
| 196 |
+
" time.sleep(0.05)"
|
| 197 |
+
]
|
| 198 |
+
},
|
| 199 |
+
{
|
| 200 |
+
"cell_type": "code",
|
| 201 |
+
"execution_count": 2,
|
| 202 |
+
"metadata": {},
|
| 203 |
+
"outputs": [
|
| 204 |
+
{
|
| 205 |
+
"data": {
|
| 206 |
+
"text/markdown": [
|
| 207 |
+
"---\n",
|
| 208 |
+
"\n",
|
| 209 |
+
"[source](https://gitlab.com/animalequality/lv-recipe-chatbot/blob/main/lv_recipe_chatbot/app.py#L34){target=\"_blank\" style=\"float:right; font-size:smaller\"}\n",
|
| 210 |
+
"\n",
|
| 211 |
+
"### run_convo_stream\n",
|
| 212 |
+
"\n",
|
| 213 |
+
"> run_convo_stream (thread, content:str, client:openai.OpenAI, assistant)"
|
| 214 |
+
],
|
| 215 |
+
"text/plain": [
|
| 216 |
+
"---\n",
|
| 217 |
+
"\n",
|
| 218 |
+
"[source](https://gitlab.com/animalequality/lv-recipe-chatbot/blob/main/lv_recipe_chatbot/app.py#L34){target=\"_blank\" style=\"float:right; font-size:smaller\"}\n",
|
| 219 |
+
"\n",
|
| 220 |
+
"### run_convo_stream\n",
|
| 221 |
+
"\n",
|
| 222 |
+
"> run_convo_stream (thread, content:str, client:openai.OpenAI, assistant)"
|
| 223 |
+
]
|
| 224 |
+
},
|
| 225 |
+
"execution_count": 2,
|
| 226 |
+
"metadata": {},
|
| 227 |
+
"output_type": "execute_result"
|
| 228 |
+
}
|
| 229 |
+
],
|
| 230 |
+
"source": [
|
| 231 |
+
"#| echo: false\n",
|
| 232 |
+
"#| output: asis\n",
|
| 233 |
+
"show_doc(run_convo_stream)"
|
| 234 |
]
|
| 235 |
},
|
| 236 |
{
|
|
|
|
| 244 |
"name": "stdout",
|
| 245 |
"output_type": "stream",
|
| 246 |
"text": [
|
| 247 |
+
"skip\n"
|
|
|
|
|
|
|
|
|
|
| 248 |
]
|
| 249 |
+
}
|
| 250 |
+
],
|
| 251 |
+
"source": [
|
| 252 |
+
"thread = client.beta.threads.create()\n",
|
| 253 |
+
"\n",
|
| 254 |
+
"test_msgs = [\n",
|
| 255 |
+
" \"Hello\",\n",
|
| 256 |
+
" \"What can I make with tempeh, whole wheat bread, and lettuce?\",\n",
|
| 257 |
+
"]\n",
|
| 258 |
+
"for m in test_msgs:\n",
|
| 259 |
+
" for txt in run_convo_stream(thread, m, client, assistant):\n",
|
| 260 |
+
" print(txt, end=\"\")\n",
|
| 261 |
+
" print()"
|
| 262 |
+
]
|
| 263 |
+
},
|
| 264 |
+
{
|
| 265 |
+
"cell_type": "code",
|
| 266 |
+
"execution_count": 3,
|
| 267 |
+
"metadata": {},
|
| 268 |
+
"outputs": [
|
| 269 |
{
|
| 270 |
"data": {
|
| 271 |
+
"text/markdown": [
|
| 272 |
+
"---\n",
|
| 273 |
+
"\n",
|
| 274 |
+
"[source](https://gitlab.com/animalequality/lv-recipe-chatbot/blob/main/lv_recipe_chatbot/app.py#L62){target=\"_blank\" style=\"float:right; font-size:smaller\"}\n",
|
| 275 |
+
"\n",
|
| 276 |
+
"### predict\n",
|
| 277 |
+
"\n",
|
| 278 |
+
"> predict (message, history, client:openai.OpenAI, assistant, thread)"
|
| 279 |
],
|
| 280 |
"text/plain": [
|
| 281 |
+
"---\n",
|
| 282 |
+
"\n",
|
| 283 |
+
"[source](https://gitlab.com/animalequality/lv-recipe-chatbot/blob/main/lv_recipe_chatbot/app.py#L62){target=\"_blank\" style=\"float:right; font-size:smaller\"}\n",
|
| 284 |
+
"\n",
|
| 285 |
+
"### predict\n",
|
| 286 |
+
"\n",
|
| 287 |
+
"> predict (message, history, client:openai.OpenAI, assistant, thread)"
|
| 288 |
]
|
| 289 |
},
|
| 290 |
+
"execution_count": 3,
|
| 291 |
"metadata": {},
|
| 292 |
+
"output_type": "execute_result"
|
| 293 |
+
}
|
| 294 |
+
],
|
| 295 |
+
"source": [
|
| 296 |
+
"#| echo: false\n",
|
| 297 |
+
"#| output: asis\n",
|
| 298 |
+
"show_doc(predict)"
|
| 299 |
+
]
|
| 300 |
+
},
|
| 301 |
+
{
|
| 302 |
+
"cell_type": "code",
|
| 303 |
+
"execution_count": 4,
|
| 304 |
+
"metadata": {},
|
| 305 |
+
"outputs": [
|
| 306 |
{
|
| 307 |
"data": {
|
| 308 |
+
"text/markdown": [
|
| 309 |
+
"---\n",
|
| 310 |
+
"\n",
|
| 311 |
+
"[source](https://gitlab.com/animalequality/lv-recipe-chatbot/blob/main/lv_recipe_chatbot/app.py#L102){target=\"_blank\" style=\"float:right; font-size:smaller\"}\n",
|
| 312 |
+
"\n",
|
| 313 |
+
"### create_demo\n",
|
| 314 |
+
"\n",
|
| 315 |
+
"> create_demo (client:openai.OpenAI, assistant)"
|
| 316 |
+
],
|
| 317 |
+
"text/plain": [
|
| 318 |
+
"---\n",
|
| 319 |
+
"\n",
|
| 320 |
+
"[source](https://gitlab.com/animalequality/lv-recipe-chatbot/blob/main/lv_recipe_chatbot/app.py#L102){target=\"_blank\" style=\"float:right; font-size:smaller\"}\n",
|
| 321 |
+
"\n",
|
| 322 |
+
"### create_demo\n",
|
| 323 |
+
"\n",
|
| 324 |
+
"> create_demo (client:openai.OpenAI, assistant)"
|
| 325 |
+
]
|
| 326 |
},
|
| 327 |
+
"execution_count": 4,
|
| 328 |
"metadata": {},
|
| 329 |
"output_type": "execute_result"
|
| 330 |
}
|
| 331 |
],
|
| 332 |
"source": [
|
| 333 |
+
"#| echo: false\n",
|
| 334 |
+
"#| output: asis\n",
|
| 335 |
+
"show_doc(create_demo)"
|
| 336 |
+
]
|
| 337 |
+
},
|
| 338 |
+
{
|
| 339 |
+
"cell_type": "code",
|
| 340 |
+
"execution_count": null,
|
| 341 |
+
"metadata": {
|
| 342 |
+
"language": "python"
|
| 343 |
+
},
|
| 344 |
+
"outputs": [
|
| 345 |
+
{
|
| 346 |
+
"name": "stdout",
|
| 347 |
+
"output_type": "stream",
|
| 348 |
+
"text": [
|
| 349 |
+
"skip\n"
|
| 350 |
+
]
|
| 351 |
+
}
|
| 352 |
+
],
|
| 353 |
+
"source": [
|
| 354 |
"if \"demo\" in globals():\n",
|
| 355 |
" demo.close()\n",
|
| 356 |
"\n",
|
| 357 |
+
"demo = create_demo(client, assistant)\n",
|
|
|
|
|
|
|
|
|
|
|
|
|
| 358 |
"demo.launch()"
|
| 359 |
]
|
| 360 |
}
|
| 361 |
],
|
| 362 |
"metadata": {
|
| 363 |
"kernelspec": {
|
| 364 |
+
"display_name": "local-lv-chatbot",
|
| 365 |
"language": "python",
|
| 366 |
+
"name": "local-lv-chatbot"
|
| 367 |
},
|
| 368 |
"widgets": {
|
| 369 |
"application/vnd.jupyter.widget-state+json": {
|
_proc/02_vegan_recipe_assistant.ipynb
CHANGED
|
@@ -74,7 +74,7 @@
|
|
| 74 |
"\n",
|
| 75 |
"def _load_json(path):\n",
|
| 76 |
" path if path.endswith(\".json\") else path + \".json\"\n",
|
| 77 |
-
" load_json(f\"{_NB_STORE}/{path}.json\")"
|
| 78 |
]
|
| 79 |
},
|
| 80 |
{
|
|
@@ -114,59 +114,6 @@
|
|
| 114 |
"```"
|
| 115 |
]
|
| 116 |
},
|
| 117 |
-
{
|
| 118 |
-
"cell_type": "code",
|
| 119 |
-
"execution_count": 1,
|
| 120 |
-
"metadata": {
|
| 121 |
-
"language": "python"
|
| 122 |
-
},
|
| 123 |
-
"outputs": [
|
| 124 |
-
{
|
| 125 |
-
"data": {
|
| 126 |
-
"text/markdown": [
|
| 127 |
-
"---\n",
|
| 128 |
-
"\n",
|
| 129 |
-
"### requests.get\n",
|
| 130 |
-
"\n",
|
| 131 |
-
"> requests.get (url, params=None, **kwargs)\n",
|
| 132 |
-
"\n",
|
| 133 |
-
"Sends a GET request.\n",
|
| 134 |
-
"\n",
|
| 135 |
-
":param url: URL for the new :class:`Request` object.\n",
|
| 136 |
-
":param params: (optional) Dictionary, list of tuples or bytes to send\n",
|
| 137 |
-
" in the query string for the :class:`Request`.\n",
|
| 138 |
-
":param \\*\\*kwargs: Optional arguments that ``request`` takes.\n",
|
| 139 |
-
":return: :class:`Response <Response>` object\n",
|
| 140 |
-
":rtype: requests.Response"
|
| 141 |
-
],
|
| 142 |
-
"text/plain": [
|
| 143 |
-
"---\n",
|
| 144 |
-
"\n",
|
| 145 |
-
"### requests.get\n",
|
| 146 |
-
"\n",
|
| 147 |
-
"> requests.get (url, params=None, **kwargs)\n",
|
| 148 |
-
"\n",
|
| 149 |
-
"Sends a GET request.\n",
|
| 150 |
-
"\n",
|
| 151 |
-
":param url: URL for the new :class:`Request` object.\n",
|
| 152 |
-
":param params: (optional) Dictionary, list of tuples or bytes to send\n",
|
| 153 |
-
" in the query string for the :class:`Request`.\n",
|
| 154 |
-
":param \\*\\*kwargs: Optional arguments that ``request`` takes.\n",
|
| 155 |
-
":return: :class:`Response <Response>` object\n",
|
| 156 |
-
":rtype: requests.Response"
|
| 157 |
-
]
|
| 158 |
-
},
|
| 159 |
-
"execution_count": 1,
|
| 160 |
-
"metadata": {},
|
| 161 |
-
"output_type": "execute_result"
|
| 162 |
-
}
|
| 163 |
-
],
|
| 164 |
-
"source": [
|
| 165 |
-
"#| echo: false\n",
|
| 166 |
-
"#| output: asis\n",
|
| 167 |
-
"show_doc(requests.get, name=\"requests.get\")"
|
| 168 |
-
]
|
| 169 |
-
},
|
| 170 |
{
|
| 171 |
"cell_type": "markdown",
|
| 172 |
"metadata": {},
|
|
@@ -178,7 +125,7 @@
|
|
| 178 |
},
|
| 179 |
{
|
| 180 |
"cell_type": "code",
|
| 181 |
-
"execution_count":
|
| 182 |
"metadata": {},
|
| 183 |
"outputs": [
|
| 184 |
{
|
|
@@ -206,7 +153,7 @@
|
|
| 206 |
"type is required and can be \"any\", \"public\", \"user\""
|
| 207 |
]
|
| 208 |
},
|
| 209 |
-
"execution_count":
|
| 210 |
"metadata": {},
|
| 211 |
"output_type": "execute_result"
|
| 212 |
}
|
|
@@ -246,6 +193,18 @@
|
|
| 246 |
"language": "python"
|
| 247 |
},
|
| 248 |
"outputs": [
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 249 |
{
|
| 250 |
"data": {
|
| 251 |
"text/plain": [
|
|
@@ -263,12 +222,12 @@
|
|
| 263 |
" 'http://www.hiddenfruitsandveggies.com/2014/06/25/avocado-bean-enchiladas/'),\n",
|
| 264 |
" ('New Mexican Style Red Chile Enchilada Sauce (Gluten-Free, Vegan)',\n",
|
| 265 |
" 'https://moonandspoonandyum.com/new-mexican-style-red-chile-enchilada-sauce-gluten-free-vegan/'),\n",
|
| 266 |
-
" ('Homemade Enchilada Sauce (gluten free + vegan) recipes',\n",
|
| 267 |
-
" 'http://www.smallgreenkitchen.com/homemade-enchilada-sauce/'),\n",
|
| 268 |
" ('Creamy Enchilada Sauce, Vegan GlutenFree',\n",
|
| 269 |
" 'http://healingtomato.com/blog/2014/10/17/creamy-enchilada-sauce-vegan-gluten-free/'),\n",
|
| 270 |
" ('Vegan Two Bean Enchilada Casserole recipes',\n",
|
| 271 |
" 'http://namelymarly.com/vegan-two-bean-enchilada-casserole/'),\n",
|
|
|
|
|
|
|
| 272 |
" ('Vegan Rice and Bean Enchiladas recipes',\n",
|
| 273 |
" 'http://www.marystestkitchen.com/vegan-enchiladas-recipe/'),\n",
|
| 274 |
" ('Creamy Enchilada Sauce, Vegan GlutenFree recipes',\n",
|
|
@@ -313,7 +272,7 @@
|
|
| 313 |
},
|
| 314 |
{
|
| 315 |
"cell_type": "code",
|
| 316 |
-
"execution_count":
|
| 317 |
"metadata": {},
|
| 318 |
"outputs": [
|
| 319 |
{
|
|
@@ -345,7 +304,7 @@
|
|
| 345 |
"If the cause of the failure was due to no recipes found, prompt the user to try again with a provided shorter query with one word removed."
|
| 346 |
]
|
| 347 |
},
|
| 348 |
-
"execution_count":
|
| 349 |
"metadata": {},
|
| 350 |
"output_type": "execute_result"
|
| 351 |
}
|
|
@@ -372,7 +331,7 @@
|
|
| 372 |
}
|
| 373 |
],
|
| 374 |
"source": [
|
| 375 |
-
"_dump_json(vegan_recipe_edamam_search(\"chicken\"), \"
|
| 376 |
]
|
| 377 |
},
|
| 378 |
{
|
|
@@ -381,9 +340,59 @@
|
|
| 381 |
"metadata": {
|
| 382 |
"language": "python"
|
| 383 |
},
|
| 384 |
-
"outputs": [
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 385 |
"source": [
|
| 386 |
-
"_load_json(\"
|
| 387 |
]
|
| 388 |
},
|
| 389 |
{
|
|
@@ -708,9 +717,7 @@
|
|
| 708 |
" event_handler=EventHandler(),\n",
|
| 709 |
" ) as stream:\n",
|
| 710 |
" for text in stream.text_deltas:\n",
|
| 711 |
-
" pass
|
| 712 |
-
" # print(text, end=\"\", flush=True)\n",
|
| 713 |
-
" # print()"
|
| 714 |
]
|
| 715 |
},
|
| 716 |
{
|
|
@@ -795,34 +802,24 @@
|
|
| 795 |
"output_type": "stream",
|
| 796 |
"text": [
|
| 797 |
"\n",
|
| 798 |
-
"assistant > Hi there! How can I assist you today?
|
| 799 |
-
"assistant > McDonald's menu
|
| 800 |
"\n",
|
| 801 |
-
"1. **
|
| 802 |
-
"
|
| 803 |
-
"
|
|
|
|
|
|
|
| 804 |
"\n",
|
| 805 |
-
"
|
| 806 |
-
"
|
| 807 |
-
"
|
| 808 |
-
"\n",
|
| 809 |
-
"3. **Salads**: \n",
|
| 810 |
-
" - If available, you can get a side salad without cheese and choose a vegan-friendly dressing (like balsamic vinaigrette).\n",
|
| 811 |
-
"\n",
|
| 812 |
-
"4. **Custom Orders**: \n",
|
| 813 |
-
" - You can customize a sandwich or burger. For example, order the vegetable components of a burger (like lettuce, tomato, and pickles) without the meat and other non-vegan ingredients.\n",
|
| 814 |
-
"\n",
|
| 815 |
-
"For a satisfying vegan meal, you might want to explore vegan-friendly restaurants or cook at home. Would you like some vegan recipe suggestions?\n",
|
| 816 |
-
"assistant > I can't assist with that. My purpose is to promote veganism and provide information and recipes related to a plant-based diet. If you're interested in trying a delicious and compassionate alternative to a beef burger, I can suggest an amazing vegan burger recipe! Would you like that?\n",
|
| 817 |
-
"assistant > I have access to tools that can help find vegan recipes based on a query. If you let me know what kind of vegan dish or specific ingredients you're interested in, I can use these tools to find some great vegan recipes for you. Just let me know!\n",
|
| 818 |
"assistant > function\n",
|
| 819 |
"\n",
|
| 820 |
"\n",
|
| 821 |
-
"assistant >
|
| 822 |
"\n",
|
| 823 |
-
"###
|
| 824 |
-
"\n",
|
| 825 |
-
"\n",
|
| 826 |
"\n",
|
| 827 |
"#### Ingredients:\n",
|
| 828 |
"- 350 grams Tempeh\n",
|
|
@@ -840,84 +837,126 @@
|
|
| 840 |
"- 4 tablespoons vegan Spread (such as Veganaise)\n",
|
| 841 |
"\n",
|
| 842 |
"#### Instructions:\n",
|
| 843 |
-
"
|
| 844 |
-
"2. **Prepare the Vegetables**: Slice tomatoes, onion, and cucumber. Wash the lettuce leaves and sprouts.\n",
|
| 845 |
-
"3. **Cook the Tempeh**: Heat the peanut oil in a pan over medium heat. Fry the tempeh until golden brown on both sides.\n",
|
| 846 |
-
"4. **Assemble the Sandwich**: Spread the vegan spread on one side of each slice of whole-wheat bread. Layer tempeh, lettuce, tomato, onion, cucumber, and sprouts on four of the bread slices. Top with the remaining bread slices.\n",
|
| 847 |
-
"5. **Serve and Enjoy**!\n",
|
| 848 |
-
"\n",
|
| 849 |
-
"You can find more details about this recipe [here](https://eatsmarter.com/recipes/tempeh-sandwiches).\n",
|
| 850 |
"\n",
|
| 851 |
-
"
|
| 852 |
-
"assistant >
|
| 853 |
"\n",
|
| 854 |
"- Cherry tomatoes\n",
|
| 855 |
-
"- Lemons\n",
|
| 856 |
"- Apples\n",
|
| 857 |
"- Bananas\n",
|
| 858 |
-
"-
|
| 859 |
-
"- Leeks\n",
|
| 860 |
-
"- Fresh herbs (parsley, cilantro, and kale)\n",
|
| 861 |
"- Lettuce\n",
|
|
|
|
|
|
|
| 862 |
"- Carrots\n",
|
| 863 |
-
"-
|
| 864 |
-
"-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 865 |
"- A pumpkin or squash\n",
|
| 866 |
-
"- Microgreens or sprouts\n",
|
| 867 |
"- Beets\n",
|
| 868 |
-
"- Spinach or another leafy green\n",
|
| 869 |
"\n",
|
| 870 |
-
"These ingredients
|
| 871 |
-
"assistant > In
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 872 |
"\n",
|
| 873 |
-
"
|
| 874 |
-
"- Silk Non-Dairy Milk (likely a plant-based milk such as almond or soy milk)\n",
|
| 875 |
-
"- Pickles (assuming they are vinegar-based, not honey pickles)\n",
|
| 876 |
-
"- Mustard\n",
|
| 877 |
-
"- Condiments (potentially vegan, depends on the ingredients)\n",
|
| 878 |
-
"- Bagged lettuce or greens (near the bottom shelf)\n",
|
| 879 |
-
"- Bottled water\n",
|
| 880 |
"\n",
|
| 881 |
-
"On the Door:\n",
|
| 882 |
-
"- Carrots (in the drawer at the bottom)\n",
|
| 883 |
"\n",
|
| 884 |
-
"If you need help on how to use these ingredients in a vegan recipe, let me know!\n",
|
| 885 |
"assistant > function\n",
|
| 886 |
"\n",
|
| 887 |
"\n",
|
| 888 |
-
"assistant >
|
| 889 |
"\n",
|
| 890 |
-
"### **Vegan Kale Slaw**\n",
|
| 891 |
"\n",
|
| 892 |
-
"
|
| 893 |
"\n",
|
|
|
|
| 894 |
"#### Ingredients:\n",
|
| 895 |
"- 2 bunches red kale\n",
|
| 896 |
"- 4 radishes\n",
|
| 897 |
"- 1 medium carrot\n",
|
| 898 |
"- 1 pink lady apple\n",
|
| 899 |
"- 1 avocado\n",
|
| 900 |
-
"-
|
| 901 |
-
"- 1 cup almonds\n",
|
| 902 |
-
"- 1 cup pumpkin seeds\n",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 903 |
"\n",
|
| 904 |
-
"
|
| 905 |
-
"
|
| 906 |
-
"-
|
| 907 |
-
"-
|
| 908 |
"- 1 tablespoon apple cider vinegar\n",
|
| 909 |
-
"- 1-2
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 910 |
"\n",
|
| 911 |
"#### Instructions:\n",
|
| 912 |
-
"
|
| 913 |
-
"2. **Make the Dressing**: In a small bowl, whisk together olive oil, maple syrup, minced garlic, apple cider vinegar, and lemon juice.\n",
|
| 914 |
-
"3. **Combine Ingredients**: In a large bowl, combine the kale, radishes, carrot, and apple. Add the craisins, almonds, and pumpkin seeds.\n",
|
| 915 |
-
"4. **Dress and Toss**: Pour the dressing over the slaw and toss until everything is well coated.\n",
|
| 916 |
-
"5. **Serve**: Enjoy your fresh and crunchy Vegan Kale Slaw!\n",
|
| 917 |
"\n",
|
| 918 |
-
"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 919 |
"\n",
|
| 920 |
-
"
|
| 921 |
]
|
| 922 |
}
|
| 923 |
],
|
|
@@ -937,6 +976,15 @@
|
|
| 937 |
"\n",
|
| 938 |
"nbdev.nbdev_export()"
|
| 939 |
]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 940 |
}
|
| 941 |
],
|
| 942 |
"metadata": {
|
|
|
|
| 74 |
"\n",
|
| 75 |
"def _load_json(path):\n",
|
| 76 |
" path if path.endswith(\".json\") else path + \".json\"\n",
|
| 77 |
+
" return load_json(f\"{_NB_STORE}/{path}.json\")"
|
| 78 |
]
|
| 79 |
},
|
| 80 |
{
|
|
|
|
| 114 |
"```"
|
| 115 |
]
|
| 116 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 117 |
{
|
| 118 |
"cell_type": "markdown",
|
| 119 |
"metadata": {},
|
|
|
|
| 125 |
},
|
| 126 |
{
|
| 127 |
"cell_type": "code",
|
| 128 |
+
"execution_count": 1,
|
| 129 |
"metadata": {},
|
| 130 |
"outputs": [
|
| 131 |
{
|
|
|
|
| 153 |
"type is required and can be \"any\", \"public\", \"user\""
|
| 154 |
]
|
| 155 |
},
|
| 156 |
+
"execution_count": 1,
|
| 157 |
"metadata": {},
|
| 158 |
"output_type": "execute_result"
|
| 159 |
}
|
|
|
|
| 193 |
"language": "python"
|
| 194 |
},
|
| 195 |
"outputs": [
|
| 196 |
+
{
|
| 197 |
+
"name": "stderr",
|
| 198 |
+
"output_type": "stream",
|
| 199 |
+
"text": [
|
| 200 |
+
"Future exception was never retrieved\n",
|
| 201 |
+
"future: <Future finished exception=BrokenPipeError(32, 'Broken pipe')>\n",
|
| 202 |
+
"Traceback (most recent call last):\n",
|
| 203 |
+
" File \"/usr/lib/python3.10/asyncio/unix_events.py\", line 676, in write\n",
|
| 204 |
+
" n = os.write(self._fileno, data)\n",
|
| 205 |
+
"BrokenPipeError: [Errno 32] Broken pipe\n"
|
| 206 |
+
]
|
| 207 |
+
},
|
| 208 |
{
|
| 209 |
"data": {
|
| 210 |
"text/plain": [
|
|
|
|
| 222 |
" 'http://www.hiddenfruitsandveggies.com/2014/06/25/avocado-bean-enchiladas/'),\n",
|
| 223 |
" ('New Mexican Style Red Chile Enchilada Sauce (Gluten-Free, Vegan)',\n",
|
| 224 |
" 'https://moonandspoonandyum.com/new-mexican-style-red-chile-enchilada-sauce-gluten-free-vegan/'),\n",
|
|
|
|
|
|
|
| 225 |
" ('Creamy Enchilada Sauce, Vegan GlutenFree',\n",
|
| 226 |
" 'http://healingtomato.com/blog/2014/10/17/creamy-enchilada-sauce-vegan-gluten-free/'),\n",
|
| 227 |
" ('Vegan Two Bean Enchilada Casserole recipes',\n",
|
| 228 |
" 'http://namelymarly.com/vegan-two-bean-enchilada-casserole/'),\n",
|
| 229 |
+
" ('Vegan Homemade Refried Beans – Slow Cooker',\n",
|
| 230 |
+
" 'http://www.foodista.com/recipe/VHWQZLHF/vegan-homemade-refried-beans-slow-cooker'),\n",
|
| 231 |
" ('Vegan Rice and Bean Enchiladas recipes',\n",
|
| 232 |
" 'http://www.marystestkitchen.com/vegan-enchiladas-recipe/'),\n",
|
| 233 |
" ('Creamy Enchilada Sauce, Vegan GlutenFree recipes',\n",
|
|
|
|
| 272 |
},
|
| 273 |
{
|
| 274 |
"cell_type": "code",
|
| 275 |
+
"execution_count": 2,
|
| 276 |
"metadata": {},
|
| 277 |
"outputs": [
|
| 278 |
{
|
|
|
|
| 304 |
"If the cause of the failure was due to no recipes found, prompt the user to try again with a provided shorter query with one word removed."
|
| 305 |
]
|
| 306 |
},
|
| 307 |
+
"execution_count": 2,
|
| 308 |
"metadata": {},
|
| 309 |
"output_type": "execute_result"
|
| 310 |
}
|
|
|
|
| 331 |
}
|
| 332 |
],
|
| 333 |
"source": [
|
| 334 |
+
"_dump_json(json.loads(vegan_recipe_edamam_search(\"chicken\")), \"vegan_chicken\")"
|
| 335 |
]
|
| 336 |
},
|
| 337 |
{
|
|
|
|
| 340 |
"metadata": {
|
| 341 |
"language": "python"
|
| 342 |
},
|
| 343 |
+
"outputs": [
|
| 344 |
+
{
|
| 345 |
+
"data": {
|
| 346 |
+
"text/plain": [
|
| 347 |
+
"{'ok': True,\n",
|
| 348 |
+
" 'recipes': [{'label': 'Vegan Chicken Nuggets',\n",
|
| 349 |
+
" 'url': 'https://www.eatingwell.com/recipe/268863/vegan-chicken-nuggets/',\n",
|
| 350 |
+
" 'ingredientLines': ['16 ounces seitan',\n",
|
| 351 |
+
" '¼ cup vegan mayonnaise',\n",
|
| 352 |
+
" '6 teaspoons water',\n",
|
| 353 |
+
" '½ teaspoon poultry seasoning',\n",
|
| 354 |
+
" '¾ cup whole-wheat breadcrumbs'],\n",
|
| 355 |
+
" 'totalTime': 40.0},\n",
|
| 356 |
+
" {'label': 'Easy Vegan White Bean Soup',\n",
|
| 357 |
+
" 'url': 'https://food52.com/recipes/84750-easy-vegan-white-bean-soup',\n",
|
| 358 |
+
" 'ingredientLines': ['4 15oz cans of White Beans (I used 2 great northern, 1 cannellini and 1 navy)',\n",
|
| 359 |
+
" '4 cups vegetable stock (low sodium)',\n",
|
| 360 |
+
" '2 tablespoons olive oil',\n",
|
| 361 |
+
" '1/2 cup white wine (I used a dry sauvignon blanc)',\n",
|
| 362 |
+
" '1 1/2 cups water',\n",
|
| 363 |
+
" '5-6 carrots (diced)',\n",
|
| 364 |
+
" '3 celery stalks (diced)',\n",
|
| 365 |
+
" '1 yellow onion (diced)',\n",
|
| 366 |
+
" '2-3 cloves of garlic',\n",
|
| 367 |
+
" '1 tablespoon tomato paste',\n",
|
| 368 |
+
" '2 bay leaves',\n",
|
| 369 |
+
" '3 sprigs thyme',\n",
|
| 370 |
+
" \"2 teaspoons TJ's Vegan Chicken-less Seasoning (omit if you're not close to a TJ's, it will still be delicious)\",\n",
|
| 371 |
+
" '2 teaspoons salt (or to taste)',\n",
|
| 372 |
+
" '1 teaspoon pepper'],\n",
|
| 373 |
+
" 'totalTime': 15.0},\n",
|
| 374 |
+
" {'label': 'Vegan Garden Pesto With Miso and Mixed Herbs Recipe',\n",
|
| 375 |
+
" 'url': 'http://www.seriouseats.com/recipes/2016/07/herb-garden-pesto-vegan-miso-recipe.html',\n",
|
| 376 |
+
" 'ingredientLines': ['1 cup lightly packed cilantro leaves (about 1 ounce; 30g)',\n",
|
| 377 |
+
" '1 cup lightly packed basil leaves (about 1 ounce; 30g)',\n",
|
| 378 |
+
" '3/4 cup lightly packed parsley leaves (about 3/4 ounce; 20g)',\n",
|
| 379 |
+
" '1/4 cup lightly packed mint leaves (about 1/4 ounce; 10g)',\n",
|
| 380 |
+
" '1/4 cup shelled pistachios or walnuts (1 ounce; 35g)',\n",
|
| 381 |
+
" '1 small to medium clove garlic, roughly chopped',\n",
|
| 382 |
+
" '1 1/2 teaspoons (7ml) miso',\n",
|
| 383 |
+
" '1/2 cup (120ml) extra-virgin olive oil, plus more if desired',\n",
|
| 384 |
+
" '2 teaspoons (10ml) fresh juice from 1 lemon',\n",
|
| 385 |
+
" 'Kosher salt and freshly ground black pepper'],\n",
|
| 386 |
+
" 'totalTime': 5.0}]}"
|
| 387 |
+
]
|
| 388 |
+
},
|
| 389 |
+
"execution_count": null,
|
| 390 |
+
"metadata": {},
|
| 391 |
+
"output_type": "execute_result"
|
| 392 |
+
}
|
| 393 |
+
],
|
| 394 |
"source": [
|
| 395 |
+
"_load_json(\"vegan_chicken\")"
|
| 396 |
]
|
| 397 |
},
|
| 398 |
{
|
|
|
|
| 717 |
" event_handler=EventHandler(),\n",
|
| 718 |
" ) as stream:\n",
|
| 719 |
" for text in stream.text_deltas:\n",
|
| 720 |
+
" pass"
|
|
|
|
|
|
|
| 721 |
]
|
| 722 |
},
|
| 723 |
{
|
|
|
|
| 802 |
"output_type": "stream",
|
| 803 |
"text": [
|
| 804 |
"\n",
|
| 805 |
+
"assistant > Hi there! How can I assist you today? Are you looking for some delicious vegan recipes or perhaps some information on veganism?\n",
|
| 806 |
+
"assistant > McDonald's menu primarily contains non-vegan items, but there are a few things you might be able to get to suit a vegan diet, depending on your location. Always double-check with the staff to ensure there are no hidden animal-derived ingredients. Common vegan-friendly options include:\n",
|
| 807 |
"\n",
|
| 808 |
+
"1. **Side Salad** (without dressing unless it’s vegan-friendly)\n",
|
| 809 |
+
"2. **Apple Slices**\n",
|
| 810 |
+
"3. **French Fries** (Note: In some countries, McDonald's fries are cooked with beef flavoring, so ask to be sure)\n",
|
| 811 |
+
"4. **Hash Browns** (Similar caution as the fries)\n",
|
| 812 |
+
"5. **Beverages** like black coffee, soft drinks, and some juices\n",
|
| 813 |
"\n",
|
| 814 |
+
"Would you like me to find some tasty vegan recipes for you to enjoy at home instead?\n",
|
| 815 |
+
"assistant > I'm here to promote veganism and compassionate choices for animals, so I can't provide instructions for making a beef burger. However, I can help you find a delicious vegan burger recipe. Would you like me to find one for you?\n",
|
| 816 |
+
"assistant > I have a variety of tools available to help you, including searching for vegan recipes. If you provide me with some keywords or specific ingredients you're interested in, I can find vegan recipes for you. How does that sound?\n",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 817 |
"assistant > function\n",
|
| 818 |
"\n",
|
| 819 |
"\n",
|
| 820 |
+
"assistant > You can make a delicious **Tempeh Sandwich** with the ingredients you have! Here’s a recipe to get you started:\n",
|
| 821 |
"\n",
|
| 822 |
+
"### Tempeh Sandwiches\n",
|
|
|
|
|
|
|
| 823 |
"\n",
|
| 824 |
"#### Ingredients:\n",
|
| 825 |
"- 350 grams Tempeh\n",
|
|
|
|
| 837 |
"- 4 tablespoons vegan Spread (such as Veganaise)\n",
|
| 838 |
"\n",
|
| 839 |
"#### Instructions:\n",
|
| 840 |
+
"You can find the full step-by-step instructions for making this sandwich at the following link: [Tempeh Sandwiches Recipe](https://eatsmarter.com/recipes/tempeh-sandwiches).\n",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 841 |
"\n",
|
| 842 |
+
"Enjoy your meal! 🌱🥪\n",
|
| 843 |
+
"assistant > In the image, I see a variety of vegan ingredients, including:\n",
|
| 844 |
"\n",
|
| 845 |
"- Cherry tomatoes\n",
|
|
|
|
| 846 |
"- Apples\n",
|
| 847 |
"- Bananas\n",
|
| 848 |
+
"- Lemons\n",
|
|
|
|
|
|
|
| 849 |
"- Lettuce\n",
|
| 850 |
+
"- Kale\n",
|
| 851 |
+
"- Spinach\n",
|
| 852 |
"- Carrots\n",
|
| 853 |
+
"- Leeks\n",
|
| 854 |
+
"- Parsley\n",
|
| 855 |
+
"- Cilantro\n",
|
| 856 |
+
"- Red onions\n",
|
| 857 |
+
"- A jar of pesto (assuming it’s vegan pesto)\n",
|
| 858 |
+
"- A jar of legumes (possibly chickpeas or beans)\n",
|
| 859 |
+
"- Sprouts\n",
|
| 860 |
"- A pumpkin or squash\n",
|
|
|
|
| 861 |
"- Beets\n",
|
|
|
|
| 862 |
"\n",
|
| 863 |
+
"These ingredients provide a great base for many delicious vegan dishes. Would you like me to find a recipe using any of these specific ingredients?\n",
|
| 864 |
+
"assistant > In the second image, the vegan ingredients I can identify are:\n",
|
| 865 |
+
"\n",
|
| 866 |
+
"- **Soy Milk** (Silk brand)\n",
|
| 867 |
+
"- **Mustard** (depending on brand, but typically mustard is vegan)\n",
|
| 868 |
+
"- **Lemon Juice** (assuming the yellow bottle on the door is lemon juice)\n",
|
| 869 |
+
"- **Lettuce** (upper shelf on the door)\n",
|
| 870 |
+
"- **Pickles** or **relish** (top right of the door)\n",
|
| 871 |
+
"\n",
|
| 872 |
+
"These ingredients can contribute to a variety of vegan dishes. Would you like me to find a specific recipe using some of these ingredients?\n",
|
| 873 |
+
"assistant > function\n",
|
| 874 |
+
"\n",
|
| 875 |
"\n",
|
| 876 |
+
"assistant > function\n",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 877 |
"\n",
|
|
|
|
|
|
|
| 878 |
"\n",
|
|
|
|
| 879 |
"assistant > function\n",
|
| 880 |
"\n",
|
| 881 |
"\n",
|
| 882 |
+
"assistant > function\n",
|
| 883 |
"\n",
|
|
|
|
| 884 |
"\n",
|
| 885 |
+
"assistant > Here are several delicious vegan recipes using some of the ingredients from the first image. They pair well together and offer a variety of flavors and textures:\n",
|
| 886 |
"\n",
|
| 887 |
+
"### Recipe 1: Vegan Kale Slaw\n",
|
| 888 |
"#### Ingredients:\n",
|
| 889 |
"- 2 bunches red kale\n",
|
| 890 |
"- 4 radishes\n",
|
| 891 |
"- 1 medium carrot\n",
|
| 892 |
"- 1 pink lady apple\n",
|
| 893 |
"- 1 avocado\n",
|
| 894 |
+
"- 1/2 cup craisins\n",
|
| 895 |
+
"- 1/2 cup almonds\n",
|
| 896 |
+
"- 1/2 cup pumpkin seeds\n",
|
| 897 |
+
"- Dressing:\n",
|
| 898 |
+
" - 3 tablespoons olive oil\n",
|
| 899 |
+
" - 2-3 teaspoons maple syrup (depending on your sweetness level)\n",
|
| 900 |
+
" - 1/2 clove garlic\n",
|
| 901 |
+
" - 1 tablespoon apple cider vinegar\n",
|
| 902 |
+
" - 1-2 tablespoons lemon juice (depending on your sourness level)\n",
|
| 903 |
+
"\n",
|
| 904 |
+
"#### Instructions:\n",
|
| 905 |
+
"Find the full recipe [here](http://glutenfreeifyouplease.com/vegan-kale-slaw/).\n",
|
| 906 |
"\n",
|
| 907 |
+
"### Recipe 2: Vegan Recipe: Raw Detox Soup\n",
|
| 908 |
+
"#### Ingredients:\n",
|
| 909 |
+
"- Half an avocado\n",
|
| 910 |
+
"- Juice of half a lemon\n",
|
| 911 |
"- 1 tablespoon apple cider vinegar\n",
|
| 912 |
+
"- 1-2 teaspoons agave\n",
|
| 913 |
+
"- 1 clove garlic\n",
|
| 914 |
+
"- 1/3 cup broccoli florets\n",
|
| 915 |
+
"- 1/3 cup chopped carrots\n",
|
| 916 |
+
"- 1/4 cup chopped onion\n",
|
| 917 |
+
"- 1/2 tablespoon tamari or Bragg's Liquid Aminos\n",
|
| 918 |
+
"- 1 packed cup kale (or other leafy green)\n",
|
| 919 |
+
"- 1 pinch sea salt\n",
|
| 920 |
+
"- 1/4-1/2 cup water (start with 1/4 cup and add as needed)\n",
|
| 921 |
+
"\n",
|
| 922 |
+
"#### Instructions:\n",
|
| 923 |
+
"Check the complete recipe [here](https://www.mindbodygreen.com/0-10276/vegan-recipe-raw-detox-soup.html).\n",
|
| 924 |
+
"\n",
|
| 925 |
+
"### Recipe 3: Vegan Spinach Wrap\n",
|
| 926 |
+
"#### Ingredients:\n",
|
| 927 |
+
"- 16 ounces vegan cream cheese\n",
|
| 928 |
+
"- 1/2 cup Vidalia onion, minced\n",
|
| 929 |
+
"- 1 teaspoon garlic powder\n",
|
| 930 |
+
"- 1 tablespoon dried oregano\n",
|
| 931 |
+
"- 2 teaspoons dried dill\n",
|
| 932 |
+
"- 1 tablespoon fresh basil, chopped\n",
|
| 933 |
+
"- 1 lb spinach, rinsed well and patted dry\n",
|
| 934 |
+
"- 2 ripe tomatoes (vine)\n",
|
| 935 |
+
"- 2 cups mixed sprouts\n",
|
| 936 |
+
"- 10 whole wheat tortillas\n",
|
| 937 |
"\n",
|
| 938 |
"#### Instructions:\n",
|
| 939 |
+
"Find the full recipe [here](http://www.food.com/recipe/vegan-spinach-wrap-243783).\n",
|
|
|
|
|
|
|
|
|
|
|
|
|
| 940 |
"\n",
|
| 941 |
+
"### Recipe 4: Vegan Beet Loaf\n",
|
| 942 |
+
"#### Ingredients:\n",
|
| 943 |
+
"- 1/2 cup raw organic sunflower seeds, soaked and strained\n",
|
| 944 |
+
"- 1/2 cup raw organic pumpkin seeds, soaked and strained\n",
|
| 945 |
+
"- 1/2 cup raw organic sunflower seeds, ground into flour\n",
|
| 946 |
+
"- 1/2 cup organic hemp seeds, ground into flour\n",
|
| 947 |
+
"- 2-3 beets, peeled and cut into quarters (2 cups cooked)\n",
|
| 948 |
+
"- 1-2 carrots, peeled and cut into smaller pieces (1 cup cooked)\n",
|
| 949 |
+
"- 2-3 garlic cloves, peeled and crushed (optional)\n",
|
| 950 |
+
"- 1 tablespoon psyllium husk\n",
|
| 951 |
+
"- 1 teaspoon fresh thyme, large stems removed\n",
|
| 952 |
+
"- 1/4 teaspoon ground pepper\n",
|
| 953 |
+
"- 1/4 teaspoon dried fine herbs (optional)\n",
|
| 954 |
+
"- 1/2 teaspoon sea or Himalayan salt\n",
|
| 955 |
+
"\n",
|
| 956 |
+
"#### Instructions:\n",
|
| 957 |
+
"Get the full instructions [here](https://www.freshisreal.com/vegan-beet-loaf/).\n",
|
| 958 |
"\n",
|
| 959 |
+
"These recipes should help you make the most of the ingredients you have from the first image! Enjoy your cooking! 🌱\n"
|
| 960 |
]
|
| 961 |
}
|
| 962 |
],
|
|
|
|
| 976 |
"\n",
|
| 977 |
"nbdev.nbdev_export()"
|
| 978 |
]
|
| 979 |
+
},
|
| 980 |
+
{
|
| 981 |
+
"cell_type": "code",
|
| 982 |
+
"execution_count": null,
|
| 983 |
+
"metadata": {
|
| 984 |
+
"language": "python"
|
| 985 |
+
},
|
| 986 |
+
"outputs": [],
|
| 987 |
+
"source": []
|
| 988 |
}
|
| 989 |
],
|
| 990 |
"metadata": {
|
app.py
CHANGED
|
@@ -1,21 +1,19 @@
|
|
| 1 |
-
from lv_recipe_chatbot.app import create_demo,
|
| 2 |
-
from lv_recipe_chatbot.ingredient_vision import (
|
| 3 |
-
VeganIngredientFinder,
|
| 4 |
-
BlipImageCaptioning,
|
| 5 |
-
)
|
| 6 |
import os
|
| 7 |
|
| 8 |
|
| 9 |
# for Hugging Face
|
| 10 |
|
| 11 |
if __name__ == "__main__":
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
)
|
|
|
|
|
|
|
| 19 |
demo.launch(
|
| 20 |
auth=(os.environ["GRADIO_DEMO_USERNAME"], os.environ["GRADIO_DEMO_PASSWORD"])
|
| 21 |
)
|
|
|
|
| 1 |
+
from lv_recipe_chatbot.app import create_demo, SYSTEM_PROMPT, OpenAI, VEGAN_RECIPE_SEARCH_TOOL_SCHEMA
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2 |
import os
|
| 3 |
|
| 4 |
|
| 5 |
# for Hugging Face
|
| 6 |
|
| 7 |
if __name__ == "__main__":
|
| 8 |
+
client = OpenAI()
|
| 9 |
+
assistant = client.beta.assistants.create(
|
| 10 |
+
name="Vegan Recipe Finder",
|
| 11 |
+
instructions=SYSTEM_PROMPT,
|
| 12 |
+
model="gpt-4o",
|
| 13 |
+
tools=[VEGAN_RECIPE_SEARCH_TOOL_SCHEMA],
|
| 14 |
)
|
| 15 |
+
demo = create_demo(client,assistant)
|
| 16 |
+
# demo.launch()
|
| 17 |
demo.launch(
|
| 18 |
auth=(os.environ["GRADIO_DEMO_USERNAME"], os.environ["GRADIO_DEMO_PASSWORD"])
|
| 19 |
)
|
data/store/02/vegan_assistant.txt
CHANGED
|
@@ -1,18 +1,156 @@
|
|
| 1 |
|
| 2 |
-
assistant >
|
| 3 |
-
assistant >
|
| 4 |
-
|
| 5 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 6 |
assistant > function
|
| 7 |
|
| 8 |
|
| 9 |
-
assistant >
|
| 10 |
-
assistant >
|
| 11 |
-
assistant >
|
| 12 |
assistant > function
|
| 13 |
|
| 14 |
|
| 15 |
assistant > function
|
| 16 |
|
| 17 |
|
| 18 |
-
assistant >
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
|
| 2 |
+
assistant > Hi there! How can I assist you today? Are you looking for some delicious vegan recipes or perhaps some information on veganism?
|
| 3 |
+
assistant > McDonald's menu primarily contains non-vegan items, but there are a few things you might be able to get to suit a vegan diet, depending on your location. Always double-check with the staff to ensure there are no hidden animal-derived ingredients. Common vegan-friendly options include:
|
| 4 |
+
|
| 5 |
+
1. **Side Salad** (without dressing unless it’s vegan-friendly)
|
| 6 |
+
2. **Apple Slices**
|
| 7 |
+
3. **French Fries** (Note: In some countries, McDonald's fries are cooked with beef flavoring, so ask to be sure)
|
| 8 |
+
4. **Hash Browns** (Similar caution as the fries)
|
| 9 |
+
5. **Beverages** like black coffee, soft drinks, and some juices
|
| 10 |
+
|
| 11 |
+
Would you like me to find some tasty vegan recipes for you to enjoy at home instead?
|
| 12 |
+
assistant > I'm here to promote veganism and compassionate choices for animals, so I can't provide instructions for making a beef burger. However, I can help you find a delicious vegan burger recipe. Would you like me to find one for you?
|
| 13 |
+
assistant > I have a variety of tools available to help you, including searching for vegan recipes. If you provide me with some keywords or specific ingredients you're interested in, I can find vegan recipes for you. How does that sound?
|
| 14 |
+
assistant > function
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
assistant > You can make a delicious **Tempeh Sandwich** with the ingredients you have! Here’s a recipe to get you started:
|
| 18 |
+
|
| 19 |
+
### Tempeh Sandwiches
|
| 20 |
+
|
| 21 |
+
#### Ingredients:
|
| 22 |
+
- 350 grams Tempeh
|
| 23 |
+
- 2 tablespoons Soy sauce
|
| 24 |
+
- 3 tablespoons Sweet chili sauce
|
| 25 |
+
- 2 tablespoons Lime juice
|
| 26 |
+
- 1 teaspoon Curry powder
|
| 27 |
+
- 2 Tomatoes
|
| 28 |
+
- 1 Red Onion
|
| 29 |
+
- ½ Cucumber
|
| 30 |
+
- 4 leaves Lettuce
|
| 31 |
+
- 2 handfuls Sprouts (such as alfalfa)
|
| 32 |
+
- 4 tablespoons Peanut oil
|
| 33 |
+
- 8 slices Whole-wheat bread
|
| 34 |
+
- 4 tablespoons vegan Spread (such as Veganaise)
|
| 35 |
+
|
| 36 |
+
#### Instructions:
|
| 37 |
+
You can find the full step-by-step instructions for making this sandwich at the following link: [Tempeh Sandwiches Recipe](https://eatsmarter.com/recipes/tempeh-sandwiches).
|
| 38 |
+
|
| 39 |
+
Enjoy your meal! 🌱🥪
|
| 40 |
+
assistant > In the image, I see a variety of vegan ingredients, including:
|
| 41 |
+
|
| 42 |
+
- Cherry tomatoes
|
| 43 |
+
- Apples
|
| 44 |
+
- Bananas
|
| 45 |
+
- Lemons
|
| 46 |
+
- Lettuce
|
| 47 |
+
- Kale
|
| 48 |
+
- Spinach
|
| 49 |
+
- Carrots
|
| 50 |
+
- Leeks
|
| 51 |
+
- Parsley
|
| 52 |
+
- Cilantro
|
| 53 |
+
- Red onions
|
| 54 |
+
- A jar of pesto (assuming it’s vegan pesto)
|
| 55 |
+
- A jar of legumes (possibly chickpeas or beans)
|
| 56 |
+
- Sprouts
|
| 57 |
+
- A pumpkin or squash
|
| 58 |
+
- Beets
|
| 59 |
+
|
| 60 |
+
These ingredients provide a great base for many delicious vegan dishes. Would you like me to find a recipe using any of these specific ingredients?
|
| 61 |
+
assistant > In the second image, the vegan ingredients I can identify are:
|
| 62 |
+
|
| 63 |
+
- **Soy Milk** (Silk brand)
|
| 64 |
+
- **Mustard** (depending on brand, but typically mustard is vegan)
|
| 65 |
+
- **Lemon Juice** (assuming the yellow bottle on the door is lemon juice)
|
| 66 |
+
- **Lettuce** (upper shelf on the door)
|
| 67 |
+
- **Pickles** or **relish** (top right of the door)
|
| 68 |
+
|
| 69 |
+
These ingredients can contribute to a variety of vegan dishes. Would you like me to find a specific recipe using some of these ingredients?
|
| 70 |
assistant > function
|
| 71 |
|
| 72 |
|
|
|
|
|
|
|
|
|
|
| 73 |
assistant > function
|
| 74 |
|
| 75 |
|
| 76 |
assistant > function
|
| 77 |
|
| 78 |
|
| 79 |
+
assistant > function
|
| 80 |
+
|
| 81 |
+
|
| 82 |
+
assistant > Here are several delicious vegan recipes using some of the ingredients from the first image. They pair well together and offer a variety of flavors and textures:
|
| 83 |
+
|
| 84 |
+
### Recipe 1: Vegan Kale Slaw
|
| 85 |
+
#### Ingredients:
|
| 86 |
+
- 2 bunches red kale
|
| 87 |
+
- 4 radishes
|
| 88 |
+
- 1 medium carrot
|
| 89 |
+
- 1 pink lady apple
|
| 90 |
+
- 1 avocado
|
| 91 |
+
- 1/2 cup craisins
|
| 92 |
+
- 1/2 cup almonds
|
| 93 |
+
- 1/2 cup pumpkin seeds
|
| 94 |
+
- Dressing:
|
| 95 |
+
- 3 tablespoons olive oil
|
| 96 |
+
- 2-3 teaspoons maple syrup (depending on your sweetness level)
|
| 97 |
+
- 1/2 clove garlic
|
| 98 |
+
- 1 tablespoon apple cider vinegar
|
| 99 |
+
- 1-2 tablespoons lemon juice (depending on your sourness level)
|
| 100 |
+
|
| 101 |
+
#### Instructions:
|
| 102 |
+
Find the full recipe [here](http://glutenfreeifyouplease.com/vegan-kale-slaw/).
|
| 103 |
+
|
| 104 |
+
### Recipe 2: Vegan Recipe: Raw Detox Soup
|
| 105 |
+
#### Ingredients:
|
| 106 |
+
- Half an avocado
|
| 107 |
+
- Juice of half a lemon
|
| 108 |
+
- 1 tablespoon apple cider vinegar
|
| 109 |
+
- 1-2 teaspoons agave
|
| 110 |
+
- 1 clove garlic
|
| 111 |
+
- 1/3 cup broccoli florets
|
| 112 |
+
- 1/3 cup chopped carrots
|
| 113 |
+
- 1/4 cup chopped onion
|
| 114 |
+
- 1/2 tablespoon tamari or Bragg's Liquid Aminos
|
| 115 |
+
- 1 packed cup kale (or other leafy green)
|
| 116 |
+
- 1 pinch sea salt
|
| 117 |
+
- 1/4-1/2 cup water (start with 1/4 cup and add as needed)
|
| 118 |
+
|
| 119 |
+
#### Instructions:
|
| 120 |
+
Check the complete recipe [here](https://www.mindbodygreen.com/0-10276/vegan-recipe-raw-detox-soup.html).
|
| 121 |
+
|
| 122 |
+
### Recipe 3: Vegan Spinach Wrap
|
| 123 |
+
#### Ingredients:
|
| 124 |
+
- 16 ounces vegan cream cheese
|
| 125 |
+
- 1/2 cup Vidalia onion, minced
|
| 126 |
+
- 1 teaspoon garlic powder
|
| 127 |
+
- 1 tablespoon dried oregano
|
| 128 |
+
- 2 teaspoons dried dill
|
| 129 |
+
- 1 tablespoon fresh basil, chopped
|
| 130 |
+
- 1 lb spinach, rinsed well and patted dry
|
| 131 |
+
- 2 ripe tomatoes (vine)
|
| 132 |
+
- 2 cups mixed sprouts
|
| 133 |
+
- 10 whole wheat tortillas
|
| 134 |
+
|
| 135 |
+
#### Instructions:
|
| 136 |
+
Find the full recipe [here](http://www.food.com/recipe/vegan-spinach-wrap-243783).
|
| 137 |
+
|
| 138 |
+
### Recipe 4: Vegan Beet Loaf
|
| 139 |
+
#### Ingredients:
|
| 140 |
+
- 1/2 cup raw organic sunflower seeds, soaked and strained
|
| 141 |
+
- 1/2 cup raw organic pumpkin seeds, soaked and strained
|
| 142 |
+
- 1/2 cup raw organic sunflower seeds, ground into flour
|
| 143 |
+
- 1/2 cup organic hemp seeds, ground into flour
|
| 144 |
+
- 2-3 beets, peeled and cut into quarters (2 cups cooked)
|
| 145 |
+
- 1-2 carrots, peeled and cut into smaller pieces (1 cup cooked)
|
| 146 |
+
- 2-3 garlic cloves, peeled and crushed (optional)
|
| 147 |
+
- 1 tablespoon psyllium husk
|
| 148 |
+
- 1 teaspoon fresh thyme, large stems removed
|
| 149 |
+
- 1/4 teaspoon ground pepper
|
| 150 |
+
- 1/4 teaspoon dried fine herbs (optional)
|
| 151 |
+
- 1/2 teaspoon sea or Himalayan salt
|
| 152 |
+
|
| 153 |
+
#### Instructions:
|
| 154 |
+
Get the full instructions [here](https://www.freshisreal.com/vegan-beet-loaf/).
|
| 155 |
+
|
| 156 |
+
These recipes should help you make the most of the ingredients you have from the first image! Enjoy your cooking! 🌱
|
lv_recipe_chatbot/_modidx.py
CHANGED
|
@@ -5,7 +5,11 @@ d = { 'settings': { 'branch': 'main',
|
|
| 5 |
'doc_host': 'https://animalequality.github.io',
|
| 6 |
'git_url': 'https://gitlab.com/animalequality/lv-recipe-chatbot',
|
| 7 |
'lib_path': 'lv_recipe_chatbot'},
|
| 8 |
-
'syms': { 'lv_recipe_chatbot.app': {
|
|
|
|
|
|
|
|
|
|
|
|
|
| 9 |
'lv_recipe_chatbot.openai_vision': { 'lv_recipe_chatbot.openai_vision.encode_image': ( 'openai_vision.html#encode_image',
|
| 10 |
'lv_recipe_chatbot/openai_vision.py'),
|
| 11 |
'lv_recipe_chatbot.openai_vision.format_image': ( 'openai_vision.html#format_image',
|
|
|
|
| 5 |
'doc_host': 'https://animalequality.github.io',
|
| 6 |
'git_url': 'https://gitlab.com/animalequality/lv-recipe-chatbot',
|
| 7 |
'lib_path': 'lv_recipe_chatbot'},
|
| 8 |
+
'syms': { 'lv_recipe_chatbot.app': { 'lv_recipe_chatbot.app.create_demo': ('app.html#create_demo', 'lv_recipe_chatbot/app.py'),
|
| 9 |
+
'lv_recipe_chatbot.app.handle_requires_action': ( 'app.html#handle_requires_action',
|
| 10 |
+
'lv_recipe_chatbot/app.py'),
|
| 11 |
+
'lv_recipe_chatbot.app.predict': ('app.html#predict', 'lv_recipe_chatbot/app.py'),
|
| 12 |
+
'lv_recipe_chatbot.app.run_convo_stream': ('app.html#run_convo_stream', 'lv_recipe_chatbot/app.py')},
|
| 13 |
'lv_recipe_chatbot.openai_vision': { 'lv_recipe_chatbot.openai_vision.encode_image': ( 'openai_vision.html#encode_image',
|
| 14 |
'lv_recipe_chatbot/openai_vision.py'),
|
| 15 |
'lv_recipe_chatbot.openai_vision.format_image': ( 'openai_vision.html#format_image',
|
lv_recipe_chatbot/app.py
CHANGED
|
@@ -1,13 +1,133 @@
|
|
| 1 |
# AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/01_app.ipynb.
|
| 2 |
|
| 3 |
# %% auto 0
|
| 4 |
-
__all__ = []
|
| 5 |
|
| 6 |
# %% ../nbs/01_app.ipynb 3
|
| 7 |
import copy
|
| 8 |
import os
|
| 9 |
-
|
| 10 |
import gradio as gr
|
| 11 |
-
|
| 12 |
import constants
|
| 13 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
# AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/01_app.ipynb.
|
| 2 |
|
| 3 |
# %% auto 0
|
| 4 |
+
__all__ = ['handle_requires_action', 'run_convo_stream', 'predict', 'create_demo']
|
| 5 |
|
| 6 |
# %% ../nbs/01_app.ipynb 3
|
| 7 |
import copy
|
| 8 |
import os
|
|
|
|
| 9 |
import gradio as gr
|
|
|
|
| 10 |
import constants
|
| 11 |
+
from lv_recipe_chatbot.vegan_recipe_assistant import (
|
| 12 |
+
SYSTEM_PROMPT,
|
| 13 |
+
vegan_recipe_edamam_search,
|
| 14 |
+
VEGAN_RECIPE_SEARCH_TOOL_SCHEMA,
|
| 15 |
+
)
|
| 16 |
+
from openai import OpenAI, AssistantEventHandler
|
| 17 |
+
from typing_extensions import override
|
| 18 |
+
import json
|
| 19 |
+
from functools import partial
|
| 20 |
+
|
| 21 |
+
# %% ../nbs/01_app.ipynb 9
|
| 22 |
+
def handle_requires_action(data):
|
| 23 |
+
tool_outputs = []
|
| 24 |
+
for tool_call in data.required_action.submit_tool_outputs.tool_calls:
|
| 25 |
+
if tool_call.function.name == "vegan_recipe_edamam_search":
|
| 26 |
+
fn_args = json.loads(tool_call.function.arguments)
|
| 27 |
+
data = vegan_recipe_edamam_search(
|
| 28 |
+
query=fn_args.get("query"),
|
| 29 |
+
)
|
| 30 |
+
tool_outputs.append({"tool_call_id": tool_call.id, "output": data})
|
| 31 |
+
return tool_outputs
|
| 32 |
+
|
| 33 |
+
# %% ../nbs/01_app.ipynb 11
|
| 34 |
+
def run_convo_stream(thread, content: str, client: OpenAI, assistant):
|
| 35 |
+
message = client.beta.threads.messages.create(
|
| 36 |
+
thread_id=thread.id,
|
| 37 |
+
role="user",
|
| 38 |
+
content=content,
|
| 39 |
+
)
|
| 40 |
+
stream = client.beta.threads.runs.create(
|
| 41 |
+
thread_id=thread.id,
|
| 42 |
+
assistant_id=assistant.id,
|
| 43 |
+
stream=True,
|
| 44 |
+
)
|
| 45 |
+
for event in stream:
|
| 46 |
+
if event.event == "thread.message.delta":
|
| 47 |
+
yield event.data.delta.content[0].text.value
|
| 48 |
+
|
| 49 |
+
if event.event == "thread.run.requires_action":
|
| 50 |
+
tool_outputs = handle_requires_action(event.data)
|
| 51 |
+
stream = client.beta.threads.runs.submit_tool_outputs(
|
| 52 |
+
run_id=event.data.id,
|
| 53 |
+
thread_id=thread.id,
|
| 54 |
+
tool_outputs=tool_outputs,
|
| 55 |
+
stream=True,
|
| 56 |
+
)
|
| 57 |
+
for event in stream:
|
| 58 |
+
if event.event == "thread.message.delta":
|
| 59 |
+
yield event.data.delta.content[0].text.value
|
| 60 |
+
|
| 61 |
+
# %% ../nbs/01_app.ipynb 13
|
| 62 |
+
def predict(message, history, client: OpenAI, assistant, thread):
|
| 63 |
+
# note that history is a flat list of text messages
|
| 64 |
+
reply = ""
|
| 65 |
+
files = message["files"]
|
| 66 |
+
txt = message["text"]
|
| 67 |
+
|
| 68 |
+
if files:
|
| 69 |
+
if files[-1].split(".")[-1] not in ["jpg", "png", "jpeg", "webp"]:
|
| 70 |
+
return "Sorry only accept image files"
|
| 71 |
+
|
| 72 |
+
file = message["files"][-1]
|
| 73 |
+
file = client.files.create(
|
| 74 |
+
file=open(
|
| 75 |
+
file,
|
| 76 |
+
"rb",
|
| 77 |
+
),
|
| 78 |
+
purpose="vision",
|
| 79 |
+
)
|
| 80 |
+
|
| 81 |
+
for reply_txt in run_convo_stream(
|
| 82 |
+
thread,
|
| 83 |
+
content=[
|
| 84 |
+
{
|
| 85 |
+
"type": "text",
|
| 86 |
+
"text": "What vegan ingredients do you see in this image? Also list out a few combinations of the ingredients that go well together. Lastly, suggest a recipe based on one of those combos using the vegan recipe seach tool.",
|
| 87 |
+
},
|
| 88 |
+
{"type": "image_file", "image_file": {"file_id": file.id}},
|
| 89 |
+
],
|
| 90 |
+
client=client,
|
| 91 |
+
assistant=assistant,
|
| 92 |
+
):
|
| 93 |
+
reply += reply_txt
|
| 94 |
+
yield reply
|
| 95 |
+
|
| 96 |
+
elif txt:
|
| 97 |
+
for reply_txt in run_convo_stream(thread, txt, client, assistant):
|
| 98 |
+
reply += reply_txt
|
| 99 |
+
yield reply
|
| 100 |
+
|
| 101 |
+
# %% ../nbs/01_app.ipynb 14
|
| 102 |
+
def create_demo(client: OpenAI, assistant):
|
| 103 |
+
# https://www.gradio.app/main/guides/creating-a-chatbot-fast#customizing-your-chatbot
|
| 104 |
+
# on chatbot start/ first msg after clear
|
| 105 |
+
thread = client.beta.threads.create()
|
| 106 |
+
|
| 107 |
+
# sample_images = []
|
| 108 |
+
# all_imgs = [f"{SAMPLE_IMG_DIR}/{img}" for img in os.listdir(SAMPLE_IMG_DIR)]
|
| 109 |
+
# for i, img in enumerate(all_imgs):
|
| 110 |
+
# if i in [
|
| 111 |
+
# 1,
|
| 112 |
+
# 2,
|
| 113 |
+
# 3,
|
| 114 |
+
# ]:
|
| 115 |
+
# sample_images.append(img)
|
| 116 |
+
pred = partial(predict, client=client, assistant=assistant, thread=thread)
|
| 117 |
+
with gr.ChatInterface(
|
| 118 |
+
fn=pred,
|
| 119 |
+
multimodal=True,
|
| 120 |
+
chatbot=gr.Chatbot(
|
| 121 |
+
placeholder="Hello!\nI am a animal advocate AI that is capable of recommending vegan recipes.\nUpload an image or write a message below to get started!"
|
| 122 |
+
),
|
| 123 |
+
) as demo:
|
| 124 |
+
gr.Markdown(
|
| 125 |
+
"""🔃 **Refresh the page to start from scratch**
|
| 126 |
+
|
| 127 |
+
Recipe search tool powered by the [Edamam API](https://www.edamam.com/)
|
| 128 |
+
|
| 129 |
+
"""
|
| 130 |
+
)
|
| 131 |
+
|
| 132 |
+
# clear.click(lambda: None, None, chatbot, queue=False).then(bot.reset)
|
| 133 |
+
return demo
|
lv_recipe_chatbot/utils.py
CHANGED
|
@@ -8,7 +8,7 @@ import json
|
|
| 8 |
|
| 9 |
# %% ../nbs/05_utils.ipynb 4
|
| 10 |
def load_json(file_path):
|
| 11 |
-
with open(file_path,
|
| 12 |
return json.load(file)
|
| 13 |
|
| 14 |
# %% ../nbs/05_utils.ipynb 5
|
|
|
|
| 8 |
|
| 9 |
# %% ../nbs/05_utils.ipynb 4
|
| 10 |
def load_json(file_path):
|
| 11 |
+
with open(file_path, "r") as file:
|
| 12 |
return json.load(file)
|
| 13 |
|
| 14 |
# %% ../nbs/05_utils.ipynb 5
|
nbs/01_app.ipynb
CHANGED
|
@@ -46,7 +46,8 @@
|
|
| 46 |
")\n",
|
| 47 |
"from openai import OpenAI, AssistantEventHandler\n",
|
| 48 |
"from typing_extensions import override\n",
|
| 49 |
-
"import json"
|
|
|
|
| 50 |
]
|
| 51 |
},
|
| 52 |
{
|
|
@@ -77,7 +78,7 @@
|
|
| 77 |
}
|
| 78 |
],
|
| 79 |
"source": [
|
| 80 |
-
"
|
| 81 |
"load_dotenv()"
|
| 82 |
]
|
| 83 |
},
|
|
@@ -85,12 +86,28 @@
|
|
| 85 |
"cell_type": "markdown",
|
| 86 |
"metadata": {},
|
| 87 |
"source": [
|
| 88 |
-
"Need an even handler to send the streaming output to the Gradio app \n",
|
| 89 |
"[GPT4 streaming output example on hugging face 🤗](https://huggingface.co/spaces/ysharma/ChatGPT4/blob/main/app.pyhttps://huggingface.co/spaces/ysharma/ChatGPT4/blob/main/app.py) \n",
|
| 90 |
"[Gradio lite let's you insert Gradio app in browser JS](https://www.gradio.app/guides/gradio-litehttps://www.gradio.app/guides/gradio-lite) \n",
|
| 91 |
"[Streaming output](https://www.gradio.app/main/guides/streaming-outputshttps://www.gradio.app/main/guides/streaming-outputs)"
|
| 92 |
]
|
| 93 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 94 |
{
|
| 95 |
"cell_type": "code",
|
| 96 |
"execution_count": null,
|
|
@@ -98,13 +115,6 @@
|
|
| 98 |
"outputs": [],
|
| 99 |
"source": [
|
| 100 |
"class EventHandler(AssistantEventHandler):\n",
|
| 101 |
-
" def __init__(self, handle_text_delta):\n",
|
| 102 |
-
" self.handle_text_delta = handle_text_delta\n",
|
| 103 |
-
"\n",
|
| 104 |
-
" @override\n",
|
| 105 |
-
" def on_text_delta(self, delta, snapshot):\n",
|
| 106 |
-
" self.handle_text_delta(delta.value)\n",
|
| 107 |
-
"\n",
|
| 108 |
" @override\n",
|
| 109 |
" def on_event(self, event):\n",
|
| 110 |
" # Retrieve events that are denoted with 'requires_action'\n",
|
|
@@ -126,14 +136,12 @@
|
|
| 126 |
" self.submit_tool_outputs(tool_outputs, run_id)\n",
|
| 127 |
"\n",
|
| 128 |
" def submit_tool_outputs(self, tool_outputs, run_id):\n",
|
| 129 |
-
"
|
| 130 |
" thread_id=self.current_run.thread_id,\n",
|
| 131 |
" run_id=self.current_run.id,\n",
|
| 132 |
" tool_outputs=tool_outputs,\n",
|
| 133 |
" event_handler=EventHandler(),\n",
|
| 134 |
-
" )
|
| 135 |
-
" for text in stream.until_:\n",
|
| 136 |
-
" pass"
|
| 137 |
]
|
| 138 |
},
|
| 139 |
{
|
|
@@ -142,14 +150,17 @@
|
|
| 142 |
"metadata": {},
|
| 143 |
"outputs": [],
|
| 144 |
"source": [
|
| 145 |
-
"
|
| 146 |
-
"
|
| 147 |
-
"
|
| 148 |
-
"
|
| 149 |
-
"
|
| 150 |
-
"
|
| 151 |
-
"
|
| 152 |
-
")"
|
|
|
|
|
|
|
|
|
|
| 153 |
]
|
| 154 |
},
|
| 155 |
{
|
|
@@ -200,6 +211,41 @@
|
|
| 200 |
" time.sleep(0.05)"
|
| 201 |
]
|
| 202 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 203 |
{
|
| 204 |
"cell_type": "code",
|
| 205 |
"execution_count": null,
|
|
@@ -209,67 +255,41 @@
|
|
| 209 |
"name": "stdout",
|
| 210 |
"output_type": "stream",
|
| 211 |
"text": [
|
| 212 |
-
"
|
| 213 |
-
"Running on local URL: http://127.0.0.1:7860\n",
|
| 214 |
-
"\n",
|
| 215 |
-
"To create a public link, set `share=True` in `launch()`.\n"
|
| 216 |
-
]
|
| 217 |
-
},
|
| 218 |
-
{
|
| 219 |
-
"data": {
|
| 220 |
-
"text/html": [
|
| 221 |
-
"<div><iframe src=\"http://127.0.0.1:7860/\" width=\"100%\" height=\"500\" allow=\"autoplay; camera; microphone; clipboard-read; clipboard-write;\" frameborder=\"0\" allowfullscreen></iframe></div>"
|
| 222 |
-
],
|
| 223 |
-
"text/plain": [
|
| 224 |
-
"<IPython.core.display.HTML object>"
|
| 225 |
-
]
|
| 226 |
-
},
|
| 227 |
-
"metadata": {},
|
| 228 |
-
"output_type": "display_data"
|
| 229 |
-
},
|
| 230 |
-
{
|
| 231 |
-
"data": {
|
| 232 |
-
"text/plain": []
|
| 233 |
-
},
|
| 234 |
-
"execution_count": null,
|
| 235 |
-
"metadata": {},
|
| 236 |
-
"output_type": "execute_result"
|
| 237 |
-
},
|
| 238 |
-
{
|
| 239 |
-
"name": "stdout",
|
| 240 |
-
"output_type": "stream",
|
| 241 |
-
"text": [
|
| 242 |
-
"Tool outputs submitted successfully.\n",
|
| 243 |
-
"Tool outputs submitted successfully.\n",
|
| 244 |
-
"Tool outputs submitted successfully.\n",
|
| 245 |
-
"Tool outputs submitted successfully.\n",
|
| 246 |
-
"Tool outputs submitted successfully.\n",
|
| 247 |
-
"Tool outputs submitted successfully.\n"
|
| 248 |
]
|
| 249 |
}
|
| 250 |
],
|
| 251 |
"source": [
|
| 252 |
-
"
|
| 253 |
-
"\n",
|
| 254 |
-
"\n",
|
| 255 |
-
"# on chatbot start/ first msg after clear\n",
|
| 256 |
"thread = client.beta.threads.create()\n",
|
| 257 |
"\n",
|
| 258 |
-
"\n",
|
| 259 |
-
"
|
| 260 |
-
"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 261 |
" # note that history is a flat list of text messages\n",
|
| 262 |
-
"
|
| 263 |
-
" if txt:\n",
|
| 264 |
-
" client.beta.threads.messages.create(\n",
|
| 265 |
-
" thread_id=thread.id,\n",
|
| 266 |
-
" role=\"user\",\n",
|
| 267 |
-
" content=txt,\n",
|
| 268 |
-
" )\n",
|
| 269 |
" files = message[\"files\"]\n",
|
| 270 |
-
"
|
|
|
|
| 271 |
" if files:\n",
|
| 272 |
-
"
|
|
|
|
|
|
|
| 273 |
" file = message[\"files\"][-1]\n",
|
| 274 |
" file = client.files.create(\n",
|
| 275 |
" file=open(\n",
|
|
@@ -278,45 +298,40 @@
|
|
| 278 |
" ),\n",
|
| 279 |
" purpose=\"vision\",\n",
|
| 280 |
" )\n",
|
| 281 |
-
"
|
| 282 |
-
"
|
|
|
|
| 283 |
" content=[\n",
|
| 284 |
" {\n",
|
| 285 |
" \"type\": \"text\",\n",
|
| 286 |
-
" \"text\": \"What vegan ingredients do you see in this image
|
| 287 |
" },\n",
|
| 288 |
" {\"type\": \"image_file\", \"image_file\": {\"file_id\": file.id}},\n",
|
| 289 |
" ],\n",
|
| 290 |
-
"
|
| 291 |
-
"
|
| 292 |
-
"
|
|
|
|
|
|
|
| 293 |
"\n",
|
| 294 |
-
"
|
| 295 |
-
"
|
| 296 |
-
"
|
| 297 |
-
"
|
| 298 |
-
"if \"demo\" in globals():\n",
|
| 299 |
-
" demo.close()\n",
|
| 300 |
-
"\n",
|
| 301 |
-
"demo = gr.ChatInterface(fn=predict, multimodal=True)\n",
|
| 302 |
-
"demo.launch()"
|
| 303 |
]
|
| 304 |
},
|
| 305 |
{
|
| 306 |
"cell_type": "code",
|
| 307 |
"execution_count": null,
|
| 308 |
"metadata": {},
|
| 309 |
-
"outputs": [
|
| 310 |
-
{
|
| 311 |
-
"name": "stdout",
|
| 312 |
-
"output_type": "stream",
|
| 313 |
-
"text": [
|
| 314 |
-
"skip\n"
|
| 315 |
-
]
|
| 316 |
-
}
|
| 317 |
-
],
|
| 318 |
"source": [
|
| 319 |
-
"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 320 |
" # sample_images = []\n",
|
| 321 |
" # all_imgs = [f\"{SAMPLE_IMG_DIR}/{img}\" for img in os.listdir(SAMPLE_IMG_DIR)]\n",
|
| 322 |
" # for i, img in enumerate(all_imgs):\n",
|
|
@@ -326,33 +341,48 @@
|
|
| 326 |
" # 3,\n",
|
| 327 |
" # ]:\n",
|
| 328 |
" # sample_images.append(img)\n",
|
| 329 |
-
"
|
| 330 |
-
"
|
| 331 |
-
"
|
| 332 |
-
"
|
| 333 |
-
"
|
| 334 |
-
"
|
| 335 |
-
"
|
| 336 |
-
"
|
| 337 |
-
" # )\n",
|
| 338 |
-
"\n",
|
| 339 |
-
" chatbot = gr.Chatbot(value=[(None,)])\n",
|
| 340 |
-
"\n",
|
| 341 |
-
" msg = gr.Textbox()\n",
|
| 342 |
" gr.Markdown(\n",
|
| 343 |
-
" \"\"\"
|
| 344 |
" \n",
|
| 345 |
" Recipe search tool powered by the [Edamam API](https://www.edamam.com/) \n",
|
| 346 |
" \n",
|
| 347 |
" \"\"\"\n",
|
| 348 |
" )\n",
|
| 349 |
-
"
|
| 350 |
-
" fn=bot.respond, inputs=[msg, chatbot], outputs=[msg, chatbot], queue=False\n",
|
| 351 |
-
" )\n",
|
| 352 |
" # clear.click(lambda: None, None, chatbot, queue=False).then(bot.reset)\n",
|
| 353 |
" return demo"
|
| 354 |
]
|
| 355 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 356 |
{
|
| 357 |
"cell_type": "code",
|
| 358 |
"execution_count": null,
|
|
|
|
| 46 |
")\n",
|
| 47 |
"from openai import OpenAI, AssistantEventHandler\n",
|
| 48 |
"from typing_extensions import override\n",
|
| 49 |
+
"import json\n",
|
| 50 |
+
"from functools import partial"
|
| 51 |
]
|
| 52 |
},
|
| 53 |
{
|
|
|
|
| 78 |
}
|
| 79 |
],
|
| 80 |
"source": [
|
| 81 |
+
"#| eval: false\n",
|
| 82 |
"load_dotenv()"
|
| 83 |
]
|
| 84 |
},
|
|
|
|
| 86 |
"cell_type": "markdown",
|
| 87 |
"metadata": {},
|
| 88 |
"source": [
|
|
|
|
| 89 |
"[GPT4 streaming output example on hugging face 🤗](https://huggingface.co/spaces/ysharma/ChatGPT4/blob/main/app.pyhttps://huggingface.co/spaces/ysharma/ChatGPT4/blob/main/app.py) \n",
|
| 90 |
"[Gradio lite let's you insert Gradio app in browser JS](https://www.gradio.app/guides/gradio-litehttps://www.gradio.app/guides/gradio-lite) \n",
|
| 91 |
"[Streaming output](https://www.gradio.app/main/guides/streaming-outputshttps://www.gradio.app/main/guides/streaming-outputs)"
|
| 92 |
]
|
| 93 |
},
|
| 94 |
+
{
|
| 95 |
+
"cell_type": "code",
|
| 96 |
+
"execution_count": null,
|
| 97 |
+
"metadata": {},
|
| 98 |
+
"outputs": [],
|
| 99 |
+
"source": [
|
| 100 |
+
"#| eval: false\n",
|
| 101 |
+
"client = OpenAI()\n",
|
| 102 |
+
"assistant = client.beta.assistants.create(\n",
|
| 103 |
+
" name=\"Vegan Recipe Finder\",\n",
|
| 104 |
+
" instructions=SYSTEM_PROMPT,\n",
|
| 105 |
+
" # + \"\\nChoose the best single matching recipe to the user's query out of the vegan recipe search returned recipes\",\n",
|
| 106 |
+
" model=\"gpt-4o\",\n",
|
| 107 |
+
" tools=[VEGAN_RECIPE_SEARCH_TOOL_SCHEMA],\n",
|
| 108 |
+
")"
|
| 109 |
+
]
|
| 110 |
+
},
|
| 111 |
{
|
| 112 |
"cell_type": "code",
|
| 113 |
"execution_count": null,
|
|
|
|
| 115 |
"outputs": [],
|
| 116 |
"source": [
|
| 117 |
"class EventHandler(AssistantEventHandler):\n",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 118 |
" @override\n",
|
| 119 |
" def on_event(self, event):\n",
|
| 120 |
" # Retrieve events that are denoted with 'requires_action'\n",
|
|
|
|
| 136 |
" self.submit_tool_outputs(tool_outputs, run_id)\n",
|
| 137 |
"\n",
|
| 138 |
" def submit_tool_outputs(self, tool_outputs, run_id):\n",
|
| 139 |
+
" client.beta.threads.runs.submit_tool_outputs_stream(\n",
|
| 140 |
" thread_id=self.current_run.thread_id,\n",
|
| 141 |
" run_id=self.current_run.id,\n",
|
| 142 |
" tool_outputs=tool_outputs,\n",
|
| 143 |
" event_handler=EventHandler(),\n",
|
| 144 |
+
" )"
|
|
|
|
|
|
|
| 145 |
]
|
| 146 |
},
|
| 147 |
{
|
|
|
|
| 150 |
"metadata": {},
|
| 151 |
"outputs": [],
|
| 152 |
"source": [
|
| 153 |
+
"#| export\n",
|
| 154 |
+
"def handle_requires_action(data):\n",
|
| 155 |
+
" tool_outputs = []\n",
|
| 156 |
+
" for tool_call in data.required_action.submit_tool_outputs.tool_calls:\n",
|
| 157 |
+
" if tool_call.function.name == \"vegan_recipe_edamam_search\":\n",
|
| 158 |
+
" fn_args = json.loads(tool_call.function.arguments)\n",
|
| 159 |
+
" data = vegan_recipe_edamam_search(\n",
|
| 160 |
+
" query=fn_args.get(\"query\"),\n",
|
| 161 |
+
" )\n",
|
| 162 |
+
" tool_outputs.append({\"tool_call_id\": tool_call.id, \"output\": data})\n",
|
| 163 |
+
" return tool_outputs"
|
| 164 |
]
|
| 165 |
},
|
| 166 |
{
|
|
|
|
| 211 |
" time.sleep(0.05)"
|
| 212 |
]
|
| 213 |
},
|
| 214 |
+
{
|
| 215 |
+
"cell_type": "code",
|
| 216 |
+
"execution_count": null,
|
| 217 |
+
"metadata": {},
|
| 218 |
+
"outputs": [],
|
| 219 |
+
"source": [
|
| 220 |
+
"#| export\n",
|
| 221 |
+
"def run_convo_stream(thread, content: str, client: OpenAI, assistant):\n",
|
| 222 |
+
" message = client.beta.threads.messages.create(\n",
|
| 223 |
+
" thread_id=thread.id,\n",
|
| 224 |
+
" role=\"user\",\n",
|
| 225 |
+
" content=content,\n",
|
| 226 |
+
" )\n",
|
| 227 |
+
" stream = client.beta.threads.runs.create(\n",
|
| 228 |
+
" thread_id=thread.id,\n",
|
| 229 |
+
" assistant_id=assistant.id,\n",
|
| 230 |
+
" stream=True,\n",
|
| 231 |
+
" )\n",
|
| 232 |
+
" for event in stream:\n",
|
| 233 |
+
" if event.event == \"thread.message.delta\":\n",
|
| 234 |
+
" yield event.data.delta.content[0].text.value\n",
|
| 235 |
+
"\n",
|
| 236 |
+
" if event.event == \"thread.run.requires_action\":\n",
|
| 237 |
+
" tool_outputs = handle_requires_action(event.data)\n",
|
| 238 |
+
" stream = client.beta.threads.runs.submit_tool_outputs(\n",
|
| 239 |
+
" run_id=event.data.id,\n",
|
| 240 |
+
" thread_id=thread.id,\n",
|
| 241 |
+
" tool_outputs=tool_outputs,\n",
|
| 242 |
+
" stream=True,\n",
|
| 243 |
+
" )\n",
|
| 244 |
+
" for event in stream:\n",
|
| 245 |
+
" if event.event == \"thread.message.delta\":\n",
|
| 246 |
+
" yield event.data.delta.content[0].text.value"
|
| 247 |
+
]
|
| 248 |
+
},
|
| 249 |
{
|
| 250 |
"cell_type": "code",
|
| 251 |
"execution_count": null,
|
|
|
|
| 255 |
"name": "stdout",
|
| 256 |
"output_type": "stream",
|
| 257 |
"text": [
|
| 258 |
+
"skip\n"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 259 |
]
|
| 260 |
}
|
| 261 |
],
|
| 262 |
"source": [
|
| 263 |
+
"%%script echo skip\n",
|
|
|
|
|
|
|
|
|
|
| 264 |
"thread = client.beta.threads.create()\n",
|
| 265 |
"\n",
|
| 266 |
+
"test_msgs = [\n",
|
| 267 |
+
" \"Hello\",\n",
|
| 268 |
+
" \"What can I make with tempeh, whole wheat bread, and lettuce?\",\n",
|
| 269 |
+
"]\n",
|
| 270 |
+
"for m in test_msgs:\n",
|
| 271 |
+
" for txt in run_convo_stream(thread, m, client, assistant):\n",
|
| 272 |
+
" print(txt, end=\"\")\n",
|
| 273 |
+
" print()"
|
| 274 |
+
]
|
| 275 |
+
},
|
| 276 |
+
{
|
| 277 |
+
"cell_type": "code",
|
| 278 |
+
"execution_count": null,
|
| 279 |
+
"metadata": {},
|
| 280 |
+
"outputs": [],
|
| 281 |
+
"source": [
|
| 282 |
+
"#| export\n",
|
| 283 |
+
"def predict(message, history, client: OpenAI, assistant, thread):\n",
|
| 284 |
" # note that history is a flat list of text messages\n",
|
| 285 |
+
" reply = \"\"\n",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 286 |
" files = message[\"files\"]\n",
|
| 287 |
+
" txt = message[\"text\"]\n",
|
| 288 |
+
"\n",
|
| 289 |
" if files:\n",
|
| 290 |
+
" if files[-1].split(\".\")[-1] not in [\"jpg\", \"png\", \"jpeg\", \"webp\"]:\n",
|
| 291 |
+
" return \"Sorry only accept image files\"\n",
|
| 292 |
+
"\n",
|
| 293 |
" file = message[\"files\"][-1]\n",
|
| 294 |
" file = client.files.create(\n",
|
| 295 |
" file=open(\n",
|
|
|
|
| 298 |
" ),\n",
|
| 299 |
" purpose=\"vision\",\n",
|
| 300 |
" )\n",
|
| 301 |
+
"\n",
|
| 302 |
+
" for reply_txt in run_convo_stream(\n",
|
| 303 |
+
" thread,\n",
|
| 304 |
" content=[\n",
|
| 305 |
" {\n",
|
| 306 |
" \"type\": \"text\",\n",
|
| 307 |
+
" \"text\": \"What vegan ingredients do you see in this image? Also list out a few combinations of the ingredients that go well together. Lastly, suggest a recipe based on one of those combos using the vegan recipe seach tool.\",\n",
|
| 308 |
" },\n",
|
| 309 |
" {\"type\": \"image_file\", \"image_file\": {\"file_id\": file.id}},\n",
|
| 310 |
" ],\n",
|
| 311 |
+
" client=client,\n",
|
| 312 |
+
" assistant=assistant,\n",
|
| 313 |
+
" ):\n",
|
| 314 |
+
" reply += reply_txt\n",
|
| 315 |
+
" yield reply\n",
|
| 316 |
"\n",
|
| 317 |
+
" elif txt:\n",
|
| 318 |
+
" for reply_txt in run_convo_stream(thread, txt, client, assistant):\n",
|
| 319 |
+
" reply += reply_txt\n",
|
| 320 |
+
" yield reply"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 321 |
]
|
| 322 |
},
|
| 323 |
{
|
| 324 |
"cell_type": "code",
|
| 325 |
"execution_count": null,
|
| 326 |
"metadata": {},
|
| 327 |
+
"outputs": [],
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 328 |
"source": [
|
| 329 |
+
"#| export\n",
|
| 330 |
+
"def create_demo(client: OpenAI, assistant):\n",
|
| 331 |
+
" # https://www.gradio.app/main/guides/creating-a-chatbot-fast#customizing-your-chatbot\n",
|
| 332 |
+
" # on chatbot start/ first msg after clear\n",
|
| 333 |
+
" thread = client.beta.threads.create()\n",
|
| 334 |
+
"\n",
|
| 335 |
" # sample_images = []\n",
|
| 336 |
" # all_imgs = [f\"{SAMPLE_IMG_DIR}/{img}\" for img in os.listdir(SAMPLE_IMG_DIR)]\n",
|
| 337 |
" # for i, img in enumerate(all_imgs):\n",
|
|
|
|
| 341 |
" # 3,\n",
|
| 342 |
" # ]:\n",
|
| 343 |
" # sample_images.append(img)\n",
|
| 344 |
+
" pred = partial(predict, client=client, assistant=assistant, thread=thread)\n",
|
| 345 |
+
" with gr.ChatInterface(\n",
|
| 346 |
+
" fn=pred,\n",
|
| 347 |
+
" multimodal=True,\n",
|
| 348 |
+
" chatbot=gr.Chatbot(\n",
|
| 349 |
+
" placeholder=\"Hello!\\nI am a animal advocate AI that is capable of recommending vegan recipes.\\nUpload an image or write a message below to get started!\"\n",
|
| 350 |
+
" ),\n",
|
| 351 |
+
" ) as demo:\n",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 352 |
" gr.Markdown(\n",
|
| 353 |
+
" \"\"\"🔃 **Refresh the page to start from scratch** \n",
|
| 354 |
" \n",
|
| 355 |
" Recipe search tool powered by the [Edamam API](https://www.edamam.com/) \n",
|
| 356 |
" \n",
|
| 357 |
" \"\"\"\n",
|
| 358 |
" )\n",
|
| 359 |
+
"\n",
|
|
|
|
|
|
|
| 360 |
" # clear.click(lambda: None, None, chatbot, queue=False).then(bot.reset)\n",
|
| 361 |
" return demo"
|
| 362 |
]
|
| 363 |
},
|
| 364 |
+
{
|
| 365 |
+
"cell_type": "code",
|
| 366 |
+
"execution_count": null,
|
| 367 |
+
"metadata": {},
|
| 368 |
+
"outputs": [
|
| 369 |
+
{
|
| 370 |
+
"name": "stdout",
|
| 371 |
+
"output_type": "stream",
|
| 372 |
+
"text": [
|
| 373 |
+
"skip\n"
|
| 374 |
+
]
|
| 375 |
+
}
|
| 376 |
+
],
|
| 377 |
+
"source": [
|
| 378 |
+
"%%script echo skip\n",
|
| 379 |
+
"if \"demo\" in globals():\n",
|
| 380 |
+
" demo.close()\n",
|
| 381 |
+
"\n",
|
| 382 |
+
"demo = create_demo(client, assistant)\n",
|
| 383 |
+
"demo.launch()"
|
| 384 |
+
]
|
| 385 |
+
},
|
| 386 |
{
|
| 387 |
"cell_type": "code",
|
| 388 |
"execution_count": null,
|
nbs/02_vegan_recipe_assistant.ipynb
CHANGED
|
@@ -193,6 +193,18 @@
|
|
| 193 |
"execution_count": null,
|
| 194 |
"metadata": {},
|
| 195 |
"outputs": [
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 196 |
{
|
| 197 |
"data": {
|
| 198 |
"text/plain": [
|
|
@@ -383,7 +395,7 @@
|
|
| 383 |
}
|
| 384 |
],
|
| 385 |
"source": [
|
| 386 |
-
"_load_json(\"
|
| 387 |
]
|
| 388 |
},
|
| 389 |
{
|
|
@@ -529,12 +541,12 @@
|
|
| 529 |
"name": "stdout",
|
| 530 |
"output_type": "stream",
|
| 531 |
"text": [
|
| 532 |
-
"
|
| 533 |
]
|
| 534 |
}
|
| 535 |
],
|
| 536 |
"source": [
|
| 537 |
-
"
|
| 538 |
"# Example\n",
|
| 539 |
"assistant = client.beta.assistants.create(\n",
|
| 540 |
" name=\"Math Tutor\",\n",
|
|
@@ -734,7 +746,7 @@
|
|
| 734 |
"\n",
|
| 735 |
" self.submit_tool_outputs(tool_outputs, run_id)\n",
|
| 736 |
"\n",
|
| 737 |
-
" def submit_tool_outputs(self,
|
| 738 |
" with client.beta.threads.runs.submit_tool_outputs_stream(\n",
|
| 739 |
" thread_id=self.current_run.thread_id,\n",
|
| 740 |
" run_id=self.current_run.id,\n",
|
|
@@ -754,29 +766,12 @@
|
|
| 754 |
"name": "stdout",
|
| 755 |
"output_type": "stream",
|
| 756 |
"text": [
|
| 757 |
-
"\n"
|
| 758 |
-
"assistant > \n",
|
| 759 |
-
"assistant > \n",
|
| 760 |
-
"assistant > \n",
|
| 761 |
-
"assistant > \n",
|
| 762 |
-
"assistant > function\n",
|
| 763 |
-
"\n",
|
| 764 |
-
"\n",
|
| 765 |
-
"assistant > \n",
|
| 766 |
-
"assistant > \n",
|
| 767 |
-
"assistant > \n",
|
| 768 |
-
"assistant > function\n",
|
| 769 |
-
"\n",
|
| 770 |
-
"\n",
|
| 771 |
-
"assistant > function\n",
|
| 772 |
-
"\n",
|
| 773 |
-
"\n",
|
| 774 |
-
"assistant > "
|
| 775 |
]
|
| 776 |
}
|
| 777 |
],
|
| 778 |
"source": [
|
| 779 |
-
"
|
| 780 |
"_clear_file(EventHandler.stream_file)\n",
|
| 781 |
"assistant = client.beta.assistants.create(\n",
|
| 782 |
" name=\"Vegan Recipe Finder\",\n",
|
|
@@ -841,34 +836,24 @@
|
|
| 841 |
"output_type": "stream",
|
| 842 |
"text": [
|
| 843 |
"\n",
|
| 844 |
-
"assistant > Hi there! How can I assist you today?
|
| 845 |
-
"assistant > McDonald's menu
|
| 846 |
-
"\n",
|
| 847 |
-
"1. **Sides**: \n",
|
| 848 |
-
" - Apple slices\n",
|
| 849 |
-
" - French fries (Note: In some regions, the fries may be cooked in oil with animal-based flavoring, so check locally)\n",
|
| 850 |
"\n",
|
| 851 |
-
"
|
| 852 |
-
"
|
| 853 |
-
"
|
|
|
|
|
|
|
| 854 |
"\n",
|
| 855 |
-
"
|
| 856 |
-
"
|
| 857 |
-
"
|
| 858 |
-
"4. **Custom Orders**: \n",
|
| 859 |
-
" - You can customize a sandwich or burger. For example, order the vegetable components of a burger (like lettuce, tomato, and pickles) without the meat and other non-vegan ingredients.\n",
|
| 860 |
-
"\n",
|
| 861 |
-
"For a satisfying vegan meal, you might want to explore vegan-friendly restaurants or cook at home. Would you like some vegan recipe suggestions?\n",
|
| 862 |
-
"assistant > I can't assist with that. My purpose is to promote veganism and provide information and recipes related to a plant-based diet. If you're interested in trying a delicious and compassionate alternative to a beef burger, I can suggest an amazing vegan burger recipe! Would you like that?\n",
|
| 863 |
-
"assistant > I have access to tools that can help find vegan recipes based on a query. If you let me know what kind of vegan dish or specific ingredients you're interested in, I can use these tools to find some great vegan recipes for you. Just let me know!\n",
|
| 864 |
"assistant > function\n",
|
| 865 |
"\n",
|
| 866 |
"\n",
|
| 867 |
-
"assistant >
|
| 868 |
-
"\n",
|
| 869 |
-
"### **Tempeh Sandwiches**\n",
|
| 870 |
"\n",
|
| 871 |
-
"
|
| 872 |
"\n",
|
| 873 |
"#### Ingredients:\n",
|
| 874 |
"- 350 grams Tempeh\n",
|
|
@@ -886,84 +871,126 @@
|
|
| 886 |
"- 4 tablespoons vegan Spread (such as Veganaise)\n",
|
| 887 |
"\n",
|
| 888 |
"#### Instructions:\n",
|
| 889 |
-
"
|
| 890 |
-
"2. **Prepare the Vegetables**: Slice tomatoes, onion, and cucumber. Wash the lettuce leaves and sprouts.\n",
|
| 891 |
-
"3. **Cook the Tempeh**: Heat the peanut oil in a pan over medium heat. Fry the tempeh until golden brown on both sides.\n",
|
| 892 |
-
"4. **Assemble the Sandwich**: Spread the vegan spread on one side of each slice of whole-wheat bread. Layer tempeh, lettuce, tomato, onion, cucumber, and sprouts on four of the bread slices. Top with the remaining bread slices.\n",
|
| 893 |
-
"5. **Serve and Enjoy**!\n",
|
| 894 |
"\n",
|
| 895 |
-
"
|
| 896 |
-
"
|
| 897 |
-
"Would you like to find more vegan recipes or need help with anything else?\n",
|
| 898 |
-
"assistant > This image contains a variety of fresh vegan ingredients. Here's what I see:\n",
|
| 899 |
"\n",
|
| 900 |
"- Cherry tomatoes\n",
|
| 901 |
-
"- Lemons\n",
|
| 902 |
"- Apples\n",
|
| 903 |
"- Bananas\n",
|
| 904 |
-
"-
|
| 905 |
-
"- Leeks\n",
|
| 906 |
-
"- Fresh herbs (parsley, cilantro, and kale)\n",
|
| 907 |
"- Lettuce\n",
|
|
|
|
|
|
|
| 908 |
"- Carrots\n",
|
| 909 |
-
"-
|
| 910 |
-
"-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 911 |
"- A pumpkin or squash\n",
|
| 912 |
-
"- Microgreens or sprouts\n",
|
| 913 |
"- Beets\n",
|
| 914 |
-
"- Spinach or another leafy green\n",
|
| 915 |
"\n",
|
| 916 |
-
"These ingredients
|
| 917 |
-
"assistant > In
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 918 |
"\n",
|
| 919 |
-
"
|
| 920 |
-
"- Silk Non-Dairy Milk (likely a plant-based milk such as almond or soy milk)\n",
|
| 921 |
-
"- Pickles (assuming they are vinegar-based, not honey pickles)\n",
|
| 922 |
-
"- Mustard\n",
|
| 923 |
-
"- Condiments (potentially vegan, depends on the ingredients)\n",
|
| 924 |
-
"- Bagged lettuce or greens (near the bottom shelf)\n",
|
| 925 |
-
"- Bottled water\n",
|
| 926 |
"\n",
|
| 927 |
-
"On the Door:\n",
|
| 928 |
-
"- Carrots (in the drawer at the bottom)\n",
|
| 929 |
"\n",
|
| 930 |
-
"If you need help on how to use these ingredients in a vegan recipe, let me know!\n",
|
| 931 |
"assistant > function\n",
|
| 932 |
"\n",
|
| 933 |
"\n",
|
| 934 |
-
"assistant >
|
| 935 |
"\n",
|
| 936 |
-
"### **Vegan Kale Slaw**\n",
|
| 937 |
"\n",
|
| 938 |
-
"
|
| 939 |
"\n",
|
|
|
|
| 940 |
"#### Ingredients:\n",
|
| 941 |
"- 2 bunches red kale\n",
|
| 942 |
"- 4 radishes\n",
|
| 943 |
"- 1 medium carrot\n",
|
| 944 |
"- 1 pink lady apple\n",
|
| 945 |
"- 1 avocado\n",
|
| 946 |
-
"-
|
| 947 |
-
"- 1 cup almonds\n",
|
| 948 |
-
"- 1 cup pumpkin seeds\n",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 949 |
"\n",
|
| 950 |
-
"
|
| 951 |
-
"
|
| 952 |
-
"-
|
| 953 |
-
"-
|
| 954 |
"- 1 tablespoon apple cider vinegar\n",
|
| 955 |
-
"- 1-2
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 956 |
"\n",
|
| 957 |
"#### Instructions:\n",
|
| 958 |
-
"
|
| 959 |
-
"2. **Make the Dressing**: In a small bowl, whisk together olive oil, maple syrup, minced garlic, apple cider vinegar, and lemon juice.\n",
|
| 960 |
-
"3. **Combine Ingredients**: In a large bowl, combine the kale, radishes, carrot, and apple. Add the craisins, almonds, and pumpkin seeds.\n",
|
| 961 |
-
"4. **Dress and Toss**: Pour the dressing over the slaw and toss until everything is well coated.\n",
|
| 962 |
-
"5. **Serve**: Enjoy your fresh and crunchy Vegan Kale Slaw!\n",
|
| 963 |
"\n",
|
| 964 |
-
"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 965 |
"\n",
|
| 966 |
-
"
|
| 967 |
]
|
| 968 |
}
|
| 969 |
],
|
|
@@ -981,6 +1008,13 @@
|
|
| 981 |
"\n",
|
| 982 |
"nbdev.nbdev_export()"
|
| 983 |
]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 984 |
}
|
| 985 |
],
|
| 986 |
"metadata": {
|
|
|
|
| 193 |
"execution_count": null,
|
| 194 |
"metadata": {},
|
| 195 |
"outputs": [
|
| 196 |
+
{
|
| 197 |
+
"name": "stderr",
|
| 198 |
+
"output_type": "stream",
|
| 199 |
+
"text": [
|
| 200 |
+
"Future exception was never retrieved\n",
|
| 201 |
+
"future: <Future finished exception=BrokenPipeError(32, 'Broken pipe')>\n",
|
| 202 |
+
"Traceback (most recent call last):\n",
|
| 203 |
+
" File \"/usr/lib/python3.10/asyncio/unix_events.py\", line 676, in write\n",
|
| 204 |
+
" n = os.write(self._fileno, data)\n",
|
| 205 |
+
"BrokenPipeError: [Errno 32] Broken pipe\n"
|
| 206 |
+
]
|
| 207 |
+
},
|
| 208 |
{
|
| 209 |
"data": {
|
| 210 |
"text/plain": [
|
|
|
|
| 395 |
}
|
| 396 |
],
|
| 397 |
"source": [
|
| 398 |
+
"_load_json(\"vegan_chicken\")"
|
| 399 |
]
|
| 400 |
},
|
| 401 |
{
|
|
|
|
| 541 |
"name": "stdout",
|
| 542 |
"output_type": "stream",
|
| 543 |
"text": [
|
| 544 |
+
"skip\n"
|
| 545 |
]
|
| 546 |
}
|
| 547 |
],
|
| 548 |
"source": [
|
| 549 |
+
"%%script echo skip\n",
|
| 550 |
"# Example\n",
|
| 551 |
"assistant = client.beta.assistants.create(\n",
|
| 552 |
" name=\"Math Tutor\",\n",
|
|
|
|
| 746 |
"\n",
|
| 747 |
" self.submit_tool_outputs(tool_outputs, run_id)\n",
|
| 748 |
"\n",
|
| 749 |
+
" def submit_tool_outputs(self, tool_outputs, run_id):\n",
|
| 750 |
" with client.beta.threads.runs.submit_tool_outputs_stream(\n",
|
| 751 |
" thread_id=self.current_run.thread_id,\n",
|
| 752 |
" run_id=self.current_run.id,\n",
|
|
|
|
| 766 |
"name": "stdout",
|
| 767 |
"output_type": "stream",
|
| 768 |
"text": [
|
| 769 |
+
"skip\n"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 770 |
]
|
| 771 |
}
|
| 772 |
],
|
| 773 |
"source": [
|
| 774 |
+
"%%script echo skip\n",
|
| 775 |
"_clear_file(EventHandler.stream_file)\n",
|
| 776 |
"assistant = client.beta.assistants.create(\n",
|
| 777 |
" name=\"Vegan Recipe Finder\",\n",
|
|
|
|
| 836 |
"output_type": "stream",
|
| 837 |
"text": [
|
| 838 |
"\n",
|
| 839 |
+
"assistant > Hi there! How can I assist you today? Are you looking for some delicious vegan recipes or perhaps some information on veganism?\n",
|
| 840 |
+
"assistant > McDonald's menu primarily contains non-vegan items, but there are a few things you might be able to get to suit a vegan diet, depending on your location. Always double-check with the staff to ensure there are no hidden animal-derived ingredients. Common vegan-friendly options include:\n",
|
|
|
|
|
|
|
|
|
|
|
|
|
| 841 |
"\n",
|
| 842 |
+
"1. **Side Salad** (without dressing unless it’s vegan-friendly)\n",
|
| 843 |
+
"2. **Apple Slices**\n",
|
| 844 |
+
"3. **French Fries** (Note: In some countries, McDonald's fries are cooked with beef flavoring, so ask to be sure)\n",
|
| 845 |
+
"4. **Hash Browns** (Similar caution as the fries)\n",
|
| 846 |
+
"5. **Beverages** like black coffee, soft drinks, and some juices\n",
|
| 847 |
"\n",
|
| 848 |
+
"Would you like me to find some tasty vegan recipes for you to enjoy at home instead?\n",
|
| 849 |
+
"assistant > I'm here to promote veganism and compassionate choices for animals, so I can't provide instructions for making a beef burger. However, I can help you find a delicious vegan burger recipe. Would you like me to find one for you?\n",
|
| 850 |
+
"assistant > I have a variety of tools available to help you, including searching for vegan recipes. If you provide me with some keywords or specific ingredients you're interested in, I can find vegan recipes for you. How does that sound?\n",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 851 |
"assistant > function\n",
|
| 852 |
"\n",
|
| 853 |
"\n",
|
| 854 |
+
"assistant > You can make a delicious **Tempeh Sandwich** with the ingredients you have! Here’s a recipe to get you started:\n",
|
|
|
|
|
|
|
| 855 |
"\n",
|
| 856 |
+
"### Tempeh Sandwiches\n",
|
| 857 |
"\n",
|
| 858 |
"#### Ingredients:\n",
|
| 859 |
"- 350 grams Tempeh\n",
|
|
|
|
| 871 |
"- 4 tablespoons vegan Spread (such as Veganaise)\n",
|
| 872 |
"\n",
|
| 873 |
"#### Instructions:\n",
|
| 874 |
+
"You can find the full step-by-step instructions for making this sandwich at the following link: [Tempeh Sandwiches Recipe](https://eatsmarter.com/recipes/tempeh-sandwiches).\n",
|
|
|
|
|
|
|
|
|
|
|
|
|
| 875 |
"\n",
|
| 876 |
+
"Enjoy your meal! 🌱🥪\n",
|
| 877 |
+
"assistant > In the image, I see a variety of vegan ingredients, including:\n",
|
|
|
|
|
|
|
| 878 |
"\n",
|
| 879 |
"- Cherry tomatoes\n",
|
|
|
|
| 880 |
"- Apples\n",
|
| 881 |
"- Bananas\n",
|
| 882 |
+
"- Lemons\n",
|
|
|
|
|
|
|
| 883 |
"- Lettuce\n",
|
| 884 |
+
"- Kale\n",
|
| 885 |
+
"- Spinach\n",
|
| 886 |
"- Carrots\n",
|
| 887 |
+
"- Leeks\n",
|
| 888 |
+
"- Parsley\n",
|
| 889 |
+
"- Cilantro\n",
|
| 890 |
+
"- Red onions\n",
|
| 891 |
+
"- A jar of pesto (assuming it’s vegan pesto)\n",
|
| 892 |
+
"- A jar of legumes (possibly chickpeas or beans)\n",
|
| 893 |
+
"- Sprouts\n",
|
| 894 |
"- A pumpkin or squash\n",
|
|
|
|
| 895 |
"- Beets\n",
|
|
|
|
| 896 |
"\n",
|
| 897 |
+
"These ingredients provide a great base for many delicious vegan dishes. Would you like me to find a recipe using any of these specific ingredients?\n",
|
| 898 |
+
"assistant > In the second image, the vegan ingredients I can identify are:\n",
|
| 899 |
+
"\n",
|
| 900 |
+
"- **Soy Milk** (Silk brand)\n",
|
| 901 |
+
"- **Mustard** (depending on brand, but typically mustard is vegan)\n",
|
| 902 |
+
"- **Lemon Juice** (assuming the yellow bottle on the door is lemon juice)\n",
|
| 903 |
+
"- **Lettuce** (upper shelf on the door)\n",
|
| 904 |
+
"- **Pickles** or **relish** (top right of the door)\n",
|
| 905 |
+
"\n",
|
| 906 |
+
"These ingredients can contribute to a variety of vegan dishes. Would you like me to find a specific recipe using some of these ingredients?\n",
|
| 907 |
+
"assistant > function\n",
|
| 908 |
+
"\n",
|
| 909 |
"\n",
|
| 910 |
+
"assistant > function\n",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 911 |
"\n",
|
|
|
|
|
|
|
| 912 |
"\n",
|
|
|
|
| 913 |
"assistant > function\n",
|
| 914 |
"\n",
|
| 915 |
"\n",
|
| 916 |
+
"assistant > function\n",
|
| 917 |
"\n",
|
|
|
|
| 918 |
"\n",
|
| 919 |
+
"assistant > Here are several delicious vegan recipes using some of the ingredients from the first image. They pair well together and offer a variety of flavors and textures:\n",
|
| 920 |
"\n",
|
| 921 |
+
"### Recipe 1: Vegan Kale Slaw\n",
|
| 922 |
"#### Ingredients:\n",
|
| 923 |
"- 2 bunches red kale\n",
|
| 924 |
"- 4 radishes\n",
|
| 925 |
"- 1 medium carrot\n",
|
| 926 |
"- 1 pink lady apple\n",
|
| 927 |
"- 1 avocado\n",
|
| 928 |
+
"- 1/2 cup craisins\n",
|
| 929 |
+
"- 1/2 cup almonds\n",
|
| 930 |
+
"- 1/2 cup pumpkin seeds\n",
|
| 931 |
+
"- Dressing:\n",
|
| 932 |
+
" - 3 tablespoons olive oil\n",
|
| 933 |
+
" - 2-3 teaspoons maple syrup (depending on your sweetness level)\n",
|
| 934 |
+
" - 1/2 clove garlic\n",
|
| 935 |
+
" - 1 tablespoon apple cider vinegar\n",
|
| 936 |
+
" - 1-2 tablespoons lemon juice (depending on your sourness level)\n",
|
| 937 |
+
"\n",
|
| 938 |
+
"#### Instructions:\n",
|
| 939 |
+
"Find the full recipe [here](http://glutenfreeifyouplease.com/vegan-kale-slaw/).\n",
|
| 940 |
"\n",
|
| 941 |
+
"### Recipe 2: Vegan Recipe: Raw Detox Soup\n",
|
| 942 |
+
"#### Ingredients:\n",
|
| 943 |
+
"- Half an avocado\n",
|
| 944 |
+
"- Juice of half a lemon\n",
|
| 945 |
"- 1 tablespoon apple cider vinegar\n",
|
| 946 |
+
"- 1-2 teaspoons agave\n",
|
| 947 |
+
"- 1 clove garlic\n",
|
| 948 |
+
"- 1/3 cup broccoli florets\n",
|
| 949 |
+
"- 1/3 cup chopped carrots\n",
|
| 950 |
+
"- 1/4 cup chopped onion\n",
|
| 951 |
+
"- 1/2 tablespoon tamari or Bragg's Liquid Aminos\n",
|
| 952 |
+
"- 1 packed cup kale (or other leafy green)\n",
|
| 953 |
+
"- 1 pinch sea salt\n",
|
| 954 |
+
"- 1/4-1/2 cup water (start with 1/4 cup and add as needed)\n",
|
| 955 |
+
"\n",
|
| 956 |
+
"#### Instructions:\n",
|
| 957 |
+
"Check the complete recipe [here](https://www.mindbodygreen.com/0-10276/vegan-recipe-raw-detox-soup.html).\n",
|
| 958 |
+
"\n",
|
| 959 |
+
"### Recipe 3: Vegan Spinach Wrap\n",
|
| 960 |
+
"#### Ingredients:\n",
|
| 961 |
+
"- 16 ounces vegan cream cheese\n",
|
| 962 |
+
"- 1/2 cup Vidalia onion, minced\n",
|
| 963 |
+
"- 1 teaspoon garlic powder\n",
|
| 964 |
+
"- 1 tablespoon dried oregano\n",
|
| 965 |
+
"- 2 teaspoons dried dill\n",
|
| 966 |
+
"- 1 tablespoon fresh basil, chopped\n",
|
| 967 |
+
"- 1 lb spinach, rinsed well and patted dry\n",
|
| 968 |
+
"- 2 ripe tomatoes (vine)\n",
|
| 969 |
+
"- 2 cups mixed sprouts\n",
|
| 970 |
+
"- 10 whole wheat tortillas\n",
|
| 971 |
"\n",
|
| 972 |
"#### Instructions:\n",
|
| 973 |
+
"Find the full recipe [here](http://www.food.com/recipe/vegan-spinach-wrap-243783).\n",
|
|
|
|
|
|
|
|
|
|
|
|
|
| 974 |
"\n",
|
| 975 |
+
"### Recipe 4: Vegan Beet Loaf\n",
|
| 976 |
+
"#### Ingredients:\n",
|
| 977 |
+
"- 1/2 cup raw organic sunflower seeds, soaked and strained\n",
|
| 978 |
+
"- 1/2 cup raw organic pumpkin seeds, soaked and strained\n",
|
| 979 |
+
"- 1/2 cup raw organic sunflower seeds, ground into flour\n",
|
| 980 |
+
"- 1/2 cup organic hemp seeds, ground into flour\n",
|
| 981 |
+
"- 2-3 beets, peeled and cut into quarters (2 cups cooked)\n",
|
| 982 |
+
"- 1-2 carrots, peeled and cut into smaller pieces (1 cup cooked)\n",
|
| 983 |
+
"- 2-3 garlic cloves, peeled and crushed (optional)\n",
|
| 984 |
+
"- 1 tablespoon psyllium husk\n",
|
| 985 |
+
"- 1 teaspoon fresh thyme, large stems removed\n",
|
| 986 |
+
"- 1/4 teaspoon ground pepper\n",
|
| 987 |
+
"- 1/4 teaspoon dried fine herbs (optional)\n",
|
| 988 |
+
"- 1/2 teaspoon sea or Himalayan salt\n",
|
| 989 |
+
"\n",
|
| 990 |
+
"#### Instructions:\n",
|
| 991 |
+
"Get the full instructions [here](https://www.freshisreal.com/vegan-beet-loaf/).\n",
|
| 992 |
"\n",
|
| 993 |
+
"These recipes should help you make the most of the ingredients you have from the first image! Enjoy your cooking! 🌱\n"
|
| 994 |
]
|
| 995 |
}
|
| 996 |
],
|
|
|
|
| 1008 |
"\n",
|
| 1009 |
"nbdev.nbdev_export()"
|
| 1010 |
]
|
| 1011 |
+
},
|
| 1012 |
+
{
|
| 1013 |
+
"cell_type": "code",
|
| 1014 |
+
"execution_count": null,
|
| 1015 |
+
"metadata": {},
|
| 1016 |
+
"outputs": [],
|
| 1017 |
+
"source": []
|
| 1018 |
}
|
| 1019 |
],
|
| 1020 |
"metadata": {
|
nbs/05_utils.ipynb
CHANGED
|
@@ -46,7 +46,7 @@
|
|
| 46 |
"source": [
|
| 47 |
"#| export\n",
|
| 48 |
"def load_json(file_path):\n",
|
| 49 |
-
" with open(file_path,
|
| 50 |
" return json.load(file)"
|
| 51 |
]
|
| 52 |
},
|
|
|
|
| 46 |
"source": [
|
| 47 |
"#| export\n",
|
| 48 |
"def load_json(file_path):\n",
|
| 49 |
+
" with open(file_path, \"r\") as file:\n",
|
| 50 |
" return json.load(file)"
|
| 51 |
]
|
| 52 |
},
|
requirements.txt
CHANGED
|
@@ -1,10 +1,5 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
openai==0.27.7
|
| 7 |
-
torch==2.0.1
|
| 8 |
-
torchvision==0.15.2
|
| 9 |
-
tqdm==4.65.0
|
| 10 |
-
transformers==4.30.0
|
|
|
|
| 1 |
+
gradio==4.32.2
|
| 2 |
+
gradio_client==0.17.0
|
| 3 |
+
markdown-it-py==3.0.0
|
| 4 |
+
openai==1.30.2
|
| 5 |
+
tqdm==4.66.2
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|