From 4fd5b9de32dab9a7260b9ac3388b4837181ebeb7 Mon Sep 17 00:00:00 2001 From: casey Date: Mon, 30 Dec 2024 11:29:16 +1100 Subject: [PATCH] adding factory --- LLM_Factory.ipynb | 185 ++++++++++++++++++++++++++++++++++++++++++ chatbot_example.ipynb | 70 +++++++++++++++- google_maps.ipynb | 17 ++-- 3 files changed, 257 insertions(+), 15 deletions(-) create mode 100644 LLM_Factory.ipynb diff --git a/LLM_Factory.ipynb b/LLM_Factory.ipynb new file mode 100644 index 0000000..166bf44 --- /dev/null +++ b/LLM_Factory.ipynb @@ -0,0 +1,185 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 46, + "id": "0bf0e410-0031-4983-a868-f2f1253f6947", + "metadata": {}, + "outputs": [], + "source": [ + "from typing import Optional\n", + "from pydantic_settings import BaseSettings\n", + "from functools import lru_cache\n", + "from dotenv import load_dotenv\n", + "import os\n", + "\n", + "\n", + "class LLMProviderSettings(BaseSettings):\n", + " temperature: float = 0.0\n", + " max_tokens: Optional[int] = None\n", + " max_retries: int = 3\n", + "\n", + "class LlamaSettings(LLMProviderSettings):\n", + " api_key: str = \"key\" # required, but not used\n", + " # default_model: str = \"phi3:3.8b\"\n", + " # default_model: str = \"llama3.2:latest\"\n", + " # default_model: str = \"deepseek-coder-v2:latest\"\n", + " # default_model: str = \"gemma2:27b\"\n", + " # default_model: str = \"solar-pro:latest\" # Need to upgrade Ollama\n", + " # default_model: str = \"phi3:14b\"\n", + " default_model: str = \"qwen2:0.5b\" # String validation errors \n", + " \n", + " \n", + " base_url: str = 'http://192.168.20.30:7869/v1'\n", + "\n", + "\n", + "\n", + "\n", + "class Settings(BaseSettings):\n", + " app_name: str = \"GenAI Project Template\"\n", + " # openai: OpenAISettings = OpenAISettings()\n", + " # anthropic: AnthropicSettings = AnthropicSettings()\n", + " llama: LlamaSettings = LlamaSettings()\n", + " \n", + "\n", + "@lru_cache\n", + "def get_settings():\n", + " return Settings()\n" + ] + }, + { + "cell_type": "code", + "execution_count": 47, + "id": "f4993f4b-398e-4ad3-938f-5421677939c4", + "metadata": {}, + "outputs": [ + { + "ename": "InstructorRetryException", + "evalue": "2 validation errors for CompletionModel\nresponse\n Input should be a valid string [type=string_type, input_value={'reasoning': 'To find ou...s) * (rate per shirt).'}, input_type=dict]\n For further information visit https://errors.pydantic.dev/2.10/v/string_type\nreasoning\n Field required [type=missing, input_value={'response': {'reasoning'...odel', 'type': 'object'}, input_type=dict]\n For further information visit https://errors.pydantic.dev/2.10/v/missing", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mValidationError\u001b[0m Traceback (most recent call last)", + "File \u001b[0;32m~/miniconda3/envs/LLMatie/lib/python3.13/site-packages/instructor/retry.py:178\u001b[0m, in \u001b[0;36mretry_sync\u001b[0;34m(func, response_model, args, kwargs, context, max_retries, strict, mode, hooks)\u001b[0m\n\u001b[1;32m 172\u001b[0m kwargs \u001b[38;5;241m=\u001b[39m handle_reask_kwargs(\n\u001b[1;32m 173\u001b[0m kwargs\u001b[38;5;241m=\u001b[39mkwargs,\n\u001b[1;32m 174\u001b[0m mode\u001b[38;5;241m=\u001b[39mmode,\n\u001b[1;32m 175\u001b[0m response\u001b[38;5;241m=\u001b[39mresponse,\n\u001b[1;32m 176\u001b[0m exception\u001b[38;5;241m=\u001b[39me,\n\u001b[1;32m 177\u001b[0m )\n\u001b[0;32m--> 178\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m e\n\u001b[1;32m 179\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m RetryError \u001b[38;5;28;01mas\u001b[39;00m e:\n", + "File \u001b[0;32m~/miniconda3/envs/LLMatie/lib/python3.13/site-packages/instructor/retry.py:161\u001b[0m, in \u001b[0;36mretry_sync\u001b[0;34m(func, response_model, args, kwargs, context, max_retries, strict, mode, hooks)\u001b[0m\n\u001b[1;32m 158\u001b[0m response \u001b[38;5;241m=\u001b[39m update_total_usage(\n\u001b[1;32m 159\u001b[0m response\u001b[38;5;241m=\u001b[39mresponse, total_usage\u001b[38;5;241m=\u001b[39mtotal_usage\n\u001b[1;32m 160\u001b[0m )\n\u001b[0;32m--> 161\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mprocess_response\u001b[49m\u001b[43m(\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;66;43;03m# type: ignore\u001b[39;49;00m\n\u001b[1;32m 162\u001b[0m \u001b[43m \u001b[49m\u001b[43mresponse\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mresponse\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 163\u001b[0m \u001b[43m \u001b[49m\u001b[43mresponse_model\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mresponse_model\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 164\u001b[0m \u001b[43m \u001b[49m\u001b[43mvalidation_context\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mcontext\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 165\u001b[0m \u001b[43m \u001b[49m\u001b[43mstrict\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mstrict\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 166\u001b[0m \u001b[43m \u001b[49m\u001b[43mmode\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mmode\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 167\u001b[0m \u001b[43m \u001b[49m\u001b[43mstream\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mget\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mstream\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43;01mFalse\u001b[39;49;00m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 168\u001b[0m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 169\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m (ValidationError, JSONDecodeError) \u001b[38;5;28;01mas\u001b[39;00m e:\n", + "File \u001b[0;32m~/miniconda3/envs/LLMatie/lib/python3.13/site-packages/instructor/process_response.py:164\u001b[0m, in \u001b[0;36mprocess_response\u001b[0;34m(response, response_model, stream, validation_context, strict, mode)\u001b[0m\n\u001b[1;32m 162\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m model\n\u001b[0;32m--> 164\u001b[0m model \u001b[38;5;241m=\u001b[39m \u001b[43mresponse_model\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mfrom_response\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 165\u001b[0m \u001b[43m \u001b[49m\u001b[43mresponse\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 166\u001b[0m \u001b[43m \u001b[49m\u001b[43mvalidation_context\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mvalidation_context\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 167\u001b[0m \u001b[43m \u001b[49m\u001b[43mstrict\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mstrict\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 168\u001b[0m \u001b[43m \u001b[49m\u001b[43mmode\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mmode\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 169\u001b[0m \u001b[43m\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 171\u001b[0m \u001b[38;5;66;03m# ? This really hints at the fact that we need a better way of\u001b[39;00m\n\u001b[1;32m 172\u001b[0m \u001b[38;5;66;03m# ? attaching usage data and the raw response to the model we return.\u001b[39;00m\n", + "File \u001b[0;32m~/miniconda3/envs/LLMatie/lib/python3.13/site-packages/instructor/function_calls.py:166\u001b[0m, in \u001b[0;36mOpenAISchema.from_response\u001b[0;34m(cls, completion, validation_context, strict, mode)\u001b[0m\n\u001b[1;32m 158\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m mode \u001b[38;5;129;01min\u001b[39;00m {\n\u001b[1;32m 159\u001b[0m Mode\u001b[38;5;241m.\u001b[39mJSON,\n\u001b[1;32m 160\u001b[0m Mode\u001b[38;5;241m.\u001b[39mJSON_SCHEMA,\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 164\u001b[0m Mode\u001b[38;5;241m.\u001b[39mFIREWORKS_JSON,\n\u001b[1;32m 165\u001b[0m }:\n\u001b[0;32m--> 166\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mcls\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mparse_json\u001b[49m\u001b[43m(\u001b[49m\u001b[43mcompletion\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mvalidation_context\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mstrict\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 168\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(\u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mInvalid patch mode: \u001b[39m\u001b[38;5;132;01m{\u001b[39;00mmode\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m\"\u001b[39m)\n", + "File \u001b[0;32m~/miniconda3/envs/LLMatie/lib/python3.13/site-packages/instructor/function_calls.py:384\u001b[0m, in \u001b[0;36mOpenAISchema.parse_json\u001b[0;34m(cls, completion, validation_context, strict)\u001b[0m\n\u001b[1;32m 382\u001b[0m message \u001b[38;5;241m=\u001b[39m extract_json_from_codeblock(message)\n\u001b[0;32m--> 384\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mcls\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mmodel_validate_json\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 385\u001b[0m \u001b[43m \u001b[49m\u001b[43mmessage\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 386\u001b[0m \u001b[43m \u001b[49m\u001b[43mcontext\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mvalidation_context\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 387\u001b[0m \u001b[43m \u001b[49m\u001b[43mstrict\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mstrict\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 388\u001b[0m \u001b[43m\u001b[49m\u001b[43m)\u001b[49m\n", + "File \u001b[0;32m~/miniconda3/envs/LLMatie/lib/python3.13/site-packages/pydantic/main.py:656\u001b[0m, in \u001b[0;36mBaseModel.model_validate_json\u001b[0;34m(cls, json_data, strict, context)\u001b[0m\n\u001b[1;32m 655\u001b[0m __tracebackhide__ \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mTrue\u001b[39;00m\n\u001b[0;32m--> 656\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mcls\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m__pydantic_validator__\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mvalidate_json\u001b[49m\u001b[43m(\u001b[49m\u001b[43mjson_data\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mstrict\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mstrict\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mcontext\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mcontext\u001b[49m\u001b[43m)\u001b[49m\n", + "\u001b[0;31mValidationError\u001b[0m: 2 validation errors for CompletionModel\nresponse\n Input should be a valid string [type=string_type, input_value={'reasoning': 'To find ou...s) * (rate per shirt).'}, input_type=dict]\n For further information visit https://errors.pydantic.dev/2.10/v/string_type\nreasoning\n Field required [type=missing, input_value={'response': {'reasoning'...odel', 'type': 'object'}, input_type=dict]\n For further information visit https://errors.pydantic.dev/2.10/v/missing", + "\nThe above exception was the direct cause of the following exception:\n", + "\u001b[0;31mRetryError\u001b[0m Traceback (most recent call last)", + "File \u001b[0;32m~/miniconda3/envs/LLMatie/lib/python3.13/site-packages/instructor/retry.py:151\u001b[0m, in \u001b[0;36mretry_sync\u001b[0;34m(func, response_model, args, kwargs, context, max_retries, strict, mode, hooks)\u001b[0m\n\u001b[1;32m 150\u001b[0m response \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m\n\u001b[0;32m--> 151\u001b[0m \u001b[43m\u001b[49m\u001b[38;5;28;43;01mfor\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43mattempt\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;129;43;01min\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43mmax_retries\u001b[49m\u001b[43m:\u001b[49m\n\u001b[1;32m 152\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;28;43;01mwith\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43mattempt\u001b[49m\u001b[43m:\u001b[49m\n", + "File \u001b[0;32m~/miniconda3/envs/LLMatie/lib/python3.13/site-packages/tenacity/__init__.py:443\u001b[0m, in \u001b[0;36mBaseRetrying.__iter__\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 442\u001b[0m \u001b[38;5;28;01mwhile\u001b[39;00m \u001b[38;5;28;01mTrue\u001b[39;00m:\n\u001b[0;32m--> 443\u001b[0m do \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43miter\u001b[49m\u001b[43m(\u001b[49m\u001b[43mretry_state\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mretry_state\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 444\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(do, DoAttempt):\n", + "File \u001b[0;32m~/miniconda3/envs/LLMatie/lib/python3.13/site-packages/tenacity/__init__.py:376\u001b[0m, in \u001b[0;36mBaseRetrying.iter\u001b[0;34m(self, retry_state)\u001b[0m\n\u001b[1;32m 375\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m action \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39miter_state\u001b[38;5;241m.\u001b[39mactions:\n\u001b[0;32m--> 376\u001b[0m result \u001b[38;5;241m=\u001b[39m \u001b[43maction\u001b[49m\u001b[43m(\u001b[49m\u001b[43mretry_state\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 377\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m result\n", + "File \u001b[0;32m~/miniconda3/envs/LLMatie/lib/python3.13/site-packages/tenacity/__init__.py:419\u001b[0m, in \u001b[0;36mBaseRetrying._post_stop_check_actions..exc_check\u001b[0;34m(rs)\u001b[0m\n\u001b[1;32m 418\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m retry_exc\u001b[38;5;241m.\u001b[39mreraise()\n\u001b[0;32m--> 419\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m retry_exc \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mfut\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mexception\u001b[39;00m()\n", + "\u001b[0;31mRetryError\u001b[0m: RetryError[]", + "\nThe above exception was the direct cause of the following exception:\n", + "\u001b[0;31mInstructorRetryException\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[47], line 57\u001b[0m\n\u001b[1;32m 48\u001b[0m messages \u001b[38;5;241m=\u001b[39m [\n\u001b[1;32m 49\u001b[0m {\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mrole\u001b[39m\u001b[38;5;124m\"\u001b[39m: \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124msystem\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mcontent\u001b[39m\u001b[38;5;124m\"\u001b[39m: \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mYou are a helpful assistant.\u001b[39m\u001b[38;5;124m\"\u001b[39m},\n\u001b[1;32m 50\u001b[0m {\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 53\u001b[0m },\n\u001b[1;32m 54\u001b[0m ]\n\u001b[1;32m 56\u001b[0m llm \u001b[38;5;241m=\u001b[39m LLMFactory(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mllama\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[0;32m---> 57\u001b[0m completion \u001b[38;5;241m=\u001b[39m \u001b[43mllm\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mcreate_completion\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 58\u001b[0m \u001b[43m \u001b[49m\u001b[43mresponse_model\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mCompletionModel\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 59\u001b[0m \u001b[43m \u001b[49m\u001b[43mmessages\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mmessages\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 60\u001b[0m \u001b[43m\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 61\u001b[0m \u001b[38;5;28;01massert\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(completion, CompletionModel)\n\u001b[1;32m 63\u001b[0m \u001b[38;5;28mprint\u001b[39m(\u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mResponse: \u001b[39m\u001b[38;5;132;01m{\u001b[39;00mcompletion\u001b[38;5;241m.\u001b[39mresponse\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;130;01m\\n\u001b[39;00m\u001b[38;5;124m\"\u001b[39m)\n", + "Cell \u001b[0;32mIn[47], line 39\u001b[0m, in \u001b[0;36mLLMFactory.create_completion\u001b[0;34m(self, response_model, messages, **kwargs)\u001b[0m\n\u001b[1;32m 28\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mcreate_completion\u001b[39m(\n\u001b[1;32m 29\u001b[0m \u001b[38;5;28mself\u001b[39m, response_model: Type[BaseModel], messages: List[Dict[\u001b[38;5;28mstr\u001b[39m, \u001b[38;5;28mstr\u001b[39m]], \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs\n\u001b[1;32m 30\u001b[0m ) \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m>\u001b[39m Any:\n\u001b[1;32m 31\u001b[0m completion_params \u001b[38;5;241m=\u001b[39m {\n\u001b[1;32m 32\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mmodel\u001b[39m\u001b[38;5;124m\"\u001b[39m: kwargs\u001b[38;5;241m.\u001b[39mget(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mmodel\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39msettings\u001b[38;5;241m.\u001b[39mdefault_model),\n\u001b[1;32m 33\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mtemperature\u001b[39m\u001b[38;5;124m\"\u001b[39m: kwargs\u001b[38;5;241m.\u001b[39mget(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mtemperature\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39msettings\u001b[38;5;241m.\u001b[39mtemperature),\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 37\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mmessages\u001b[39m\u001b[38;5;124m\"\u001b[39m: messages,\n\u001b[1;32m 38\u001b[0m }\n\u001b[0;32m---> 39\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mclient\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mchat\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mcompletions\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mcreate\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mcompletion_params\u001b[49m\u001b[43m)\u001b[49m\n", + "File \u001b[0;32m~/miniconda3/envs/LLMatie/lib/python3.13/site-packages/instructor/client.py:176\u001b[0m, in \u001b[0;36mInstructor.create\u001b[0;34m(self, response_model, messages, max_retries, validation_context, context, strict, **kwargs)\u001b[0m\n\u001b[1;32m 164\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mcreate\u001b[39m(\n\u001b[1;32m 165\u001b[0m \u001b[38;5;28mself\u001b[39m,\n\u001b[1;32m 166\u001b[0m response_model: \u001b[38;5;28mtype\u001b[39m[T] \u001b[38;5;241m|\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m,\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 172\u001b[0m \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs: Any,\n\u001b[1;32m 173\u001b[0m ) \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m>\u001b[39m T \u001b[38;5;241m|\u001b[39m Any \u001b[38;5;241m|\u001b[39m Awaitable[T] \u001b[38;5;241m|\u001b[39m Awaitable[Any]:\n\u001b[1;32m 174\u001b[0m kwargs \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mhandle_kwargs(kwargs)\n\u001b[0;32m--> 176\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mcreate_fn\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 177\u001b[0m \u001b[43m \u001b[49m\u001b[43mresponse_model\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mresponse_model\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 178\u001b[0m \u001b[43m \u001b[49m\u001b[43mmessages\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mmessages\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 179\u001b[0m \u001b[43m \u001b[49m\u001b[43mmax_retries\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mmax_retries\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 180\u001b[0m \u001b[43m \u001b[49m\u001b[43mvalidation_context\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mvalidation_context\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 181\u001b[0m \u001b[43m \u001b[49m\u001b[43mcontext\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mcontext\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 182\u001b[0m \u001b[43m \u001b[49m\u001b[43mstrict\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mstrict\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 183\u001b[0m \u001b[43m \u001b[49m\u001b[43mhooks\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mhooks\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 184\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 185\u001b[0m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m\n", + "File \u001b[0;32m~/miniconda3/envs/LLMatie/lib/python3.13/site-packages/instructor/patch.py:193\u001b[0m, in \u001b[0;36mpatch..new_create_sync\u001b[0;34m(response_model, validation_context, context, max_retries, strict, hooks, *args, **kwargs)\u001b[0m\n\u001b[1;32m 187\u001b[0m response_model, new_kwargs \u001b[38;5;241m=\u001b[39m handle_response_model(\n\u001b[1;32m 188\u001b[0m response_model\u001b[38;5;241m=\u001b[39mresponse_model, mode\u001b[38;5;241m=\u001b[39mmode, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs\n\u001b[1;32m 189\u001b[0m ) \u001b[38;5;66;03m# type: ignore\u001b[39;00m\n\u001b[1;32m 191\u001b[0m new_kwargs \u001b[38;5;241m=\u001b[39m handle_templating(new_kwargs, context)\n\u001b[0;32m--> 193\u001b[0m response \u001b[38;5;241m=\u001b[39m \u001b[43mretry_sync\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 194\u001b[0m \u001b[43m \u001b[49m\u001b[43mfunc\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mfunc\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;66;43;03m# type: ignore\u001b[39;49;00m\n\u001b[1;32m 195\u001b[0m \u001b[43m \u001b[49m\u001b[43mresponse_model\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mresponse_model\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 196\u001b[0m \u001b[43m \u001b[49m\u001b[43mcontext\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mcontext\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 197\u001b[0m \u001b[43m \u001b[49m\u001b[43mmax_retries\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mmax_retries\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 198\u001b[0m \u001b[43m \u001b[49m\u001b[43margs\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43margs\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 199\u001b[0m \u001b[43m \u001b[49m\u001b[43mhooks\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mhooks\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 200\u001b[0m \u001b[43m \u001b[49m\u001b[43mstrict\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mstrict\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 201\u001b[0m \u001b[43m \u001b[49m\u001b[43mkwargs\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mnew_kwargs\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 202\u001b[0m \u001b[43m \u001b[49m\u001b[43mmode\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mmode\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 203\u001b[0m \u001b[43m\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 204\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m response\n", + "File \u001b[0;32m~/miniconda3/envs/LLMatie/lib/python3.13/site-packages/instructor/retry.py:181\u001b[0m, in \u001b[0;36mretry_sync\u001b[0;34m(func, response_model, args, kwargs, context, max_retries, strict, mode, hooks)\u001b[0m\n\u001b[1;32m 179\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m RetryError \u001b[38;5;28;01mas\u001b[39;00m e:\n\u001b[1;32m 180\u001b[0m logger\u001b[38;5;241m.\u001b[39mdebug(\u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mRetry error: \u001b[39m\u001b[38;5;132;01m{\u001b[39;00me\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m\"\u001b[39m)\n\u001b[0;32m--> 181\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m InstructorRetryException(\n\u001b[1;32m 182\u001b[0m e\u001b[38;5;241m.\u001b[39mlast_attempt\u001b[38;5;241m.\u001b[39m_exception,\n\u001b[1;32m 183\u001b[0m last_completion\u001b[38;5;241m=\u001b[39mresponse,\n\u001b[1;32m 184\u001b[0m n_attempts\u001b[38;5;241m=\u001b[39mattempt\u001b[38;5;241m.\u001b[39mretry_state\u001b[38;5;241m.\u001b[39mattempt_number,\n\u001b[1;32m 185\u001b[0m \u001b[38;5;66;03m#! deprecate messages soon\u001b[39;00m\n\u001b[1;32m 186\u001b[0m messages\u001b[38;5;241m=\u001b[39mkwargs\u001b[38;5;241m.\u001b[39mget(\n\u001b[1;32m 187\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mmessages\u001b[39m\u001b[38;5;124m\"\u001b[39m, kwargs\u001b[38;5;241m.\u001b[39mget(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mcontents\u001b[39m\u001b[38;5;124m\"\u001b[39m, kwargs\u001b[38;5;241m.\u001b[39mget(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mchat_history\u001b[39m\u001b[38;5;124m\"\u001b[39m, []))\n\u001b[1;32m 188\u001b[0m ),\n\u001b[1;32m 189\u001b[0m create_kwargs\u001b[38;5;241m=\u001b[39mkwargs,\n\u001b[1;32m 190\u001b[0m total_usage\u001b[38;5;241m=\u001b[39mtotal_usage,\n\u001b[1;32m 191\u001b[0m ) \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01me\u001b[39;00m\n", + "\u001b[0;31mInstructorRetryException\u001b[0m: 2 validation errors for CompletionModel\nresponse\n Input should be a valid string [type=string_type, input_value={'reasoning': 'To find ou...s) * (rate per shirt).'}, input_type=dict]\n For further information visit https://errors.pydantic.dev/2.10/v/string_type\nreasoning\n Field required [type=missing, input_value={'response': {'reasoning'...odel', 'type': 'object'}, input_type=dict]\n For further information visit https://errors.pydantic.dev/2.10/v/missing" + ] + } + ], + "source": [ + "from typing import Any, Dict, List, Type\n", + "\n", + "import instructor\n", + "# from anthropic import Anthropic\n", + "# from config.settings import get_settings\n", + "from openai import OpenAI\n", + "from pydantic import BaseModel, Field\n", + "\n", + "class LLMFactory:\n", + " def __init__(self, provider: str):\n", + " self.provider = provider\n", + " self.settings = getattr(get_settings(), provider)\n", + " self.client = self._initialize_client()\n", + "\n", + " def _initialize_client(self) -> Any:\n", + " client_initializers = {\n", + " \"llama\": lambda s: instructor.from_openai(\n", + " OpenAI(base_url=s.base_url, api_key=s.api_key),\n", + " mode=instructor.Mode.JSON,\n", + " ),\n", + " }\n", + "\n", + " initializer = client_initializers.get(self.provider)\n", + " if initializer:\n", + " return initializer(self.settings)\n", + " raise ValueError(f\"Unsupported LLM provider: {self.provider}\")\n", + "\n", + " def create_completion(\n", + " self, response_model: Type[BaseModel], messages: List[Dict[str, str]], **kwargs\n", + " ) -> Any:\n", + " completion_params = {\n", + " \"model\": kwargs.get(\"model\", self.settings.default_model),\n", + " \"temperature\": kwargs.get(\"temperature\", self.settings.temperature),\n", + " \"max_retries\": kwargs.get(\"max_retries\", self.settings.max_retries),\n", + " \"max_tokens\": kwargs.get(\"max_tokens\", self.settings.max_tokens),\n", + " \"response_model\": response_model,\n", + " \"messages\": messages,\n", + " }\n", + " return self.client.chat.completions.create(**completion_params)\n", + "\n", + "\n", + "if __name__ == \"__main__\":\n", + "\n", + " class CompletionModel(BaseModel):\n", + " response: str = Field(description=\"Your response to the user.\")\n", + " reasoning: str = Field(description=\"Explain your reasoning for the response.\")\n", + "\n", + " messages = [\n", + " {\"role\": \"system\", \"content\": \"You are a helpful assistant.\"},\n", + " {\n", + " \"role\": \"user\",\n", + " \"content\": \"If it takes 2 hours to dry 1 shirt out in the sun, how long will it take to dry 5 shirts?\",\n", + " },\n", + " ]\n", + "\n", + " llm = LLMFactory(\"llama\")\n", + " completion = llm.create_completion(\n", + " response_model=CompletionModel,\n", + " messages=messages,\n", + " )\n", + " assert isinstance(completion, CompletionModel)\n", + "\n", + " print(f\"Response: {completion.response}\\n\")\n", + " print(f\"Reasoning: {completion.reasoning}\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fa7ea636-7abe-4dc4-9665-1eb9bc4fde17", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.13.1" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/chatbot_example.ipynb b/chatbot_example.ipynb index dede16f..274a7a0 100644 --- a/chatbot_example.ipynb +++ b/chatbot_example.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": 26, + "execution_count": 2, "id": "7acc51ac-8514-4e77-99d6-cfe31e74c2f1", "metadata": {}, "outputs": [], @@ -52,7 +52,7 @@ }, { "cell_type": "code", - "execution_count": 49, + "execution_count": 3, "id": "90ec821c-34ef-447d-a822-eccd25d694a8", "metadata": {}, "outputs": [ @@ -66,9 +66,13 @@ "\n", " \"function\": \"get_local_weather_update\",\n", "\n", - " \"args\": [\"Australia\"],\n", + " \"args\": [\"Australia\", \"Northern Territory\"],\n", "\n", - " \"ai_notes\": \"This function retrieves current localized weather conditions for Uluru, Australia. It likely queries a database or uses an API to fetch real-time data.\"\n", + " \"ai_notes\": {\n", + "\n", + " \"clarification\": \"The function is called with the country and state parameters for Uluru, ensuring that local weather conditions are accurately represented.\"\n", + "\n", + " }\n", "\n", "}\n", "\n", @@ -112,6 +116,64 @@ "print(response.choices[0].message.content)" ] }, + { + "cell_type": "code", + "execution_count": 9, + "id": "c8cc674d-21b3-4c30-8239-b0368fa21087", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "```json\n", + "\n", + "{\n", + "\n", + " \"business_type\": \"bar/restaurant\",\n", + " \n", + " \"location\": \"near Uluru, Alice Springs region in Northern Territory of Australia.\",\n", + " \n", + " \"ai_notes\": \"Uluru is a popular tourist destination; suitable options for dining might require travel from the immediate area or specific accommodations with such amenities.\"\n", + "\n", + "} \n", + "\n", + "```\n" + ] + } + ], + "source": [ + "# adding ollama\n", + "client = openai.OpenAI(\n", + " base_url = 'http://192.168.20.30:7869/v1',\n", + " api_key='ollama', # required, but unused\n", + ")\n", + "model=\"phi3:3.8b\"\n", + "\n", + "system = \"\"\"You are a helpful assistent, that only comunicates using JSON files.\n", + "The expected output from you has to be: \n", + " {\n", + " \"business_type\": {type},\n", + " \"location\": {location},\n", + " \"ai_notes\": {explanation}\n", + " }\n", + "\n", + "Limit the ai_notes to 200 characters or less.\n", + "Use the folowing text to inform your response:\n", + "\"\"\"\n", + "user = \"pizza and beers near uluru?\"\n", + "\n", + "\n", + "response = client.chat.completions.create(\n", + " model=model,\n", + " messages=[\n", + " {\"role\": \"system\", \"content\": system },\n", + " {\"role\": \"user\", \"content\": user},\n", + " ]\n", + ")\n", + "print(response.choices[0].message.content)" + ] + }, { "cell_type": "code", "execution_count": null, diff --git a/google_maps.ipynb b/google_maps.ipynb index 7545356..2cece18 100644 --- a/google_maps.ipynb +++ b/google_maps.ipynb @@ -15,20 +15,15 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 2, "id": "d33dd2cd-1f38-48eb-b576-fabbcca22bb1", "metadata": {}, "outputs": [ { - "ename": "Exception", - "evalue": "Error: 400 - {\n \"error\": {\n \"code\": 400,\n \"message\": \"Request contains an invalid argument.\",\n \"status\": \"INVALID_ARGUMENT\",\n \"details\": [\n {\n \"@type\": \"type.googleapis.com/google.rpc.BadRequest\",\n \"fieldViolations\": [\n {\n \"field\": \"places.displayName,places.formattedAddress,places.priceLevel,places.opening_hours.open_now\",\n \"description\": \"Error expanding 'fields' parameter. Cannot find matching fields for path 'places.opening_hours.open_now'.\"\n }\n ]\n }\n ]\n }\n}\n", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mException\u001b[0m Traceback (most recent call last)", - "Cell \u001b[0;32mIn[7], line 24\u001b[0m\n\u001b[1;32m 22\u001b[0m API_KEY \u001b[38;5;241m=\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mAIzaSyAkUb_CaNH5kO1yihOeB7QUlFBm5qoBw-s\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 23\u001b[0m text_query \u001b[38;5;241m=\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mkebabs near 102 boldrewood parade\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m---> 24\u001b[0m result \u001b[38;5;241m=\u001b[39m \u001b[43msearch_places\u001b[49m\u001b[43m(\u001b[49m\u001b[43mAPI_KEY\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mtext_query\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 25\u001b[0m \u001b[38;5;28mprint\u001b[39m(result)\n", - "Cell \u001b[0;32mIn[7], line 19\u001b[0m, in \u001b[0;36msearch_places\u001b[0;34m(api_key, text_query)\u001b[0m\n\u001b[1;32m 17\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m response\u001b[38;5;241m.\u001b[39mjson()\n\u001b[1;32m 18\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[0;32m---> 19\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mException\u001b[39;00m(\u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mError: \u001b[39m\u001b[38;5;132;01m{\u001b[39;00mresponse\u001b[38;5;241m.\u001b[39mstatus_code\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m - \u001b[39m\u001b[38;5;132;01m{\u001b[39;00mresponse\u001b[38;5;241m.\u001b[39mtext\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m\"\u001b[39m)\n", - "\u001b[0;31mException\u001b[0m: Error: 400 - {\n \"error\": {\n \"code\": 400,\n \"message\": \"Request contains an invalid argument.\",\n \"status\": \"INVALID_ARGUMENT\",\n \"details\": [\n {\n \"@type\": \"type.googleapis.com/google.rpc.BadRequest\",\n \"fieldViolations\": [\n {\n \"field\": \"places.displayName,places.formattedAddress,places.priceLevel,places.opening_hours.open_now\",\n \"description\": \"Error expanding 'fields' parameter. Cannot find matching fields for path 'places.opening_hours.open_now'.\"\n }\n ]\n }\n ]\n }\n}\n" + "name": "stdout", + "output_type": "stream", + "text": [ + "{'places': [{'formattedAddress': '766A Plenty Rd, Reservoir VIC 3073, Australia', 'displayName': {'text': 'Melbourne Kebabs', 'languageCode': 'en'}}, {'formattedAddress': '939 High St, Reservoir VIC 3073, Australia', 'priceLevel': 'PRICE_LEVEL_INEXPENSIVE', 'displayName': {'text': 'Five Star Kebabs', 'languageCode': 'en'}}, {'formattedAddress': 'Summerhill Shopping Centre, 3/850 Plenty Rd, Reservoir VIC 3073, Australia', 'displayName': {'text': \"Steffey's Pizza & Kebab\", 'languageCode': 'en'}}, {'formattedAddress': '701 Plenty Rd, Reservoir VIC 3073, Australia', 'displayName': {'text': 'K Lish Spuds', 'languageCode': 'en'}}, {'formattedAddress': '258 Broadway, Reservoir VIC 3073, Australia', 'priceLevel': 'PRICE_LEVEL_INEXPENSIVE', 'displayName': {'text': 'Broadway Kebabs', 'languageCode': 'en'}}, {'formattedAddress': '42 Edwardes St, Reservoir VIC 3073, Australia', 'displayName': {'text': 'Tasty Slice Pizza & Kebab', 'languageCode': 'en'}}, {'formattedAddress': '299 Spring St, Reservoir VIC 3073, Australia', 'priceLevel': 'PRICE_LEVEL_MODERATE', 'displayName': {'text': 'Garlic Boyz Kebabs (Reservoir)', 'languageCode': 'en'}}, {'formattedAddress': 'beside metro petroleum station, 139 Spring St, Reservoir VIC 3073, Australia', 'displayName': {'text': 'Kebab At Reservoir', 'languageCode': 'en'}}, {'formattedAddress': '25 Massey Ave, Reservoir VIC 3073, Australia', 'displayName': {'text': 'Adana Sofra', 'languageCode': 'en'}}, {'formattedAddress': 'Latrobe University, Kingsbury Drive, Shop 6 The Agora, Bundoora VIC 3083, Australia', 'displayName': {'text': \"Charlie's Kebabs\", 'languageCode': 'en'}}, {'formattedAddress': '257 Plenty Rd, Preston VIC 3072, Australia', 'priceLevel': 'PRICE_LEVEL_INEXPENSIVE', 'displayName': {'text': 'Sam’s Kebabworx', 'languageCode': 'en'}}, {'formattedAddress': '299 Spring St, Reservoir VIC 3073, Australia', 'displayName': {'text': 'Cheesy Bite Pizza & Kebab - Reservoir', 'languageCode': 'en'}}, {'formattedAddress': 'Level G, 8/58 Mahoneys Rd, Thomastown VIC 3074, Australia', 'displayName': {'text': 'Kebab Crew Thomastown', 'languageCode': 'en'}}, {'formattedAddress': '415-417 Plenty Rd, Preston VIC 3072, Australia', 'displayName': {'text': 'Preston Kebabs', 'languageCode': 'en'}}, {'formattedAddress': '101 Bell St, Preston VIC 3072, Australia', 'priceLevel': 'PRICE_LEVEL_INEXPENSIVE', 'displayName': {'text': 'Ozzie Kebabs', 'languageCode': 'en'}}, {'formattedAddress': '10 Copernicus Cres, Bundoora VIC 3083, Australia', 'displayName': {'text': 'Kebab Centre', 'languageCode': 'en'}}, {'formattedAddress': '265 High St, Thomastown VIC 3074, Australia', 'priceLevel': 'PRICE_LEVEL_MODERATE', 'displayName': {'text': 'Melbourne Kebabs & Grill', 'languageCode': 'en'}}, {'formattedAddress': '2/50 Murray Rd, Preston VIC 3072, Australia', 'displayName': {'text': 'My Kebabz', 'languageCode': 'en'}}, {'formattedAddress': 'Shop 4/13 Edgars Rd, Thomastown VIC 3074, Australia', 'priceLevel': 'PRICE_LEVEL_INEXPENSIVE', 'displayName': {'text': 'Kebab 66 Thomastown', 'languageCode': 'en'}}, {'formattedAddress': '434 Bell St, Preston VIC 3072, Australia', 'priceLevel': 'PRICE_LEVEL_INEXPENSIVE', 'displayName': {'text': \"Haci's Kebabs\", 'languageCode': 'en'}}]}\n" ] } ], @@ -40,7 +35,7 @@ " headers = {\n", " \"Content-Type\": \"application/json\",\n", " \"X-Goog-Api-Key\": api_key,\n", - " \"X-Goog-FieldMask\": \"places.displayName,places.formattedAddress,places.priceLevel,places.currentOpeningHours\" #, places.servesBeer\"\n", + " \"X-Goog-FieldMask\": \"places.displayName,places.formattedAddress,places.priceLevel\" #,places.currentOpeningHours\" #, places.servesBeer\"\n", " }\n", " data = {\n", " \"textQuery\": text_query\n",