# embeddings_queue

created_at: 2024-07-28 18:59:18
topic: persistent://default/default/4bfc3c11-fb71-4cc9-8c12-01ed076a0e01
id: 195b09b6-d73d-4700-857a-6f4437a02ab3
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/How_to_use_guardrails.ipynb", "title": "How to use guardrails", "tokens": 3850, "retrieve_doc": true, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"195b09b6-d73d-4700-857a-6f4437a02ab3\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_use_guardrails.ipynb\", \"title\": \"How to use guardrails\", \"tokens\": 3850, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"a231c185-0dcb-4549-b2dc-bfa4a7bee89b\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_use_guardrails.ipynb\", \"title\": \"How to use guardrails\", \"tokens\": 3850, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"337c350bcca7d75854758eb0cad65acdf3e435a6ccea5bdebc39c067aeee844b\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"00872e91-e4a6-464a-a756-4bca21c924f9\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_use_guardrails.ipynb\", \"title\": \"How to use guardrails\", \"tokens\": 3850, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"36ee9026eab3e5564534cebb660e84bccd878465ee688370d4ae212501105f70\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"446b8cc1-ae71-4365-953e-e9262ad921f5\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"01d5271694fc3c539a2161ccddec0c0bfd6a285d726e60280e6bb0578aa7bac3\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 1767, \"end_char_idx\": 5400, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "a231c185-0dcb-4549-b2dc-bfa4a7bee89b", "doc_id": "a231c185-0dcb-4549-b2dc-bfa4a7bee89b", "ref_doc_id": "a231c185-0dcb-4549-b2dc-bfa4a7bee89b", "chroma:document": "- **Jailbreaking:** Detect when a user is trying to hijack the LLM and override its prompting.\n- **Prompt injection:** Pick up instances of prompt injection where users try to hide malicious code that will be executed in any downstream functions the LLM executes. \n\nIn all of these they act as a preventative control, running either before or in parallel with the LLM, and triggering your application to behave differently if one of these criteria are met.\n\n### Designing a guardrail\n\nWhen designing guardrails it is important to consider the trade-off between **accuracy**, **latency** and **cost**, where you try to achieve maximum accuracy for the least impact to your bottom line and the user's experience. \n\nWe'll begin with a simple **topical guardrail** which aims to detect off-topic questions and prevent the LLM from answering if triggered. This guardrail consists of a simple prompt and uses `gpt-4o-mini`, maximising latency/cost holding a good enough accuracy, but if we wanted to optimize further we could consider:\n- **Accuracy:** You could consider fine-tuning `gpt-4o-mini` or few-shot examples to increase the accuracy. RAG can also be effective if you have a corpus of information that can help determine whether a piece of content is allowed or not.\n- **Latency/Cost:** You could try fine-tuning smaller models, such as `babbage-002` or open-source offerings like Llama, which can perform quite well when given enough training examples. When using open-source offerings you can also tune the machines you are using for inference to maximize either cost or latency reduction.\n\nThis simple guardrail aims to ensure the LLM only answers to a predefined set of topics, and responds to out-of-bounds queries with a canned message.\n\n### Embrace async\n\nA common design to minimize latency is to send your guardrails asynchronously along with your main LLM call. If your guardrails get triggered you send back their response, otherwise send back the LLM response.\n\nWe'll use this approach, creating an `execute_chat_with_guardrails` function that will run our LLM's `get_chat_response` and the `topical_guardrail` guardrail in parallel, and return the LLM response only if the guardrail returns `allowed`.\n\n### Limitations\n\nYou should always consider the limitations of guardrails when developing your design. A few of the key ones to be aware of are:\n- When using LLMs as a guardrail, be aware that they have the same vulnerabilities as your base LLM call itself. For example, a **prompt injection** attempt could be successful in evading both your guardrail and your actual LLM call.\n- As conversations get longer, LLMs are more susceptible to **jailbreaking** as your instructions become diluted by the extra text.\n- Guardrails can harm the user experience if you make them overly restrictive to compensate for the issues noted above. This manifests as **over-refusals**, where your guardrails reject innocuous user requests because there are similarities with prompt injection or jailbreaking attempts.\n\n### Mitigations\n\nIf you can combine guardrails with rules-based or more traditional machine learning models for detection this can mitigate some of these risks. We've also seen customers have guardrails that only ever consider the latest message, to alleviate the risks of the model being confused by a long conversation.\n\nWe would also recommend doing a gradual roll-out with active monitoring of conversations so you can pick up instances of prompt injection or jailbreaking, and either add more guardrails to cover these new types of behaviour, or include them as training examples to your existing guardrails."}


created_at: 2024-07-28 18:59:18
topic: persistent://default/default/4bfc3c11-fb71-4cc9-8c12-01ed076a0e01
id: 446b8cc1-ae71-4365-953e-e9262ad921f5
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/How_to_use_guardrails.ipynb", "title": "How to use guardrails", "tokens": 3850, "retrieve_doc": true, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"446b8cc1-ae71-4365-953e-e9262ad921f5\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_use_guardrails.ipynb\", \"title\": \"How to use guardrails\", \"tokens\": 3850, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"a231c185-0dcb-4549-b2dc-bfa4a7bee89b\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_use_guardrails.ipynb\", \"title\": \"How to use guardrails\", \"tokens\": 3850, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"337c350bcca7d75854758eb0cad65acdf3e435a6ccea5bdebc39c067aeee844b\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"195b09b6-d73d-4700-857a-6f4437a02ab3\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_use_guardrails.ipynb\", \"title\": \"How to use guardrails\", \"tokens\": 3850, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"be21df79ed339a4629b380a28f4599945e2c06044d39b9591439664a0ca44d0c\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"b68cc8ec-c52c-46c5-a23b-c497376870b2\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"c137f74e2e1f1c0e6efe9c3dcddcf768eacee5a4b4a986a276e7d955329100e2\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 3514, \"end_char_idx\": 6613, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "a231c185-0dcb-4549-b2dc-bfa4a7bee89b", "doc_id": "a231c185-0dcb-4549-b2dc-bfa4a7bee89b", "ref_doc_id": "a231c185-0dcb-4549-b2dc-bfa4a7bee89b", "chroma:document": "### Embrace async\n\nA common design to minimize latency is to send your guardrails asynchronously along with your main LLM call. If your guardrails get triggered you send back their response, otherwise send back the LLM response.\n\nWe'll use this approach, creating an `execute_chat_with_guardrails` function that will run our LLM's `get_chat_response` and the `topical_guardrail` guardrail in parallel, and return the LLM response only if the guardrail returns `allowed`.\n\n### Limitations\n\nYou should always consider the limitations of guardrails when developing your design. A few of the key ones to be aware of are:\n- When using LLMs as a guardrail, be aware that they have the same vulnerabilities as your base LLM call itself. For example, a **prompt injection** attempt could be successful in evading both your guardrail and your actual LLM call.\n- As conversations get longer, LLMs are more susceptible to **jailbreaking** as your instructions become diluted by the extra text.\n- Guardrails can harm the user experience if you make them overly restrictive to compensate for the issues noted above. This manifests as **over-refusals**, where your guardrails reject innocuous user requests because there are similarities with prompt injection or jailbreaking attempts.\n\n### Mitigations\n\nIf you can combine guardrails with rules-based or more traditional machine learning models for detection this can mitigate some of these risks. We've also seen customers have guardrails that only ever consider the latest message, to alleviate the risks of the model being confused by a long conversation.\n\nWe would also recommend doing a gradual roll-out with active monitoring of conversations so you can pick up instances of prompt injection or jailbreaking, and either add more guardrails to cover these new types of behaviour, or include them as training examples to your existing guardrails.\n\n\n```python\nsystem_prompt = \"You are a helpful assistant.\"\n\nbad_request = \"I want to talk about horses\"\ngood_request = \"What are the best breeds of dog for people that like cats?\"\n```\n\n\n```python\nimport asyncio\n\n\nasync def get_chat_response(user_request):\n    print(\"Getting LLM response\")\n    messages = [\n        {\"role\": \"system\", \"content\": system_prompt},\n        {\"role\": \"user\", \"content\": user_request},\n    ]\n    response = openai.chat.completions.create(\n        model=GPT_MODEL, messages=messages, temperature=0.5\n    )\n    print(\"Got LLM response\")\n\n    return response.choices[0].message.content\n\n\nasync def topical_guardrail(user_request):\n    print(\"Checking topical guardrail\")\n    messages = [\n        {\n            \"role\": \"system\",\n            \"content\": \"Your role is to assess whether the user question is allowed or not. The allowed topics are cats and dogs. If the topic is allowed, say 'allowed' otherwise say 'not_allowed'\",\n        },\n        {\"role\": \"user\", \"content\": user_request},\n    ]\n    response = openai.chat.completions.create(\n        model=GPT_MODEL, messages=messages, temperature=0\n    )\n\n    print(\"Got guardrail response\")\n    return response.choices[0].message.content"}


created_at: 2024-07-28 18:59:18
topic: persistent://default/default/4bfc3c11-fb71-4cc9-8c12-01ed076a0e01
id: b68cc8ec-c52c-46c5-a23b-c497376870b2
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/How_to_use_guardrails.ipynb", "title": "How to use guardrails", "tokens": 3850, "retrieve_doc": true, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"b68cc8ec-c52c-46c5-a23b-c497376870b2\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_use_guardrails.ipynb\", \"title\": \"How to use guardrails\", \"tokens\": 3850, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"a231c185-0dcb-4549-b2dc-bfa4a7bee89b\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_use_guardrails.ipynb\", \"title\": \"How to use guardrails\", \"tokens\": 3850, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"337c350bcca7d75854758eb0cad65acdf3e435a6ccea5bdebc39c067aeee844b\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"446b8cc1-ae71-4365-953e-e9262ad921f5\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_use_guardrails.ipynb\", \"title\": \"How to use guardrails\", \"tokens\": 3850, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"a1dcc370bc826a97359413dccd43974ea9d58fb48bf9cc3d3dd1acf99cedfe6a\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"9f4640d7-778a-43f2-a15a-418549aaea86\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"a992f8e782c8497123bc919d39f4f2136c90c581ce80031cad2dd46a8e96fda6\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 4787, \"end_char_idx\": 7543, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "a231c185-0dcb-4549-b2dc-bfa4a7bee89b", "doc_id": "a231c185-0dcb-4549-b2dc-bfa4a7bee89b", "ref_doc_id": "a231c185-0dcb-4549-b2dc-bfa4a7bee89b", "chroma:document": "### Mitigations\n\nIf you can combine guardrails with rules-based or more traditional machine learning models for detection this can mitigate some of these risks. We've also seen customers have guardrails that only ever consider the latest message, to alleviate the risks of the model being confused by a long conversation.\n\nWe would also recommend doing a gradual roll-out with active monitoring of conversations so you can pick up instances of prompt injection or jailbreaking, and either add more guardrails to cover these new types of behaviour, or include them as training examples to your existing guardrails.\n\n\n```python\nsystem_prompt = \"You are a helpful assistant.\"\n\nbad_request = \"I want to talk about horses\"\ngood_request = \"What are the best breeds of dog for people that like cats?\"\n```\n\n\n```python\nimport asyncio\n\n\nasync def get_chat_response(user_request):\n    print(\"Getting LLM response\")\n    messages = [\n        {\"role\": \"system\", \"content\": system_prompt},\n        {\"role\": \"user\", \"content\": user_request},\n    ]\n    response = openai.chat.completions.create(\n        model=GPT_MODEL, messages=messages, temperature=0.5\n    )\n    print(\"Got LLM response\")\n\n    return response.choices[0].message.content\n\n\nasync def topical_guardrail(user_request):\n    print(\"Checking topical guardrail\")\n    messages = [\n        {\n            \"role\": \"system\",\n            \"content\": \"Your role is to assess whether the user question is allowed or not. The allowed topics are cats and dogs. If the topic is allowed, say 'allowed' otherwise say 'not_allowed'\",\n        },\n        {\"role\": \"user\", \"content\": user_request},\n    ]\n    response = openai.chat.completions.create(\n        model=GPT_MODEL, messages=messages, temperature=0\n    )\n\n    print(\"Got guardrail response\")\n    return response.choices[0].message.content\n\n\nasync def execute_chat_with_guardrail(user_request):\n    topical_guardrail_task = asyncio.create_task(topical_guardrail(user_request))\n    chat_task = asyncio.create_task(get_chat_response(user_request))\n\n    while True:\n        done, _ = await asyncio.wait(\n            [topical_guardrail_task, chat_task], return_when=asyncio.FIRST_COMPLETED\n        )\n        if topical_guardrail_task in done:\n            guardrail_response = topical_guardrail_task.result()\n            if guardrail_response == \"not_allowed\":\n                chat_task.cancel()\n                print(\"Topical guardrail triggered\")\n                return \"I can only talk about cats and dogs, the best animals that ever lived.\"\n            elif chat_task in done:\n                chat_response = chat_task.result()\n                return chat_response\n        else:\n            await asyncio.sleep(0.1)  # sleep for a bit before checking the tasks again\n```"}


created_at: 2024-07-28 18:59:18
topic: persistent://default/default/4bfc3c11-fb71-4cc9-8c12-01ed076a0e01
id: 9f4640d7-778a-43f2-a15a-418549aaea86
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/How_to_use_guardrails.ipynb", "title": "How to use guardrails", "tokens": 3850, "retrieve_doc": true, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"9f4640d7-778a-43f2-a15a-418549aaea86\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_use_guardrails.ipynb\", \"title\": \"How to use guardrails\", \"tokens\": 3850, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"a231c185-0dcb-4549-b2dc-bfa4a7bee89b\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_use_guardrails.ipynb\", \"title\": \"How to use guardrails\", \"tokens\": 3850, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"337c350bcca7d75854758eb0cad65acdf3e435a6ccea5bdebc39c067aeee844b\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"b68cc8ec-c52c-46c5-a23b-c497376870b2\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_use_guardrails.ipynb\", \"title\": \"How to use guardrails\", \"tokens\": 3850, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"29b0d615f6c5c8da04a7c03058e855688d9fd0553e2043de08779222a7c1d7c3\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"4b6689e1-ffa3-470b-8b60-60968749d34a\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"9e19fcc41be81fb1393d3127fe432725d65d4c932c0d8ab4711c3128c69285f2\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 6012, \"end_char_idx\": 9566, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "a231c185-0dcb-4549-b2dc-bfa4a7bee89b", "doc_id": "a231c185-0dcb-4549-b2dc-bfa4a7bee89b", "ref_doc_id": "a231c185-0dcb-4549-b2dc-bfa4a7bee89b", "chroma:document": "async def topical_guardrail(user_request):\n    print(\"Checking topical guardrail\")\n    messages = [\n        {\n            \"role\": \"system\",\n            \"content\": \"Your role is to assess whether the user question is allowed or not. The allowed topics are cats and dogs. If the topic is allowed, say 'allowed' otherwise say 'not_allowed'\",\n        },\n        {\"role\": \"user\", \"content\": user_request},\n    ]\n    response = openai.chat.completions.create(\n        model=GPT_MODEL, messages=messages, temperature=0\n    )\n\n    print(\"Got guardrail response\")\n    return response.choices[0].message.content\n\n\nasync def execute_chat_with_guardrail(user_request):\n    topical_guardrail_task = asyncio.create_task(topical_guardrail(user_request))\n    chat_task = asyncio.create_task(get_chat_response(user_request))\n\n    while True:\n        done, _ = await asyncio.wait(\n            [topical_guardrail_task, chat_task], return_when=asyncio.FIRST_COMPLETED\n        )\n        if topical_guardrail_task in done:\n            guardrail_response = topical_guardrail_task.result()\n            if guardrail_response == \"not_allowed\":\n                chat_task.cancel()\n                print(\"Topical guardrail triggered\")\n                return \"I can only talk about cats and dogs, the best animals that ever lived.\"\n            elif chat_task in done:\n                chat_response = chat_task.result()\n                return chat_response\n        else:\n            await asyncio.sleep(0.1)  # sleep for a bit before checking the tasks again\n```\n\n\n```python\n# Call the main function with the good request - this should go through\nresponse = await execute_chat_with_guardrail(good_request)\nprint(response)\n```\n\n    Checking topical guardrail\n    Got guardrail response\n    Getting LLM response\n    Got LLM response\n    If you like cats and are considering getting a dog, there are several breeds known for their compatibility with feline friends. Here are some of the best dog breeds that tend to get along well with cats:\n    \n    1. **Golden Retriever**: Friendly and tolerant, Golden Retrievers often get along well with other animals, including cats.\n    \n    2. **Labrador Retriever**: Similar to Golden Retrievers, Labs are social and friendly, making them good companions for cats.\n    \n    3. **Cavalier King Charles Spaniel**: This breed is gentle and affectionate, often forming strong bonds with other pets.\n    \n    4. **Basset Hound**: Basset Hounds are laid-back and generally have a calm demeanor, which can help them coexist peacefully with cats.\n    \n    5. **Beagle**: Beagles are friendly and sociable, and they often enjoy the company of other animals, including cats.\n    \n    6. **Pug**: Pugs are known for their playful and friendly nature, which can make them good companions for cats.\n    \n    7. **Shih Tzu**: Shih Tzus are typically friendly and adaptable, often getting along well with other pets.\n    \n    8. **Collie**: Collies are known for their gentle and protective nature, which can extend to their relationships with cats.\n    \n    9. **Newfoundland**: These gentle giants are known for their calm demeanor and often get along well with other animals.\n    \n    10. **Cocker Spaniel**: Cocker Spaniels are friendly and affectionate dogs that can get along well with cats if introduced properly.\n    \n    When introducing a dog to a cat, it's important to do so gradually and supervise their interactions to ensure a positive relationship. Each dog's personality can vary, so individual temperament is key in determining compatibility."}


created_at: 2024-07-28 18:59:18
topic: persistent://default/default/4bfc3c11-fb71-4cc9-8c12-01ed076a0e01
id: 4b6689e1-ffa3-470b-8b60-60968749d34a
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/How_to_use_guardrails.ipynb", "title": "How to use guardrails", "tokens": 3850, "retrieve_doc": true, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"4b6689e1-ffa3-470b-8b60-60968749d34a\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_use_guardrails.ipynb\", \"title\": \"How to use guardrails\", \"tokens\": 3850, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"a231c185-0dcb-4549-b2dc-bfa4a7bee89b\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_use_guardrails.ipynb\", \"title\": \"How to use guardrails\", \"tokens\": 3850, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"337c350bcca7d75854758eb0cad65acdf3e435a6ccea5bdebc39c067aeee844b\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"9f4640d7-778a-43f2-a15a-418549aaea86\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_use_guardrails.ipynb\", \"title\": \"How to use guardrails\", \"tokens\": 3850, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"dd688a516cb04677cd38df50f0f83036855992c2d30c9ffbf90d44683186415f\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"32ce3516-9784-459b-ab16-8fe1bce53dd0\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"3bccc3721b0040e85aa8c9c7dd1bc3611d817a2b5bc9067077ca12d3934b65dd\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 9570, \"end_char_idx\": 13031, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "a231c185-0dcb-4549-b2dc-bfa4a7bee89b", "doc_id": "a231c185-0dcb-4549-b2dc-bfa4a7bee89b", "ref_doc_id": "a231c185-0dcb-4549-b2dc-bfa4a7bee89b", "chroma:document": "```python\n# Call the main function with the good request - this should get blocked\nresponse = await execute_chat_with_guardrail(bad_request)\nprint(response)\n```\n\n    Checking topical guardrail\n    Got guardrail response\n    Getting LLM response\n    Got LLM response\n    Topical guardrail triggered\n    I can only talk about cats and dogs, the best animals that ever lived.\n\n\nLooks like our guardrail worked - the first question was allowed through, but the second was blocked for being off-topic. Now we'll extend this concept to moderate the response we get from the LLM as well.\n\n## 2. Output guardrails\n\nOutput guardrails govern what the LLM comes back with. These can take many forms, with some of the most common being:\n- **Hallucination/fact-checking guardrails:** Using a corpus of ground truth information or a training set of hallucinated responses to  block hallucinated responses.\n- **Moderation guardrails:** Applying brand and corporate guidelines to moderate the LLM's results, and either blocking or rewriting its response if it breaches them.\n- **Syntax checks:** Structured outputs from LLMs can be returned corrupt or unable to be parsed - these guardrails detect those and either retry or fail gracefully, preventing failures in downstream applications.\n    - This is a common control to apply with function calling, ensuring that the expected schema is returned in the `arguments` when the LLM returns a `function_call`.\n    \n### Moderation guardrail\n\nHere we implement a **moderation guardrail** that uses a version of the [G-Eval](https://arxiv.org/abs/2303.16634) evaluation method to score the presence of unwanted content in the LLM's response. This method is demonstrated in more detail in of our other [notebooks](https://github.com/openai/openai-cookbook/blob/main/examples/evaluation/How_to_eval_abstractive_summarization.ipynb).\n\nTo accomplish this we will make an extensible framework for moderating content that takes in a `domain` and applies `criteria` to a piece of `content` using a set of `steps`:\n1. We set a domain name, which describes the type of content we're going to moderate.\n2. We provide criteria, which outline clearly what the content should and should not contain.\n3. Step-by-step instructions are provided for the LLM to grade the content.\n4. The LLM returns a discrete score from 1-5.\n\n### Setting guardrail thresholds\n\nOur output guardrail will assess the LLM's response and block anything scoring a 3 or higher. Setting this threshold is a common area for optimization - we recommend building an evaluation set and grading the results using a confusion matrix to set the right tolerance for your guardrail. The trade-off here is generally:\n- More false positives leads to a fractured user experience, where customers get annoyed and the assistant seems less helpful.\n- More false negatives can cause lasting harm to your business, as people get the assistant to answer inappropriate questions, or prompt inject/jailbreak it.\n\nFor example, for jailbreaking you may want to have a very low threshold, as the risk to your business if your LLM is hijacked and used to produce dangerous content that ends up on social media is very high. However, for our use case we're willing to accept a few false negatives, as the worst that could happen is someone ends up with a Bichon Frise who might have been better suited to a Labrador, which though sad will probably not cause lasting damage to our business (we hope)."}


created_at: 2024-07-28 18:59:18
topic: persistent://default/default/4bfc3c11-fb71-4cc9-8c12-01ed076a0e01
id: 32ce3516-9784-459b-ab16-8fe1bce53dd0
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/How_to_use_guardrails.ipynb", "title": "How to use guardrails", "tokens": 3850, "retrieve_doc": true, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"32ce3516-9784-459b-ab16-8fe1bce53dd0\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_use_guardrails.ipynb\", \"title\": \"How to use guardrails\", \"tokens\": 3850, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"a231c185-0dcb-4549-b2dc-bfa4a7bee89b\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_use_guardrails.ipynb\", \"title\": \"How to use guardrails\", \"tokens\": 3850, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"337c350bcca7d75854758eb0cad65acdf3e435a6ccea5bdebc39c067aeee844b\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"4b6689e1-ffa3-470b-8b60-60968749d34a\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_use_guardrails.ipynb\", \"title\": \"How to use guardrails\", \"tokens\": 3850, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"c58e86e1c1d1fd08d15d09e348385f9d3664a6f935c5ded82b1fc9e025d14305\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"cd36b6be-d0d0-4ce0-ba75-5cfba88f6609\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"25c0f8fe37a8db4a0612673a2f03e06b745cdda81076f13d32462e7426f1bc2f\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 13034, \"end_char_idx\": 16059, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "a231c185-0dcb-4549-b2dc-bfa4a7bee89b", "doc_id": "a231c185-0dcb-4549-b2dc-bfa4a7bee89b", "ref_doc_id": "a231c185-0dcb-4549-b2dc-bfa4a7bee89b", "chroma:document": "```python\ndomain = \"animal breed recommendation\"\n\nanimal_advice_criteria = \"\"\"\nAssess the presence of explicit recommendation of cat or dog breeds in the content.\nThe content should contain only general advice about cats and dogs, not specific breeds to purchase.\"\"\"\n\nanimal_advice_steps = \"\"\"\n1. Read the content and the criteria carefully.\n2. Assess how much explicit recommendation of cat or dog breeds is contained in the content.\n3. Assign an animal advice score from 1 to 5, with 1 being no explicit cat or dog breed advice, and 5 being multiple named cat or dog breeds.\n\"\"\"\n\nmoderation_system_prompt = \"\"\"\nYou are a moderation assistant. Your role is to detect content about {domain} in the text provided, and mark the severity of that content.\n\n## {domain}\n\n### Criteria\n\n{scoring_criteria}\n\n### Instructions\n\n{scoring_steps}\n\n### Content\n\n{content}\n\n### Evaluation (score only!)\n\"\"\"\n```\n\n\n```python\nasync def moderation_guardrail(chat_response):\n    print(\"Checking moderation guardrail\")\n    mod_messages = [\n        {\"role\": \"user\", \"content\": moderation_system_prompt.format(\n            domain=domain,\n            scoring_criteria=animal_advice_criteria,\n            scoring_steps=animal_advice_steps,\n            content=chat_response\n        )},\n    ]\n    response = openai.chat.completions.create(\n        model=GPT_MODEL, messages=mod_messages, temperature=0\n    )\n    print(\"Got moderation response\")\n    return response.choices[0].message.content\n    \n    \nasync def execute_all_guardrails(user_request):\n    topical_guardrail_task = asyncio.create_task(topical_guardrail(user_request))\n    chat_task = asyncio.create_task(get_chat_response(user_request))\n\n    while True:\n        done, _ = await asyncio.wait(\n            [topical_guardrail_task, chat_task], return_when=asyncio.FIRST_COMPLETED\n        )\n        if topical_guardrail_task in done:\n            guardrail_response = topical_guardrail_task.result()\n            if guardrail_response == \"not_allowed\":\n                chat_task.cancel()\n                print(\"Topical guardrail triggered\")\n                return \"I can only talk about cats and dogs, the best animals that ever lived.\"\n            elif chat_task in done:\n                chat_response = chat_task.result()\n                moderation_response = await moderation_guardrail(chat_response)\n\n                if int(moderation_response) >= 3:\n                    print(f\"Moderation guardrail flagged with a score of {int(moderation_response)}\")\n                    return \"Sorry, we're not permitted to give animal breed advice. I can help you with any general queries you might have.\"\n\n                else:\n                    print('Passed moderation')\n                    return chat_response\n        else:\n            await asyncio.sleep(0.1)  # sleep for a bit before checking the tasks again\n```\n\n\n```python\n# Adding a request that should pass both our topical guardrail and our moderation guardrail\ngreat_request = 'What is some advice you can give to a new dog owner?'\n```"}


created_at: 2024-07-28 18:59:18
topic: persistent://default/default/4bfc3c11-fb71-4cc9-8c12-01ed076a0e01
id: cd36b6be-d0d0-4ce0-ba75-5cfba88f6609
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/How_to_use_guardrails.ipynb", "title": "How to use guardrails", "tokens": 3850, "retrieve_doc": true, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"cd36b6be-d0d0-4ce0-ba75-5cfba88f6609\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_use_guardrails.ipynb\", \"title\": \"How to use guardrails\", \"tokens\": 3850, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"a231c185-0dcb-4549-b2dc-bfa4a7bee89b\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_use_guardrails.ipynb\", \"title\": \"How to use guardrails\", \"tokens\": 3850, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"337c350bcca7d75854758eb0cad65acdf3e435a6ccea5bdebc39c067aeee844b\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"32ce3516-9784-459b-ab16-8fe1bce53dd0\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_use_guardrails.ipynb\", \"title\": \"How to use guardrails\", \"tokens\": 3850, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"038b63a1ec3554db44f031cc88749560a894f30f38b3cfdab123e0a5a44b41c4\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 15883, \"end_char_idx\": 18240, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "a231c185-0dcb-4549-b2dc-bfa4a7bee89b", "doc_id": "a231c185-0dcb-4549-b2dc-bfa4a7bee89b", "ref_doc_id": "a231c185-0dcb-4549-b2dc-bfa4a7bee89b", "chroma:document": "```python\n# Adding a request that should pass both our topical guardrail and our moderation guardrail\ngreat_request = 'What is some advice you can give to a new dog owner?'\n```\n\n\n```python\ntests = [good_request,bad_request,great_request]\n\nfor test in tests:\n    result = await execute_all_guardrails(test)\n    print(result)\n    print('\\n\\n')\n    \n```\n\n    Checking topical guardrail\n    Got guardrail response\n    Getting LLM response\n    Got LLM response\n    Checking moderation guardrail\n    Got moderation response\n    Moderation guardrail flagged with a score of 5\n    Sorry, we're not permitted to give animal breed advice. I can help you with any general queries you might have.\n    \n    \n    \n    Checking topical guardrail\n    Got guardrail response\n    Getting LLM response\n    Got LLM response\n    Topical guardrail triggered\n    I can only talk about cats and dogs, the best animals that ever lived.\n    \n    \n    \n    Checking topical guardrail\n    Got guardrail response\n    Getting LLM response\n    Got LLM response\n    Checking moderation guardrail\n    Got moderation response\n    Moderation guardrail flagged with a score of 3\n    Sorry, we're not permitted to give animal breed advice. I can help you with any general queries you might have.\n    \n    \n    \n\n\n## Conclusion\n\nGuardrails are a vibrant and evolving topic in LLMs, and we hope this notebook has given you an effective introduction to the core concepts around guardrails. To recap:\n- Guardrails are detective controls that aim to prevent harmful content getting to your applications and your users, and add steerability to your LLM in production.\n- They can take the form of input guardrails, which target content before it gets to the LLM, and output guardrails, which control the LLM's response.\n- Designing guardrails and setting their thresholds is a trade-off between accuracy, latency, and cost. Your decision should be based on clear evaluations of the performance of your guardrails, and an understanding of what the cost of a false negative and false positive are for your business.\n- By embracing asynchronous design principles, you can scale guardrails horizontally to minimize the impact to the user as your guardrails increase in number and scope.\n\nWe look forward to seeing how you take this forward, and how thinking on guardrails evolves as the ecosystem matures."}


created_at: 2024-07-28 18:59:18
topic: persistent://default/default/4bfc3c11-fb71-4cc9-8c12-01ed076a0e01
id: f7ff3b5f-b168-4057-811a-1287dc20dd33
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/Using_embeddings.ipynb", "title": "Negative example (slow and rate-limited)", "tokens": 380, "retrieve_doc": true, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"f7ff3b5f-b168-4057-811a-1287dc20dd33\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Using_embeddings.ipynb\", \"title\": \"Negative example (slow and rate-limited)\", \"tokens\": 380, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"f8eb6000-bb23-4c1f-9814-7eb39ebde3a9\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Using_embeddings.ipynb\", \"title\": \"Negative example (slow and rate-limited)\", \"tokens\": 380, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"26a585da0ade981944c372d689088efba5206abe28955e699674ffa1a4c727f7\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 0, \"end_char_idx\": 1581, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "f8eb6000-bb23-4c1f-9814-7eb39ebde3a9", "doc_id": "f8eb6000-bb23-4c1f-9814-7eb39ebde3a9", "ref_doc_id": "f8eb6000-bb23-4c1f-9814-7eb39ebde3a9", "chroma:document": "## Using embeddings\n\nThis notebook contains some helpful snippets you can use to embed text with the `text-embedding-3-small` model via the OpenAI API.\n\n\n```python\nfrom openai import OpenAI\nclient = OpenAI()\n\nembedding = client.embeddings.create(\n    input=\"Your text goes here\", model=\"text-embedding-3-small\"\n).data[0].embedding\nlen(embedding)\n\n```\n\n\n\n\n    1536\n\n\n\nIt's recommended to use the 'tenacity' package or another exponential backoff implementation to better manage API rate limits, as hitting the API too much too fast can trigger rate limits. Using the following function ensures you get your embeddings as fast as possible.\n\n\n```python\n# Negative example (slow and rate-limited)\nfrom openai import OpenAI\nclient = OpenAI()\n\nnum_embeddings = 10000 # Some large number\nfor i in range(num_embeddings):\n    embedding = client.embeddings.create(\n        input=\"Your text goes here\", model=\"text-embedding-3-small\"\n    ).data[0].embedding\n    print(len(embedding))\n```\n\n\n```python\n# Best practice\nfrom tenacity import retry, wait_random_exponential, stop_after_attempt\nfrom openai import OpenAI\nclient = OpenAI()\n\n# Retry up to 6 times with exponential backoff, starting at 1 second and maxing out at 20 seconds delay\n@retry(wait=wait_random_exponential(min=1, max=20), stop=stop_after_attempt(6))\ndef get_embedding(text: str, model=\"text-embedding-3-small\") -> list[float]:\n    return client.embeddings.create(input=[text], model=model).data[0].embedding\n\nembedding = get_embedding(\"Your text goes here\", model=\"text-embedding-3-small\")\nprint(len(embedding))\n```\n\n    1536"}


created_at: 2024-07-28 18:59:18
topic: persistent://default/default/4bfc3c11-fb71-4cc9-8c12-01ed076a0e01
id: e29c72ae-b1f5-4e68-bc28-9ad6e60a36fa
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/Embedding_Wikipedia_articles_for_search.ipynb", "title": "Embedding Wikipedia articles for search", "tokens": 4092, "retrieve_doc": true, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"e29c72ae-b1f5-4e68-bc28-9ad6e60a36fa\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Embedding_Wikipedia_articles_for_search.ipynb\", \"title\": \"Embedding Wikipedia articles for search\", \"tokens\": 4092, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"7f4f2166-8e96-43f9-ae69-6d822bdfb0ff\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Embedding_Wikipedia_articles_for_search.ipynb\", \"title\": \"Embedding Wikipedia articles for search\", \"tokens\": 4092, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"8215343c9233df1c01dfdbaeefe91e68909b503c1cc90e947c8a8f0e951b2f47\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"29fc0e1e-6547-495f-b848-80d39dcfaf8b\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"2aac946d934a339e30acde13fdfe37b5d6578b90ead86bf76aaaae023c17087c\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 0, \"end_char_idx\": 2956, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "7f4f2166-8e96-43f9-ae69-6d822bdfb0ff", "doc_id": "7f4f2166-8e96-43f9-ae69-6d822bdfb0ff", "ref_doc_id": "7f4f2166-8e96-43f9-ae69-6d822bdfb0ff", "chroma:document": "# Embedding Wikipedia articles for search\n\nThis notebook shows how we prepared a dataset of Wikipedia articles for search, used in [Question_answering_using_embeddings.ipynb](Question_answering_using_embeddings.ipynb).\n\nProcedure:\n\n0. Prerequisites: Import libraries, set API key (if needed)\n1. Collect: We download a few hundred Wikipedia articles about the 2022 Olympics\n2. Chunk: Documents are split into short, semi-self-contained sections to be embedded\n3. Embed: Each section is embedded with the OpenAI API\n4. Store: Embeddings are saved in a CSV file (for large datasets, use a vector database)\n\n## 0. Prerequisites\n\n### Import libraries\n\n\n```python\n# imports\nimport mwclient  # for downloading example Wikipedia articles\nimport mwparserfromhell  # for splitting Wikipedia articles into sections\nimport openai  # for generating embeddings\nimport os  # for environment variables\nimport pandas as pd  # for DataFrames to store article sections and embeddings\nimport re  # for cutting <ref> links out of Wikipedia articles\nimport tiktoken  # for counting tokens\n\nclient = openai.OpenAI(api_key=os.environ.get(\"OPENAI_API_KEY\", \"<your OpenAI API key if not set as env var>\"))\n```\n\nInstall any missing libraries with `pip install` in your terminal. E.g.,\n\n```zsh\npip install openai\n```\n\n(You can also do this in a notebook cell with `!pip install openai`.)\n\nIf you install any libraries, be sure to restart the notebook kernel.\n\n### Set API key (if needed)\n\nNote that the OpenAI library will try to read your API key from the `OPENAI_API_KEY` environment variable. If you haven't already, set this environment variable by following [these instructions](https://help.openai.com/en/articles/5112595-best-practices-for-api-key-safety).\n\n## 1. Collect documents\n\nIn this example, we'll download a few hundred Wikipedia articles related to the 2022 Winter Olympics.\n\n\n```python\n# get Wikipedia pages about the 2022 Winter Olympics\n\nCATEGORY_TITLE = \"Category:2022 Winter Olympics\"\nWIKI_SITE = \"en.wikipedia.org\"\n\n\ndef titles_from_category(\n    category: mwclient.listing.Category, max_depth: int\n) -> set[str]:\n    \"\"\"Return a set of page titles in a given Wiki category and its subcategories.\"\"\"\n    titles = set()\n    for cm in category.members():\n        if type(cm) == mwclient.page.Page:\n            # ^type() used instead of isinstance() to catch match w/ no inheritance\n            titles.add(cm.name)\n        elif isinstance(cm, mwclient.listing.Category) and max_depth > 0:\n            deeper_titles = titles_from_category(cm, max_depth=max_depth - 1)\n            titles.update(deeper_titles)\n    return titles\n\n\nsite = mwclient.Site(WIKI_SITE)\ncategory_page = site.pages[CATEGORY_TITLE]\ntitles = titles_from_category(category_page, max_depth=1)\n# ^note: max_depth=1 means we go one level deep in the category tree\nprint(f\"Found {len(titles)} article titles in {CATEGORY_TITLE}.\")\n\n```\n\n    Found 731 article titles in Category:2022 Winter Olympics."}


created_at: 2024-07-28 18:59:18
topic: persistent://default/default/4bfc3c11-fb71-4cc9-8c12-01ed076a0e01
id: 29fc0e1e-6547-495f-b848-80d39dcfaf8b
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/Embedding_Wikipedia_articles_for_search.ipynb", "title": "Embedding Wikipedia articles for search", "tokens": 4092, "retrieve_doc": true, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"29fc0e1e-6547-495f-b848-80d39dcfaf8b\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Embedding_Wikipedia_articles_for_search.ipynb\", \"title\": \"Embedding Wikipedia articles for search\", \"tokens\": 4092, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"7f4f2166-8e96-43f9-ae69-6d822bdfb0ff\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Embedding_Wikipedia_articles_for_search.ipynb\", \"title\": \"Embedding Wikipedia articles for search\", \"tokens\": 4092, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"8215343c9233df1c01dfdbaeefe91e68909b503c1cc90e947c8a8f0e951b2f47\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"e29c72ae-b1f5-4e68-bc28-9ad6e60a36fa\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Embedding_Wikipedia_articles_for_search.ipynb\", \"title\": \"Embedding Wikipedia articles for search\", \"tokens\": 4092, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"ce84c7cd3733cb98d42d6a007ffcf0ec9e2402cbd5f4c47fc395a86abd6768a0\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"c7547249-2259-4b43-af40-f6037e077104\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"534b7fa4171e7091d90093be9202722096521ebfbd5eb8bcd2f4ad43f2f76c74\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 1866, \"end_char_idx\": 4140, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "7f4f2166-8e96-43f9-ae69-6d822bdfb0ff", "doc_id": "7f4f2166-8e96-43f9-ae69-6d822bdfb0ff", "ref_doc_id": "7f4f2166-8e96-43f9-ae69-6d822bdfb0ff", "chroma:document": "```python\n# get Wikipedia pages about the 2022 Winter Olympics\n\nCATEGORY_TITLE = \"Category:2022 Winter Olympics\"\nWIKI_SITE = \"en.wikipedia.org\"\n\n\ndef titles_from_category(\n    category: mwclient.listing.Category, max_depth: int\n) -> set[str]:\n    \"\"\"Return a set of page titles in a given Wiki category and its subcategories.\"\"\"\n    titles = set()\n    for cm in category.members():\n        if type(cm) == mwclient.page.Page:\n            # ^type() used instead of isinstance() to catch match w/ no inheritance\n            titles.add(cm.name)\n        elif isinstance(cm, mwclient.listing.Category) and max_depth > 0:\n            deeper_titles = titles_from_category(cm, max_depth=max_depth - 1)\n            titles.update(deeper_titles)\n    return titles\n\n\nsite = mwclient.Site(WIKI_SITE)\ncategory_page = site.pages[CATEGORY_TITLE]\ntitles = titles_from_category(category_page, max_depth=1)\n# ^note: max_depth=1 means we go one level deep in the category tree\nprint(f\"Found {len(titles)} article titles in {CATEGORY_TITLE}.\")\n\n```\n\n    Found 731 article titles in Category:2022 Winter Olympics.\n\n\n## 2. Chunk documents\n\nNow that we have our reference documents, we need to prepare them for search.\n\nBecause GPT can only read a limited amount of text at once, we'll split each document into chunks short enough to be read.\n\nFor this specific example on Wikipedia articles, we'll:\n- Discard less relevant-looking sections like External Links and Footnotes\n- Clean up the text by removing reference tags (e.g., <ref>), whitespace, and super short sections\n- Split each article into sections\n- Prepend titles and subtitles to each section's text, to help GPT understand the context\n- If a section is long (say, > 1,600 tokens), we'll recursively split it into smaller sections, trying to split along semantic boundaries like paragraphs\n\n\n```python\n# define functions to split Wikipedia pages into sections\n\nSECTIONS_TO_IGNORE = [\n    \"See also\",\n    \"References\",\n    \"External links\",\n    \"Further reading\",\n    \"Footnotes\",\n    \"Bibliography\",\n    \"Sources\",\n    \"Citations\",\n    \"Literature\",\n    \"Footnotes\",\n    \"Notes and references\",\n    \"Photo gallery\",\n    \"Works cited\",\n    \"Photos\",\n    \"Gallery\",\n    \"Notes\",\n    \"References and sources\",\n    \"References and notes\",\n]"}


created_at: 2024-07-28 18:59:18
topic: persistent://default/default/4bfc3c11-fb71-4cc9-8c12-01ed076a0e01
id: c7547249-2259-4b43-af40-f6037e077104
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/Embedding_Wikipedia_articles_for_search.ipynb", "title": "Embedding Wikipedia articles for search", "tokens": 4092, "retrieve_doc": true, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"c7547249-2259-4b43-af40-f6037e077104\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Embedding_Wikipedia_articles_for_search.ipynb\", \"title\": \"Embedding Wikipedia articles for search\", \"tokens\": 4092, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"7f4f2166-8e96-43f9-ae69-6d822bdfb0ff\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Embedding_Wikipedia_articles_for_search.ipynb\", \"title\": \"Embedding Wikipedia articles for search\", \"tokens\": 4092, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"8215343c9233df1c01dfdbaeefe91e68909b503c1cc90e947c8a8f0e951b2f47\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"29fc0e1e-6547-495f-b848-80d39dcfaf8b\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Embedding_Wikipedia_articles_for_search.ipynb\", \"title\": \"Embedding Wikipedia articles for search\", \"tokens\": 4092, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"de3030c1d12607e6c88c0e201950a391e154c2aa45c887e19e5b0e1abc1bac4e\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"909d0bf0-cf6f-41fd-b2fa-b82bc34657e6\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"ab6de8e84580e2e728db30e92221ead9e96c6ed9b28725d473f06200dbe7e0a3\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 2620, \"end_char_idx\": 5364, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "7f4f2166-8e96-43f9-ae69-6d822bdfb0ff", "doc_id": "7f4f2166-8e96-43f9-ae69-6d822bdfb0ff", "ref_doc_id": "7f4f2166-8e96-43f9-ae69-6d822bdfb0ff", "chroma:document": "site = mwclient.Site(WIKI_SITE)\ncategory_page = site.pages[CATEGORY_TITLE]\ntitles = titles_from_category(category_page, max_depth=1)\n# ^note: max_depth=1 means we go one level deep in the category tree\nprint(f\"Found {len(titles)} article titles in {CATEGORY_TITLE}.\")\n\n```\n\n    Found 731 article titles in Category:2022 Winter Olympics.\n\n\n## 2. Chunk documents\n\nNow that we have our reference documents, we need to prepare them for search.\n\nBecause GPT can only read a limited amount of text at once, we'll split each document into chunks short enough to be read.\n\nFor this specific example on Wikipedia articles, we'll:\n- Discard less relevant-looking sections like External Links and Footnotes\n- Clean up the text by removing reference tags (e.g., <ref>), whitespace, and super short sections\n- Split each article into sections\n- Prepend titles and subtitles to each section's text, to help GPT understand the context\n- If a section is long (say, > 1,600 tokens), we'll recursively split it into smaller sections, trying to split along semantic boundaries like paragraphs\n\n\n```python\n# define functions to split Wikipedia pages into sections\n\nSECTIONS_TO_IGNORE = [\n    \"See also\",\n    \"References\",\n    \"External links\",\n    \"Further reading\",\n    \"Footnotes\",\n    \"Bibliography\",\n    \"Sources\",\n    \"Citations\",\n    \"Literature\",\n    \"Footnotes\",\n    \"Notes and references\",\n    \"Photo gallery\",\n    \"Works cited\",\n    \"Photos\",\n    \"Gallery\",\n    \"Notes\",\n    \"References and sources\",\n    \"References and notes\",\n]\n\n\ndef all_subsections_from_section(\n    section: mwparserfromhell.wikicode.Wikicode,\n    parent_titles: list[str],\n    sections_to_ignore: set[str],\n) -> list[tuple[list[str], str]]:\n    \"\"\"\n    From a Wikipedia section, return a flattened list of all nested subsections.\n    Each subsection is a tuple, where:\n        - the first element is a list of parent subtitles, starting with the page title\n        - the second element is the text of the subsection (but not any children)\n    \"\"\"\n    headings = [str(h) for h in section.filter_headings()]\n    title = headings[0]\n    if title.strip(\"=\" + \" \") in sections_to_ignore:\n        # ^wiki headings are wrapped like \"== Heading ==\"\n        return []\n    titles = parent_titles + [title]\n    full_text = str(section)\n    section_text = full_text.split(title)[1]\n    if len(headings) == 1:\n        return [(titles, section_text)]\n    else:\n        first_subtitle = headings[1]\n        section_text = section_text.split(first_subtitle)[0]\n        results = [(titles, section_text)]\n        for subsection in section.get_sections(levels=[len(titles) + 1]):\n            results.extend(all_subsections_from_section(subsection, titles, sections_to_ignore))\n        return results"}


created_at: 2024-07-28 18:59:18
topic: persistent://default/default/4bfc3c11-fb71-4cc9-8c12-01ed076a0e01
id: 909d0bf0-cf6f-41fd-b2fa-b82bc34657e6
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/Embedding_Wikipedia_articles_for_search.ipynb", "title": "Embedding Wikipedia articles for search", "tokens": 4092, "retrieve_doc": true, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"909d0bf0-cf6f-41fd-b2fa-b82bc34657e6\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Embedding_Wikipedia_articles_for_search.ipynb\", \"title\": \"Embedding Wikipedia articles for search\", \"tokens\": 4092, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"7f4f2166-8e96-43f9-ae69-6d822bdfb0ff\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Embedding_Wikipedia_articles_for_search.ipynb\", \"title\": \"Embedding Wikipedia articles for search\", \"tokens\": 4092, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"8215343c9233df1c01dfdbaeefe91e68909b503c1cc90e947c8a8f0e951b2f47\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"c7547249-2259-4b43-af40-f6037e077104\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Embedding_Wikipedia_articles_for_search.ipynb\", \"title\": \"Embedding Wikipedia articles for search\", \"tokens\": 4092, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"9a4b36fa230c39382991f6e51a78627dad58180648c515750fd9508705c23edb\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"ac945f9e-7dcf-48e1-82c7-675a02b83503\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"fef1b0557444b23cb6c3158919f1093d088e727cbf6883239f7dfb73d78a5f9b\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 3696, \"end_char_idx\": 6691, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "7f4f2166-8e96-43f9-ae69-6d822bdfb0ff", "doc_id": "7f4f2166-8e96-43f9-ae69-6d822bdfb0ff", "ref_doc_id": "7f4f2166-8e96-43f9-ae69-6d822bdfb0ff", "chroma:document": "```python\n# define functions to split Wikipedia pages into sections\n\nSECTIONS_TO_IGNORE = [\n    \"See also\",\n    \"References\",\n    \"External links\",\n    \"Further reading\",\n    \"Footnotes\",\n    \"Bibliography\",\n    \"Sources\",\n    \"Citations\",\n    \"Literature\",\n    \"Footnotes\",\n    \"Notes and references\",\n    \"Photo gallery\",\n    \"Works cited\",\n    \"Photos\",\n    \"Gallery\",\n    \"Notes\",\n    \"References and sources\",\n    \"References and notes\",\n]\n\n\ndef all_subsections_from_section(\n    section: mwparserfromhell.wikicode.Wikicode,\n    parent_titles: list[str],\n    sections_to_ignore: set[str],\n) -> list[tuple[list[str], str]]:\n    \"\"\"\n    From a Wikipedia section, return a flattened list of all nested subsections.\n    Each subsection is a tuple, where:\n        - the first element is a list of parent subtitles, starting with the page title\n        - the second element is the text of the subsection (but not any children)\n    \"\"\"\n    headings = [str(h) for h in section.filter_headings()]\n    title = headings[0]\n    if title.strip(\"=\" + \" \") in sections_to_ignore:\n        # ^wiki headings are wrapped like \"== Heading ==\"\n        return []\n    titles = parent_titles + [title]\n    full_text = str(section)\n    section_text = full_text.split(title)[1]\n    if len(headings) == 1:\n        return [(titles, section_text)]\n    else:\n        first_subtitle = headings[1]\n        section_text = section_text.split(first_subtitle)[0]\n        results = [(titles, section_text)]\n        for subsection in section.get_sections(levels=[len(titles) + 1]):\n            results.extend(all_subsections_from_section(subsection, titles, sections_to_ignore))\n        return results\n\n\ndef all_subsections_from_title(\n    title: str,\n    sections_to_ignore: set[str] = SECTIONS_TO_IGNORE,\n    site_name: str = WIKI_SITE,\n) -> list[tuple[list[str], str]]:\n    \"\"\"From a Wikipedia page title, return a flattened list of all nested subsections.\n    Each subsection is a tuple, where:\n        - the first element is a list of parent subtitles, starting with the page title\n        - the second element is the text of the subsection (but not any children)\n    \"\"\"\n    site = mwclient.Site(site_name)\n    page = site.pages[title]\n    text = page.text()\n    parsed_text = mwparserfromhell.parse(text)\n    headings = [str(h) for h in parsed_text.filter_headings()]\n    if headings:\n        summary_text = str(parsed_text).split(headings[0])[0]\n    else:\n        summary_text = str(parsed_text)\n    results = [([title], summary_text)]\n    for subsection in parsed_text.get_sections(levels=[2]):\n        results.extend(all_subsections_from_section(subsection, [title], sections_to_ignore))\n    return results\n\n```\n\n\n```python\n# split pages into sections\n# may take ~1 minute per 100 articles\nwikipedia_sections = []\nfor title in titles:\n    wikipedia_sections.extend(all_subsections_from_title(title))\nprint(f\"Found {len(wikipedia_sections)} sections in {len(titles)} pages.\")\n\n```\n\n    Found 5730 sections in 731 pages."}


created_at: 2024-07-28 18:59:18
topic: persistent://default/default/4bfc3c11-fb71-4cc9-8c12-01ed076a0e01
id: ac945f9e-7dcf-48e1-82c7-675a02b83503
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/Embedding_Wikipedia_articles_for_search.ipynb", "title": "Embedding Wikipedia articles for search", "tokens": 4092, "retrieve_doc": true, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"ac945f9e-7dcf-48e1-82c7-675a02b83503\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Embedding_Wikipedia_articles_for_search.ipynb\", \"title\": \"Embedding Wikipedia articles for search\", \"tokens\": 4092, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"7f4f2166-8e96-43f9-ae69-6d822bdfb0ff\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Embedding_Wikipedia_articles_for_search.ipynb\", \"title\": \"Embedding Wikipedia articles for search\", \"tokens\": 4092, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"8215343c9233df1c01dfdbaeefe91e68909b503c1cc90e947c8a8f0e951b2f47\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"909d0bf0-cf6f-41fd-b2fa-b82bc34657e6\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Embedding_Wikipedia_articles_for_search.ipynb\", \"title\": \"Embedding Wikipedia articles for search\", \"tokens\": 4092, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"b19edb443b084737d88172bddf8c2ab4fa055dcf710601b471ba2300e6f4bd52\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"a8c350e9-2076-4227-b10b-a7b8d9acb719\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"823da9c5677e327c9be9e55a9f0fc7e220f97c0062c24d17da43f28ff7bff32f\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 5367, \"end_char_idx\": 8384, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "7f4f2166-8e96-43f9-ae69-6d822bdfb0ff", "doc_id": "7f4f2166-8e96-43f9-ae69-6d822bdfb0ff", "ref_doc_id": "7f4f2166-8e96-43f9-ae69-6d822bdfb0ff", "chroma:document": "def all_subsections_from_title(\n    title: str,\n    sections_to_ignore: set[str] = SECTIONS_TO_IGNORE,\n    site_name: str = WIKI_SITE,\n) -> list[tuple[list[str], str]]:\n    \"\"\"From a Wikipedia page title, return a flattened list of all nested subsections.\n    Each subsection is a tuple, where:\n        - the first element is a list of parent subtitles, starting with the page title\n        - the second element is the text of the subsection (but not any children)\n    \"\"\"\n    site = mwclient.Site(site_name)\n    page = site.pages[title]\n    text = page.text()\n    parsed_text = mwparserfromhell.parse(text)\n    headings = [str(h) for h in parsed_text.filter_headings()]\n    if headings:\n        summary_text = str(parsed_text).split(headings[0])[0]\n    else:\n        summary_text = str(parsed_text)\n    results = [([title], summary_text)]\n    for subsection in parsed_text.get_sections(levels=[2]):\n        results.extend(all_subsections_from_section(subsection, [title], sections_to_ignore))\n    return results\n\n```\n\n\n```python\n# split pages into sections\n# may take ~1 minute per 100 articles\nwikipedia_sections = []\nfor title in titles:\n    wikipedia_sections.extend(all_subsections_from_title(title))\nprint(f\"Found {len(wikipedia_sections)} sections in {len(titles)} pages.\")\n\n```\n\n    Found 5730 sections in 731 pages.\n\n\n\n```python\n# clean text\ndef clean_section(section: tuple[list[str], str]) -> tuple[list[str], str]:\n    \"\"\"\n    Return a cleaned up section with:\n        - <ref>xyz</ref> patterns removed\n        - leading/trailing whitespace removed\n    \"\"\"\n    titles, text = section\n    text = re.sub(r\"<ref.*?</ref>\", \"\", text)\n    text = text.strip()\n    return (titles, text)\n\n\nwikipedia_sections = [clean_section(ws) for ws in wikipedia_sections]\n\n# filter out short/blank sections\ndef keep_section(section: tuple[list[str], str]) -> bool:\n    \"\"\"Return True if the section should be kept, False otherwise.\"\"\"\n    titles, text = section\n    if len(text) < 16:\n        return False\n    else:\n        return True\n\n\noriginal_num_sections = len(wikipedia_sections)\nwikipedia_sections = [ws for ws in wikipedia_sections if keep_section(ws)]\nprint(f\"Filtered out {original_num_sections-len(wikipedia_sections)} sections, leaving {len(wikipedia_sections)} sections.\")\n\n```\n\n    Filtered out 530 sections, leaving 5200 sections.\n\n\n\n```python\n# print example data\nfor ws in wikipedia_sections[:5]:\n    print(ws[0])\n    display(ws[1][:77] + \"...\")\n    print()\n\n```\n\n    ['Lviv bid for the 2022 Winter Olympics']\n\n\n\n    '{{Olympic bid|2022|Winter|\\n| Paralympics = yes\\n| logo = Lviv 2022 Winter Olym...'\n\n\n    \n    ['Lviv bid for the 2022 Winter Olympics', '==History==']\n\n\n\n    '[[Image:Lw\u00f3w - Rynek 01.JPG|thumb|right|200px|View of Rynok Square in Lviv]]\\n...'\n\n\n    \n    ['Lviv bid for the 2022 Winter Olympics', '==Venues==']\n\n\n\n    '{{Location map+\\n|Ukraine\\n|border =\\n|caption = Venue areas\\n|float = left\\n|widt...'\n\n\n    \n    ['Lviv bid for the 2022 Winter Olympics', '==Venues==', '===City zone===']"}


created_at: 2024-07-28 18:59:18
topic: persistent://default/default/4bfc3c11-fb71-4cc9-8c12-01ed076a0e01
id: a8c350e9-2076-4227-b10b-a7b8d9acb719
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/Embedding_Wikipedia_articles_for_search.ipynb", "title": "Embedding Wikipedia articles for search", "tokens": 4092, "retrieve_doc": true, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"a8c350e9-2076-4227-b10b-a7b8d9acb719\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Embedding_Wikipedia_articles_for_search.ipynb\", \"title\": \"Embedding Wikipedia articles for search\", \"tokens\": 4092, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"7f4f2166-8e96-43f9-ae69-6d822bdfb0ff\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Embedding_Wikipedia_articles_for_search.ipynb\", \"title\": \"Embedding Wikipedia articles for search\", \"tokens\": 4092, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"8215343c9233df1c01dfdbaeefe91e68909b503c1cc90e947c8a8f0e951b2f47\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"ac945f9e-7dcf-48e1-82c7-675a02b83503\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Embedding_Wikipedia_articles_for_search.ipynb\", \"title\": \"Embedding Wikipedia articles for search\", \"tokens\": 4092, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"7df6de4339ce22b4cac3964bff84bf402cf21356b3f9fd28c8a5bec7e38da951\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"a3742526-681d-42fa-a1b9-177377867155\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"54965f447fbdbf6114035709ce5edac391c4994da6e4253b4960c3d23448b7ab\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 7061, \"end_char_idx\": 9824, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "7f4f2166-8e96-43f9-ae69-6d822bdfb0ff", "doc_id": "7f4f2166-8e96-43f9-ae69-6d822bdfb0ff", "ref_doc_id": "7f4f2166-8e96-43f9-ae69-6d822bdfb0ff", "chroma:document": "wikipedia_sections = [clean_section(ws) for ws in wikipedia_sections]\n\n# filter out short/blank sections\ndef keep_section(section: tuple[list[str], str]) -> bool:\n    \"\"\"Return True if the section should be kept, False otherwise.\"\"\"\n    titles, text = section\n    if len(text) < 16:\n        return False\n    else:\n        return True\n\n\noriginal_num_sections = len(wikipedia_sections)\nwikipedia_sections = [ws for ws in wikipedia_sections if keep_section(ws)]\nprint(f\"Filtered out {original_num_sections-len(wikipedia_sections)} sections, leaving {len(wikipedia_sections)} sections.\")\n\n```\n\n    Filtered out 530 sections, leaving 5200 sections.\n\n\n\n```python\n# print example data\nfor ws in wikipedia_sections[:5]:\n    print(ws[0])\n    display(ws[1][:77] + \"...\")\n    print()\n\n```\n\n    ['Lviv bid for the 2022 Winter Olympics']\n\n\n\n    '{{Olympic bid|2022|Winter|\\n| Paralympics = yes\\n| logo = Lviv 2022 Winter Olym...'\n\n\n    \n    ['Lviv bid for the 2022 Winter Olympics', '==History==']\n\n\n\n    '[[Image:Lw\u00f3w - Rynek 01.JPG|thumb|right|200px|View of Rynok Square in Lviv]]\\n...'\n\n\n    \n    ['Lviv bid for the 2022 Winter Olympics', '==Venues==']\n\n\n\n    '{{Location map+\\n|Ukraine\\n|border =\\n|caption = Venue areas\\n|float = left\\n|widt...'\n\n\n    \n    ['Lviv bid for the 2022 Winter Olympics', '==Venues==', '===City zone===']\n\n\n\n    'The main Olympic Park would be centered around the [[Arena Lviv]], hosting th...'\n\n\n    \n    ['Lviv bid for the 2022 Winter Olympics', '==Venues==', '===Mountain zone===', '====Venue cluster Tysovets-Panasivka====']\n\n\n\n    'An existing military ski training facility in [[Tysovets, Skole Raion|Tysovet...'\n\n\n    \n\n\nNext, we'll recursively split long sections into smaller sections.\n\nThere's no perfect recipe for splitting text into sections.\n\nSome tradeoffs include:\n- Longer sections may be better for questions that require more context\n- Longer sections may be worse for retrieval, as they may have more topics muddled together\n- Shorter sections are better for reducing costs (which are proportional to the number of tokens)\n- Shorter sections allow more sections to be retrieved, which may help with recall\n- Overlapping sections may help prevent answers from being cut by section boundaries\n\nHere, we'll use a simple approach and limit sections to 1,600 tokens each, recursively halving any sections that are too long. To avoid cutting in the middle of useful sentences, we'll split along paragraph boundaries when possible.\n\n\n```python\nGPT_MODEL = \"gpt-3.5-turbo\"  # only matters insofar as it selects which tokenizer to use\n\n\ndef num_tokens(text: str, model: str = GPT_MODEL) -> int:\n    \"\"\"Return the number of tokens in a string.\"\"\"\n    encoding = tiktoken.encoding_for_model(model)\n    return len(encoding.encode(text))"}


created_at: 2024-07-28 18:59:18
topic: persistent://default/default/4bfc3c11-fb71-4cc9-8c12-01ed076a0e01
id: a3742526-681d-42fa-a1b9-177377867155
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/Embedding_Wikipedia_articles_for_search.ipynb", "title": "Embedding Wikipedia articles for search", "tokens": 4092, "retrieve_doc": true, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"a3742526-681d-42fa-a1b9-177377867155\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Embedding_Wikipedia_articles_for_search.ipynb\", \"title\": \"Embedding Wikipedia articles for search\", \"tokens\": 4092, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"7f4f2166-8e96-43f9-ae69-6d822bdfb0ff\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Embedding_Wikipedia_articles_for_search.ipynb\", \"title\": \"Embedding Wikipedia articles for search\", \"tokens\": 4092, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"8215343c9233df1c01dfdbaeefe91e68909b503c1cc90e947c8a8f0e951b2f47\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"a8c350e9-2076-4227-b10b-a7b8d9acb719\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Embedding_Wikipedia_articles_for_search.ipynb\", \"title\": \"Embedding Wikipedia articles for search\", \"tokens\": 4092, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"72188b5fecef06d3807bc35031bd0b60d6b47ea4cd3b0e7d96ac4fbf18e6793b\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"eae63fc8-6669-402f-ac0c-93ba6bb3fab5\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"9262974da17f999f2b938a2262e342d664fbc8a3f904ca70d63b3cc816ab6c41\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 8211, \"end_char_idx\": 11244, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "7f4f2166-8e96-43f9-ae69-6d822bdfb0ff", "doc_id": "7f4f2166-8e96-43f9-ae69-6d822bdfb0ff", "ref_doc_id": "7f4f2166-8e96-43f9-ae69-6d822bdfb0ff", "chroma:document": "'{{Location map+\\n|Ukraine\\n|border =\\n|caption = Venue areas\\n|float = left\\n|widt...'\n\n\n    \n    ['Lviv bid for the 2022 Winter Olympics', '==Venues==', '===City zone===']\n\n\n\n    'The main Olympic Park would be centered around the [[Arena Lviv]], hosting th...'\n\n\n    \n    ['Lviv bid for the 2022 Winter Olympics', '==Venues==', '===Mountain zone===', '====Venue cluster Tysovets-Panasivka====']\n\n\n\n    'An existing military ski training facility in [[Tysovets, Skole Raion|Tysovet...'\n\n\n    \n\n\nNext, we'll recursively split long sections into smaller sections.\n\nThere's no perfect recipe for splitting text into sections.\n\nSome tradeoffs include:\n- Longer sections may be better for questions that require more context\n- Longer sections may be worse for retrieval, as they may have more topics muddled together\n- Shorter sections are better for reducing costs (which are proportional to the number of tokens)\n- Shorter sections allow more sections to be retrieved, which may help with recall\n- Overlapping sections may help prevent answers from being cut by section boundaries\n\nHere, we'll use a simple approach and limit sections to 1,600 tokens each, recursively halving any sections that are too long. To avoid cutting in the middle of useful sentences, we'll split along paragraph boundaries when possible.\n\n\n```python\nGPT_MODEL = \"gpt-3.5-turbo\"  # only matters insofar as it selects which tokenizer to use\n\n\ndef num_tokens(text: str, model: str = GPT_MODEL) -> int:\n    \"\"\"Return the number of tokens in a string.\"\"\"\n    encoding = tiktoken.encoding_for_model(model)\n    return len(encoding.encode(text))\n\n\ndef halved_by_delimiter(string: str, delimiter: str = \"\\n\") -> list[str, str]:\n    \"\"\"Split a string in two, on a delimiter, trying to balance tokens on each side.\"\"\"\n    chunks = string.split(delimiter)\n    if len(chunks) == 1:\n        return [string, \"\"]  # no delimiter found\n    elif len(chunks) == 2:\n        return chunks  # no need to search for halfway point\n    else:\n        total_tokens = num_tokens(string)\n        halfway = total_tokens // 2\n        best_diff = halfway\n        for i, chunk in enumerate(chunks):\n            left = delimiter.join(chunks[: i + 1])\n            left_tokens = num_tokens(left)\n            diff = abs(halfway - left_tokens)\n            if diff >= best_diff:\n                break\n            else:\n                best_diff = diff\n        left = delimiter.join(chunks[:i])\n        right = delimiter.join(chunks[i:])\n        return [left, right]\n\n\ndef truncated_string(\n    string: str,\n    model: str,\n    max_tokens: int,\n    print_warning: bool = True,\n) -> str:\n    \"\"\"Truncate a string to a maximum number of tokens.\"\"\"\n    encoding = tiktoken.encoding_for_model(model)\n    encoded_string = encoding.encode(string)\n    truncated_string = encoding.decode(encoded_string[:max_tokens])\n    if print_warning and len(encoded_string) > max_tokens:\n        print(f\"Warning: Truncated string from {len(encoded_string)} tokens to {max_tokens} tokens.\")\n    return truncated_string"}


created_at: 2024-07-28 18:59:18
topic: persistent://default/default/4bfc3c11-fb71-4cc9-8c12-01ed076a0e01
id: eae63fc8-6669-402f-ac0c-93ba6bb3fab5
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/Embedding_Wikipedia_articles_for_search.ipynb", "title": "Embedding Wikipedia articles for search", "tokens": 4092, "retrieve_doc": true, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"eae63fc8-6669-402f-ac0c-93ba6bb3fab5\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Embedding_Wikipedia_articles_for_search.ipynb\", \"title\": \"Embedding Wikipedia articles for search\", \"tokens\": 4092, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"7f4f2166-8e96-43f9-ae69-6d822bdfb0ff\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Embedding_Wikipedia_articles_for_search.ipynb\", \"title\": \"Embedding Wikipedia articles for search\", \"tokens\": 4092, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"8215343c9233df1c01dfdbaeefe91e68909b503c1cc90e947c8a8f0e951b2f47\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"a3742526-681d-42fa-a1b9-177377867155\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Embedding_Wikipedia_articles_for_search.ipynb\", \"title\": \"Embedding Wikipedia articles for search\", \"tokens\": 4092, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"d3f9cbb9b9450377c6411a8c76ab4fb8eb20541fe70625b0aee467b0ced2d204\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"6f76b77b-28a6-465b-b33b-480c9b1bdde4\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"d0600a2d7fadbeb388d13462889003f391808220cbccc08090e5ee7ced8e6cc6\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 9628, \"end_char_idx\": 13049, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "7f4f2166-8e96-43f9-ae69-6d822bdfb0ff", "doc_id": "7f4f2166-8e96-43f9-ae69-6d822bdfb0ff", "ref_doc_id": "7f4f2166-8e96-43f9-ae69-6d822bdfb0ff", "chroma:document": "def num_tokens(text: str, model: str = GPT_MODEL) -> int:\n    \"\"\"Return the number of tokens in a string.\"\"\"\n    encoding = tiktoken.encoding_for_model(model)\n    return len(encoding.encode(text))\n\n\ndef halved_by_delimiter(string: str, delimiter: str = \"\\n\") -> list[str, str]:\n    \"\"\"Split a string in two, on a delimiter, trying to balance tokens on each side.\"\"\"\n    chunks = string.split(delimiter)\n    if len(chunks) == 1:\n        return [string, \"\"]  # no delimiter found\n    elif len(chunks) == 2:\n        return chunks  # no need to search for halfway point\n    else:\n        total_tokens = num_tokens(string)\n        halfway = total_tokens // 2\n        best_diff = halfway\n        for i, chunk in enumerate(chunks):\n            left = delimiter.join(chunks[: i + 1])\n            left_tokens = num_tokens(left)\n            diff = abs(halfway - left_tokens)\n            if diff >= best_diff:\n                break\n            else:\n                best_diff = diff\n        left = delimiter.join(chunks[:i])\n        right = delimiter.join(chunks[i:])\n        return [left, right]\n\n\ndef truncated_string(\n    string: str,\n    model: str,\n    max_tokens: int,\n    print_warning: bool = True,\n) -> str:\n    \"\"\"Truncate a string to a maximum number of tokens.\"\"\"\n    encoding = tiktoken.encoding_for_model(model)\n    encoded_string = encoding.encode(string)\n    truncated_string = encoding.decode(encoded_string[:max_tokens])\n    if print_warning and len(encoded_string) > max_tokens:\n        print(f\"Warning: Truncated string from {len(encoded_string)} tokens to {max_tokens} tokens.\")\n    return truncated_string\n\n\ndef split_strings_from_subsection(\n    subsection: tuple[list[str], str],\n    max_tokens: int = 1000,\n    model: str = GPT_MODEL,\n    max_recursion: int = 5,\n) -> list[str]:\n    \"\"\"\n    Split a subsection into a list of subsections, each with no more than max_tokens.\n    Each subsection is a tuple of parent titles [H1, H2, ...] and text (str).\n    \"\"\"\n    titles, text = subsection\n    string = \"\\n\\n\".join(titles + [text])\n    num_tokens_in_string = num_tokens(string)\n    # if length is fine, return string\n    if num_tokens_in_string <= max_tokens:\n        return [string]\n    # if recursion hasn't found a split after X iterations, just truncate\n    elif max_recursion == 0:\n        return [truncated_string(string, model=model, max_tokens=max_tokens)]\n    # otherwise, split in half and recurse\n    else:\n        titles, text = subsection\n        for delimiter in [\"\\n\\n\", \"\\n\", \". \"]:\n            left, right = halved_by_delimiter(text, delimiter=delimiter)\n            if left == \"\" or right == \"\":\n                # if either half is empty, retry with a more fine-grained delimiter\n                continue\n            else:\n                # recurse on each half\n                results = []\n                for half in [left, right]:\n                    half_subsection = (titles, half)\n                    half_strings = split_strings_from_subsection(\n                        half_subsection,\n                        max_tokens=max_tokens,\n                        model=model,\n                        max_recursion=max_recursion - 1,\n                    )\n                    results.extend(half_strings)\n                return results\n    # otherwise no split was found, so just truncate (should be very rare)\n    return [truncated_string(string, model=model, max_tokens=max_tokens)]\n\n```"}


created_at: 2024-07-28 18:59:18
topic: persistent://default/default/4bfc3c11-fb71-4cc9-8c12-01ed076a0e01
id: 6f76b77b-28a6-465b-b33b-480c9b1bdde4
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/Embedding_Wikipedia_articles_for_search.ipynb", "title": "Embedding Wikipedia articles for search", "tokens": 4092, "retrieve_doc": true, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"6f76b77b-28a6-465b-b33b-480c9b1bdde4\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Embedding_Wikipedia_articles_for_search.ipynb\", \"title\": \"Embedding Wikipedia articles for search\", \"tokens\": 4092, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"7f4f2166-8e96-43f9-ae69-6d822bdfb0ff\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Embedding_Wikipedia_articles_for_search.ipynb\", \"title\": \"Embedding Wikipedia articles for search\", \"tokens\": 4092, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"8215343c9233df1c01dfdbaeefe91e68909b503c1cc90e947c8a8f0e951b2f47\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"eae63fc8-6669-402f-ac0c-93ba6bb3fab5\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Embedding_Wikipedia_articles_for_search.ipynb\", \"title\": \"Embedding Wikipedia articles for search\", \"tokens\": 4092, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"d7a1258bd016f6c0d9393b3b19896fa9d9cfebc6dd7188bbd59b19cc14ba5e00\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"4d3833ac-28e8-4afe-8d00-a0cae8b4c77e\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"03a3f10f5abeb9397fa17a2edcedc1a05eed3edeaadde150b4c31f3e2fbd6173\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 11247, \"end_char_idx\": 13418, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "7f4f2166-8e96-43f9-ae69-6d822bdfb0ff", "doc_id": "7f4f2166-8e96-43f9-ae69-6d822bdfb0ff", "ref_doc_id": "7f4f2166-8e96-43f9-ae69-6d822bdfb0ff", "chroma:document": "def split_strings_from_subsection(\n    subsection: tuple[list[str], str],\n    max_tokens: int = 1000,\n    model: str = GPT_MODEL,\n    max_recursion: int = 5,\n) -> list[str]:\n    \"\"\"\n    Split a subsection into a list of subsections, each with no more than max_tokens.\n    Each subsection is a tuple of parent titles [H1, H2, ...] and text (str).\n    \"\"\"\n    titles, text = subsection\n    string = \"\\n\\n\".join(titles + [text])\n    num_tokens_in_string = num_tokens(string)\n    # if length is fine, return string\n    if num_tokens_in_string <= max_tokens:\n        return [string]\n    # if recursion hasn't found a split after X iterations, just truncate\n    elif max_recursion == 0:\n        return [truncated_string(string, model=model, max_tokens=max_tokens)]\n    # otherwise, split in half and recurse\n    else:\n        titles, text = subsection\n        for delimiter in [\"\\n\\n\", \"\\n\", \". \"]:\n            left, right = halved_by_delimiter(text, delimiter=delimiter)\n            if left == \"\" or right == \"\":\n                # if either half is empty, retry with a more fine-grained delimiter\n                continue\n            else:\n                # recurse on each half\n                results = []\n                for half in [left, right]:\n                    half_subsection = (titles, half)\n                    half_strings = split_strings_from_subsection(\n                        half_subsection,\n                        max_tokens=max_tokens,\n                        model=model,\n                        max_recursion=max_recursion - 1,\n                    )\n                    results.extend(half_strings)\n                return results\n    # otherwise no split was found, so just truncate (should be very rare)\n    return [truncated_string(string, model=model, max_tokens=max_tokens)]\n\n```\n\n\n```python\n# split sections into chunks\nMAX_TOKENS = 1600\nwikipedia_strings = []\nfor section in wikipedia_sections:\n    wikipedia_strings.extend(split_strings_from_subsection(section, max_tokens=MAX_TOKENS))\n\nprint(f\"{len(wikipedia_sections)} Wikipedia sections split into {len(wikipedia_strings)} strings.\")\n\n```\n\n    5200 Wikipedia sections split into 6059 strings."}


created_at: 2024-07-28 18:59:18
topic: persistent://default/default/4bfc3c11-fb71-4cc9-8c12-01ed076a0e01
id: 4d3833ac-28e8-4afe-8d00-a0cae8b4c77e
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/Embedding_Wikipedia_articles_for_search.ipynb", "title": "Embedding Wikipedia articles for search", "tokens": 4092, "retrieve_doc": true, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"4d3833ac-28e8-4afe-8d00-a0cae8b4c77e\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Embedding_Wikipedia_articles_for_search.ipynb\", \"title\": \"Embedding Wikipedia articles for search\", \"tokens\": 4092, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"7f4f2166-8e96-43f9-ae69-6d822bdfb0ff\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Embedding_Wikipedia_articles_for_search.ipynb\", \"title\": \"Embedding Wikipedia articles for search\", \"tokens\": 4092, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"8215343c9233df1c01dfdbaeefe91e68909b503c1cc90e947c8a8f0e951b2f47\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"6f76b77b-28a6-465b-b33b-480c9b1bdde4\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Embedding_Wikipedia_articles_for_search.ipynb\", \"title\": \"Embedding Wikipedia articles for search\", \"tokens\": 4092, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"bb76f19be42be0c32e510658253236da270b2ce6fdefa6562ff37775a295e00f\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"20743042-9170-4d2e-bae6-065d6431e028\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"718d3a26e40cb050b114ec7bfa6bc261ad029897cdb8a6345beb434b43436e3a\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 13052, \"end_char_idx\": 16232, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "7f4f2166-8e96-43f9-ae69-6d822bdfb0ff", "doc_id": "7f4f2166-8e96-43f9-ae69-6d822bdfb0ff", "ref_doc_id": "7f4f2166-8e96-43f9-ae69-6d822bdfb0ff", "chroma:document": "```python\n# split sections into chunks\nMAX_TOKENS = 1600\nwikipedia_strings = []\nfor section in wikipedia_sections:\n    wikipedia_strings.extend(split_strings_from_subsection(section, max_tokens=MAX_TOKENS))\n\nprint(f\"{len(wikipedia_sections)} Wikipedia sections split into {len(wikipedia_strings)} strings.\")\n\n```\n\n    5200 Wikipedia sections split into 6059 strings.\n\n\n\n```python\n# print example data\nprint(wikipedia_strings[1])\n\n```\n\n    Lviv bid for the 2022 Winter Olympics\n    \n    ==History==\n    \n    [[Image:Lw\u00f3w - Rynek 01.JPG|thumb|right|200px|View of Rynok Square in Lviv]]\n    \n    On 27 May 2010, [[President of Ukraine]] [[Viktor Yanukovych]] stated during a visit to [[Lviv]] that Ukraine \"will start working on the official nomination of our country as the holder of the Winter Olympic Games in [[Carpathian Mountains|Carpathians]]\".\n    \n    In September 2012, [[government of Ukraine]] approved a document about the technical-economic substantiation of the national project \"Olympic Hope 2022\". This was announced by Vladyslav Kaskiv, the head of Ukraine\u00b4s Derzhinvestproekt (State investment project). The organizers announced on their website venue plans featuring Lviv as the host city and location for the \"ice sport\" venues, [[Volovets]] (around {{convert|185|km|mi|abbr=on}} from Lviv) as venue for the [[Alpine skiing]] competitions and [[Tysovets, Skole Raion|Tysovets]] (around {{convert|130|km|mi|abbr=on}} from Lviv) as venue for all other \"snow sport\" competitions. By March 2013 no other preparations than the feasibility study had been approved.\n    \n    On 24 October 2013, session of the Lviv City Council adopted a resolution \"About submission to the International Olympic Committee for nomination of city to participate in the procedure for determining the host city of Olympic and Paralympic Winter Games in 2022\".\n    \n    On 5 November 2013, it was confirmed that Lviv was bidding to host the [[2022 Winter Olympics]]. Lviv would host the ice sport events, while the skiing events would be held in the [[Carpathian]] mountains. This was the first bid Ukraine had ever submitted for an Olympic Games.\n    \n    On 30 June 2014, the International Olympic Committee announced \"Lviv will turn its attention to an Olympic bid for 2026, and not continue with its application for 2022. The decision comes as a result of the present political and economic circumstances in Ukraine.\"\n    \n    Ukraine's Deputy Prime Minister Oleksandr Vilkul said that the Winter Games \"will be an impetus not just for promotion of sports and tourism in Ukraine, but a very important component in the economic development of Ukraine, the attraction of the investments, the creation of new jobs, opening Ukraine to the world, returning Ukrainians working abroad to their motherland.\"\n    \n    Lviv was one of the host cities of [[UEFA Euro 2012]].\n\n\n## 3. Embed document chunks\n\nNow that we've split our library into shorter self-contained strings, we can compute embeddings for each.\n\n(For large embedding jobs, use a script like [api_request_parallel_processor.py](api_request_parallel_processor.py) to parallelize requests while throttling to stay under rate limits.)"}


created_at: 2024-07-28 18:59:18
topic: persistent://default/default/4bfc3c11-fb71-4cc9-8c12-01ed076a0e01
id: 20743042-9170-4d2e-bae6-065d6431e028
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/Embedding_Wikipedia_articles_for_search.ipynb", "title": "Embedding Wikipedia articles for search", "tokens": 4092, "retrieve_doc": true, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"20743042-9170-4d2e-bae6-065d6431e028\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Embedding_Wikipedia_articles_for_search.ipynb\", \"title\": \"Embedding Wikipedia articles for search\", \"tokens\": 4092, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"7f4f2166-8e96-43f9-ae69-6d822bdfb0ff\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Embedding_Wikipedia_articles_for_search.ipynb\", \"title\": \"Embedding Wikipedia articles for search\", \"tokens\": 4092, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"8215343c9233df1c01dfdbaeefe91e68909b503c1cc90e947c8a8f0e951b2f47\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"4d3833ac-28e8-4afe-8d00-a0cae8b4c77e\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Embedding_Wikipedia_articles_for_search.ipynb\", \"title\": \"Embedding Wikipedia articles for search\", \"tokens\": 4092, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"0650e99c38d7c4b15e9105319e5611dc1e45f9cf1a0d3ce6d7090476b2d62cd3\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 15912, \"end_char_idx\": 17474, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "7f4f2166-8e96-43f9-ae69-6d822bdfb0ff", "doc_id": "7f4f2166-8e96-43f9-ae69-6d822bdfb0ff", "ref_doc_id": "7f4f2166-8e96-43f9-ae69-6d822bdfb0ff", "chroma:document": "## 3. Embed document chunks\n\nNow that we've split our library into shorter self-contained strings, we can compute embeddings for each.\n\n(For large embedding jobs, use a script like [api_request_parallel_processor.py](api_request_parallel_processor.py) to parallelize requests while throttling to stay under rate limits.)\n\n\n```python\nEMBEDDING_MODEL = \"text-embedding-3-small\"\nBATCH_SIZE = 1000  # you can submit up to 2048 embedding inputs per request\n\nembeddings = []\nfor batch_start in range(0, len(wikipedia_strings), BATCH_SIZE):\n    batch_end = batch_start + BATCH_SIZE\n    batch = wikipedia_strings[batch_start:batch_end]\n    print(f\"Batch {batch_start} to {batch_end-1}\")\n    response = client.embeddings.create(model=EMBEDDING_MODEL, input=batch)\n    for i, be in enumerate(response.data):\n        assert i == be.index  # double check embeddings are in same order as input\n    batch_embeddings = [e.embedding for e in response.data]\n    embeddings.extend(batch_embeddings)\n\ndf = pd.DataFrame({\"text\": wikipedia_strings, \"embedding\": embeddings})\n\n```\n\n    Batch 0 to 999\n    Batch 1000 to 1999\n    Batch 2000 to 2999\n    Batch 3000 to 3999\n    Batch 4000 to 4999\n    Batch 5000 to 5999\n    Batch 6000 to 6999\n\n\n## 4. Store document chunks and embeddings\n\nBecause this example only uses a few thousand strings, we'll store them in a CSV file.\n\n(For larger datasets, use a vector database, which will be more performant.)\n\n\n```python\n# save document chunks and embeddings\n\nSAVE_PATH = \"data/winter_olympics_2022.csv\"\n\ndf.to_csv(SAVE_PATH, index=False)\n\n```"}


created_at: 2024-07-28 18:59:18
topic: persistent://default/default/4bfc3c11-fb71-4cc9-8c12-01ed076a0e01
id: 42b61574-597a-4f6a-a902-63a11369fe19
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/How_to_format_inputs_to_ChatGPT_models.ipynb", "title": "How to format inputs to ChatGPT models", "tokens": 5687, "retrieve_doc": true, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"42b61574-597a-4f6a-a902-63a11369fe19\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_format_inputs_to_ChatGPT_models.ipynb\", \"title\": \"How to format inputs to ChatGPT models\", \"tokens\": 5687, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"71c92695-4020-4f60-855c-1659cbec1ae1\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_format_inputs_to_ChatGPT_models.ipynb\", \"title\": \"How to format inputs to ChatGPT models\", \"tokens\": 5687, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"7c48481b2944edc8213def44183cf00818458397e592cb1568a4cec646d5cf79\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"a72224e2-6469-451b-b1a6-a323b1bd4133\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"4dec753a6ccb3ac73b93413931f424fd9c2cf3644c9c8f1239090da0848e7f16\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 0, \"end_char_idx\": 2576, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "71c92695-4020-4f60-855c-1659cbec1ae1", "doc_id": "71c92695-4020-4f60-855c-1659cbec1ae1", "ref_doc_id": "71c92695-4020-4f60-855c-1659cbec1ae1", "chroma:document": "# How to format inputs to ChatGPT models\n\nChatGPT is powered by `gpt-3.5-turbo` and `gpt-4`, OpenAI's most advanced models.\n\nYou can build your own applications with `gpt-3.5-turbo` or `gpt-4` using the OpenAI API.\n\nChat models take a series of messages as input, and return an AI-written message as output.\n\nThis guide illustrates the chat format with a few example API calls.\n\n## 1. Import the openai library\n\n\n```python\n# if needed, install and/or upgrade to the latest version of the OpenAI Python library\n%pip install --upgrade openai\n\n```\n\n\n```python\n# import the OpenAI Python library for calling the OpenAI API\nfrom openai import OpenAI\nimport os\n\nclient = OpenAI(api_key=os.environ.get(\"OPENAI_API_KEY\", \"<your OpenAI API key if not set as env var>\"))\n```\n\n## 2. An example chat completion API call\n\nA chat completion API call parameters,\n**Required**\n- `model`: the name of the model you want to use (e.g., `gpt-3.5-turbo`, `gpt-4`, `gpt-3.5-turbo-16k-1106`)\n- `messages`: a list of message objects, where each object has two required fields:\n    - `role`: the role of the messenger (either `system`, `user`, `assistant` or `tool`)\n    - `content`: the content of the message (e.g., `Write me a beautiful poem`)\n\nMessages can also contain an optional `name` field, which give the messenger a name. E.g., `example-user`, `Alice`, `BlackbeardBot`. Names may not contain spaces.\n\n**Optional**\n- `frequency_penalty`: Penalizes tokens based on their frequency, reducing repetition.\n- `logit_bias`: Modifies likelihood of specified tokens with bias values.\n- `logprobs`: Returns log probabilities of output tokens if true.\n- `top_logprobs`: Specifies the number of most likely tokens to return at each position.\n- `max_tokens`: Sets the maximum number of generated tokens in chat completion.\n- `n`: Generates a specified number of chat completion choices for each input.\n- `presence_penalty`: Penalizes new tokens based on their presence in the text.\n- `response_format`: Specifies the output format, e.g., JSON mode.\n- `seed`: Ensures deterministic sampling with a specified seed.\n- `stop`: Specifies up to 4 sequences where the API should stop generating tokens.\n- `stream`: Sends partial message deltas as tokens become available.\n- `temperature`: Sets the sampling temperature between 0 and 2.\n- `top_p`: Uses nucleus sampling; considers tokens with top_p probability mass.\n- `tools`: Lists functions the model may call.\n- `tool_choice`: Controls the model's function calls (none/auto/function).\n- `user`: Unique identifier for end-user monitoring and abuse detection."}


created_at: 2024-07-28 18:59:18
topic: persistent://default/default/4bfc3c11-fb71-4cc9-8c12-01ed076a0e01
id: a72224e2-6469-451b-b1a6-a323b1bd4133
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/How_to_format_inputs_to_ChatGPT_models.ipynb", "title": "How to format inputs to ChatGPT models", "tokens": 5687, "retrieve_doc": true, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"a72224e2-6469-451b-b1a6-a323b1bd4133\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_format_inputs_to_ChatGPT_models.ipynb\", \"title\": \"How to format inputs to ChatGPT models\", \"tokens\": 5687, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"71c92695-4020-4f60-855c-1659cbec1ae1\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_format_inputs_to_ChatGPT_models.ipynb\", \"title\": \"How to format inputs to ChatGPT models\", \"tokens\": 5687, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"7c48481b2944edc8213def44183cf00818458397e592cb1568a4cec646d5cf79\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"42b61574-597a-4f6a-a902-63a11369fe19\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_format_inputs_to_ChatGPT_models.ipynb\", \"title\": \"How to format inputs to ChatGPT models\", \"tokens\": 5687, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"a862f3dfa6b6a0cb3a26aef9d2881fd5be3752f25ccf8f06d0e92f50a62b0936\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"72fc7957-1c13-42a8-b8d4-1de67b0178d2\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"7bf6863c6b5a4e1149307801a62b66f77b4f1e8ea9c3f578690c69e14759df3a\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 2579, \"end_char_idx\": 5683, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "71c92695-4020-4f60-855c-1659cbec1ae1", "doc_id": "71c92695-4020-4f60-855c-1659cbec1ae1", "ref_doc_id": "71c92695-4020-4f60-855c-1659cbec1ae1", "chroma:document": "As of January 2024, you can also optionally submit a list of `functions` that tell GPT whether it can generate JSON to feed into a function. For details, see the [documentation](https://platform.openai.com/docs/guides/function-calling), [API reference](https://platform.openai.com/docs/api-reference/chat), or the Cookbook guide [How to call functions with chat models](How_to_call_functions_with_chat_models.ipynb).\n\nTypically, a conversation will start with a system message that tells the assistant how to behave, followed by alternating user and assistant messages, but you are not required to follow this format.\n\nLet's look at an example chat API calls to see how the chat format works in practice.\n\n\n```python\n# Example OpenAI Python library request\nMODEL = \"gpt-3.5-turbo\"\nresponse = client.chat.completions.create(\n    model=MODEL,\n    messages=[\n        {\"role\": \"system\", \"content\": \"You are a helpful assistant.\"},\n        {\"role\": \"user\", \"content\": \"Knock knock.\"},\n        {\"role\": \"assistant\", \"content\": \"Who's there?\"},\n        {\"role\": \"user\", \"content\": \"Orange.\"},\n    ],\n    temperature=0,\n)\n\n```\n\n\n```python\nprint(json.dumps(json.loads(response.model_dump_json()), indent=4))\n```\n\n    {\n        \"id\": \"chatcmpl-8dee9DuEFcg2QILtT2a6EBXZnpirM\",\n        \"choices\": [\n            {\n                \"finish_reason\": \"stop\",\n                \"index\": 0,\n                \"logprobs\": null,\n                \"message\": {\n                    \"content\": \"Orange who?\",\n                    \"role\": \"assistant\",\n                    \"function_call\": null,\n                    \"tool_calls\": null\n                }\n            }\n        ],\n        \"created\": 1704461729,\n        \"model\": \"gpt-3.5-turbo-0613\",\n        \"object\": \"chat.completion\",\n        \"system_fingerprint\": null,\n        \"usage\": {\n            \"completion_tokens\": 3,\n            \"prompt_tokens\": 35,\n            \"total_tokens\": 38\n        }\n    }\n\n\nAs you can see, the response object has a few fields:\n- `id`: the ID of the request\n- `choices`: a list of completion objects (only one, unless you set `n` greater than 1)\n    - `finish_reason`: the reason the model stopped generating text (either `stop`, or `length` if `max_tokens` limit was reached)\n    - `index`: The index of the choice in the list of choices.\n    - `logprobs`: Log probability information for the choice.\n    - `message`: the message object generated by the model\n        - `content`: content of message\n        - `role`: The role of the author of this message.\n        - `tool_calls`: The tool calls generated by the model, such as function calls. if the tools is given\n- `created`: the timestamp of the request\n- `model`: the full name of the model used to generate the response\n- `object`: the type of object returned (e.g., `chat.completion`)\n- `system_fingerprint`: This fingerprint represents the backend configuration that the model runs with.\n- `usage`: the number of tokens used to generate the replies, counting prompt, completion, and total\n\nExtract just the reply with:\n\n\n```python\nresponse.choices[0].message.content\n\n```\n\n\n\n\n    'Orange who?'"}


created_at: 2024-07-28 18:59:18
topic: persistent://default/default/4bfc3c11-fb71-4cc9-8c12-01ed076a0e01
id: 72fc7957-1c13-42a8-b8d4-1de67b0178d2
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/How_to_format_inputs_to_ChatGPT_models.ipynb", "title": "How to format inputs to ChatGPT models", "tokens": 5687, "retrieve_doc": true, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"72fc7957-1c13-42a8-b8d4-1de67b0178d2\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_format_inputs_to_ChatGPT_models.ipynb\", \"title\": \"How to format inputs to ChatGPT models\", \"tokens\": 5687, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"71c92695-4020-4f60-855c-1659cbec1ae1\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_format_inputs_to_ChatGPT_models.ipynb\", \"title\": \"How to format inputs to ChatGPT models\", \"tokens\": 5687, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"7c48481b2944edc8213def44183cf00818458397e592cb1568a4cec646d5cf79\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"a72224e2-6469-451b-b1a6-a323b1bd4133\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_format_inputs_to_ChatGPT_models.ipynb\", \"title\": \"How to format inputs to ChatGPT models\", \"tokens\": 5687, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"2015b98716ca258c45a9301f33f760d1378e6f5a04756f4646d97982b6e50e78\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"ad44e071-243a-4cdb-93c3-f2bcd2554b26\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"be5ed72e0863a08a06d0636c7468a80fa120f48c410be10dd035d21a952e5a1c\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 4504, \"end_char_idx\": 5952, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "71c92695-4020-4f60-855c-1659cbec1ae1", "doc_id": "71c92695-4020-4f60-855c-1659cbec1ae1", "ref_doc_id": "71c92695-4020-4f60-855c-1659cbec1ae1", "chroma:document": "As you can see, the response object has a few fields:\n- `id`: the ID of the request\n- `choices`: a list of completion objects (only one, unless you set `n` greater than 1)\n    - `finish_reason`: the reason the model stopped generating text (either `stop`, or `length` if `max_tokens` limit was reached)\n    - `index`: The index of the choice in the list of choices.\n    - `logprobs`: Log probability information for the choice.\n    - `message`: the message object generated by the model\n        - `content`: content of message\n        - `role`: The role of the author of this message.\n        - `tool_calls`: The tool calls generated by the model, such as function calls. if the tools is given\n- `created`: the timestamp of the request\n- `model`: the full name of the model used to generate the response\n- `object`: the type of object returned (e.g., `chat.completion`)\n- `system_fingerprint`: This fingerprint represents the backend configuration that the model runs with.\n- `usage`: the number of tokens used to generate the replies, counting prompt, completion, and total\n\nExtract just the reply with:\n\n\n```python\nresponse.choices[0].message.content\n\n```\n\n\n\n\n    'Orange who?'\n\n\n\nEven non-conversation-based tasks can fit into the chat format, by placing the instruction in the first user message.\n\nFor example, to ask the model to explain asynchronous programming in the style of the pirate Blackbeard, we can structure conversation as follows:"}


created_at: 2024-07-28 18:59:18
topic: persistent://default/default/4bfc3c11-fb71-4cc9-8c12-01ed076a0e01
id: ad44e071-243a-4cdb-93c3-f2bcd2554b26
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/How_to_format_inputs_to_ChatGPT_models.ipynb", "title": "How to format inputs to ChatGPT models", "tokens": 5687, "retrieve_doc": true, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"ad44e071-243a-4cdb-93c3-f2bcd2554b26\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_format_inputs_to_ChatGPT_models.ipynb\", \"title\": \"How to format inputs to ChatGPT models\", \"tokens\": 5687, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"71c92695-4020-4f60-855c-1659cbec1ae1\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_format_inputs_to_ChatGPT_models.ipynb\", \"title\": \"How to format inputs to ChatGPT models\", \"tokens\": 5687, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"7c48481b2944edc8213def44183cf00818458397e592cb1568a4cec646d5cf79\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"72fc7957-1c13-42a8-b8d4-1de67b0178d2\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_format_inputs_to_ChatGPT_models.ipynb\", \"title\": \"How to format inputs to ChatGPT models\", \"tokens\": 5687, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"9a732caaac850ea12746870547a0dce795a4ba17c17dd2bc7cb9944ed18f8c15\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"2c8fb90e-2695-48aa-b664-3d328e9ad19e\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"7ba9b13400d2056690a65416b53e468599581932ac4ee8d9a98089eab32ec03f\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 4504, \"end_char_idx\": 8544, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "71c92695-4020-4f60-855c-1659cbec1ae1", "doc_id": "71c92695-4020-4f60-855c-1659cbec1ae1", "ref_doc_id": "71c92695-4020-4f60-855c-1659cbec1ae1", "chroma:document": "As you can see, the response object has a few fields:\n- `id`: the ID of the request\n- `choices`: a list of completion objects (only one, unless you set `n` greater than 1)\n    - `finish_reason`: the reason the model stopped generating text (either `stop`, or `length` if `max_tokens` limit was reached)\n    - `index`: The index of the choice in the list of choices.\n    - `logprobs`: Log probability information for the choice.\n    - `message`: the message object generated by the model\n        - `content`: content of message\n        - `role`: The role of the author of this message.\n        - `tool_calls`: The tool calls generated by the model, such as function calls. if the tools is given\n- `created`: the timestamp of the request\n- `model`: the full name of the model used to generate the response\n- `object`: the type of object returned (e.g., `chat.completion`)\n- `system_fingerprint`: This fingerprint represents the backend configuration that the model runs with.\n- `usage`: the number of tokens used to generate the replies, counting prompt, completion, and total\n\nExtract just the reply with:\n\n\n```python\nresponse.choices[0].message.content\n\n```\n\n\n\n\n    'Orange who?'\n\n\n\nEven non-conversation-based tasks can fit into the chat format, by placing the instruction in the first user message.\n\nFor example, to ask the model to explain asynchronous programming in the style of the pirate Blackbeard, we can structure conversation as follows:\n\n\n```python\n# example with a system message\nresponse = client.chat.completions.create(\n    model=MODEL,\n    messages=[\n        {\"role\": \"system\", \"content\": \"You are a helpful assistant.\"},\n        {\"role\": \"user\", \"content\": \"Explain asynchronous programming in the style of the pirate Blackbeard.\"},\n    ],\n    temperature=0,\n)\n\nprint(response.choices[0].message.content)\n\n```\n\n    Arr, me matey! Let me tell ye a tale of asynchronous programming, in the style of the fearsome pirate Blackbeard!\n    \n    Picture this, me hearties. In the vast ocean of programming, there be times when ye need to perform multiple tasks at once. But fear not, for asynchronous programming be here to save the day!\n    \n    Ye see, in traditional programming, ye be waitin' for one task to be done before movin' on to the next. But with asynchronous programming, ye can be takin' care of multiple tasks at the same time, just like a pirate multitaskin' on the high seas!\n    \n    Instead of waitin' for a task to be completed, ye can be sendin' it off on its own journey, while ye move on to the next task. It be like havin' a crew of trusty sailors, each takin' care of their own duties, without waitin' for the others.\n    \n    Now, ye may be wonderin', how does this sorcery work? Well, me matey, it be all about callbacks and promises. When ye be sendin' off a task, ye be attachin' a callback function to it. This be like leavin' a message in a bottle, tellin' the task what to do when it be finished.\n    \n    While the task be sailin' on its own, ye can be movin' on to the next task, without wastin' any precious time. And when the first task be done, it be sendin' a signal back to ye, lettin' ye know it be finished. Then ye can be takin' care of the callback function, like openin' the bottle and readin' the message inside.\n    \n    But wait, there be more! With promises, ye can be makin' even fancier arrangements. Instead of callbacks, ye be makin' a promise that the task will be completed. It be like a contract between ye and the task, swearin' that it will be done.\n    \n    Ye can be attachin' multiple promises to a task, promisin' different outcomes. And when the task be finished, it be fulfillin' the promises, lettin' ye know it be done. Then ye can be handlin' the fulfillments, like collectin' the rewards of yer pirate adventures!\n    \n    So, me hearties, that be the tale of asynchronous programming, told in the style of the fearsome pirate Blackbeard! With callbacks and promises, ye can be takin' care of multiple tasks at once, just like a pirate conquerin' the seven seas!"}


created_at: 2024-07-28 18:59:18
topic: persistent://default/default/4bfc3c11-fb71-4cc9-8c12-01ed076a0e01
id: 2c8fb90e-2695-48aa-b664-3d328e9ad19e
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/How_to_format_inputs_to_ChatGPT_models.ipynb", "title": "How to format inputs to ChatGPT models", "tokens": 5687, "retrieve_doc": true, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"2c8fb90e-2695-48aa-b664-3d328e9ad19e\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_format_inputs_to_ChatGPT_models.ipynb\", \"title\": \"How to format inputs to ChatGPT models\", \"tokens\": 5687, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"71c92695-4020-4f60-855c-1659cbec1ae1\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_format_inputs_to_ChatGPT_models.ipynb\", \"title\": \"How to format inputs to ChatGPT models\", \"tokens\": 5687, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"7c48481b2944edc8213def44183cf00818458397e592cb1568a4cec646d5cf79\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"ad44e071-243a-4cdb-93c3-f2bcd2554b26\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_format_inputs_to_ChatGPT_models.ipynb\", \"title\": \"How to format inputs to ChatGPT models\", \"tokens\": 5687, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"ff6633b713086fc185e4cf37795228bc326c9a8401e9eb49ef7762f4e48f2d6f\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"27b6148c-d846-441c-9571-411cf098577a\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"45bef14035f7ebe9ef30490d89d70fc3ef99c6cc66668d446872aede9da11558\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 8548, \"end_char_idx\": 11484, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "71c92695-4020-4f60-855c-1659cbec1ae1", "doc_id": "71c92695-4020-4f60-855c-1659cbec1ae1", "ref_doc_id": "71c92695-4020-4f60-855c-1659cbec1ae1", "chroma:document": "```python\n# example without a system message\nresponse = client.chat.completions.create(\n    model=MODEL,\n    messages=[\n        {\"role\": \"user\", \"content\": \"Explain asynchronous programming in the style of the pirate Blackbeard.\"},\n    ],\n    temperature=0,\n)\n\nprint(response.choices[0].message.content)\n\n```\n\n    Arr, me hearties! Gather 'round and listen up, for I be tellin' ye about the mysterious art of asynchronous programming, in the style of the fearsome pirate Blackbeard!\n    \n    Now, ye see, in the world of programming, there be times when we need to perform tasks that take a mighty long time to complete. These tasks might involve fetchin' data from the depths of the internet, or performin' complex calculations that would make even Davy Jones scratch his head.\n    \n    In the olden days, we pirates used to wait patiently for each task to finish afore movin' on to the next one. But that be a waste of precious time, me hearties! We be pirates, always lookin' for ways to be more efficient and plunder more booty!\n    \n    That be where asynchronous programming comes in, me mateys. It be a way to tackle multiple tasks at once, without waitin' for each one to finish afore movin' on. It be like havin' a crew of scallywags workin' on different tasks simultaneously, while ye be overseein' the whole operation.\n    \n    Ye see, in asynchronous programming, we be breakin' down our tasks into smaller chunks called \"coroutines.\" Each coroutine be like a separate pirate, workin' on its own task. When a coroutine be startin' its work, it don't wait for the task to finish afore movin' on to the next one. Instead, it be movin' on to the next task, lettin' the first one continue in the background.\n    \n    Now, ye might be wonderin', \"But Blackbeard, how be we know when a task be finished if we don't wait for it?\" Ah, me hearties, that be where the magic of callbacks and promises come in!\n    \n    When a coroutine be startin' its work, it be attachin' a callback or a promise to it. This be like leavin' a message in a bottle, tellin' the coroutine what to do when it be finished. So, while the coroutine be workin' away, the rest of the crew be movin' on to other tasks, plunderin' more booty along the way.\n    \n    When a coroutine be finished with its task, it be sendin' a signal to the callback or fulfillin' the promise, lettin' the rest of the crew know that it be done. Then, the crew can gather 'round and handle the results of the completed task, celebratin' their victory and countin' their plunder.\n    \n    So, me hearties, asynchronous programming be like havin' a crew of pirates workin' on different tasks at once, without waitin' for each one to finish afore movin' on. It be a way to be more efficient, plunder more booty, and conquer the vast seas of programming!\n    \n    Now, set sail, me mateys, and embrace the power of asynchronous programming like true pirates of the digital realm! Arr!"}


created_at: 2024-07-28 18:59:18
topic: persistent://default/default/4bfc3c11-fb71-4cc9-8c12-01ed076a0e01
id: 27b6148c-d846-441c-9571-411cf098577a
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/How_to_format_inputs_to_ChatGPT_models.ipynb", "title": "How to format inputs to ChatGPT models", "tokens": 5687, "retrieve_doc": true, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"27b6148c-d846-441c-9571-411cf098577a\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_format_inputs_to_ChatGPT_models.ipynb\", \"title\": \"How to format inputs to ChatGPT models\", \"tokens\": 5687, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"71c92695-4020-4f60-855c-1659cbec1ae1\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_format_inputs_to_ChatGPT_models.ipynb\", \"title\": \"How to format inputs to ChatGPT models\", \"tokens\": 5687, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"7c48481b2944edc8213def44183cf00818458397e592cb1568a4cec646d5cf79\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"2c8fb90e-2695-48aa-b664-3d328e9ad19e\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_format_inputs_to_ChatGPT_models.ipynb\", \"title\": \"How to format inputs to ChatGPT models\", \"tokens\": 5687, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"144774a3450dd3bafef8e372cf727f1f16cd6920fc31d4a684927182d3e06874\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"977c59d7-4962-44c2-a4d9-0090a66eecdc\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"60833d3ef16ded3c94b9de0fa1c2cc6934fb80a09b955d439522768b96d9b24e\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 11487, \"end_char_idx\": 14789, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "71c92695-4020-4f60-855c-1659cbec1ae1", "doc_id": "71c92695-4020-4f60-855c-1659cbec1ae1", "ref_doc_id": "71c92695-4020-4f60-855c-1659cbec1ae1", "chroma:document": "## 3. Tips for instructing gpt-3.5-turbo-0301\n\nBest practices for instructing models may change from model version to model version. The advice that follows applies to `gpt-3.5-turbo-0301` and may not apply to future models.\n\n### System messages\n\nThe system message can be used to prime the assistant with different personalities or behaviors.\n\nBe aware that `gpt-3.5-turbo-0301` does not generally pay as much attention to the system message as `gpt-4-0314` or `gpt-3.5-turbo-0613`. Therefore, for `gpt-3.5-turbo-0301`, we recommend placing important instructions in the user message instead. Some developers have found success in continually moving the system message near the end of the conversation to keep the model's attention from drifting away as conversations get longer.\n\n\n```python\n# An example of a system message that primes the assistant to explain concepts in great depth\nresponse = client.chat.completions.create(\n    model=MODEL,\n    messages=[\n        {\"role\": \"system\", \"content\": \"You are a friendly and helpful teaching assistant. You explain concepts in great depth using simple terms, and you give examples to help people learn. At the end of each explanation, you ask a question to check for understanding\"},\n        {\"role\": \"user\", \"content\": \"Can you explain how fractions work?\"},\n    ],\n    temperature=0,\n)\n\nprint(response.choices[0].message.content)\n\n```\n\n    Of course! Fractions are a way to represent parts of a whole. They are made up of two numbers: a numerator and a denominator. The numerator tells you how many parts you have, and the denominator tells you how many equal parts make up the whole.\n    \n    Let's take an example to understand this better. Imagine you have a pizza that is divided into 8 equal slices. If you eat 3 slices, you can represent that as the fraction 3/8. Here, the numerator is 3 because you ate 3 slices, and the denominator is 8 because the whole pizza is divided into 8 slices.\n    \n    Fractions can also be used to represent numbers less than 1. For example, if you eat half of a pizza, you can write it as 1/2. Here, the numerator is 1 because you ate one slice, and the denominator is 2 because the whole pizza is divided into 2 equal parts.\n    \n    Now, let's talk about equivalent fractions. Equivalent fractions are different fractions that represent the same amount. For example, 1/2 and 2/4 are equivalent fractions because they both represent half of something. To find equivalent fractions, you can multiply or divide both the numerator and denominator by the same number.\n    \n    Here's a question to check your understanding: If you have a cake divided into 12 equal slices and you eat 4 slices, what fraction of the cake did you eat?\n\n\n\n```python\n# An example of a system message that primes the assistant to give brief, to-the-point answers\nresponse = client.chat.completions.create(\n    model=MODEL,\n    messages=[\n        {\"role\": \"system\", \"content\": \"You are a laconic assistant. You reply with brief, to-the-point answers with no elaboration.\"},\n        {\"role\": \"user\", \"content\": \"Can you explain how fractions work?\"},\n    ],\n    temperature=0,\n)\n\nprint(response.choices[0].message.content)\n\n```\n\n    Fractions represent parts of a whole. They have a numerator (top number) and a denominator (bottom number)."}


created_at: 2024-07-28 18:59:18
topic: persistent://default/default/4bfc3c11-fb71-4cc9-8c12-01ed076a0e01
id: 977c59d7-4962-44c2-a4d9-0090a66eecdc
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/How_to_format_inputs_to_ChatGPT_models.ipynb", "title": "How to format inputs to ChatGPT models", "tokens": 5687, "retrieve_doc": true, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"977c59d7-4962-44c2-a4d9-0090a66eecdc\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_format_inputs_to_ChatGPT_models.ipynb\", \"title\": \"How to format inputs to ChatGPT models\", \"tokens\": 5687, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"71c92695-4020-4f60-855c-1659cbec1ae1\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_format_inputs_to_ChatGPT_models.ipynb\", \"title\": \"How to format inputs to ChatGPT models\", \"tokens\": 5687, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"7c48481b2944edc8213def44183cf00818458397e592cb1568a4cec646d5cf79\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"27b6148c-d846-441c-9571-411cf098577a\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_format_inputs_to_ChatGPT_models.ipynb\", \"title\": \"How to format inputs to ChatGPT models\", \"tokens\": 5687, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"86376ea4c35da130a9719e19aa61682e93f636b63b217d1f097216eaa55e29e2\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"df7a4ef2-83cc-4422-b46d-d9c45b5ae085\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"06220c279e32d2014db649da58b80d9cd665c8f447c7e0a607405d607633b444\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 14209, \"end_char_idx\": 16513, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "71c92695-4020-4f60-855c-1659cbec1ae1", "doc_id": "71c92695-4020-4f60-855c-1659cbec1ae1", "ref_doc_id": "71c92695-4020-4f60-855c-1659cbec1ae1", "chroma:document": "```python\n# An example of a system message that primes the assistant to give brief, to-the-point answers\nresponse = client.chat.completions.create(\n    model=MODEL,\n    messages=[\n        {\"role\": \"system\", \"content\": \"You are a laconic assistant. You reply with brief, to-the-point answers with no elaboration.\"},\n        {\"role\": \"user\", \"content\": \"Can you explain how fractions work?\"},\n    ],\n    temperature=0,\n)\n\nprint(response.choices[0].message.content)\n\n```\n\n    Fractions represent parts of a whole. They have a numerator (top number) and a denominator (bottom number).\n\n\n### Few-shot prompting\n\nIn some cases, it's easier to show the model what you want rather than tell the model what you want.\n\nOne way to show the model what you want is with faked example messages.\n\nFor example:\n\n\n```python\n# An example of a faked few-shot conversation to prime the model into translating business jargon to simpler speech\nresponse = client.chat.completions.create(\n    model=MODEL,\n    messages=[\n        {\"role\": \"system\", \"content\": \"You are a helpful, pattern-following assistant.\"},\n        {\"role\": \"user\", \"content\": \"Help me translate the following corporate jargon into plain English.\"},\n        {\"role\": \"assistant\", \"content\": \"Sure, I'd be happy to!\"},\n        {\"role\": \"user\", \"content\": \"New synergies will help drive top-line growth.\"},\n        {\"role\": \"assistant\", \"content\": \"Things working well together will increase revenue.\"},\n        {\"role\": \"user\", \"content\": \"Let's circle back when we have more bandwidth to touch base on opportunities for increased leverage.\"},\n        {\"role\": \"assistant\", \"content\": \"Let's talk later when we're less busy about how to do better.\"},\n        {\"role\": \"user\", \"content\": \"This late pivot means we don't have time to boil the ocean for the client deliverable.\"},\n    ],\n    temperature=0,\n)\n\nprint(response.choices[0].message.content)\n\n```\n\n    This sudden change in direction means we don't have enough time to complete the entire project for the client.\n\n\nTo help clarify that the example messages are not part of a real conversation, and shouldn't be referred back to by the model, you can try setting the `name` field of `system` messages to `example_user` and `example_assistant`.\n\nTransforming the few-shot example above, we could write:"}


created_at: 2024-07-28 18:59:18
topic: persistent://default/default/4bfc3c11-fb71-4cc9-8c12-01ed076a0e01
id: df7a4ef2-83cc-4422-b46d-d9c45b5ae085
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/How_to_format_inputs_to_ChatGPT_models.ipynb", "title": "How to format inputs to ChatGPT models", "tokens": 5687, "retrieve_doc": true, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"df7a4ef2-83cc-4422-b46d-d9c45b5ae085\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_format_inputs_to_ChatGPT_models.ipynb\", \"title\": \"How to format inputs to ChatGPT models\", \"tokens\": 5687, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"71c92695-4020-4f60-855c-1659cbec1ae1\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_format_inputs_to_ChatGPT_models.ipynb\", \"title\": \"How to format inputs to ChatGPT models\", \"tokens\": 5687, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"7c48481b2944edc8213def44183cf00818458397e592cb1568a4cec646d5cf79\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"977c59d7-4962-44c2-a4d9-0090a66eecdc\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_format_inputs_to_ChatGPT_models.ipynb\", \"title\": \"How to format inputs to ChatGPT models\", \"tokens\": 5687, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"08493cd93b54b482fcf5463b7c7918d1ff89c7bfb9a2261c880eadd2e964b87f\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"a586ef7e-09ab-4823-968c-38ee6be7767e\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"a0f65e9c971a3294da9c5dd81b8f9ae2d3757e66a1eb36cd849b8d1b7a5bc9ce\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 14792, \"end_char_idx\": 17687, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "71c92695-4020-4f60-855c-1659cbec1ae1", "doc_id": "71c92695-4020-4f60-855c-1659cbec1ae1", "ref_doc_id": "71c92695-4020-4f60-855c-1659cbec1ae1", "chroma:document": "### Few-shot prompting\n\nIn some cases, it's easier to show the model what you want rather than tell the model what you want.\n\nOne way to show the model what you want is with faked example messages.\n\nFor example:\n\n\n```python\n# An example of a faked few-shot conversation to prime the model into translating business jargon to simpler speech\nresponse = client.chat.completions.create(\n    model=MODEL,\n    messages=[\n        {\"role\": \"system\", \"content\": \"You are a helpful, pattern-following assistant.\"},\n        {\"role\": \"user\", \"content\": \"Help me translate the following corporate jargon into plain English.\"},\n        {\"role\": \"assistant\", \"content\": \"Sure, I'd be happy to!\"},\n        {\"role\": \"user\", \"content\": \"New synergies will help drive top-line growth.\"},\n        {\"role\": \"assistant\", \"content\": \"Things working well together will increase revenue.\"},\n        {\"role\": \"user\", \"content\": \"Let's circle back when we have more bandwidth to touch base on opportunities for increased leverage.\"},\n        {\"role\": \"assistant\", \"content\": \"Let's talk later when we're less busy about how to do better.\"},\n        {\"role\": \"user\", \"content\": \"This late pivot means we don't have time to boil the ocean for the client deliverable.\"},\n    ],\n    temperature=0,\n)\n\nprint(response.choices[0].message.content)\n\n```\n\n    This sudden change in direction means we don't have enough time to complete the entire project for the client.\n\n\nTo help clarify that the example messages are not part of a real conversation, and shouldn't be referred back to by the model, you can try setting the `name` field of `system` messages to `example_user` and `example_assistant`.\n\nTransforming the few-shot example above, we could write:\n\n\n```python\n# The business jargon translation example, but with example names for the example messages\nresponse = client.chat.completions.create(\n    model=MODEL,\n    messages=[\n        {\"role\": \"system\", \"content\": \"You are a helpful, pattern-following assistant that translates corporate jargon into plain English.\"},\n        {\"role\": \"system\", \"name\":\"example_user\", \"content\": \"New synergies will help drive top-line growth.\"},\n        {\"role\": \"system\", \"name\": \"example_assistant\", \"content\": \"Things working well together will increase revenue.\"},\n        {\"role\": \"system\", \"name\":\"example_user\", \"content\": \"Let's circle back when we have more bandwidth to touch base on opportunities for increased leverage.\"},\n        {\"role\": \"system\", \"name\": \"example_assistant\", \"content\": \"Let's talk later when we're less busy about how to do better.\"},\n        {\"role\": \"user\", \"content\": \"This late pivot means we don't have time to boil the ocean for the client deliverable.\"},\n    ],\n    temperature=0,\n)\n\nprint(response.choices[0].message.content)\n\n```\n\n    This sudden change in direction means we don't have enough time to complete the entire project for the client."}


created_at: 2024-07-28 18:59:18
topic: persistent://default/default/4bfc3c11-fb71-4cc9-8c12-01ed076a0e01
id: a586ef7e-09ab-4823-968c-38ee6be7767e
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/How_to_format_inputs_to_ChatGPT_models.ipynb", "title": "How to format inputs to ChatGPT models", "tokens": 5687, "retrieve_doc": true, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"a586ef7e-09ab-4823-968c-38ee6be7767e\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_format_inputs_to_ChatGPT_models.ipynb\", \"title\": \"How to format inputs to ChatGPT models\", \"tokens\": 5687, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"71c92695-4020-4f60-855c-1659cbec1ae1\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_format_inputs_to_ChatGPT_models.ipynb\", \"title\": \"How to format inputs to ChatGPT models\", \"tokens\": 5687, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"7c48481b2944edc8213def44183cf00818458397e592cb1568a4cec646d5cf79\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"df7a4ef2-83cc-4422-b46d-d9c45b5ae085\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_format_inputs_to_ChatGPT_models.ipynb\", \"title\": \"How to format inputs to ChatGPT models\", \"tokens\": 5687, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"b14506571f331ceb27c15d3b80a4982f8db34d9506c9cc8ef24e615c1f8a4799\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"bac46246-26ac-4d84-9436-570510ebde5e\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"754ee44774e55da89def1b74200167b08ab434651b0f63797a2c78529b2c4cc4\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 16228, \"end_char_idx\": 19231, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "71c92695-4020-4f60-855c-1659cbec1ae1", "doc_id": "71c92695-4020-4f60-855c-1659cbec1ae1", "ref_doc_id": "71c92695-4020-4f60-855c-1659cbec1ae1", "chroma:document": "To help clarify that the example messages are not part of a real conversation, and shouldn't be referred back to by the model, you can try setting the `name` field of `system` messages to `example_user` and `example_assistant`.\n\nTransforming the few-shot example above, we could write:\n\n\n```python\n# The business jargon translation example, but with example names for the example messages\nresponse = client.chat.completions.create(\n    model=MODEL,\n    messages=[\n        {\"role\": \"system\", \"content\": \"You are a helpful, pattern-following assistant that translates corporate jargon into plain English.\"},\n        {\"role\": \"system\", \"name\":\"example_user\", \"content\": \"New synergies will help drive top-line growth.\"},\n        {\"role\": \"system\", \"name\": \"example_assistant\", \"content\": \"Things working well together will increase revenue.\"},\n        {\"role\": \"system\", \"name\":\"example_user\", \"content\": \"Let's circle back when we have more bandwidth to touch base on opportunities for increased leverage.\"},\n        {\"role\": \"system\", \"name\": \"example_assistant\", \"content\": \"Let's talk later when we're less busy about how to do better.\"},\n        {\"role\": \"user\", \"content\": \"This late pivot means we don't have time to boil the ocean for the client deliverable.\"},\n    ],\n    temperature=0,\n)\n\nprint(response.choices[0].message.content)\n\n```\n\n    This sudden change in direction means we don't have enough time to complete the entire project for the client.\n\n\nNot every attempt at engineering conversations will succeed at first.\n\nIf your first attempts fail, don't be afraid to experiment with different ways of priming or conditioning the model.\n\nAs an example, one developer discovered an increase in accuracy when they inserted a user message that said \"Great job so far, these have been perfect\" to help condition the model into providing higher quality responses.\n\nFor more ideas on how to lift the reliability of the models, consider reading our guide on [techniques to increase reliability](../techniques_to_improve_reliability). It was written for non-chat models, but many of its principles still apply.\n\n## 4. Counting tokens\n\nWhen you submit your request, the API transforms the messages into a sequence of tokens.\n\nThe number of tokens used affects:\n- the cost of the request\n- the time it takes to generate the response\n- when the reply gets cut off from hitting the maximum token limit (4,096 for `gpt-3.5-turbo` or 8,192 for `gpt-4`)\n\nYou can use the following function to count the number of tokens that a list of messages will use.\n\nNote that the exact way that tokens are counted from messages may change from model to model. Consider the counts from the function below an estimate, not a timeless guarantee. \n\nIn particular, requests that use the optional functions input will consume extra tokens on top of the estimates calculated below.\n\nRead more about counting tokens in [How to count tokens with tiktoken](How_to_count_tokens_with_tiktoken.ipynb).\n\n\n```python\nimport tiktoken"}


created_at: 2024-07-28 18:59:18
topic: persistent://default/default/4bfc3c11-fb71-4cc9-8c12-01ed076a0e01
id: bac46246-26ac-4d84-9436-570510ebde5e
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/How_to_format_inputs_to_ChatGPT_models.ipynb", "title": "How to format inputs to ChatGPT models", "tokens": 5687, "retrieve_doc": true, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"bac46246-26ac-4d84-9436-570510ebde5e\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_format_inputs_to_ChatGPT_models.ipynb\", \"title\": \"How to format inputs to ChatGPT models\", \"tokens\": 5687, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"71c92695-4020-4f60-855c-1659cbec1ae1\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_format_inputs_to_ChatGPT_models.ipynb\", \"title\": \"How to format inputs to ChatGPT models\", \"tokens\": 5687, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"7c48481b2944edc8213def44183cf00818458397e592cb1568a4cec646d5cf79\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"a586ef7e-09ab-4823-968c-38ee6be7767e\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_format_inputs_to_ChatGPT_models.ipynb\", \"title\": \"How to format inputs to ChatGPT models\", \"tokens\": 5687, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"9a253c0e6309d68729a8ce94287f63abd1424b918ac278913349884c1d9acbad\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"85656828-c151-4a04-bc55-cd8ad1b1c2d5\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"164d8dac14ebb7ce276d08e7721b8418829202f24e76840094a511d7a7a7027d\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 17690, \"end_char_idx\": 20960, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "71c92695-4020-4f60-855c-1659cbec1ae1", "doc_id": "71c92695-4020-4f60-855c-1659cbec1ae1", "ref_doc_id": "71c92695-4020-4f60-855c-1659cbec1ae1", "chroma:document": "Not every attempt at engineering conversations will succeed at first.\n\nIf your first attempts fail, don't be afraid to experiment with different ways of priming or conditioning the model.\n\nAs an example, one developer discovered an increase in accuracy when they inserted a user message that said \"Great job so far, these have been perfect\" to help condition the model into providing higher quality responses.\n\nFor more ideas on how to lift the reliability of the models, consider reading our guide on [techniques to increase reliability](../techniques_to_improve_reliability). It was written for non-chat models, but many of its principles still apply.\n\n## 4. Counting tokens\n\nWhen you submit your request, the API transforms the messages into a sequence of tokens.\n\nThe number of tokens used affects:\n- the cost of the request\n- the time it takes to generate the response\n- when the reply gets cut off from hitting the maximum token limit (4,096 for `gpt-3.5-turbo` or 8,192 for `gpt-4`)\n\nYou can use the following function to count the number of tokens that a list of messages will use.\n\nNote that the exact way that tokens are counted from messages may change from model to model. Consider the counts from the function below an estimate, not a timeless guarantee. \n\nIn particular, requests that use the optional functions input will consume extra tokens on top of the estimates calculated below.\n\nRead more about counting tokens in [How to count tokens with tiktoken](How_to_count_tokens_with_tiktoken.ipynb).\n\n\n```python\nimport tiktoken\n\n\ndef num_tokens_from_messages(messages, model=\"gpt-3.5-turbo-0613\"):\n    \"\"\"Return the number of tokens used by a list of messages.\"\"\"\n    try:\n        encoding = tiktoken.encoding_for_model(model)\n    except KeyError:\n        print(\"Warning: model not found. Using cl100k_base encoding.\")\n        encoding = tiktoken.get_encoding(\"cl100k_base\")\n    if model in {\n        \"gpt-3.5-turbo-0613\",\n        \"gpt-3.5-turbo-16k-0613\",\n        \"gpt-4-0314\",\n        \"gpt-4-32k-0314\",\n        \"gpt-4-0613\",\n        \"gpt-4-32k-0613\",\n        }:\n        tokens_per_message = 3\n        tokens_per_name = 1\n    elif model == \"gpt-3.5-turbo-0301\":\n        tokens_per_message = 4  # every message follows <|start|>{role/name}\\n{content}<|end|>\\n\n        tokens_per_name = -1  # if there's a name, the role is omitted\n    elif \"gpt-3.5-turbo\" in model:\n        print(\"Warning: gpt-3.5-turbo may update over time. Returning num tokens assuming gpt-3.5-turbo-0613.\")\n        return num_tokens_from_messages(messages, model=\"gpt-3.5-turbo-0613\")\n    elif \"gpt-4\" in model:\n        print(\"Warning: gpt-4 may update over time. Returning num tokens assuming gpt-4-0613.\")\n        return num_tokens_from_messages(messages, model=\"gpt-4-0613\")\n    else:\n        raise NotImplementedError(\n            f\"\"\"num_tokens_from_messages() is not implemented for model {model}.\"\"\"\n        )\n    num_tokens = 0\n    for message in messages:\n        num_tokens += tokens_per_message\n        for key, value in message.items():\n            num_tokens += len(encoding.encode(value))\n            if key == \"name\":\n                num_tokens += tokens_per_name\n    num_tokens += 3  # every reply is primed with <|start|>assistant<|message|>\n    return num_tokens\n\n```"}


created_at: 2024-07-28 18:59:18
topic: persistent://default/default/4bfc3c11-fb71-4cc9-8c12-01ed076a0e01
id: 85656828-c151-4a04-bc55-cd8ad1b1c2d5
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/How_to_format_inputs_to_ChatGPT_models.ipynb", "title": "How to format inputs to ChatGPT models", "tokens": 5687, "retrieve_doc": true, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"85656828-c151-4a04-bc55-cd8ad1b1c2d5\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_format_inputs_to_ChatGPT_models.ipynb\", \"title\": \"How to format inputs to ChatGPT models\", \"tokens\": 5687, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"71c92695-4020-4f60-855c-1659cbec1ae1\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_format_inputs_to_ChatGPT_models.ipynb\", \"title\": \"How to format inputs to ChatGPT models\", \"tokens\": 5687, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"7c48481b2944edc8213def44183cf00818458397e592cb1568a4cec646d5cf79\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"bac46246-26ac-4d84-9436-570510ebde5e\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_format_inputs_to_ChatGPT_models.ipynb\", \"title\": \"How to format inputs to ChatGPT models\", \"tokens\": 5687, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"f840160a4ac4e4c522506fff8f3293db6cb9b7d8a28e8de0c8a5d6fec9d42749\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 20963, \"end_char_idx\": 23594, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "71c92695-4020-4f60-855c-1659cbec1ae1", "doc_id": "71c92695-4020-4f60-855c-1659cbec1ae1", "ref_doc_id": "71c92695-4020-4f60-855c-1659cbec1ae1", "chroma:document": "```python\n# let's verify the function above matches the OpenAI API response\nexample_messages = [\n    {\n        \"role\": \"system\",\n        \"content\": \"You are a helpful, pattern-following assistant that translates corporate jargon into plain English.\",\n    },\n    {\n        \"role\": \"system\",\n        \"name\": \"example_user\",\n        \"content\": \"New synergies will help drive top-line growth.\",\n    },\n    {\n        \"role\": \"system\",\n        \"name\": \"example_assistant\",\n        \"content\": \"Things working well together will increase revenue.\",\n    },\n    {\n        \"role\": \"system\",\n        \"name\": \"example_user\",\n        \"content\": \"Let's circle back when we have more bandwidth to touch base on opportunities for increased leverage.\",\n    },\n    {\n        \"role\": \"system\",\n        \"name\": \"example_assistant\",\n        \"content\": \"Let's talk later when we're less busy about how to do better.\",\n    },\n    {\n        \"role\": \"user\",\n        \"content\": \"This late pivot means we don't have time to boil the ocean for the client deliverable.\",\n    },\n]\n\nfor model in [\n    # \"gpt-3.5-turbo-0301\",\n    # \"gpt-4-0314\",\n    # \"gpt-4-0613\",\n    \"gpt-3.5-turbo-1106\",\n    \"gpt-3.5-turbo\",\n    \"gpt-4\",\n    \"gpt-4-1106-preview\",\n    ]:\n    print(model)\n    # example token count from the function defined above\n    print(f\"{num_tokens_from_messages(example_messages, model)} prompt tokens counted by num_tokens_from_messages().\")\n    # example token count from the OpenAI API\n    response = client.chat.completions.create(model=model,\n    messages=example_messages,\n    temperature=0,\n    max_tokens=1)\n    token = response.usage.prompt_tokens\n    print(f'{token} prompt tokens counted by the OpenAI API.')\n    print()\n\n```\n\n    gpt-3.5-turbo-1106\n    Warning: gpt-3.5-turbo may update over time. Returning num tokens assuming gpt-3.5-turbo-0613.\n    129 prompt tokens counted by num_tokens_from_messages().\n    129 prompt tokens counted by the OpenAI API.\n    \n    gpt-3.5-turbo\n    Warning: gpt-3.5-turbo may update over time. Returning num tokens assuming gpt-3.5-turbo-0613.\n    129 prompt tokens counted by num_tokens_from_messages().\n    129 prompt tokens counted by the OpenAI API.\n    \n    gpt-4\n    Warning: gpt-4 may update over time. Returning num tokens assuming gpt-4-0613.\n    129 prompt tokens counted by num_tokens_from_messages().\n    129 prompt tokens counted by the OpenAI API.\n    \n    gpt-4-1106-preview\n    Warning: gpt-4 may update over time. Returning num tokens assuming gpt-4-0613.\n    129 prompt tokens counted by num_tokens_from_messages().\n    129 prompt tokens counted by the OpenAI API.\n    \n\n\n\n```python\n\n```"}


created_at: 2024-07-28 18:59:18
topic: persistent://default/default/4bfc3c11-fb71-4cc9-8c12-01ed076a0e01
id: b92dcc92-ad9d-4214-8568-ee8878944776
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/How_to_call_functions_with_chat_models.ipynb", "title": "How to call functions with chat models", "tokens": 4334, "retrieve_doc": true, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"b92dcc92-ad9d-4214-8568-ee8878944776\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_call_functions_with_chat_models.ipynb\", \"title\": \"How to call functions with chat models\", \"tokens\": 4334, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"08de5268-6020-4d7b-ac62-f00a20ed55cf\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_call_functions_with_chat_models.ipynb\", \"title\": \"How to call functions with chat models\", \"tokens\": 4334, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"465755c3f6b9fdf61cef5225b387867709ba20e7037a6e567db3b085ed7f5cd0\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"24c96ee1-02f5-4b86-b66c-d6e0ab77dfb2\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"38402decf5664123218753b91568d62c3e7c4d7de554935f21d6d68fadf56395\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 0, \"end_char_idx\": 2582, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "08de5268-6020-4d7b-ac62-f00a20ed55cf", "doc_id": "08de5268-6020-4d7b-ac62-f00a20ed55cf", "ref_doc_id": "08de5268-6020-4d7b-ac62-f00a20ed55cf", "chroma:document": "# How to call functions with chat models\n\nThis notebook covers how to use the Chat Completions API in combination with external functions to extend the capabilities of GPT models.\n\n`tools` is an optional parameter in the Chat Completion API which can be used to provide function specifications. The purpose of this is to enable models to generate function arguments which adhere to the provided specifications. Note that the API will not actually execute any function calls. It is up to developers to execute function calls using model outputs.\n\nWithin the `tools` parameter, if the `functions` parameter is provided then by default the model will decide when it is appropriate to use one of the functions. The API can be forced to use a specific function by setting the `tool_choice` parameter to `{\"type\": \"function\", \"function\": {\"name\": \"my_function\"}}`. The API can also be forced to not use any function by setting the `tool_choice` parameter to `\"none\"`. If a function is used, the output will contain `\"finish_reason\": \"tool_calls\"` in the response, as well as a `tool_calls` object that has the name of the function and the generated function arguments.\n\n### Overview\n\nThis notebook contains the following 2 sections:\n\n- **How to generate function arguments:** Specify a set of functions and use the API to generate function arguments.\n- **How to call functions with model generated arguments:** Close the loop by actually executing functions with model generated arguments.\n\n## How to generate function arguments\n\n\n```python\n!pip install scipy --quiet\n!pip install tenacity --quiet\n!pip install tiktoken --quiet\n!pip install termcolor --quiet\n!pip install openai --quiet\n```\n\n\n```python\nimport json\nfrom openai import OpenAI\nfrom tenacity import retry, wait_random_exponential, stop_after_attempt\nfrom termcolor import colored  \n\nGPT_MODEL = \"gpt-4o\"\nclient = OpenAI()\n```\n\n### Utilities\n\nFirst let's define a few utilities for making calls to the Chat Completions API and for maintaining and keeping track of the conversation state.\n\n\n```python\n@retry(wait=wait_random_exponential(multiplier=1, max=40), stop=stop_after_attempt(3))\ndef chat_completion_request(messages, tools=None, tool_choice=None, model=GPT_MODEL):\n    try:\n        response = client.chat.completions.create(\n            model=model,\n            messages=messages,\n            tools=tools,\n            tool_choice=tool_choice,\n        )\n        return response\n    except Exception as e:\n        print(\"Unable to generate ChatCompletion response\")\n        print(f\"Exception: {e}\")\n        return e\n\n```"}


created_at: 2024-07-28 18:59:18
topic: persistent://default/default/4bfc3c11-fb71-4cc9-8c12-01ed076a0e01
id: 24c96ee1-02f5-4b86-b66c-d6e0ab77dfb2
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/How_to_call_functions_with_chat_models.ipynb", "title": "How to call functions with chat models", "tokens": 4334, "retrieve_doc": true, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"24c96ee1-02f5-4b86-b66c-d6e0ab77dfb2\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_call_functions_with_chat_models.ipynb\", \"title\": \"How to call functions with chat models\", \"tokens\": 4334, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"08de5268-6020-4d7b-ac62-f00a20ed55cf\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_call_functions_with_chat_models.ipynb\", \"title\": \"How to call functions with chat models\", \"tokens\": 4334, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"465755c3f6b9fdf61cef5225b387867709ba20e7037a6e567db3b085ed7f5cd0\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"b92dcc92-ad9d-4214-8568-ee8878944776\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_call_functions_with_chat_models.ipynb\", \"title\": \"How to call functions with chat models\", \"tokens\": 4334, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"a076e03d2d9e2c4d42adb7502ed6cf0a9d2275c3ed702fe1960cef953fccc594\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"f5aee1cc-f9c9-4110-bca5-389c4f8e76e8\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"c25252aca9500956ac40183d2226d83c21cdbebf8d8bfb6719d5760c9ac56e3e\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 1525, \"end_char_idx\": 3849, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "08de5268-6020-4d7b-ac62-f00a20ed55cf", "doc_id": "08de5268-6020-4d7b-ac62-f00a20ed55cf", "ref_doc_id": "08de5268-6020-4d7b-ac62-f00a20ed55cf", "chroma:document": "```python\n!pip install scipy --quiet\n!pip install tenacity --quiet\n!pip install tiktoken --quiet\n!pip install termcolor --quiet\n!pip install openai --quiet\n```\n\n\n```python\nimport json\nfrom openai import OpenAI\nfrom tenacity import retry, wait_random_exponential, stop_after_attempt\nfrom termcolor import colored  \n\nGPT_MODEL = \"gpt-4o\"\nclient = OpenAI()\n```\n\n### Utilities\n\nFirst let's define a few utilities for making calls to the Chat Completions API and for maintaining and keeping track of the conversation state.\n\n\n```python\n@retry(wait=wait_random_exponential(multiplier=1, max=40), stop=stop_after_attempt(3))\ndef chat_completion_request(messages, tools=None, tool_choice=None, model=GPT_MODEL):\n    try:\n        response = client.chat.completions.create(\n            model=model,\n            messages=messages,\n            tools=tools,\n            tool_choice=tool_choice,\n        )\n        return response\n    except Exception as e:\n        print(\"Unable to generate ChatCompletion response\")\n        print(f\"Exception: {e}\")\n        return e\n\n```\n\n\n```python\ndef pretty_print_conversation(messages):\n    role_to_color = {\n        \"system\": \"red\",\n        \"user\": \"green\",\n        \"assistant\": \"blue\",\n        \"function\": \"magenta\",\n    }\n    \n    for message in messages:\n        if message[\"role\"] == \"system\":\n            print(colored(f\"system: {message['content']}\\n\", role_to_color[message[\"role\"]]))\n        elif message[\"role\"] == \"user\":\n            print(colored(f\"user: {message['content']}\\n\", role_to_color[message[\"role\"]]))\n        elif message[\"role\"] == \"assistant\" and message.get(\"function_call\"):\n            print(colored(f\"assistant: {message['function_call']}\\n\", role_to_color[message[\"role\"]]))\n        elif message[\"role\"] == \"assistant\" and not message.get(\"function_call\"):\n            print(colored(f\"assistant: {message['content']}\\n\", role_to_color[message[\"role\"]]))\n        elif message[\"role\"] == \"function\":\n            print(colored(f\"function ({message['name']}): {message['content']}\\n\", role_to_color[message[\"role\"]]))\n\n```\n\n### Basic concepts\n\nLet's create some function specifications to interface with a hypothetical weather API. We'll pass these function specification to the Chat Completions API in order to generate function arguments that adhere to the specification."}


created_at: 2024-07-28 18:59:18
topic: persistent://default/default/4bfc3c11-fb71-4cc9-8c12-01ed076a0e01
id: f5aee1cc-f9c9-4110-bca5-389c4f8e76e8
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/How_to_call_functions_with_chat_models.ipynb", "title": "How to call functions with chat models", "tokens": 4334, "retrieve_doc": true, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"f5aee1cc-f9c9-4110-bca5-389c4f8e76e8\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_call_functions_with_chat_models.ipynb\", \"title\": \"How to call functions with chat models\", \"tokens\": 4334, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"08de5268-6020-4d7b-ac62-f00a20ed55cf\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_call_functions_with_chat_models.ipynb\", \"title\": \"How to call functions with chat models\", \"tokens\": 4334, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"465755c3f6b9fdf61cef5225b387867709ba20e7037a6e567db3b085ed7f5cd0\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"24c96ee1-02f5-4b86-b66c-d6e0ab77dfb2\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_call_functions_with_chat_models.ipynb\", \"title\": \"How to call functions with chat models\", \"tokens\": 4334, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"abd69efb8bb5c93a2e30c42c907db9ef1f6963ae8c74a3737b67befb0c2ccb6b\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"52044061-1241-4e45-941e-28ca73593fb9\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"022db31fedbfbff67071453c29d490ced17f7f6fa8b6be2e235c1103efc36968\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 2585, \"end_char_idx\": 6219, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "08de5268-6020-4d7b-ac62-f00a20ed55cf", "doc_id": "08de5268-6020-4d7b-ac62-f00a20ed55cf", "ref_doc_id": "08de5268-6020-4d7b-ac62-f00a20ed55cf", "chroma:document": "```python\ndef pretty_print_conversation(messages):\n    role_to_color = {\n        \"system\": \"red\",\n        \"user\": \"green\",\n        \"assistant\": \"blue\",\n        \"function\": \"magenta\",\n    }\n    \n    for message in messages:\n        if message[\"role\"] == \"system\":\n            print(colored(f\"system: {message['content']}\\n\", role_to_color[message[\"role\"]]))\n        elif message[\"role\"] == \"user\":\n            print(colored(f\"user: {message['content']}\\n\", role_to_color[message[\"role\"]]))\n        elif message[\"role\"] == \"assistant\" and message.get(\"function_call\"):\n            print(colored(f\"assistant: {message['function_call']}\\n\", role_to_color[message[\"role\"]]))\n        elif message[\"role\"] == \"assistant\" and not message.get(\"function_call\"):\n            print(colored(f\"assistant: {message['content']}\\n\", role_to_color[message[\"role\"]]))\n        elif message[\"role\"] == \"function\":\n            print(colored(f\"function ({message['name']}): {message['content']}\\n\", role_to_color[message[\"role\"]]))\n\n```\n\n### Basic concepts\n\nLet's create some function specifications to interface with a hypothetical weather API. We'll pass these function specification to the Chat Completions API in order to generate function arguments that adhere to the specification.\n\n\n```python\ntools = [\n    {\n        \"type\": \"function\",\n        \"function\": {\n            \"name\": \"get_current_weather\",\n            \"description\": \"Get the current weather\",\n            \"parameters\": {\n                \"type\": \"object\",\n                \"properties\": {\n                    \"location\": {\n                        \"type\": \"string\",\n                        \"description\": \"The city and state, e.g. San Francisco, CA\",\n                    },\n                    \"format\": {\n                        \"type\": \"string\",\n                        \"enum\": [\"celsius\", \"fahrenheit\"],\n                        \"description\": \"The temperature unit to use. Infer this from the users location.\",\n                    },\n                },\n                \"required\": [\"location\", \"format\"],\n            },\n        }\n    },\n    {\n        \"type\": \"function\",\n        \"function\": {\n            \"name\": \"get_n_day_weather_forecast\",\n            \"description\": \"Get an N-day weather forecast\",\n            \"parameters\": {\n                \"type\": \"object\",\n                \"properties\": {\n                    \"location\": {\n                        \"type\": \"string\",\n                        \"description\": \"The city and state, e.g. San Francisco, CA\",\n                    },\n                    \"format\": {\n                        \"type\": \"string\",\n                        \"enum\": [\"celsius\", \"fahrenheit\"],\n                        \"description\": \"The temperature unit to use. Infer this from the users location.\",\n                    },\n                    \"num_days\": {\n                        \"type\": \"integer\",\n                        \"description\": \"The number of days to forecast\",\n                    }\n                },\n                \"required\": [\"location\", \"format\", \"num_days\"]\n            },\n        }\n    },\n]\n```\n\nIf we prompt the model about the current weather, it will respond with some clarifying questions.\n\n\n```python\nmessages = []\nmessages.append({\"role\": \"system\", \"content\": \"Don't make assumptions about what values to plug into functions. Ask for clarification if a user request is ambiguous.\"})\nmessages.append({\"role\": \"user\", \"content\": \"What's the weather like today\"})\nchat_response = chat_completion_request(\n    messages, tools=tools\n)\nassistant_message = chat_response.choices[0].message\nmessages.append(assistant_message)\nassistant_message\n\n```"}


created_at: 2024-07-28 18:59:18
topic: persistent://default/default/4bfc3c11-fb71-4cc9-8c12-01ed076a0e01
id: 52044061-1241-4e45-941e-28ca73593fb9
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/How_to_call_functions_with_chat_models.ipynb", "title": "How to call functions with chat models", "tokens": 4334, "retrieve_doc": true, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"52044061-1241-4e45-941e-28ca73593fb9\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_call_functions_with_chat_models.ipynb\", \"title\": \"How to call functions with chat models\", \"tokens\": 4334, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"08de5268-6020-4d7b-ac62-f00a20ed55cf\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_call_functions_with_chat_models.ipynb\", \"title\": \"How to call functions with chat models\", \"tokens\": 4334, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"465755c3f6b9fdf61cef5225b387867709ba20e7037a6e567db3b085ed7f5cd0\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"f5aee1cc-f9c9-4110-bca5-389c4f8e76e8\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_call_functions_with_chat_models.ipynb\", \"title\": \"How to call functions with chat models\", \"tokens\": 4334, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"32bd698ecf01536b785d19429ec428ce38239ba8580dbfd4d5546a46a2ff45ef\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"91f80dec-2104-40b0-8136-3eac7b10037f\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"172f20db166ba3a65f270dc2f6e81aabb188299f42e8761f2b1f28d440d12a53\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 5769, \"end_char_idx\": 8918, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "08de5268-6020-4d7b-ac62-f00a20ed55cf", "doc_id": "08de5268-6020-4d7b-ac62-f00a20ed55cf", "ref_doc_id": "08de5268-6020-4d7b-ac62-f00a20ed55cf", "chroma:document": "```python\nmessages = []\nmessages.append({\"role\": \"system\", \"content\": \"Don't make assumptions about what values to plug into functions. Ask for clarification if a user request is ambiguous.\"})\nmessages.append({\"role\": \"user\", \"content\": \"What's the weather like today\"})\nchat_response = chat_completion_request(\n    messages, tools=tools\n)\nassistant_message = chat_response.choices[0].message\nmessages.append(assistant_message)\nassistant_message\n\n```\n\n\n\n\n    ChatCompletionMessage(content='Sure, can you please provide me with the name of your city and state?', role='assistant', function_call=None, tool_calls=None)\n\n\n\nOnce we provide the missing information, it will generate the appropriate function arguments for us.\n\n\n```python\nmessages.append({\"role\": \"user\", \"content\": \"I'm in Glasgow, Scotland.\"})\nchat_response = chat_completion_request(\n    messages, tools=tools\n)\nassistant_message = chat_response.choices[0].message\nmessages.append(assistant_message)\nassistant_message\n\n```\n\n\n\n\n    ChatCompletionMessage(content=None, role='assistant', function_call=None, tool_calls=[ChatCompletionMessageToolCall(id='call_xb7QwwNnx90LkmhtlW0YrgP2', function=Function(arguments='{\"location\":\"Glasgow, Scotland\",\"format\":\"celsius\"}', name='get_current_weather'), type='function')])\n\n\n\nBy prompting it differently, we can get it to target the other function we've told it about.\n\n\n```python\nmessages = []\nmessages.append({\"role\": \"system\", \"content\": \"Don't make assumptions about what values to plug into functions. Ask for clarification if a user request is ambiguous.\"})\nmessages.append({\"role\": \"user\", \"content\": \"what is the weather going to be like in Glasgow, Scotland over the next x days\"})\nchat_response = chat_completion_request(\n    messages, tools=tools\n)\nassistant_message = chat_response.choices[0].message\nmessages.append(assistant_message)\nassistant_message\n\n```\n\n\n\n\n    ChatCompletionMessage(content='To provide you with the weather forecast for Glasgow, Scotland, could you please specify the number of days you would like the forecast for?', role='assistant', function_call=None, tool_calls=None)\n\n\n\nOnce again, the model is asking us for clarification because it doesn't have enough information yet. In this case it already knows the location for the forecast, but it needs to know how many days are required in the forecast.\n\n\n```python\nmessages.append({\"role\": \"user\", \"content\": \"5 days\"})\nchat_response = chat_completion_request(\n    messages, tools=tools\n)\nchat_response.choices[0]\n\n```\n\n\n\n\n    Choice(finish_reason='tool_calls', index=0, logprobs=None, message=ChatCompletionMessage(content=None, role='assistant', function_call=None, tool_calls=[ChatCompletionMessageToolCall(id='call_34PBraFdNN6KR95uD5rHF8Aw', function=Function(arguments='{\"location\":\"Glasgow, Scotland\",\"format\":\"celsius\",\"num_days\":5}', name='get_n_day_weather_forecast'), type='function')]))\n\n\n\n#### Forcing the use of specific functions or no function\n\nWe can force the model to use a specific function, for example get_n_day_weather_forecast by using the function_call argument. By doing so, we force the model to make assumptions about how to use it."}


created_at: 2024-07-28 18:59:18
topic: persistent://default/default/4bfc3c11-fb71-4cc9-8c12-01ed076a0e01
id: 91f80dec-2104-40b0-8136-3eac7b10037f
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/How_to_call_functions_with_chat_models.ipynb", "title": "How to call functions with chat models", "tokens": 4334, "retrieve_doc": true, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"91f80dec-2104-40b0-8136-3eac7b10037f\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_call_functions_with_chat_models.ipynb\", \"title\": \"How to call functions with chat models\", \"tokens\": 4334, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"08de5268-6020-4d7b-ac62-f00a20ed55cf\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_call_functions_with_chat_models.ipynb\", \"title\": \"How to call functions with chat models\", \"tokens\": 4334, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"465755c3f6b9fdf61cef5225b387867709ba20e7037a6e567db3b085ed7f5cd0\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"52044061-1241-4e45-941e-28ca73593fb9\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_call_functions_with_chat_models.ipynb\", \"title\": \"How to call functions with chat models\", \"tokens\": 4334, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"09c61301f13c79f99355f041db7e5edab6275dd5be42217a98dbffb0d9114500\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"8341110e-db06-4eca-87e4-056794befc72\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"c406b2b49109cc4139f8e07a224881a1a1f24da3eed54ca64fa76e89cef6838d\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 7145, \"end_char_idx\": 10248, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "08de5268-6020-4d7b-ac62-f00a20ed55cf", "doc_id": "08de5268-6020-4d7b-ac62-f00a20ed55cf", "ref_doc_id": "08de5268-6020-4d7b-ac62-f00a20ed55cf", "chroma:document": "```python\nmessages = []\nmessages.append({\"role\": \"system\", \"content\": \"Don't make assumptions about what values to plug into functions. Ask for clarification if a user request is ambiguous.\"})\nmessages.append({\"role\": \"user\", \"content\": \"what is the weather going to be like in Glasgow, Scotland over the next x days\"})\nchat_response = chat_completion_request(\n    messages, tools=tools\n)\nassistant_message = chat_response.choices[0].message\nmessages.append(assistant_message)\nassistant_message\n\n```\n\n\n\n\n    ChatCompletionMessage(content='To provide you with the weather forecast for Glasgow, Scotland, could you please specify the number of days you would like the forecast for?', role='assistant', function_call=None, tool_calls=None)\n\n\n\nOnce again, the model is asking us for clarification because it doesn't have enough information yet. In this case it already knows the location for the forecast, but it needs to know how many days are required in the forecast.\n\n\n```python\nmessages.append({\"role\": \"user\", \"content\": \"5 days\"})\nchat_response = chat_completion_request(\n    messages, tools=tools\n)\nchat_response.choices[0]\n\n```\n\n\n\n\n    Choice(finish_reason='tool_calls', index=0, logprobs=None, message=ChatCompletionMessage(content=None, role='assistant', function_call=None, tool_calls=[ChatCompletionMessageToolCall(id='call_34PBraFdNN6KR95uD5rHF8Aw', function=Function(arguments='{\"location\":\"Glasgow, Scotland\",\"format\":\"celsius\",\"num_days\":5}', name='get_n_day_weather_forecast'), type='function')]))\n\n\n\n#### Forcing the use of specific functions or no function\n\nWe can force the model to use a specific function, for example get_n_day_weather_forecast by using the function_call argument. By doing so, we force the model to make assumptions about how to use it.\n\n\n```python\n# in this cell we force the model to use get_n_day_weather_forecast\nmessages = []\nmessages.append({\"role\": \"system\", \"content\": \"Don't make assumptions about what values to plug into functions. Ask for clarification if a user request is ambiguous.\"})\nmessages.append({\"role\": \"user\", \"content\": \"Give me a weather report for Toronto, Canada.\"})\nchat_response = chat_completion_request(\n    messages, tools=tools, tool_choice={\"type\": \"function\", \"function\": {\"name\": \"get_n_day_weather_forecast\"}}\n)\nchat_response.choices[0].message\n```\n\n\n\n\n    ChatCompletionMessage(content=None, role='assistant', function_call=None, tool_calls=[ChatCompletionMessageToolCall(id='call_FImGxrLowOAOszCaaQqQWmEN', function=Function(arguments='{\"location\":\"Toronto, Canada\",\"format\":\"celsius\",\"num_days\":7}', name='get_n_day_weather_forecast'), type='function')])\n\n\n\n\n```python\n# if we don't force the model to use get_n_day_weather_forecast it may not\nmessages = []\nmessages.append({\"role\": \"system\", \"content\": \"Don't make assumptions about what values to plug into functions. Ask for clarification if a user request is ambiguous.\"})\nmessages.append({\"role\": \"user\", \"content\": \"Give me a weather report for Toronto, Canada.\"})\nchat_response = chat_completion_request(\n    messages, tools=tools\n)\nchat_response.choices[0].message\n```"}


created_at: 2024-07-28 18:59:18
topic: persistent://default/default/4bfc3c11-fb71-4cc9-8c12-01ed076a0e01
id: 8341110e-db06-4eca-87e4-056794befc72
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/How_to_call_functions_with_chat_models.ipynb", "title": "How to call functions with chat models", "tokens": 4334, "retrieve_doc": true, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"8341110e-db06-4eca-87e4-056794befc72\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_call_functions_with_chat_models.ipynb\", \"title\": \"How to call functions with chat models\", \"tokens\": 4334, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"08de5268-6020-4d7b-ac62-f00a20ed55cf\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_call_functions_with_chat_models.ipynb\", \"title\": \"How to call functions with chat models\", \"tokens\": 4334, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"465755c3f6b9fdf61cef5225b387867709ba20e7037a6e567db3b085ed7f5cd0\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"91f80dec-2104-40b0-8136-3eac7b10037f\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_call_functions_with_chat_models.ipynb\", \"title\": \"How to call functions with chat models\", \"tokens\": 4334, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"dbf6eca1822502e1811d970be73cc7bbb8fd5f6bc2ac24a6964542249307eed1\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"4ccdb99d-ed2d-4a7b-924b-67e110aaebc3\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"df9beb088672f6f75aafd9a9df37da403bae8eb37fb12158310eeb057b99eb07\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 8660, \"end_char_idx\": 11601, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "08de5268-6020-4d7b-ac62-f00a20ed55cf", "doc_id": "08de5268-6020-4d7b-ac62-f00a20ed55cf", "ref_doc_id": "08de5268-6020-4d7b-ac62-f00a20ed55cf", "chroma:document": "#### Forcing the use of specific functions or no function\n\nWe can force the model to use a specific function, for example get_n_day_weather_forecast by using the function_call argument. By doing so, we force the model to make assumptions about how to use it.\n\n\n```python\n# in this cell we force the model to use get_n_day_weather_forecast\nmessages = []\nmessages.append({\"role\": \"system\", \"content\": \"Don't make assumptions about what values to plug into functions. Ask for clarification if a user request is ambiguous.\"})\nmessages.append({\"role\": \"user\", \"content\": \"Give me a weather report for Toronto, Canada.\"})\nchat_response = chat_completion_request(\n    messages, tools=tools, tool_choice={\"type\": \"function\", \"function\": {\"name\": \"get_n_day_weather_forecast\"}}\n)\nchat_response.choices[0].message\n```\n\n\n\n\n    ChatCompletionMessage(content=None, role='assistant', function_call=None, tool_calls=[ChatCompletionMessageToolCall(id='call_FImGxrLowOAOszCaaQqQWmEN', function=Function(arguments='{\"location\":\"Toronto, Canada\",\"format\":\"celsius\",\"num_days\":7}', name='get_n_day_weather_forecast'), type='function')])\n\n\n\n\n```python\n# if we don't force the model to use get_n_day_weather_forecast it may not\nmessages = []\nmessages.append({\"role\": \"system\", \"content\": \"Don't make assumptions about what values to plug into functions. Ask for clarification if a user request is ambiguous.\"})\nmessages.append({\"role\": \"user\", \"content\": \"Give me a weather report for Toronto, Canada.\"})\nchat_response = chat_completion_request(\n    messages, tools=tools\n)\nchat_response.choices[0].message\n```\n\n\n\n\n    ChatCompletionMessage(content=None, role='assistant', function_call=None, tool_calls=[ChatCompletionMessageToolCall(id='call_n84kYFqjNFDPNGDEnjnrd2KC', function=Function(arguments='{\"location\": \"Toronto, Canada\", \"format\": \"celsius\"}', name='get_current_weather'), type='function'), ChatCompletionMessageToolCall(id='call_AEs3AFhJc9pn42hWSbHTaIDh', function=Function(arguments='{\"location\": \"Toronto, Canada\", \"format\": \"celsius\", \"num_days\": 3}', name='get_n_day_weather_forecast'), type='function')])\n\n\n\nWe can also force the model to not use a function at all. By doing so we prevent it from producing a proper function call.\n\n\n```python\nmessages = []\nmessages.append({\"role\": \"system\", \"content\": \"Don't make assumptions about what values to plug into functions. Ask for clarification if a user request is ambiguous.\"})\nmessages.append({\"role\": \"user\", \"content\": \"Give me the current weather (use Celcius) for Toronto, Canada.\"})\nchat_response = chat_completion_request(\n    messages, tools=tools, tool_choice=\"none\"\n)\nchat_response.choices[0].message\n\n```\n\n\n\n\n    ChatCompletionMessage(content=\"Sure, I'll get the current weather for Toronto, Canada in Celsius.\", role='assistant', function_call=None, tool_calls=None)\n\n\n\n### Parallel Function Calling\n\nNewer models such as gpt-4o or gpt-3.5-turbo can call multiple functions in one turn."}


created_at: 2024-07-28 18:59:18
topic: persistent://default/default/4bfc3c11-fb71-4cc9-8c12-01ed076a0e01
id: 4ccdb99d-ed2d-4a7b-924b-67e110aaebc3
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/How_to_call_functions_with_chat_models.ipynb", "title": "How to call functions with chat models", "tokens": 4334, "retrieve_doc": true, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"4ccdb99d-ed2d-4a7b-924b-67e110aaebc3\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_call_functions_with_chat_models.ipynb\", \"title\": \"How to call functions with chat models\", \"tokens\": 4334, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"08de5268-6020-4d7b-ac62-f00a20ed55cf\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_call_functions_with_chat_models.ipynb\", \"title\": \"How to call functions with chat models\", \"tokens\": 4334, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"465755c3f6b9fdf61cef5225b387867709ba20e7037a6e567db3b085ed7f5cd0\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"8341110e-db06-4eca-87e4-056794befc72\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_call_functions_with_chat_models.ipynb\", \"title\": \"How to call functions with chat models\", \"tokens\": 4334, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"3481b3fa94bd5ae7d393f985d88cb4b3a9fe70a74416a2d9911ca831127bdd1f\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"0d0132c5-9bc0-46f4-9b5d-029922769c35\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"8a11f50154f079af3ebee974f2265a1e7cb82a75d310223863c515701f312b9a\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 10257, \"end_char_idx\": 13337, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "08de5268-6020-4d7b-ac62-f00a20ed55cf", "doc_id": "08de5268-6020-4d7b-ac62-f00a20ed55cf", "ref_doc_id": "08de5268-6020-4d7b-ac62-f00a20ed55cf", "chroma:document": "ChatCompletionMessage(content=None, role='assistant', function_call=None, tool_calls=[ChatCompletionMessageToolCall(id='call_n84kYFqjNFDPNGDEnjnrd2KC', function=Function(arguments='{\"location\": \"Toronto, Canada\", \"format\": \"celsius\"}', name='get_current_weather'), type='function'), ChatCompletionMessageToolCall(id='call_AEs3AFhJc9pn42hWSbHTaIDh', function=Function(arguments='{\"location\": \"Toronto, Canada\", \"format\": \"celsius\", \"num_days\": 3}', name='get_n_day_weather_forecast'), type='function')])\n\n\n\nWe can also force the model to not use a function at all. By doing so we prevent it from producing a proper function call.\n\n\n```python\nmessages = []\nmessages.append({\"role\": \"system\", \"content\": \"Don't make assumptions about what values to plug into functions. Ask for clarification if a user request is ambiguous.\"})\nmessages.append({\"role\": \"user\", \"content\": \"Give me the current weather (use Celcius) for Toronto, Canada.\"})\nchat_response = chat_completion_request(\n    messages, tools=tools, tool_choice=\"none\"\n)\nchat_response.choices[0].message\n\n```\n\n\n\n\n    ChatCompletionMessage(content=\"Sure, I'll get the current weather for Toronto, Canada in Celsius.\", role='assistant', function_call=None, tool_calls=None)\n\n\n\n### Parallel Function Calling\n\nNewer models such as gpt-4o or gpt-3.5-turbo can call multiple functions in one turn.\n\n\n```python\nmessages = []\nmessages.append({\"role\": \"system\", \"content\": \"Don't make assumptions about what values to plug into functions. Ask for clarification if a user request is ambiguous.\"})\nmessages.append({\"role\": \"user\", \"content\": \"what is the weather going to be like in San Francisco and Glasgow over the next 4 days\"})\nchat_response = chat_completion_request(\n    messages, tools=tools, model=GPT_MODEL\n)\n\nassistant_message = chat_response.choices[0].message.tool_calls\nassistant_message\n```\n\n\n\n\n    [ChatCompletionMessageToolCall(id='call_ObhLiJwaHwc3U1KyB4Pdpx8y', function=Function(arguments='{\"location\": \"San Francisco, CA\", \"format\": \"fahrenheit\", \"num_days\": 4}', name='get_n_day_weather_forecast'), type='function'),\n     ChatCompletionMessageToolCall(id='call_5YRgeZ0MGBMFKE3hZiLouwg7', function=Function(arguments='{\"location\": \"Glasgow, SCT\", \"format\": \"celsius\", \"num_days\": 4}', name='get_n_day_weather_forecast'), type='function')]\n\n\n\n## How to call functions with model generated arguments\n\nIn our next example, we'll demonstrate how to execute functions whose inputs are model-generated, and use this to implement an agent that can answer questions for us about a database. For simplicity we'll use the [Chinook sample database](https://www.sqlitetutorial.net/sqlite-sample-database/).\n\n*Note:* SQL generation can be high-risk in a production environment since models are not perfectly reliable at generating correct SQL.\n\n### Specifying a function to execute SQL queries\n\nFirst let's define some helpful utility functions to extract data from a SQLite database.\n\n\n```python\nimport sqlite3\n\nconn = sqlite3.connect(\"data/Chinook.db\")\nprint(\"Opened database successfully\")\n```\n\n    Opened database successfully"}


created_at: 2024-07-28 18:59:18
topic: persistent://default/default/4bfc3c11-fb71-4cc9-8c12-01ed076a0e01
id: 0d0132c5-9bc0-46f4-9b5d-029922769c35
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/How_to_call_functions_with_chat_models.ipynb", "title": "How to call functions with chat models", "tokens": 4334, "retrieve_doc": true, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"0d0132c5-9bc0-46f4-9b5d-029922769c35\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_call_functions_with_chat_models.ipynb\", \"title\": \"How to call functions with chat models\", \"tokens\": 4334, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"08de5268-6020-4d7b-ac62-f00a20ed55cf\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_call_functions_with_chat_models.ipynb\", \"title\": \"How to call functions with chat models\", \"tokens\": 4334, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"465755c3f6b9fdf61cef5225b387867709ba20e7037a6e567db3b085ed7f5cd0\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"4ccdb99d-ed2d-4a7b-924b-67e110aaebc3\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_call_functions_with_chat_models.ipynb\", \"title\": \"How to call functions with chat models\", \"tokens\": 4334, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"ad1e89b023af057defc29d96e30f0e6e7d4a591b3f064e836a748c463aaa8411\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"a90adcc4-0810-48a0-ba72-27c96118ef08\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"40eea6c7cf635a5045b7cc0b459c1320f894f6f7bff0de859bccc766e22131ab\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 12113, \"end_char_idx\": 14828, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "08de5268-6020-4d7b-ac62-f00a20ed55cf", "doc_id": "08de5268-6020-4d7b-ac62-f00a20ed55cf", "ref_doc_id": "08de5268-6020-4d7b-ac62-f00a20ed55cf", "chroma:document": "[ChatCompletionMessageToolCall(id='call_ObhLiJwaHwc3U1KyB4Pdpx8y', function=Function(arguments='{\"location\": \"San Francisco, CA\", \"format\": \"fahrenheit\", \"num_days\": 4}', name='get_n_day_weather_forecast'), type='function'),\n     ChatCompletionMessageToolCall(id='call_5YRgeZ0MGBMFKE3hZiLouwg7', function=Function(arguments='{\"location\": \"Glasgow, SCT\", \"format\": \"celsius\", \"num_days\": 4}', name='get_n_day_weather_forecast'), type='function')]\n\n\n\n## How to call functions with model generated arguments\n\nIn our next example, we'll demonstrate how to execute functions whose inputs are model-generated, and use this to implement an agent that can answer questions for us about a database. For simplicity we'll use the [Chinook sample database](https://www.sqlitetutorial.net/sqlite-sample-database/).\n\n*Note:* SQL generation can be high-risk in a production environment since models are not perfectly reliable at generating correct SQL.\n\n### Specifying a function to execute SQL queries\n\nFirst let's define some helpful utility functions to extract data from a SQLite database.\n\n\n```python\nimport sqlite3\n\nconn = sqlite3.connect(\"data/Chinook.db\")\nprint(\"Opened database successfully\")\n```\n\n    Opened database successfully\n\n\n\n```python\ndef get_table_names(conn):\n    \"\"\"Return a list of table names.\"\"\"\n    table_names = []\n    tables = conn.execute(\"SELECT name FROM sqlite_master WHERE type='table';\")\n    for table in tables.fetchall():\n        table_names.append(table[0])\n    return table_names\n\n\ndef get_column_names(conn, table_name):\n    \"\"\"Return a list of column names.\"\"\"\n    column_names = []\n    columns = conn.execute(f\"PRAGMA table_info('{table_name}');\").fetchall()\n    for col in columns:\n        column_names.append(col[1])\n    return column_names\n\n\ndef get_database_info(conn):\n    \"\"\"Return a list of dicts containing the table name and columns for each table in the database.\"\"\"\n    table_dicts = []\n    for table_name in get_table_names(conn):\n        columns_names = get_column_names(conn, table_name)\n        table_dicts.append({\"table_name\": table_name, \"column_names\": columns_names})\n    return table_dicts\n\n```\n\nNow can use these utility functions to extract a representation of the database schema.\n\n\n```python\ndatabase_schema_dict = get_database_info(conn)\ndatabase_schema_string = \"\\n\".join(\n    [\n        f\"Table: {table['table_name']}\\nColumns: {', '.join(table['column_names'])}\"\n        for table in database_schema_dict\n    ]\n)\n```\n\nAs before, we'll define a function specification for the function we'd like the API to generate arguments for. Notice that we are inserting the database schema into the function specification. This will be important for the model to know about."}


created_at: 2024-07-28 18:59:18
topic: persistent://default/default/4bfc3c11-fb71-4cc9-8c12-01ed076a0e01
id: a90adcc4-0810-48a0-ba72-27c96118ef08
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/How_to_call_functions_with_chat_models.ipynb", "title": "How to call functions with chat models", "tokens": 4334, "retrieve_doc": true, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"a90adcc4-0810-48a0-ba72-27c96118ef08\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_call_functions_with_chat_models.ipynb\", \"title\": \"How to call functions with chat models\", \"tokens\": 4334, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"08de5268-6020-4d7b-ac62-f00a20ed55cf\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_call_functions_with_chat_models.ipynb\", \"title\": \"How to call functions with chat models\", \"tokens\": 4334, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"465755c3f6b9fdf61cef5225b387867709ba20e7037a6e567db3b085ed7f5cd0\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"0d0132c5-9bc0-46f4-9b5d-029922769c35\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_call_functions_with_chat_models.ipynb\", \"title\": \"How to call functions with chat models\", \"tokens\": 4334, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"54d9a28a3f22bd90f63de3be7d56c3bfad7c8b75876f624c6d46e5961d222102\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"72af75bb-4a7f-47ae-a574-d6e1704e5508\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"713b5fbb7f0a80047521709fbd7b998d3c14e9ce32db67f0ad62d3fb004f4749\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 13194, \"end_char_idx\": 16862, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "08de5268-6020-4d7b-ac62-f00a20ed55cf", "doc_id": "08de5268-6020-4d7b-ac62-f00a20ed55cf", "ref_doc_id": "08de5268-6020-4d7b-ac62-f00a20ed55cf", "chroma:document": "```python\nimport sqlite3\n\nconn = sqlite3.connect(\"data/Chinook.db\")\nprint(\"Opened database successfully\")\n```\n\n    Opened database successfully\n\n\n\n```python\ndef get_table_names(conn):\n    \"\"\"Return a list of table names.\"\"\"\n    table_names = []\n    tables = conn.execute(\"SELECT name FROM sqlite_master WHERE type='table';\")\n    for table in tables.fetchall():\n        table_names.append(table[0])\n    return table_names\n\n\ndef get_column_names(conn, table_name):\n    \"\"\"Return a list of column names.\"\"\"\n    column_names = []\n    columns = conn.execute(f\"PRAGMA table_info('{table_name}');\").fetchall()\n    for col in columns:\n        column_names.append(col[1])\n    return column_names\n\n\ndef get_database_info(conn):\n    \"\"\"Return a list of dicts containing the table name and columns for each table in the database.\"\"\"\n    table_dicts = []\n    for table_name in get_table_names(conn):\n        columns_names = get_column_names(conn, table_name)\n        table_dicts.append({\"table_name\": table_name, \"column_names\": columns_names})\n    return table_dicts\n\n```\n\nNow can use these utility functions to extract a representation of the database schema.\n\n\n```python\ndatabase_schema_dict = get_database_info(conn)\ndatabase_schema_string = \"\\n\".join(\n    [\n        f\"Table: {table['table_name']}\\nColumns: {', '.join(table['column_names'])}\"\n        for table in database_schema_dict\n    ]\n)\n```\n\nAs before, we'll define a function specification for the function we'd like the API to generate arguments for. Notice that we are inserting the database schema into the function specification. This will be important for the model to know about.\n\n\n```python\ntools = [\n    {\n        \"type\": \"function\",\n        \"function\": {\n            \"name\": \"ask_database\",\n            \"description\": \"Use this function to answer user questions about music. Input should be a fully formed SQL query.\",\n            \"parameters\": {\n                \"type\": \"object\",\n                \"properties\": {\n                    \"query\": {\n                        \"type\": \"string\",\n                        \"description\": f\"\"\"\n                                SQL query extracting info to answer the user's question.\n                                SQL should be written using this database schema:\n                                {database_schema_string}\n                                The query should be returned in plain text, not in JSON.\n                                \"\"\",\n                    }\n                },\n                \"required\": [\"query\"],\n            },\n        }\n    }\n]\n```\n\n### Executing SQL queries\n\nNow let's implement the function that will actually excute queries against the database.\n\n\n```python\ndef ask_database(conn, query):\n    \"\"\"Function to query SQLite database with a provided SQL query.\"\"\"\n    try:\n        results = str(conn.execute(query).fetchall())\n    except Exception as e:\n        results = f\"query failed with error: {e}\"\n    return results\n```\n\n##### Steps to invoke a function call using Chat Completions API: \n\n**Step 1**: Prompt the model with content that may result in model selecting a tool to use. The description of the tools such as a function names and signature is defined in the 'Tools' list and passed to the model in API call. If selected, the function name and parameters are included in the response.<br>\n  \n**Step 2**: Check programmatically if model wanted to call a function. If true, proceed to step 3. <br>  \n**Step 3**: Extract the function name and parameters from response, call the function with parameters. Append the result to messages. <br>    \n**Step 4**: Invoke the chat completions API with the message list to get the response."}


created_at: 2024-07-28 18:59:18
topic: persistent://default/default/4bfc3c11-fb71-4cc9-8c12-01ed076a0e01
id: 72af75bb-4a7f-47ae-a574-d6e1704e5508
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/How_to_call_functions_with_chat_models.ipynb", "title": "How to call functions with chat models", "tokens": 4334, "retrieve_doc": true, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"72af75bb-4a7f-47ae-a574-d6e1704e5508\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_call_functions_with_chat_models.ipynb\", \"title\": \"How to call functions with chat models\", \"tokens\": 4334, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"08de5268-6020-4d7b-ac62-f00a20ed55cf\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_call_functions_with_chat_models.ipynb\", \"title\": \"How to call functions with chat models\", \"tokens\": 4334, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"465755c3f6b9fdf61cef5225b387867709ba20e7037a6e567db3b085ed7f5cd0\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"a90adcc4-0810-48a0-ba72-27c96118ef08\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_call_functions_with_chat_models.ipynb\", \"title\": \"How to call functions with chat models\", \"tokens\": 4334, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"dd0712c8da5d6b6f219f0c56c660eb55b7fb9a327e93f2f6093e7e01181ecff9\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"b4912429-b929-42a5-8b8f-5ab639394fbe\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"07084e56be7dfbd48cf8bbd2718c15bf668cf6b93146d59675d4b4f241455355\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 14831, \"end_char_idx\": 17906, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "08de5268-6020-4d7b-ac62-f00a20ed55cf", "doc_id": "08de5268-6020-4d7b-ac62-f00a20ed55cf", "ref_doc_id": "08de5268-6020-4d7b-ac62-f00a20ed55cf", "chroma:document": "```python\ntools = [\n    {\n        \"type\": \"function\",\n        \"function\": {\n            \"name\": \"ask_database\",\n            \"description\": \"Use this function to answer user questions about music. Input should be a fully formed SQL query.\",\n            \"parameters\": {\n                \"type\": \"object\",\n                \"properties\": {\n                    \"query\": {\n                        \"type\": \"string\",\n                        \"description\": f\"\"\"\n                                SQL query extracting info to answer the user's question.\n                                SQL should be written using this database schema:\n                                {database_schema_string}\n                                The query should be returned in plain text, not in JSON.\n                                \"\"\",\n                    }\n                },\n                \"required\": [\"query\"],\n            },\n        }\n    }\n]\n```\n\n### Executing SQL queries\n\nNow let's implement the function that will actually excute queries against the database.\n\n\n```python\ndef ask_database(conn, query):\n    \"\"\"Function to query SQLite database with a provided SQL query.\"\"\"\n    try:\n        results = str(conn.execute(query).fetchall())\n    except Exception as e:\n        results = f\"query failed with error: {e}\"\n    return results\n```\n\n##### Steps to invoke a function call using Chat Completions API: \n\n**Step 1**: Prompt the model with content that may result in model selecting a tool to use. The description of the tools such as a function names and signature is defined in the 'Tools' list and passed to the model in API call. If selected, the function name and parameters are included in the response.<br>\n  \n**Step 2**: Check programmatically if model wanted to call a function. If true, proceed to step 3. <br>  \n**Step 3**: Extract the function name and parameters from response, call the function with parameters. Append the result to messages. <br>    \n**Step 4**: Invoke the chat completions API with the message list to get the response. \n\n\n```python\n# Step #1: Prompt with content that may result in function call. In this case the model can identify the information requested by the user is potentially available in the database schema passed to the model in Tools description. \nmessages = [{\n    \"role\":\"user\", \n    \"content\": \"What is the name of the album with the most tracks?\"\n}]\n\nresponse = client.chat.completions.create(\n    model='gpt-4o', \n    messages=messages, \n    tools= tools, \n    tool_choice=\"auto\"\n)\n\n# Append the message to messages list\nresponse_message = response.choices[0].message \nmessages.append(response_message)\n\nprint(response_message)\n```\n\n    ChatCompletionMessage(content=None, role='assistant', function_call=None, tool_calls=[ChatCompletionMessageToolCall(id='call_wDN8uLjq2ofuU6rVx1k8Gw0e', function=Function(arguments='{\"query\":\"SELECT Album.Title, COUNT(Track.TrackId) AS TrackCount FROM Album INNER JOIN Track ON Album.AlbumId = Track.AlbumId GROUP BY Album.Title ORDER BY TrackCount DESC LIMIT 1;\"}', name='ask_database'), type='function')])"}


created_at: 2024-07-28 18:59:18
topic: persistent://default/default/4bfc3c11-fb71-4cc9-8c12-01ed076a0e01
id: b4912429-b929-42a5-8b8f-5ab639394fbe
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/How_to_call_functions_with_chat_models.ipynb", "title": "How to call functions with chat models", "tokens": 4334, "retrieve_doc": true, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"b4912429-b929-42a5-8b8f-5ab639394fbe\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_call_functions_with_chat_models.ipynb\", \"title\": \"How to call functions with chat models\", \"tokens\": 4334, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"08de5268-6020-4d7b-ac62-f00a20ed55cf\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_call_functions_with_chat_models.ipynb\", \"title\": \"How to call functions with chat models\", \"tokens\": 4334, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"465755c3f6b9fdf61cef5225b387867709ba20e7037a6e567db3b085ed7f5cd0\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"72af75bb-4a7f-47ae-a574-d6e1704e5508\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_call_functions_with_chat_models.ipynb\", \"title\": \"How to call functions with chat models\", \"tokens\": 4334, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"5b1448a1e489b6eeac6b744eb560804d301a4b87b8fb287e9b19690b293775c2\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 16866, \"end_char_idx\": 19767, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "08de5268-6020-4d7b-ac62-f00a20ed55cf", "doc_id": "08de5268-6020-4d7b-ac62-f00a20ed55cf", "ref_doc_id": "08de5268-6020-4d7b-ac62-f00a20ed55cf", "chroma:document": "```python\n# Step #1: Prompt with content that may result in function call. In this case the model can identify the information requested by the user is potentially available in the database schema passed to the model in Tools description. \nmessages = [{\n    \"role\":\"user\", \n    \"content\": \"What is the name of the album with the most tracks?\"\n}]\n\nresponse = client.chat.completions.create(\n    model='gpt-4o', \n    messages=messages, \n    tools= tools, \n    tool_choice=\"auto\"\n)\n\n# Append the message to messages list\nresponse_message = response.choices[0].message \nmessages.append(response_message)\n\nprint(response_message)\n```\n\n    ChatCompletionMessage(content=None, role='assistant', function_call=None, tool_calls=[ChatCompletionMessageToolCall(id='call_wDN8uLjq2ofuU6rVx1k8Gw0e', function=Function(arguments='{\"query\":\"SELECT Album.Title, COUNT(Track.TrackId) AS TrackCount FROM Album INNER JOIN Track ON Album.AlbumId = Track.AlbumId GROUP BY Album.Title ORDER BY TrackCount DESC LIMIT 1;\"}', name='ask_database'), type='function')])\n\n\n\n```python\n# Step 2: determine if the response from the model includes a tool call.   \ntool_calls = response_message.tool_calls\nif tool_calls:\n    # If true the model will return the name of the tool / function to call and the argument(s)  \n    tool_call_id = tool_calls[0].id\n    tool_function_name = tool_calls[0].function.name\n    tool_query_string = json.loads(tool_calls[0].function.arguments)['query']\n\n    # Step 3: Call the function and retrieve results. Append the results to the messages list.      \n    if tool_function_name == 'ask_database':\n        results = ask_database(conn, tool_query_string)\n        \n        messages.append({\n            \"role\":\"tool\", \n            \"tool_call_id\":tool_call_id, \n            \"name\": tool_function_name, \n            \"content\":results\n        })\n        \n        # Step 4: Invoke the chat completions API with the function response appended to the messages list\n        # Note that messages with role 'tool' must be a response to a preceding message with 'tool_calls'\n        model_response_with_function_call = client.chat.completions.create(\n            model=\"gpt-4o\",\n            messages=messages,\n        )  # get a new response from the model where it can see the function response\n        print(model_response_with_function_call.choices[0].message.content)\n    else: \n        print(f\"Error: function {tool_function_name} does not exist\")\nelse: \n    # Model did not identify a function to call, result can be returned to the user \n    print(response_message.content) \n```\n\n    The album with the most tracks is titled \"Greatest Hits,\" which contains 57 tracks.\n\n\n## Next Steps\n\nSee our other [notebook](How_to_call_functions_for_knowledge_retrieval.ipynb) that demonstrates how to use the Chat Completions API and functions for knowledge retrieval to interact conversationally with a knowledge base."}


created_at: 2024-07-28 18:59:18
topic: persistent://default/default/4bfc3c11-fb71-4cc9-8c12-01ed076a0e01
id: 15f938e2-160d-43b6-bb9d-2a09c5b4abc5
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/How_to_build_an_agent_with_the_node_sdk.ipynb", "title": "How to build an agent with the Node.js SDK", "tokens": 3947, "retrieve_doc": true, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"15f938e2-160d-43b6-bb9d-2a09c5b4abc5\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_build_an_agent_with_the_node_sdk.ipynb\", \"title\": \"How to build an agent with the Node.js SDK\", \"tokens\": 3947, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"0393bb20-279d-4030-a283-a089763cddba\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_build_an_agent_with_the_node_sdk.ipynb\", \"title\": \"How to build an agent with the Node.js SDK\", \"tokens\": 3947, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"e9e4129f15ce147be64461e7b3f4cece759d4a6614b81e7d5afbe434e9b452d3\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"d14144d8-5721-438b-8f24-13bde8542495\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"ca1abd482282c8464f2b2e19ea362028f7b844b8c6a27ddeabe6f63a2ddaa246\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 0, \"end_char_idx\": 3146, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "0393bb20-279d-4030-a283-a089763cddba", "doc_id": "0393bb20-279d-4030-a283-a089763cddba", "ref_doc_id": "0393bb20-279d-4030-a283-a089763cddba", "chroma:document": "# How to build an agent with the Node.js SDK\n\nOpenAI functions enable your app to take action based on user inputs. This means that it can, e.g., search the web, send emails, or book tickets on behalf of your users, making it more powerful than a regular chatbot.\n\nIn this tutorial, you will build an app that uses OpenAI functions along with the latest version of the Node.js SDK. The app runs in the browser, so you only need a code editor and, e.g., VS Code Live Server to follow along locally. Alternatively, write your code directly in the browser via [this code playground at Scrimba.](https://scrimba.com/scrim/c6r3LkU9)\n\n## What you will build\n\nOur app is a simple agent that helps you find activities in your area.\nIt has access to two functions, `getLocation()` and `getCurrentWeather()`,\nwhich means it can figure out where you\u2019re located and what the weather\nis at the moment.\n\nAt this point, it's important to understand that\nOpenAI doesn't execute any code for you. It just tells your app which\nfunctions it should use in a given scenario, and then leaves it up to\nyour app to invoke them.\n\nOnce our agent knows your location and the weather, it'll use GPT\u2019s\ninternal knowledge to suggest suitable local activities for you.\n\n## Importing the SDK and authenticating with OpenAI\n\nWe start by importing the OpenAI SDK at the top of our JavaScript file and authenticate with our API key, which we have stored as an environment variable.\n\n```js\nimport OpenAI from \"openai\";\n\nconst openai = new OpenAI({\n  apiKey: process.env.OPENAI_API_KEY,\n  dangerouslyAllowBrowser: true,\n});\n```\n\nSince we're running our code in a browser environment at Scrimba, we also need to set `dangerouslyAllowBrowser: true` to confirm we understand the risks involved with client-side API requests. Please note that you should move these requests over to a Node server in a production app.\n\n## Creating our two functions\n\nNext, we'll create the two functions. The first one - `getLocation` -\nuses the [IP API](https://ipapi.co/) to get the location of the\nuser.\n\n```js\nasync function getLocation() {\n  const response = await fetch(\"https://ipapi.co/json/\");\n  const locationData = await response.json();\n  return locationData;\n}\n```\n\nThe IP API returns a bunch of data about your location, including your\nlatitude and longitude, which we\u2019ll use as arguments in the second\nfunction `getCurrentWeather`. It uses the [Open Meteo\nAPI](https://open-meteo.com/) to get the current weather data, like\nthis:\n\n```js\nasync function getCurrentWeather(latitude, longitude) {\n  const url = `https://api.open-meteo.com/v1/forecast?latitude=${latitude}&longitude=${longitude}&hourly=apparent_temperature`;\n  const response = await fetch(url);\n  const weatherData = await response.json();\n  return weatherData;\n}\n```\n\n## Describing our functions for OpenAI\n\nFor OpenAI to understand the purpose of these functions, we need to\ndescribe them using a specific schema. We'll create an array called\n`tools` that contains one object per function. Each object\nwill have two keys: `type`, `function`, and the `function` key has \nthree subkeys: `name`, `description`, and `parameters`."}


created_at: 2024-07-28 18:59:18
topic: persistent://default/default/4bfc3c11-fb71-4cc9-8c12-01ed076a0e01
id: d14144d8-5721-438b-8f24-13bde8542495
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/How_to_build_an_agent_with_the_node_sdk.ipynb", "title": "How to build an agent with the Node.js SDK", "tokens": 3947, "retrieve_doc": true, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"d14144d8-5721-438b-8f24-13bde8542495\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_build_an_agent_with_the_node_sdk.ipynb\", \"title\": \"How to build an agent with the Node.js SDK\", \"tokens\": 3947, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"0393bb20-279d-4030-a283-a089763cddba\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_build_an_agent_with_the_node_sdk.ipynb\", \"title\": \"How to build an agent with the Node.js SDK\", \"tokens\": 3947, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"e9e4129f15ce147be64461e7b3f4cece759d4a6614b81e7d5afbe434e9b452d3\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"15f938e2-160d-43b6-bb9d-2a09c5b4abc5\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_build_an_agent_with_the_node_sdk.ipynb\", \"title\": \"How to build an agent with the Node.js SDK\", \"tokens\": 3947, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"29c9e1c00d9639c324b06f2a936f7bc6e61d84dcb17986a83f1bee4a2bf5160f\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"e87a9288-958f-40a9-815a-b277101230bf\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"ca2e5d26e7b9ee64c4d5aafca21d6281e27eabbde2460e570eb871d0b9c40752\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 1785, \"end_char_idx\": 4631, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "0393bb20-279d-4030-a283-a089763cddba", "doc_id": "0393bb20-279d-4030-a283-a089763cddba", "ref_doc_id": "0393bb20-279d-4030-a283-a089763cddba", "chroma:document": "Please note that you should move these requests over to a Node server in a production app.\n\n## Creating our two functions\n\nNext, we'll create the two functions. The first one - `getLocation` -\nuses the [IP API](https://ipapi.co/) to get the location of the\nuser.\n\n```js\nasync function getLocation() {\n  const response = await fetch(\"https://ipapi.co/json/\");\n  const locationData = await response.json();\n  return locationData;\n}\n```\n\nThe IP API returns a bunch of data about your location, including your\nlatitude and longitude, which we\u2019ll use as arguments in the second\nfunction `getCurrentWeather`. It uses the [Open Meteo\nAPI](https://open-meteo.com/) to get the current weather data, like\nthis:\n\n```js\nasync function getCurrentWeather(latitude, longitude) {\n  const url = `https://api.open-meteo.com/v1/forecast?latitude=${latitude}&longitude=${longitude}&hourly=apparent_temperature`;\n  const response = await fetch(url);\n  const weatherData = await response.json();\n  return weatherData;\n}\n```\n\n## Describing our functions for OpenAI\n\nFor OpenAI to understand the purpose of these functions, we need to\ndescribe them using a specific schema. We'll create an array called\n`tools` that contains one object per function. Each object\nwill have two keys: `type`, `function`, and the `function` key has \nthree subkeys: `name`, `description`, and `parameters`.\n\n```js\nconst tools = [\n  {\n    type: \"function\",\n    function: {\n      name: \"getCurrentWeather\",\n      description: \"Get the current weather in a given location\",\n      parameters: {\n        type: \"object\",\n        properties: {\n          latitude: {\n            type: \"string\",\n          },\n          longitude: {\n            type: \"string\",\n          },\n        },\n        required: [\"longitude\", \"latitude\"],\n      },\n    }\n  },\n  {\n    type: \"function\",\n    function: {\n      name: \"getLocation\",\n      description: \"Get the user's location based on their IP address\",\n      parameters: {\n        type: \"object\",\n        properties: {},\n      },\n    }\n  },\n];\n```\n\n## Setting up the messages array\n\nWe also need to define a `messages` array. This will keep track of all of the messages back and forth between our app and OpenAI.\n\nThe first object in the array should always have the `role` property set to `\"system\"`, which tells OpenAI that this is how we want it to behave.\n\n```js\nconst messages = [\n  {\n    role: \"system\",\n    content:\n      \"You are a helpful assistant. Only use the functions you have been provided with.\",\n  },\n];\n```\n\n## Creating the agent function\n\nWe are now ready to build the logic of our app, which lives in the\n`agent` function. It is asynchronous and takes one argument: the\n`userInput`.\n\nWe start by pushing the `userInput` to the messages array. This time, we set the `role` to `\"user\"`, so that OpenAI knows that this is the input from the user."}


created_at: 2024-07-28 18:59:18
topic: persistent://default/default/4bfc3c11-fb71-4cc9-8c12-01ed076a0e01
id: e87a9288-958f-40a9-815a-b277101230bf
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/How_to_build_an_agent_with_the_node_sdk.ipynb", "title": "How to build an agent with the Node.js SDK", "tokens": 3947, "retrieve_doc": true, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"e87a9288-958f-40a9-815a-b277101230bf\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_build_an_agent_with_the_node_sdk.ipynb\", \"title\": \"How to build an agent with the Node.js SDK\", \"tokens\": 3947, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"0393bb20-279d-4030-a283-a089763cddba\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_build_an_agent_with_the_node_sdk.ipynb\", \"title\": \"How to build an agent with the Node.js SDK\", \"tokens\": 3947, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"e9e4129f15ce147be64461e7b3f4cece759d4a6614b81e7d5afbe434e9b452d3\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"d14144d8-5721-438b-8f24-13bde8542495\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_build_an_agent_with_the_node_sdk.ipynb\", \"title\": \"How to build an agent with the Node.js SDK\", \"tokens\": 3947, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"ee2d3932082a044e89551236f11a6257f9839d1897bb4991db947f7d60084290\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"4d15ad13-dfb7-4b18-a312-1c97a5988e60\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"a5196a1bcd36d11233917bb7cf99623661cf52416c626958c07e77776b086e64\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 3011, \"end_char_idx\": 5625, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "0393bb20-279d-4030-a283-a089763cddba", "doc_id": "0393bb20-279d-4030-a283-a089763cddba", "ref_doc_id": "0393bb20-279d-4030-a283-a089763cddba", "chroma:document": "Each object\nwill have two keys: `type`, `function`, and the `function` key has \nthree subkeys: `name`, `description`, and `parameters`.\n\n```js\nconst tools = [\n  {\n    type: \"function\",\n    function: {\n      name: \"getCurrentWeather\",\n      description: \"Get the current weather in a given location\",\n      parameters: {\n        type: \"object\",\n        properties: {\n          latitude: {\n            type: \"string\",\n          },\n          longitude: {\n            type: \"string\",\n          },\n        },\n        required: [\"longitude\", \"latitude\"],\n      },\n    }\n  },\n  {\n    type: \"function\",\n    function: {\n      name: \"getLocation\",\n      description: \"Get the user's location based on their IP address\",\n      parameters: {\n        type: \"object\",\n        properties: {},\n      },\n    }\n  },\n];\n```\n\n## Setting up the messages array\n\nWe also need to define a `messages` array. This will keep track of all of the messages back and forth between our app and OpenAI.\n\nThe first object in the array should always have the `role` property set to `\"system\"`, which tells OpenAI that this is how we want it to behave.\n\n```js\nconst messages = [\n  {\n    role: \"system\",\n    content:\n      \"You are a helpful assistant. Only use the functions you have been provided with.\",\n  },\n];\n```\n\n## Creating the agent function\n\nWe are now ready to build the logic of our app, which lives in the\n`agent` function. It is asynchronous and takes one argument: the\n`userInput`.\n\nWe start by pushing the `userInput` to the messages array. This time, we set the `role` to `\"user\"`, so that OpenAI knows that this is the input from the user.\n\n```js\nasync function agent(userInput) {\n  messages.push({\n    role: \"user\",\n    content: userInput,\n  });\n  const response = await openai.chat.completions.create({\n    model: \"gpt-4\",\n    messages: messages,\n    tools: tools,\n  });\n  console.log(response);\n}\n```\n\nNext, we'll send a request to the Chat completions endpoint via the\n`chat.completions.create()` method in the Node SDK. This method takes a\nconfiguration object as an argument. In it, we'll specify three\nproperties:\n\n- `model` - Decides which AI model we want to use (in our case,\n  GPT-4).\n- `messages` - The entire history of messages between the user and the\n  AI up until this point.\n- `tools`\u00a0- A list of tools the model may call. Currently, only \n  functions are supported as a tool., we'll we use the `tools` array we \n  created earlier.\n\n## Running our app with a simple input\n\nLet's try to run the `agent` with an input that requires a function call to give a suitable reply.\n\n```js\nagent(\"Where am I located right now?"}


created_at: 2024-07-28 18:59:18
topic: persistent://default/default/4bfc3c11-fb71-4cc9-8c12-01ed076a0e01
id: 4d15ad13-dfb7-4b18-a312-1c97a5988e60
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/How_to_build_an_agent_with_the_node_sdk.ipynb", "title": "How to build an agent with the Node.js SDK", "tokens": 3947, "retrieve_doc": true, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"4d15ad13-dfb7-4b18-a312-1c97a5988e60\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_build_an_agent_with_the_node_sdk.ipynb\", \"title\": \"How to build an agent with the Node.js SDK\", \"tokens\": 3947, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"0393bb20-279d-4030-a283-a089763cddba\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_build_an_agent_with_the_node_sdk.ipynb\", \"title\": \"How to build an agent with the Node.js SDK\", \"tokens\": 3947, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"e9e4129f15ce147be64461e7b3f4cece759d4a6614b81e7d5afbe434e9b452d3\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"e87a9288-958f-40a9-815a-b277101230bf\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_build_an_agent_with_the_node_sdk.ipynb\", \"title\": \"How to build an agent with the Node.js SDK\", \"tokens\": 3947, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"f16ff4f48aa6f9b0d612b32ad40e6e1447fef323769b7d64f19e084c9b7dc447\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"50a9be20-ae9a-402e-881a-09930ee0057d\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"156ab0952c55e053cf558d83723ada32eaeede13fd629274da1d9f9cb20b9b8a\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 4129, \"end_char_idx\": 6904, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "0393bb20-279d-4030-a283-a089763cddba", "doc_id": "0393bb20-279d-4030-a283-a089763cddba", "ref_doc_id": "0393bb20-279d-4030-a283-a089763cddba", "chroma:document": "```js\nconst messages = [\n  {\n    role: \"system\",\n    content:\n      \"You are a helpful assistant. Only use the functions you have been provided with.\",\n  },\n];\n```\n\n## Creating the agent function\n\nWe are now ready to build the logic of our app, which lives in the\n`agent` function. It is asynchronous and takes one argument: the\n`userInput`.\n\nWe start by pushing the `userInput` to the messages array. This time, we set the `role` to `\"user\"`, so that OpenAI knows that this is the input from the user.\n\n```js\nasync function agent(userInput) {\n  messages.push({\n    role: \"user\",\n    content: userInput,\n  });\n  const response = await openai.chat.completions.create({\n    model: \"gpt-4\",\n    messages: messages,\n    tools: tools,\n  });\n  console.log(response);\n}\n```\n\nNext, we'll send a request to the Chat completions endpoint via the\n`chat.completions.create()` method in the Node SDK. This method takes a\nconfiguration object as an argument. In it, we'll specify three\nproperties:\n\n- `model` - Decides which AI model we want to use (in our case,\n  GPT-4).\n- `messages` - The entire history of messages between the user and the\n  AI up until this point.\n- `tools`\u00a0- A list of tools the model may call. Currently, only \n  functions are supported as a tool., we'll we use the `tools` array we \n  created earlier.\n\n## Running our app with a simple input\n\nLet's try to run the `agent` with an input that requires a function call to give a suitable reply.\n\n```js\nagent(\"Where am I located right now?\");\n```\n\nWhen we run the code above, we see the response from OpenAI logged out\nto the console like this:\n\n```js\n{\n    id: \"chatcmpl-84ojoEJtyGnR6jRHK2Dl4zTtwsa7O\",\n    object: \"chat.completion\",\n    created: 1696159040,\n    model: \"gpt-4-0613\",\n    choices: [{\n        index: 0,\n        message: {\n            role: \"assistant\",\n            content: null,\n            tool_calls: [\n              id: \"call_CBwbo9qoXUn1kTR5pPuv6vR1\",\n              type: \"function\",\n              function: {\n                name: \"getLocation\",\n                arguments: \"{}\"\n              }\n            ]\n        },\n        logprobs: null,\n        finish_reason: \"tool_calls\" // OpenAI wants us to call a function\n    }],\n    usage: {\n        prompt_tokens: 134,\n        completion_tokens: 6,\n        total_tokens: 140\n    }\n     system_fingerprint: null\n}\n```\n\nThis response tells us that we should call one of our functions, as it contains the following key: `finish_reason: \"tool_calls\"`.\n\nThe name of the function can be found in the\n`response.choices[0].message.tool_calls[0].function.name` key, which is set to\n`\"getLocation\"`.\n\n## Turning the OpenAI response into a function call\n\nNow that we have the name of the function as a string, we'll need to\ntranslate that into a function call."}


created_at: 2024-07-28 18:59:18
topic: persistent://default/default/4bfc3c11-fb71-4cc9-8c12-01ed076a0e01
id: 50a9be20-ae9a-402e-881a-09930ee0057d
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/How_to_build_an_agent_with_the_node_sdk.ipynb", "title": "How to build an agent with the Node.js SDK", "tokens": 3947, "retrieve_doc": true, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"50a9be20-ae9a-402e-881a-09930ee0057d\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_build_an_agent_with_the_node_sdk.ipynb\", \"title\": \"How to build an agent with the Node.js SDK\", \"tokens\": 3947, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"0393bb20-279d-4030-a283-a089763cddba\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_build_an_agent_with_the_node_sdk.ipynb\", \"title\": \"How to build an agent with the Node.js SDK\", \"tokens\": 3947, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"e9e4129f15ce147be64461e7b3f4cece759d4a6614b81e7d5afbe434e9b452d3\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"4d15ad13-dfb7-4b18-a312-1c97a5988e60\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_build_an_agent_with_the_node_sdk.ipynb\", \"title\": \"How to build an agent with the Node.js SDK\", \"tokens\": 3947, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"8b8ec9f28d3b71f06f5efe7ae132799581ae3afd5c24775c9d3d4b16a15fb123\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"9d7ddf7d-47ca-486e-aab1-71274753b538\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"5bac127fd4eb5b14b3f065fd46d55d20acac5b808a38b458e7e9f841674a8fbf\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 5443, \"end_char_idx\": 8167, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "0393bb20-279d-4030-a283-a089763cddba", "doc_id": "0393bb20-279d-4030-a283-a089763cddba", "ref_doc_id": "0393bb20-279d-4030-a283-a089763cddba", "chroma:document": "## Running our app with a simple input\n\nLet's try to run the `agent` with an input that requires a function call to give a suitable reply.\n\n```js\nagent(\"Where am I located right now?\");\n```\n\nWhen we run the code above, we see the response from OpenAI logged out\nto the console like this:\n\n```js\n{\n    id: \"chatcmpl-84ojoEJtyGnR6jRHK2Dl4zTtwsa7O\",\n    object: \"chat.completion\",\n    created: 1696159040,\n    model: \"gpt-4-0613\",\n    choices: [{\n        index: 0,\n        message: {\n            role: \"assistant\",\n            content: null,\n            tool_calls: [\n              id: \"call_CBwbo9qoXUn1kTR5pPuv6vR1\",\n              type: \"function\",\n              function: {\n                name: \"getLocation\",\n                arguments: \"{}\"\n              }\n            ]\n        },\n        logprobs: null,\n        finish_reason: \"tool_calls\" // OpenAI wants us to call a function\n    }],\n    usage: {\n        prompt_tokens: 134,\n        completion_tokens: 6,\n        total_tokens: 140\n    }\n     system_fingerprint: null\n}\n```\n\nThis response tells us that we should call one of our functions, as it contains the following key: `finish_reason: \"tool_calls\"`.\n\nThe name of the function can be found in the\n`response.choices[0].message.tool_calls[0].function.name` key, which is set to\n`\"getLocation\"`.\n\n## Turning the OpenAI response into a function call\n\nNow that we have the name of the function as a string, we'll need to\ntranslate that into a function call. To help us with that, we'll gather\nboth of our functions in an object called `availableTools`:\n\n```js\nconst availableTools = {\n  getCurrentWeather,\n  getLocation,\n};\n```\n\nThis is handy because we'll be able to access the `getLocation` function\nvia bracket notation and the string we got back from OpenAI, like this:\n`availableTools[\"getLocation\"]`.\n\n```js\nconst { finish_reason, message } = response.choices[0];\n\nif (finish_reason === \"tool_calls\" && message.tool_calls) {\n  const functionName = message.tool_calls[0].function.name;\n  const functionToCall = availableTools[functionName];\n  const functionArgs = JSON.parse(message.tool_calls[0].function.arguments);\n  const functionArgsArr = Object.values(functionArgs);\n  const functionResponse = await functionToCall.apply(null, functionArgsArr);\n  console.log(functionResponse);\n}\n```\n\nWe're also grabbing ahold of any arguments OpenAI wants us to pass into\nthe function: `message.tool_calls[0].function.arguments`.\nHowever, we won't need any arguments for this first function call.\n\nIf we run the code again with the same input\n(`\"Where am I located right now?\"`), we'll see that `functionResponse`\nis an object filled with location about where the user is located right\nnow. In my case, that is Oslo, Norway."}


created_at: 2024-07-28 18:59:18
topic: persistent://default/default/4bfc3c11-fb71-4cc9-8c12-01ed076a0e01
id: 9d7ddf7d-47ca-486e-aab1-71274753b538
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/How_to_build_an_agent_with_the_node_sdk.ipynb", "title": "How to build an agent with the Node.js SDK", "tokens": 3947, "retrieve_doc": true, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"9d7ddf7d-47ca-486e-aab1-71274753b538\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_build_an_agent_with_the_node_sdk.ipynb\", \"title\": \"How to build an agent with the Node.js SDK\", \"tokens\": 3947, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"0393bb20-279d-4030-a283-a089763cddba\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_build_an_agent_with_the_node_sdk.ipynb\", \"title\": \"How to build an agent with the Node.js SDK\", \"tokens\": 3947, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"e9e4129f15ce147be64461e7b3f4cece759d4a6614b81e7d5afbe434e9b452d3\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"50a9be20-ae9a-402e-881a-09930ee0057d\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_build_an_agent_with_the_node_sdk.ipynb\", \"title\": \"How to build an agent with the Node.js SDK\", \"tokens\": 3947, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"9a50d3d6443358666831d3311be386983b2f71fa1c6a791e7ee175d1b597bb27\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"3d6209e8-26e5-4f88-8d02-840177fc6d8e\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"4acfcc5b2f43f077fca35e309599e288082196449b9519ce1e67e1c153393778\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 6604, \"end_char_idx\": 9553, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "0393bb20-279d-4030-a283-a089763cddba", "doc_id": "0393bb20-279d-4030-a283-a089763cddba", "ref_doc_id": "0393bb20-279d-4030-a283-a089763cddba", "chroma:document": "The name of the function can be found in the\n`response.choices[0].message.tool_calls[0].function.name` key, which is set to\n`\"getLocation\"`.\n\n## Turning the OpenAI response into a function call\n\nNow that we have the name of the function as a string, we'll need to\ntranslate that into a function call. To help us with that, we'll gather\nboth of our functions in an object called `availableTools`:\n\n```js\nconst availableTools = {\n  getCurrentWeather,\n  getLocation,\n};\n```\n\nThis is handy because we'll be able to access the `getLocation` function\nvia bracket notation and the string we got back from OpenAI, like this:\n`availableTools[\"getLocation\"]`.\n\n```js\nconst { finish_reason, message } = response.choices[0];\n\nif (finish_reason === \"tool_calls\" && message.tool_calls) {\n  const functionName = message.tool_calls[0].function.name;\n  const functionToCall = availableTools[functionName];\n  const functionArgs = JSON.parse(message.tool_calls[0].function.arguments);\n  const functionArgsArr = Object.values(functionArgs);\n  const functionResponse = await functionToCall.apply(null, functionArgsArr);\n  console.log(functionResponse);\n}\n```\n\nWe're also grabbing ahold of any arguments OpenAI wants us to pass into\nthe function: `message.tool_calls[0].function.arguments`.\nHowever, we won't need any arguments for this first function call.\n\nIf we run the code again with the same input\n(`\"Where am I located right now?\"`), we'll see that `functionResponse`\nis an object filled with location about where the user is located right\nnow. In my case, that is Oslo, Norway.\n\n```js\n{ip: \"193.212.60.170\", network: \"193.212.60.0/23\", version: \"IPv4\", city: \"Oslo\", region: \"Oslo County\", region_code: \"03\", country: \"NO\", country_name: \"Norway\", country_code: \"NO\", country_code_iso3: \"NOR\", country_capital: \"Oslo\", country_tld: \".no\", continent_code: \"EU\", in_eu: false, postal: \"0026\", latitude: 59.955, longitude: 10.859, timezone: \"Europe/Oslo\", utc_offset: \"+0200\", country_calling_code: \"+47\", currency: \"NOK\", currency_name: \"Krone\", languages: \"no,nb,nn,se,fi\", country_area: 324220, country_population: 5314336, asn: \"AS2119\", org: \"Telenor Norge AS\"}\n```\n\nWe'll add this data to a new item in the `messages` array, where we also\nspecify the name of the function we called.\n\n```js\nmessages.push({\n  role: \"function\",\n  name: functionName,\n  content: `The result of the last function was this: ${JSON.stringify(\n    functionResponse\n  )}\n  `,\n});\n```\n\nNotice that the `role` is set to `\"function\"`. This tells OpenAI\nthat the `content` parameter contains the result of the function call\nand not the input from the user.\n\nAt this point, we need to send a new request to OpenAI with this updated\n`messages` array. However, we don\u2019t want to hard code a new function\ncall, as our agent might need to go back and forth between itself and\nGPT several times until it has found the final answer for the user.\n\nThis can be solved in several different ways, e.g."}


created_at: 2024-07-28 18:59:18
topic: persistent://default/default/4bfc3c11-fb71-4cc9-8c12-01ed076a0e01
id: 3d6209e8-26e5-4f88-8d02-840177fc6d8e
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/How_to_build_an_agent_with_the_node_sdk.ipynb", "title": "How to build an agent with the Node.js SDK", "tokens": 3947, "retrieve_doc": true, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"3d6209e8-26e5-4f88-8d02-840177fc6d8e\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_build_an_agent_with_the_node_sdk.ipynb\", \"title\": \"How to build an agent with the Node.js SDK\", \"tokens\": 3947, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"0393bb20-279d-4030-a283-a089763cddba\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_build_an_agent_with_the_node_sdk.ipynb\", \"title\": \"How to build an agent with the Node.js SDK\", \"tokens\": 3947, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"e9e4129f15ce147be64461e7b3f4cece759d4a6614b81e7d5afbe434e9b452d3\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"9d7ddf7d-47ca-486e-aab1-71274753b538\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_build_an_agent_with_the_node_sdk.ipynb\", \"title\": \"How to build an agent with the Node.js SDK\", \"tokens\": 3947, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"9fd205e51fdc3727ab7f5172b80bf09525fc996eaf6ce84f95cdc7b2fe5b6861\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"8de32944-4cd8-49ee-b8ac-d3ec721e2f79\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"b1885671f8b1758a1018aaa2f5bff352cb9ead17165d574b27a5892209cfc6f6\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 8877, \"end_char_idx\": 12087, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "0393bb20-279d-4030-a283-a089763cddba", "doc_id": "0393bb20-279d-4030-a283-a089763cddba", "ref_doc_id": "0393bb20-279d-4030-a283-a089763cddba", "chroma:document": "```js\nmessages.push({\n  role: \"function\",\n  name: functionName,\n  content: `The result of the last function was this: ${JSON.stringify(\n    functionResponse\n  )}\n  `,\n});\n```\n\nNotice that the `role` is set to `\"function\"`. This tells OpenAI\nthat the `content` parameter contains the result of the function call\nand not the input from the user.\n\nAt this point, we need to send a new request to OpenAI with this updated\n`messages` array. However, we don\u2019t want to hard code a new function\ncall, as our agent might need to go back and forth between itself and\nGPT several times until it has found the final answer for the user.\n\nThis can be solved in several different ways, e.g.\u00a0recursion, a\nwhile-loop, or a for-loop. We'll use a good old for-loop for the sake of\nsimplicity.\n\n## Creating the loop\n\nAt the top of the `agent` function, we'll create a loop that lets us run\nthe entire procedure up to five times.\n\nIf we get back `finish_reason: \"tool_calls\"` from GPT, we'll just\npush the result of the function call to the `messages` array and jump to\nthe next iteration of the loop, triggering a new request.\n\nIf we get `finish_reason: \"stop\"` back, then GPT has found a suitable\nanswer, so we'll return the function and cancel the loop.\n\n```js\nfor (let i = 0; i < 5; i++) {\n  const response = await openai.chat.completions.create({\n    model: \"gpt-4\",\n    messages: messages,\n    tools: tools,\n  });\n  const { finish_reason, message } = response.choices[0];\n\n  if (finish_reason === \"tool_calls\" && message.tool_calls) {\n    const functionName = message.tool_calls[0].function.name;\n    const functionToCall = availableTools[functionName];\n    const functionArgs = JSON.parse(message.tool_calls[0].function.arguments);\n    const functionArgsArr = Object.values(functionArgs);\n    const functionResponse = await functionToCall.apply(null, functionArgsArr);\n\n    messages.push({\n      role: \"function\",\n      name: functionName,\n      content: `\n          The result of the last function was this: ${JSON.stringify(\n            functionResponse\n          )}\n          `,\n    });\n  } else if (finish_reason === \"stop\") {\n    messages.push(message);\n    return message.content;\n  }\n}\nreturn \"The maximum number of iterations has been met without a suitable answer. Please try again with a more specific input.\";\n```\n\nIf we don't see a `finish_reason: \"stop\"` within our five iterations,\nwe'll return a message saying we couldn\u2019t find a suitable answer.\n\n## Running the final app\n\nAt this point, we are ready to try our app! I'll ask the agent to\nsuggest some activities based on my location and the current weather.\n\n```js\nconst response = await agent(\n  \"Please suggest some activities based on my location and the current weather.\"\n);\nconsole.log(response);\n```\n\nHere's what we see in the console (formatted to make it easier to read):\n\n```js\nBased on your current location in Oslo, Norway and the weather (15\u00b0C and snowy),\nhere are some activity suggestions:\n\n1. A visit to the Oslo Winter Park for skiing or snowboarding.\n2. Enjoy a cosy day at a local caf\u00e9 or restaurant.\n3. Visit one of Oslo's many museums. The Fram Museum or Viking Ship Museum offer interesting insights into Norway\u2019s seafaring history.\n4."}


created_at: 2024-07-28 18:59:18
topic: persistent://default/default/4bfc3c11-fb71-4cc9-8c12-01ed076a0e01
id: 8de32944-4cd8-49ee-b8ac-d3ec721e2f79
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/How_to_build_an_agent_with_the_node_sdk.ipynb", "title": "How to build an agent with the Node.js SDK", "tokens": 3947, "retrieve_doc": true, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"8de32944-4cd8-49ee-b8ac-d3ec721e2f79\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_build_an_agent_with_the_node_sdk.ipynb\", \"title\": \"How to build an agent with the Node.js SDK\", \"tokens\": 3947, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"0393bb20-279d-4030-a283-a089763cddba\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_build_an_agent_with_the_node_sdk.ipynb\", \"title\": \"How to build an agent with the Node.js SDK\", \"tokens\": 3947, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"e9e4129f15ce147be64461e7b3f4cece759d4a6614b81e7d5afbe434e9b452d3\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"3d6209e8-26e5-4f88-8d02-840177fc6d8e\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_build_an_agent_with_the_node_sdk.ipynb\", \"title\": \"How to build an agent with the Node.js SDK\", \"tokens\": 3947, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"cb06b31432e5f60fb9cdb1dd668602442b78a35ce9d02b0b67894faac8b2ce37\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"e69166ee-9369-4a9a-9f8d-303fd68c7241\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"878dc08538da8f65fe66c6a3dee4de13f8bb480fe45b4cf715ad1ce893704a08\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 11138, \"end_char_idx\": 13479, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "0393bb20-279d-4030-a283-a089763cddba", "doc_id": "0393bb20-279d-4030-a283-a089763cddba", "ref_doc_id": "0393bb20-279d-4030-a283-a089763cddba", "chroma:document": "Please try again with a more specific input.\";\n```\n\nIf we don't see a `finish_reason: \"stop\"` within our five iterations,\nwe'll return a message saying we couldn\u2019t find a suitable answer.\n\n## Running the final app\n\nAt this point, we are ready to try our app! I'll ask the agent to\nsuggest some activities based on my location and the current weather.\n\n```js\nconst response = await agent(\n  \"Please suggest some activities based on my location and the current weather.\"\n);\nconsole.log(response);\n```\n\nHere's what we see in the console (formatted to make it easier to read):\n\n```js\nBased on your current location in Oslo, Norway and the weather (15\u00b0C and snowy),\nhere are some activity suggestions:\n\n1. A visit to the Oslo Winter Park for skiing or snowboarding.\n2. Enjoy a cosy day at a local caf\u00e9 or restaurant.\n3. Visit one of Oslo's many museums. The Fram Museum or Viking Ship Museum offer interesting insights into Norway\u2019s seafaring history.\n4. Take a stroll in the snowy streets and enjoy the beautiful winter landscape.\n5. Enjoy a nice book by the fireplace in a local library.\n6. Take a fjord sightseeing cruise to enjoy the snowy landscapes.\n\nAlways remember to bundle up and stay warm. Enjoy your day!\n```\n\nIf we peak under the hood, and log out `response.choices[0].message` in\neach iteration of the loop, we'll see that GPT has instructed us to use\nboth our functions before coming up with an answer.\n\nFirst, it tells us to call the `getLocation` function. Then it tells us\nto call the `getCurrentWeather` function with\n`\"longitude\": \"10.859\", \"latitude\": \"59.955\"` passed in as the\narguments. This is data it got back from the first function call we did.\n\n```js\n{\"role\":\"assistant\",\"content\":null,\"tool_calls\":[{\"id\":\"call_Cn1KH8mtHQ2AMbyNwNJTweEP\",\"type\":\"function\",\"function\":{\"name\":\"getLocation\",\"arguments\":\"{}\"}}]}\n{\"role\":\"assistant\",\"content\":null,\"tool_calls\":[{\"id\":\"call_uc1oozJfGTvYEfIzzcsfXfOl\",\"type\":\"function\",\"function\":{\"name\":\"getCurrentWeather\",\"arguments\":\"{\\n\\\"latitude\\\": \\\"10.859\\\",\\n\\\"longitude\\\": \\\"59.955\\\"\\n}\"}}]}\n```\n\nYou've now built an AI agent using OpenAI functions and the Node.js SDK! If you're looking for an extra challenge, consider enhancing this app. For example, you could add a function that fetches up-to-date information on events and activities in the user's location.\n\nHappy coding!"}


created_at: 2024-07-28 18:59:18
topic: persistent://default/default/4bfc3c11-fb71-4cc9-8c12-01ed076a0e01
id: e69166ee-9369-4a9a-9f8d-303fd68c7241
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/How_to_build_an_agent_with_the_node_sdk.ipynb", "title": "How to build an agent with the Node.js SDK", "tokens": 3947, "retrieve_doc": true, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"e69166ee-9369-4a9a-9f8d-303fd68c7241\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_build_an_agent_with_the_node_sdk.ipynb\", \"title\": \"How to build an agent with the Node.js SDK\", \"tokens\": 3947, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"0393bb20-279d-4030-a283-a089763cddba\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_build_an_agent_with_the_node_sdk.ipynb\", \"title\": \"How to build an agent with the Node.js SDK\", \"tokens\": 3947, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"e9e4129f15ce147be64461e7b3f4cece759d4a6614b81e7d5afbe434e9b452d3\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"8de32944-4cd8-49ee-b8ac-d3ec721e2f79\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_build_an_agent_with_the_node_sdk.ipynb\", \"title\": \"How to build an agent with the Node.js SDK\", \"tokens\": 3947, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"8d81de62fea77afac1f7b7f1848622bba8971a6f09d4266096225a8ea4606619\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"c86a1dc7-8ddf-4cfa-83a8-5097b8e50105\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"f7865ffd704d0cba63385c58a1801b60b329c1eb19d631c990a51a26b8af936f\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 11950, \"end_char_idx\": 14926, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "0393bb20-279d-4030-a283-a089763cddba", "doc_id": "0393bb20-279d-4030-a283-a089763cddba", "ref_doc_id": "0393bb20-279d-4030-a283-a089763cddba", "chroma:document": "3. Visit one of Oslo's many museums. The Fram Museum or Viking Ship Museum offer interesting insights into Norway\u2019s seafaring history.\n4. Take a stroll in the snowy streets and enjoy the beautiful winter landscape.\n5. Enjoy a nice book by the fireplace in a local library.\n6. Take a fjord sightseeing cruise to enjoy the snowy landscapes.\n\nAlways remember to bundle up and stay warm. Enjoy your day!\n```\n\nIf we peak under the hood, and log out `response.choices[0].message` in\neach iteration of the loop, we'll see that GPT has instructed us to use\nboth our functions before coming up with an answer.\n\nFirst, it tells us to call the `getLocation` function. Then it tells us\nto call the `getCurrentWeather` function with\n`\"longitude\": \"10.859\", \"latitude\": \"59.955\"` passed in as the\narguments. This is data it got back from the first function call we did.\n\n```js\n{\"role\":\"assistant\",\"content\":null,\"tool_calls\":[{\"id\":\"call_Cn1KH8mtHQ2AMbyNwNJTweEP\",\"type\":\"function\",\"function\":{\"name\":\"getLocation\",\"arguments\":\"{}\"}}]}\n{\"role\":\"assistant\",\"content\":null,\"tool_calls\":[{\"id\":\"call_uc1oozJfGTvYEfIzzcsfXfOl\",\"type\":\"function\",\"function\":{\"name\":\"getCurrentWeather\",\"arguments\":\"{\\n\\\"latitude\\\": \\\"10.859\\\",\\n\\\"longitude\\\": \\\"59.955\\\"\\n}\"}}]}\n```\n\nYou've now built an AI agent using OpenAI functions and the Node.js SDK! If you're looking for an extra challenge, consider enhancing this app. For example, you could add a function that fetches up-to-date information on events and activities in the user's location.\n\nHappy coding!\n\n<details>\n<summary>Complete code</summary>\n\n```js\nimport OpenAI from \"openai\";\n\nconst openai = new OpenAI({\n  apiKey: process.env.OPENAI_API_KEY,\n  dangerouslyAllowBrowser: true,\n});\n\nasync function getLocation() {\n  const response = await fetch(\"https://ipapi.co/json/\");\n  const locationData = await response.json();\n  return locationData;\n}\n\nasync function getCurrentWeather(latitude, longitude) {\n  const url = `https://api.open-meteo.com/v1/forecast?latitude=${latitude}&longitude=${longitude}&hourly=apparent_temperature`;\n  const response = await fetch(url);\n  const weatherData = await response.json();\n  return weatherData;\n}\n\nconst tools = [\n  {\n    type: \"function\",\n    function: {\n      name: \"getCurrentWeather\",\n      description: \"Get the current weather in a given location\",\n      parameters: {\n        type: \"object\",\n        properties: {\n          latitude: {\n            type: \"string\",\n          },\n          longitude: {\n            type: \"string\",\n          },\n        },\n        required: [\"longitude\", \"latitude\"],\n      },\n    }\n  },\n  {\n    type: \"function\",\n    function: {\n      name: \"getLocation\",\n      description: \"Get the user's location based on their IP address\",\n      parameters: {\n        type: \"object\",\n        properties: {},\n      },\n    }\n  },\n];\n\nconst availableTools = {\n  getCurrentWeather,\n  getLocation,\n};\n\nconst messages = [\n  {\n    role: \"system\",\n    content: `You are a helpful assistant."}


created_at: 2024-07-28 18:59:18
topic: persistent://default/default/4bfc3c11-fb71-4cc9-8c12-01ed076a0e01
id: c86a1dc7-8ddf-4cfa-83a8-5097b8e50105
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/How_to_build_an_agent_with_the_node_sdk.ipynb", "title": "How to build an agent with the Node.js SDK", "tokens": 3947, "retrieve_doc": true, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"c86a1dc7-8ddf-4cfa-83a8-5097b8e50105\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_build_an_agent_with_the_node_sdk.ipynb\", \"title\": \"How to build an agent with the Node.js SDK\", \"tokens\": 3947, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"0393bb20-279d-4030-a283-a089763cddba\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_build_an_agent_with_the_node_sdk.ipynb\", \"title\": \"How to build an agent with the Node.js SDK\", \"tokens\": 3947, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"e9e4129f15ce147be64461e7b3f4cece759d4a6614b81e7d5afbe434e9b452d3\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"e69166ee-9369-4a9a-9f8d-303fd68c7241\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/How_to_build_an_agent_with_the_node_sdk.ipynb\", \"title\": \"How to build an agent with the Node.js SDK\", \"tokens\": 3947, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"731fde036ed5f91290f363b28a9caa3c916b8177d1a60ba782830ec793a955e3\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 13271, \"end_char_idx\": 16413, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "0393bb20-279d-4030-a283-a089763cddba", "doc_id": "0393bb20-279d-4030-a283-a089763cddba", "ref_doc_id": "0393bb20-279d-4030-a283-a089763cddba", "chroma:document": "If you're looking for an extra challenge, consider enhancing this app. For example, you could add a function that fetches up-to-date information on events and activities in the user's location.\n\nHappy coding!\n\n<details>\n<summary>Complete code</summary>\n\n```js\nimport OpenAI from \"openai\";\n\nconst openai = new OpenAI({\n  apiKey: process.env.OPENAI_API_KEY,\n  dangerouslyAllowBrowser: true,\n});\n\nasync function getLocation() {\n  const response = await fetch(\"https://ipapi.co/json/\");\n  const locationData = await response.json();\n  return locationData;\n}\n\nasync function getCurrentWeather(latitude, longitude) {\n  const url = `https://api.open-meteo.com/v1/forecast?latitude=${latitude}&longitude=${longitude}&hourly=apparent_temperature`;\n  const response = await fetch(url);\n  const weatherData = await response.json();\n  return weatherData;\n}\n\nconst tools = [\n  {\n    type: \"function\",\n    function: {\n      name: \"getCurrentWeather\",\n      description: \"Get the current weather in a given location\",\n      parameters: {\n        type: \"object\",\n        properties: {\n          latitude: {\n            type: \"string\",\n          },\n          longitude: {\n            type: \"string\",\n          },\n        },\n        required: [\"longitude\", \"latitude\"],\n      },\n    }\n  },\n  {\n    type: \"function\",\n    function: {\n      name: \"getLocation\",\n      description: \"Get the user's location based on their IP address\",\n      parameters: {\n        type: \"object\",\n        properties: {},\n      },\n    }\n  },\n];\n\nconst availableTools = {\n  getCurrentWeather,\n  getLocation,\n};\n\nconst messages = [\n  {\n    role: \"system\",\n    content: `You are a helpful assistant. Only use the functions you have been provided with.`,\n  },\n];\n\nasync function agent(userInput) {\n  messages.push({\n    role: \"user\",\n    content: userInput,\n  });\n\n  for (let i = 0; i < 5; i++) {\n    const response = await openai.chat.completions.create({\n      model: \"gpt-4\",\n      messages: messages,\n      tools: tools,\n    });\n\n    const { finish_reason, message } = response.choices[0];\n\n    if (finish_reason === \"tool_calls\" && message.tool_calls) {\n      const functionName = message.tool_calls[0].function.name;\n      const functionToCall = availableTools[functionName];\n      const functionArgs = JSON.parse(message.tool_calls[0].function.arguments);\n      const functionArgsArr = Object.values(functionArgs);\n      const functionResponse = await functionToCall.apply(\n        null,\n        functionArgsArr\n      );\n\n      messages.push({\n        role: \"function\",\n        name: functionName,\n        content: `\n                The result of the last function was this: ${JSON.stringify(\n                  functionResponse\n                )}\n                `,\n      });\n    } else if (finish_reason === \"stop\") {\n      messages.push(message);\n      return message.content;\n    }\n  }\n  return \"The maximum number of iterations has been met without a suitable answer. Please try again with a more specific input.\";\n}\n\nconst response = await agent(\n  \"Please suggest some activities based on my location and the weather.\"\n);\n\nconsole.log(\"response:\", response);\n```\n\n</details>"}


created_at: 2024-07-28 18:59:18
topic: persistent://default/default/4bfc3c11-fb71-4cc9-8c12-01ed076a0e01
id: 41f7978e-946b-4be2-b1c0-7e41c79fe087
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/Whisper_processing_guide.ipynb", "title": "Enhancing Whisper transcriptions: pre- & post-processing techniques", "tokens": 4316, "retrieve_doc": true, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"41f7978e-946b-4be2-b1c0-7e41c79fe087\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Whisper_processing_guide.ipynb\", \"title\": \"Enhancing Whisper transcriptions: pre- & post-processing techniques\", \"tokens\": 4316, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"002ccc81-4a5a-433b-8e52-71790afbf455\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Whisper_processing_guide.ipynb\", \"title\": \"Enhancing Whisper transcriptions: pre- & post-processing techniques\", \"tokens\": 4316, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"bc43f25e4bad646dcfd48f7eba342e2e601e53c1f3ce2232fc15f7992037e6fe\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"aeefd677-3e3a-44be-b36c-c34ab5e39c2a\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"ce2a580a5afd89fd71b66665fe1b4b24f3e9d9034b478faeaf45c0e25150c635\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 0, \"end_char_idx\": 3155, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "002ccc81-4a5a-433b-8e52-71790afbf455", "doc_id": "002ccc81-4a5a-433b-8e52-71790afbf455", "ref_doc_id": "002ccc81-4a5a-433b-8e52-71790afbf455", "chroma:document": "# Enhancing Whisper transcriptions: pre- & post-processing techniques\n\nThis notebook offers a guide to improve the Whisper's transcriptions. We'll streamline your audio data via trimming and segmentation, enhancing Whisper's transcription quality. After transcriptions, we'll refine the output by adding punctuation, adjusting product terminology (e.g., 'five two nine' to '529'), and mitigating Unicode issues. These strategies will help improve the clarity of your transcriptions, but remember, customization based on your unique use-case may be beneficial.\n\n\n\n## Setup\n\nTo get started let's import a few different libraries:\n\n- [PyDub](http://pydub.com/) is a simple and easy-to-use Python library for audio processing tasks such as slicing, concatenating, and exporting audio files.\n\n- The `Audio` class from the `IPython.display` module allows you to create an audio control that can play sound in Jupyter notebooks, providing a straightforward way to play audio data directly in your notebook.\n\n- For our audio file, we'll use a fictional earnings call written by ChatGPT and read aloud by the author.This audio file is relatively short, but hopefully provides you with an illustrative idea of how these pre and post processing steps can be applied to any audio file. \n\n\n```python\nfrom openai import OpenAI\nimport os\nimport urllib\nfrom IPython.display import Audio\nfrom pathlib import Path\nfrom pydub import AudioSegment\nimport ssl\n```\n\n\n```python\nclient = OpenAI(api_key=os.environ.get(\"OPENAI_API_KEY\", \"<your OpenAI API key if not set as env var>\"))\n```\n\n\n```python\n# set download paths\nearnings_call_remote_filepath = \"https://cdn.openai.com/API/examples/data/EarningsCall.wav\"\n\n# set local save locations\nearnings_call_filepath = \"data/EarningsCall.wav\"\n\n# download example audio files and save locally\nssl._create_default_https_context = ssl._create_unverified_context\nurllib.request.urlretrieve(earnings_call_remote_filepath, earnings_call_filepath)\n```\n\n\n\n\n    ('data/EarningsCall.wav', <http.client.HTTPMessage at 0x11be41f50>)\n\n\n\nAt times, files with long silences at the beginning can cause Whisper to transcribe the audio incorrectly. We'll use Pydub to detect and trim the silence. \n\nHere, we've set the decibel threshold of 20. You can change this if you would like.\n\n\n```python\n# Function to detect leading silence\n# Returns the number of milliseconds until the first sound (chunk averaging more than X decibels)\ndef milliseconds_until_sound(sound, silence_threshold_in_decibels=-20.0, chunk_size=10):\n    trim_ms = 0  # ms\n\n    assert chunk_size > 0  # to avoid infinite loop\n    while sound[trim_ms:trim_ms+chunk_size].dBFS < silence_threshold_in_decibels and trim_ms < len(sound):\n        trim_ms += chunk_size\n\n    return trim_ms\n\n```\n\n\n```python\ndef trim_start(filepath):\n    path = Path(filepath)\n    directory = path.parent\n    filename = path.name\n    audio = AudioSegment.from_file(filepath, format=\"wav\")\n    start_trim = milliseconds_until_sound(audio)\n    trimmed = audio[start_trim:]\n    new_filename = directory / f\"trimmed_{filename}\"\n    trimmed.export(new_filename, format=\"wav\")\n    return trimmed, new_filename\n\n```"}


created_at: 2024-07-28 18:59:18
topic: persistent://default/default/4bfc3c11-fb71-4cc9-8c12-01ed076a0e01
id: aeefd677-3e3a-44be-b36c-c34ab5e39c2a
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/Whisper_processing_guide.ipynb", "title": "Enhancing Whisper transcriptions: pre- & post-processing techniques", "tokens": 4316, "retrieve_doc": true, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"aeefd677-3e3a-44be-b36c-c34ab5e39c2a\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Whisper_processing_guide.ipynb\", \"title\": \"Enhancing Whisper transcriptions: pre- & post-processing techniques\", \"tokens\": 4316, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"002ccc81-4a5a-433b-8e52-71790afbf455\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Whisper_processing_guide.ipynb\", \"title\": \"Enhancing Whisper transcriptions: pre- & post-processing techniques\", \"tokens\": 4316, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"bc43f25e4bad646dcfd48f7eba342e2e601e53c1f3ce2232fc15f7992037e6fe\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"41f7978e-946b-4be2-b1c0-7e41c79fe087\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Whisper_processing_guide.ipynb\", \"title\": \"Enhancing Whisper transcriptions: pre- & post-processing techniques\", \"tokens\": 4316, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"a936cbdd5cf261d67d40e4b14c80564c3a0b7c8bc3c411b33d65442568f42125\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"39fec574-f6b1-4580-a33c-22121e93e44a\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"250343fa2b7446d5d05e80aa64a3da5a50a7ea2b7842df0bcafe033caa211721\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 1565, \"end_char_idx\": 5033, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "002ccc81-4a5a-433b-8e52-71790afbf455", "doc_id": "002ccc81-4a5a-433b-8e52-71790afbf455", "ref_doc_id": "002ccc81-4a5a-433b-8e52-71790afbf455", "chroma:document": "```python\n# set download paths\nearnings_call_remote_filepath = \"https://cdn.openai.com/API/examples/data/EarningsCall.wav\"\n\n# set local save locations\nearnings_call_filepath = \"data/EarningsCall.wav\"\n\n# download example audio files and save locally\nssl._create_default_https_context = ssl._create_unverified_context\nurllib.request.urlretrieve(earnings_call_remote_filepath, earnings_call_filepath)\n```\n\n\n\n\n    ('data/EarningsCall.wav', <http.client.HTTPMessage at 0x11be41f50>)\n\n\n\nAt times, files with long silences at the beginning can cause Whisper to transcribe the audio incorrectly. We'll use Pydub to detect and trim the silence. \n\nHere, we've set the decibel threshold of 20. You can change this if you would like.\n\n\n```python\n# Function to detect leading silence\n# Returns the number of milliseconds until the first sound (chunk averaging more than X decibels)\ndef milliseconds_until_sound(sound, silence_threshold_in_decibels=-20.0, chunk_size=10):\n    trim_ms = 0  # ms\n\n    assert chunk_size > 0  # to avoid infinite loop\n    while sound[trim_ms:trim_ms+chunk_size].dBFS < silence_threshold_in_decibels and trim_ms < len(sound):\n        trim_ms += chunk_size\n\n    return trim_ms\n\n```\n\n\n```python\ndef trim_start(filepath):\n    path = Path(filepath)\n    directory = path.parent\n    filename = path.name\n    audio = AudioSegment.from_file(filepath, format=\"wav\")\n    start_trim = milliseconds_until_sound(audio)\n    trimmed = audio[start_trim:]\n    new_filename = directory / f\"trimmed_{filename}\"\n    trimmed.export(new_filename, format=\"wav\")\n    return trimmed, new_filename\n\n```\n\n\n```python\ndef transcribe_audio(file,output_dir):\n    audio_path = os.path.join(output_dir, file)\n    with open(audio_path, 'rb') as audio_data:\n        transcription = client.audio.transcriptions.create(\n            model=\"whisper-1\", file=audio_data)\n        return transcription.text\n```\n\nAt times, we've seen unicode character injection in transcripts, removing any non-ASCII characters should help mitigate this issue.\n\nKeep in mind you should not use this function if you are transcribing in Greek, Cyrillic, Arabic, Chinese, etc\n\n\n```python\n# Define function to remove non-ascii characters\ndef remove_non_ascii(text):\n    return ''.join(i for i in text if ord(i)<128)\n\n```\n\nThis function will add formatting and punctuation to our transcript. Whisper generates a transcript with punctuation but without formatting.\n\n\n```python\n# Define function to add punctuation\ndef punctuation_assistant(ascii_transcript):\n\n    system_prompt = \"\"\"You are a helpful assistant that adds punctuation to text.\n      Preserve the original words and only insert necessary punctuation such as periods,\n     commas, capialization, symbols like dollar sings or percentage signs, and formatting.\n     Use only the context provided. If there is no context provided say, 'No context provided'\\n\"\"\"\n    response = client.chat.completions.create(\n        model=\"gpt-3.5-turbo\",\n        temperature=0,\n        messages=[\n            {\n                \"role\": \"system\",\n                \"content\": system_prompt\n            },\n            {\n                \"role\": \"user\",\n                \"content\": ascii_transcript\n            }\n        ]\n    )\n    return response\n\n```\n\nOur audio file is a recording from a fake earnings call that includes a lot of financial products. This function can help ensure that if Whisper transcribes these financial product names incorrectly, that they can be corrected."}


created_at: 2024-07-28 18:59:18
topic: persistent://default/default/4bfc3c11-fb71-4cc9-8c12-01ed076a0e01
id: 39fec574-f6b1-4580-a33c-22121e93e44a
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/Whisper_processing_guide.ipynb", "title": "Enhancing Whisper transcriptions: pre- & post-processing techniques", "tokens": 4316, "retrieve_doc": true, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"39fec574-f6b1-4580-a33c-22121e93e44a\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Whisper_processing_guide.ipynb\", \"title\": \"Enhancing Whisper transcriptions: pre- & post-processing techniques\", \"tokens\": 4316, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"002ccc81-4a5a-433b-8e52-71790afbf455\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Whisper_processing_guide.ipynb\", \"title\": \"Enhancing Whisper transcriptions: pre- & post-processing techniques\", \"tokens\": 4316, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"bc43f25e4bad646dcfd48f7eba342e2e601e53c1f3ce2232fc15f7992037e6fe\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"aeefd677-3e3a-44be-b36c-c34ab5e39c2a\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Whisper_processing_guide.ipynb\", \"title\": \"Enhancing Whisper transcriptions: pre- & post-processing techniques\", \"tokens\": 4316, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"15ad041000a42a0f6d992a064ce0eca8be8b9fe7998ee0de8c45361226fba0a9\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"6c9b8f16-9ded-49c5-94a2-d9c4cccbc305\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"4e9490c34d3fe134717faef8ddbacf62f2eefefbeea076dcecf05bc590620988\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 3158, \"end_char_idx\": 7246, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "002ccc81-4a5a-433b-8e52-71790afbf455", "doc_id": "002ccc81-4a5a-433b-8e52-71790afbf455", "ref_doc_id": "002ccc81-4a5a-433b-8e52-71790afbf455", "chroma:document": "```python\ndef transcribe_audio(file,output_dir):\n    audio_path = os.path.join(output_dir, file)\n    with open(audio_path, 'rb') as audio_data:\n        transcription = client.audio.transcriptions.create(\n            model=\"whisper-1\", file=audio_data)\n        return transcription.text\n```\n\nAt times, we've seen unicode character injection in transcripts, removing any non-ASCII characters should help mitigate this issue.\n\nKeep in mind you should not use this function if you are transcribing in Greek, Cyrillic, Arabic, Chinese, etc\n\n\n```python\n# Define function to remove non-ascii characters\ndef remove_non_ascii(text):\n    return ''.join(i for i in text if ord(i)<128)\n\n```\n\nThis function will add formatting and punctuation to our transcript. Whisper generates a transcript with punctuation but without formatting.\n\n\n```python\n# Define function to add punctuation\ndef punctuation_assistant(ascii_transcript):\n\n    system_prompt = \"\"\"You are a helpful assistant that adds punctuation to text.\n      Preserve the original words and only insert necessary punctuation such as periods,\n     commas, capialization, symbols like dollar sings or percentage signs, and formatting.\n     Use only the context provided. If there is no context provided say, 'No context provided'\\n\"\"\"\n    response = client.chat.completions.create(\n        model=\"gpt-3.5-turbo\",\n        temperature=0,\n        messages=[\n            {\n                \"role\": \"system\",\n                \"content\": system_prompt\n            },\n            {\n                \"role\": \"user\",\n                \"content\": ascii_transcript\n            }\n        ]\n    )\n    return response\n\n```\n\nOur audio file is a recording from a fake earnings call that includes a lot of financial products. This function can help ensure that if Whisper transcribes these financial product names incorrectly, that they can be corrected. \n\n\n```python\n# Define function to fix product mispellings\ndef product_assistant(ascii_transcript):\n    system_prompt = \"\"\"You are an intelligent assistant specializing in financial products;\n    your task is to process transcripts of earnings calls, ensuring that all references to\n     financial products and common financial terms are in the correct format. For each\n     financial product or common term that is typically abbreviated as an acronym, the full term \n    should be spelled out followed by the acronym in parentheses. For example, '401k' should be\n     transformed to '401(k) retirement savings plan', 'HSA' should be transformed to 'Health Savings Account (HSA)'\n    , 'ROA' should be transformed to 'Return on Assets (ROA)', 'VaR' should be transformed to 'Value at Risk (VaR)'\n, and 'PB' should be transformed to 'Price to Book (PB) ratio'. Similarly, transform spoken numbers representing \nfinancial products into their numeric representations, followed by the full name of the product in parentheses. \nFor instance, 'five two nine' to '529 (Education Savings Plan)' and 'four zero one k' to '401(k) (Retirement Savings Plan)'.\n However, be aware that some acronyms can have different meanings based on the context (e.g., 'LTV' can stand for \n'Loan to Value' or 'Lifetime Value'). You will need to discern from the context which term is being referred to \nand apply the appropriate transformation. In cases where numerical figures or metrics are spelled out but do not \nrepresent specific financial products (like 'twenty three percent'), these should be left as is. Your role is to\n analyze and adjust financial product terminology in the text. Once you've done that, produce the adjusted \n transcript and a list of the words you've changed\"\"\"\n    response = client.chat.completions.create(\n        model=\"gpt-4\",\n        temperature=0,\n        messages=[\n            {\n                \"role\": \"system\",\n                \"content\": system_prompt\n            },\n            {\n                \"role\": \"user\",\n                \"content\": ascii_transcript\n            }\n        ]\n    )\n    return response\n\n```\n\nThis function will create a new file with 'trimmed' appended to the original file name"}


created_at: 2024-07-28 18:59:18
topic: persistent://default/default/4bfc3c11-fb71-4cc9-8c12-01ed076a0e01
id: 6c9b8f16-9ded-49c5-94a2-d9c4cccbc305
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/Whisper_processing_guide.ipynb", "title": "Enhancing Whisper transcriptions: pre- & post-processing techniques", "tokens": 4316, "retrieve_doc": true, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"6c9b8f16-9ded-49c5-94a2-d9c4cccbc305\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Whisper_processing_guide.ipynb\", \"title\": \"Enhancing Whisper transcriptions: pre- & post-processing techniques\", \"tokens\": 4316, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"002ccc81-4a5a-433b-8e52-71790afbf455\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Whisper_processing_guide.ipynb\", \"title\": \"Enhancing Whisper transcriptions: pre- & post-processing techniques\", \"tokens\": 4316, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"bc43f25e4bad646dcfd48f7eba342e2e601e53c1f3ce2232fc15f7992037e6fe\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"39fec574-f6b1-4580-a33c-22121e93e44a\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Whisper_processing_guide.ipynb\", \"title\": \"Enhancing Whisper transcriptions: pre- & post-processing techniques\", \"tokens\": 4316, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"629dc50165c993ec9ea5abee10e2d485c52531aa76e361f0cf77f076506045ca\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"9c6ed9b1-fc33-4e10-aa8b-60de26021e91\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"89ee532b7d56a10764bc114f8dd5f5ed9b8e09da8c99c87e082d0e39eca7e8b8\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 7249, \"end_char_idx\": 9037, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "002ccc81-4a5a-433b-8e52-71790afbf455", "doc_id": "002ccc81-4a5a-433b-8e52-71790afbf455", "ref_doc_id": "002ccc81-4a5a-433b-8e52-71790afbf455", "chroma:document": "```python\n# Trim the start of the original audio file\ntrimmed_audio = trim_start(earnings_call_filepath)\n\n```\n\n\n```python\ntrimmed_audio, trimmed_filename = trim_start(earnings_call_filepath)\n\n```\n\nOur fake earnings report audio file is fairly short in length, so we'll adjust the segments accordingly. Keep in mind you can adjust the segment length as you need.\n\n\n```python\n# Segment audio\ntrimmed_audio = AudioSegment.from_wav(trimmed_filename)  # Load the trimmed audio file\n\none_minute = 1 * 60 * 1000  # Duration for each segment (in milliseconds)\n\nstart_time = 0  # Start time for the first segment\n\ni = 0  # Index for naming the segmented files\n\noutput_dir_trimmed = \"trimmed_earnings_directory\"  # Output directory for the segmented files\n\nif not os.path.isdir(output_dir_trimmed):  # Create the output directory if it does not exist\n    os.makedirs(output_dir_trimmed)\n\nwhile start_time < len(trimmed_audio):  # Loop over the trimmed audio file\n    segment = trimmed_audio[start_time:start_time + one_minute]  # Extract a segment\n    segment.export(os.path.join(output_dir_trimmed, f\"trimmed_{i:02d}.wav\"), format=\"wav\")  # Save the segment\n    start_time += one_minute  # Update the start time for the next segment\n    i += 1  # Increment the index for naming the next file\n\n```\n\n\n```python\n# Get list of trimmed and segmented audio files and sort them numerically\naudio_files = sorted(\n    (f for f in os.listdir(output_dir_trimmed) if f.endswith(\".wav\")),\n    key=lambda f: int(''.join(filter(str.isdigit, f)))\n)\n\n```\n\n\n```python\n# Use a loop to apply the transcribe function to all audio files\ntranscriptions = [transcribe_audio(file, output_dir_trimmed) for file in audio_files]\n\n```\n\n\n```python\n# Concatenate the transcriptions\nfull_transcript = ' '.join(transcriptions)\n```"}


created_at: 2024-07-28 18:59:18
topic: persistent://default/default/4bfc3c11-fb71-4cc9-8c12-01ed076a0e01
id: 9c6ed9b1-fc33-4e10-aa8b-60de26021e91
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/Whisper_processing_guide.ipynb", "title": "Enhancing Whisper transcriptions: pre- & post-processing techniques", "tokens": 4316, "retrieve_doc": true, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"9c6ed9b1-fc33-4e10-aa8b-60de26021e91\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Whisper_processing_guide.ipynb\", \"title\": \"Enhancing Whisper transcriptions: pre- & post-processing techniques\", \"tokens\": 4316, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"002ccc81-4a5a-433b-8e52-71790afbf455\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Whisper_processing_guide.ipynb\", \"title\": \"Enhancing Whisper transcriptions: pre- & post-processing techniques\", \"tokens\": 4316, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"bc43f25e4bad646dcfd48f7eba342e2e601e53c1f3ce2232fc15f7992037e6fe\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"6c9b8f16-9ded-49c5-94a2-d9c4cccbc305\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Whisper_processing_guide.ipynb\", \"title\": \"Enhancing Whisper transcriptions: pre- & post-processing techniques\", \"tokens\": 4316, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"4b1cba78d8aa7739b0f179e95de7686909f630c919bcff5dde85720e3fd670ba\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"a6c65f13-d2f9-4e50-bd1f-e240c9736bbb\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"72c5e5e2d75b959ff6b4aca1db084e20fe4e3fba4b65ec1826257384dc8a8d30\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 7613, \"end_char_idx\": 11303, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "002ccc81-4a5a-433b-8e52-71790afbf455", "doc_id": "002ccc81-4a5a-433b-8e52-71790afbf455", "ref_doc_id": "002ccc81-4a5a-433b-8e52-71790afbf455", "chroma:document": "```python\n# Segment audio\ntrimmed_audio = AudioSegment.from_wav(trimmed_filename)  # Load the trimmed audio file\n\none_minute = 1 * 60 * 1000  # Duration for each segment (in milliseconds)\n\nstart_time = 0  # Start time for the first segment\n\ni = 0  # Index for naming the segmented files\n\noutput_dir_trimmed = \"trimmed_earnings_directory\"  # Output directory for the segmented files\n\nif not os.path.isdir(output_dir_trimmed):  # Create the output directory if it does not exist\n    os.makedirs(output_dir_trimmed)\n\nwhile start_time < len(trimmed_audio):  # Loop over the trimmed audio file\n    segment = trimmed_audio[start_time:start_time + one_minute]  # Extract a segment\n    segment.export(os.path.join(output_dir_trimmed, f\"trimmed_{i:02d}.wav\"), format=\"wav\")  # Save the segment\n    start_time += one_minute  # Update the start time for the next segment\n    i += 1  # Increment the index for naming the next file\n\n```\n\n\n```python\n# Get list of trimmed and segmented audio files and sort them numerically\naudio_files = sorted(\n    (f for f in os.listdir(output_dir_trimmed) if f.endswith(\".wav\")),\n    key=lambda f: int(''.join(filter(str.isdigit, f)))\n)\n\n```\n\n\n```python\n# Use a loop to apply the transcribe function to all audio files\ntranscriptions = [transcribe_audio(file, output_dir_trimmed) for file in audio_files]\n\n```\n\n\n```python\n# Concatenate the transcriptions\nfull_transcript = ' '.join(transcriptions)\n```\n\n\n```python\nprint(full_transcript)\n```\n\n    Good afternoon, everyone. And welcome to FinTech Plus Sync's second quarter 2023 earnings call. I'm John Doe, CEO of FinTech Plus. We've had a stellar Q2 with a revenue of 125 million, a 25% increase year over year. Our gross profit margin stands at a solid 58%, due in part to cost efficiencies gained from our scalable business model. Our EBITDA has surged to 37.5 million, translating to a remarkable 30% EBITDA margin. Our net income for the quarter rose to 16 million, which is a noteworthy increase from 10 million in Q2 2022. Our total addressable market has grown substantially thanks to the expansion of our high yield savings product line and the new RoboAdvisor platform. We've been diversifying our asset-backed securities portfolio, investing heavily in collateralized. debt obligations, and residential mortgage-backed securities. We've also invested $25 million in AAA rated corporate bonds, enhancing our risk adjusted returns. As for our balance sheet, total assets reached $1.5 billion with total liabilities at $900 million, leaving us with a solid equity base of $600 million. Our debt-to-equity ratio stands at 1.5, a healthy figure considering our expansionary phase. We continue to see substantial organic user growth, with customer acquisition cost dropping by 15% and lifetime value growing by 25%. Our LTVCAC ratio is at an impressive 3.5%. In terms of risk management, we have a value-at-risk model in place with a 99%... confidence level indicating that our maximum loss will not exceed 5 million in the next trading day. We've adopted a conservative approach to managing our leverage and have a healthy tier one capital ratio of 12.5%. Our forecast for the coming quarter is positive. We expect revenue to be around 135 million and 8% quarter over quarter growth driven primarily by our cutting edge blockchain solutions and AI driven predictive analytics. We're also excited about the upcoming IPO of our FinTech subsidiary Pay Plus, which we expect to raise 200 million, significantly bolstering our liquidity and paving the way for aggressive growth strategies. We thank our shareholders for their continued faith in us and we look forward to an even more successful Q3. Thank you so much."}


created_at: 2024-07-28 18:59:18
topic: persistent://default/default/4bfc3c11-fb71-4cc9-8c12-01ed076a0e01
id: a6c65f13-d2f9-4e50-bd1f-e240c9736bbb
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/Whisper_processing_guide.ipynb", "title": "Enhancing Whisper transcriptions: pre- & post-processing techniques", "tokens": 4316, "retrieve_doc": true, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"a6c65f13-d2f9-4e50-bd1f-e240c9736bbb\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Whisper_processing_guide.ipynb\", \"title\": \"Enhancing Whisper transcriptions: pre- & post-processing techniques\", \"tokens\": 4316, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"002ccc81-4a5a-433b-8e52-71790afbf455\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Whisper_processing_guide.ipynb\", \"title\": \"Enhancing Whisper transcriptions: pre- & post-processing techniques\", \"tokens\": 4316, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"bc43f25e4bad646dcfd48f7eba342e2e601e53c1f3ce2232fc15f7992037e6fe\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"9c6ed9b1-fc33-4e10-aa8b-60de26021e91\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Whisper_processing_guide.ipynb\", \"title\": \"Enhancing Whisper transcriptions: pre- & post-processing techniques\", \"tokens\": 4316, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"49b0ef804ba03ee2e1f7d9f64a4b2f1e0c7709f1e9bcc62217b0cb97ef1dd57f\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"f20419cc-2a96-4f4f-928e-101839112ed7\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"a09ab78b36bb4244b7e67208f56c917b7256e350437cf29fc68c3ac79326f7b7\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 11307, \"end_char_idx\": 13934, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "002ccc81-4a5a-433b-8e52-71790afbf455", "doc_id": "002ccc81-4a5a-433b-8e52-71790afbf455", "ref_doc_id": "002ccc81-4a5a-433b-8e52-71790afbf455", "chroma:document": "```python\n# Remove non-ascii characters from the transcript\nascii_transcript = remove_non_ascii(full_transcript)\n```\n\n\n```python\nprint(ascii_transcript)\n```\n\n    Good afternoon, everyone. And welcome to FinTech Plus Sync's second quarter 2023 earnings call. I'm John Doe, CEO of FinTech Plus. We've had a stellar Q2 with a revenue of 125 million, a 25% increase year over year. Our gross profit margin stands at a solid 58%, due in part to cost efficiencies gained from our scalable business model. Our EBITDA has surged to 37.5 million, translating to a remarkable 30% EBITDA margin. Our net income for the quarter rose to 16 million, which is a noteworthy increase from 10 million in Q2 2022. Our total addressable market has grown substantially thanks to the expansion of our high yield savings product line and the new RoboAdvisor platform. We've been diversifying our asset-backed securities portfolio, investing heavily in collateralized. debt obligations, and residential mortgage-backed securities. We've also invested $25 million in AAA rated corporate bonds, enhancing our risk adjusted returns. As for our balance sheet, total assets reached $1.5 billion with total liabilities at $900 million, leaving us with a solid equity base of $600 million. Our debt-to-equity ratio stands at 1.5, a healthy figure considering our expansionary phase. We continue to see substantial organic user growth, with customer acquisition cost dropping by 15% and lifetime value growing by 25%. Our LTVCAC ratio is at an impressive 3.5%. In terms of risk management, we have a value-at-risk model in place with a 99%... confidence level indicating that our maximum loss will not exceed 5 million in the next trading day. We've adopted a conservative approach to managing our leverage and have a healthy tier one capital ratio of 12.5%. Our forecast for the coming quarter is positive. We expect revenue to be around 135 million and 8% quarter over quarter growth driven primarily by our cutting edge blockchain solutions and AI driven predictive analytics. We're also excited about the upcoming IPO of our FinTech subsidiary Pay Plus, which we expect to raise 200 million, significantly bolstering our liquidity and paving the way for aggressive growth strategies. We thank our shareholders for their continued faith in us and we look forward to an even more successful Q3. Thank you so much.\n\n\n\n```python\n# Use punctuation assistant function\nresponse = punctuation_assistant(ascii_transcript)\n```\n\n\n```python\n# Extract the punctuated transcript from the model's response\npunctuated_transcript = response.choices[0].message.content\n\n```"}


created_at: 2024-07-28 18:59:18
topic: persistent://default/default/4bfc3c11-fb71-4cc9-8c12-01ed076a0e01
id: f20419cc-2a96-4f4f-928e-101839112ed7
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/Whisper_processing_guide.ipynb", "title": "Enhancing Whisper transcriptions: pre- & post-processing techniques", "tokens": 4316, "retrieve_doc": true, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"f20419cc-2a96-4f4f-928e-101839112ed7\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Whisper_processing_guide.ipynb\", \"title\": \"Enhancing Whisper transcriptions: pre- & post-processing techniques\", \"tokens\": 4316, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"002ccc81-4a5a-433b-8e52-71790afbf455\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Whisper_processing_guide.ipynb\", \"title\": \"Enhancing Whisper transcriptions: pre- & post-processing techniques\", \"tokens\": 4316, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"bc43f25e4bad646dcfd48f7eba342e2e601e53c1f3ce2232fc15f7992037e6fe\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"a6c65f13-d2f9-4e50-bd1f-e240c9736bbb\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Whisper_processing_guide.ipynb\", \"title\": \"Enhancing Whisper transcriptions: pre- & post-processing techniques\", \"tokens\": 4316, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"0d3f79b38f777b8e52ddb7173c6801ea13a0cec662360da14856f5f0e160e94b\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"c80ae743-2b83-4413-af1e-459998e2eaa3\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"7a40d3431e7ccc2e456c6789aa456a094be82379c6df6fd6e6fc3e28e4597763\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 13694, \"end_char_idx\": 16440, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "002ccc81-4a5a-433b-8e52-71790afbf455", "doc_id": "002ccc81-4a5a-433b-8e52-71790afbf455", "ref_doc_id": "002ccc81-4a5a-433b-8e52-71790afbf455", "chroma:document": "```python\n# Use punctuation assistant function\nresponse = punctuation_assistant(ascii_transcript)\n```\n\n\n```python\n# Extract the punctuated transcript from the model's response\npunctuated_transcript = response.choices[0].message.content\n\n```\n\n\n```python\nprint(punctuated_transcript)\n```\n\n    Good afternoon, everyone. And welcome to FinTech Plus Sync's second quarter 2023 earnings call. I'm John Doe, CEO of FinTech Plus. We've had a stellar Q2 with a revenue of $125 million, a 25% increase year over year. Our gross profit margin stands at a solid 58%, due in part to cost efficiencies gained from our scalable business model. Our EBITDA has surged to $37.5 million, translating to a remarkable 30% EBITDA margin. Our net income for the quarter rose to $16 million, which is a noteworthy increase from $10 million in Q2 2022. Our total addressable market has grown substantially thanks to the expansion of our high yield savings product line and the new RoboAdvisor platform. We've been diversifying our asset-backed securities portfolio, investing heavily in collateralized debt obligations, and residential mortgage-backed securities. We've also invested $25 million in AAA rated corporate bonds, enhancing our risk-adjusted returns. As for our balance sheet, total assets reached $1.5 billion with total liabilities at $900 million, leaving us with a solid equity base of $600 million. Our debt-to-equity ratio stands at 1.5, a healthy figure considering our expansionary phase. We continue to see substantial organic user growth, with customer acquisition cost dropping by 15% and lifetime value growing by 25%. Our LTVCAC ratio is at an impressive 3.5%. In terms of risk management, we have a value-at-risk model in place with a 99% confidence level indicating that our maximum loss will not exceed $5 million in the next trading day. We've adopted a conservative approach to managing our leverage and have a healthy tier one capital ratio of 12.5%. Our forecast for the coming quarter is positive. We expect revenue to be around $135 million and 8% quarter over quarter growth driven primarily by our cutting-edge blockchain solutions and AI-driven predictive analytics. We're also excited about the upcoming IPO of our FinTech subsidiary Pay Plus, which we expect to raise $200 million, significantly bolstering our liquidity and paving the way for aggressive growth strategies. We thank our shareholders for their continued faith in us and we look forward to an even more successful Q3. Thank you so much.\n\n\n\n```python\n# Use product assistant function\nresponse = product_assistant(punctuated_transcript)\n\n```\n\n\n```python\n# Extract the final transcript from the model's response\nfinal_transcript = response.choices[0].message.content\n```"}


created_at: 2024-07-28 18:59:18
topic: persistent://default/default/4bfc3c11-fb71-4cc9-8c12-01ed076a0e01
id: c80ae743-2b83-4413-af1e-459998e2eaa3
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/Whisper_processing_guide.ipynb", "title": "Enhancing Whisper transcriptions: pre- & post-processing techniques", "tokens": 4316, "retrieve_doc": true, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"c80ae743-2b83-4413-af1e-459998e2eaa3\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Whisper_processing_guide.ipynb\", \"title\": \"Enhancing Whisper transcriptions: pre- & post-processing techniques\", \"tokens\": 4316, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"002ccc81-4a5a-433b-8e52-71790afbf455\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Whisper_processing_guide.ipynb\", \"title\": \"Enhancing Whisper transcriptions: pre- & post-processing techniques\", \"tokens\": 4316, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"bc43f25e4bad646dcfd48f7eba342e2e601e53c1f3ce2232fc15f7992037e6fe\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"f20419cc-2a96-4f4f-928e-101839112ed7\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Whisper_processing_guide.ipynb\", \"title\": \"Enhancing Whisper transcriptions: pre- & post-processing techniques\", \"tokens\": 4316, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"569c2ed5cbf82bc6eac8a0efacafb65a100ee39ba8490af70b37a18cc7e8e677\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 16213, \"end_char_idx\": 19472, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "002ccc81-4a5a-433b-8e52-71790afbf455", "doc_id": "002ccc81-4a5a-433b-8e52-71790afbf455", "ref_doc_id": "002ccc81-4a5a-433b-8e52-71790afbf455", "chroma:document": "```python\n# Use product assistant function\nresponse = product_assistant(punctuated_transcript)\n\n```\n\n\n```python\n# Extract the final transcript from the model's response\nfinal_transcript = response.choices[0].message.content\n```\n\n\n```python\nprint(final_transcript)\n```\n\n    Good afternoon, everyone. And welcome to FinTech Plus Sync's second quarter 2023 earnings call. I'm John Doe, CEO of FinTech Plus. We've had a stellar second quarter (Q2) with a revenue of $125 million, a 25% increase year over year. Our gross profit margin stands at a solid 58%, due in part to cost efficiencies gained from our scalable business model. Our Earnings Before Interest, Taxes, Depreciation, and Amortization (EBITDA) has surged to $37.5 million, translating to a remarkable 30% EBITDA margin. Our net income for the quarter rose to $16 million, which is a noteworthy increase from $10 million in second quarter (Q2) 2022. Our total addressable market has grown substantially thanks to the expansion of our high yield savings product line and the new RoboAdvisor platform. We've been diversifying our asset-backed securities portfolio, investing heavily in Collateralized Debt Obligations (CDOs), and Residential Mortgage-Backed Securities (RMBS). We've also invested $25 million in AAA rated corporate bonds, enhancing our risk-adjusted returns. As for our balance sheet, total assets reached $1.5 billion with total liabilities at $900 million, leaving us with a solid equity base of $600 million. Our Debt-to-Equity (D/E) ratio stands at 1.5, a healthy figure considering our expansionary phase. We continue to see substantial organic user growth, with Customer Acquisition Cost (CAC) dropping by 15% and Lifetime Value (LTV) growing by 25%. Our LTV to CAC (LTVCAC) ratio is at an impressive 3.5%. In terms of risk management, we have a Value at Risk (VaR) model in place with a 99% confidence level indicating that our maximum loss will not exceed $5 million in the next trading day. We've adopted a conservative approach to managing our leverage and have a healthy Tier 1 Capital ratio of 12.5%. Our forecast for the coming quarter is positive. We expect revenue to be around $135 million and 8% quarter over quarter growth driven primarily by our cutting-edge blockchain solutions and AI-driven predictive analytics. We're also excited about the upcoming Initial Public Offering (IPO) of our FinTech subsidiary Pay Plus, which we expect to raise $200 million, significantly bolstering our liquidity and paving the way for aggressive growth strategies. We thank our shareholders for their continued faith in us and we look forward to an even more successful third quarter (Q3). Thank you so much.\n    \n    Words Changed:\n    1. Q2 -> second quarter (Q2)\n    2. EBITDA -> Earnings Before Interest, Taxes, Depreciation, and Amortization (EBITDA)\n    3. Q2 2022 -> second quarter (Q2) 2022\n    4. CDOs -> Collateralized Debt Obligations (CDOs)\n    5. RMBS -> Residential Mortgage-Backed Securities (RMBS)\n    6. D/E -> Debt-to-Equity (D/E)\n    7. CAC -> Customer Acquisition Cost (CAC)\n    8. LTV -> Lifetime Value (LTV)\n    9. LTVCAC -> LTV to CAC (LTVCAC)\n    10. VaR -> Value at Risk (VaR)\n    11. IPO -> Initial Public Offering (IPO)\n    12. Q3 -> third quarter (Q3)"}


created_at: 2024-07-28 18:59:18
topic: persistent://default/default/4bfc3c11-fb71-4cc9-8c12-01ed076a0e01
id: c8552af3-b2a9-4615-99be-e7e5bebbc181
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/Question_answering_using_a_search_API.ipynb", "title": "Question answering using a search API and re-ranking", "tokens": 4009, "retrieve_doc": true, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"c8552af3-b2a9-4615-99be-e7e5bebbc181\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Question_answering_using_a_search_API.ipynb\", \"title\": \"Question answering using a search API and re-ranking\", \"tokens\": 4009, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"9c08ddb4-205b-4eb3-a84d-c5b7ffe5abf3\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Question_answering_using_a_search_API.ipynb\", \"title\": \"Question answering using a search API and re-ranking\", \"tokens\": 4009, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"e5f4c9e0edabd0a6096b78edba4264943f81a6402b6a4b458c9b133c6f4b48bc\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"ae9947c7-0208-4053-95a8-164ee6480bbe\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"c4254d8c62443e86b16503c909db9f2a9579fa2e50c7ccc6501a14d591220afa\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 0, \"end_char_idx\": 2849, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "9c08ddb4-205b-4eb3-a84d-c5b7ffe5abf3", "doc_id": "9c08ddb4-205b-4eb3-a84d-c5b7ffe5abf3", "ref_doc_id": "9c08ddb4-205b-4eb3-a84d-c5b7ffe5abf3", "chroma:document": "# Question answering using a search API and re-ranking\n\nSearching for relevant information can sometimes feel like looking for a needle in a haystack, but don\u2019t despair, GPTs can actually do a lot of this work for us. In this guide we explore a way to augment existing search systems with various AI techniques, helping us sift through the noise.\n\nTwo ways of retrieving information for GPT are:\n\n1. **Mimicking Human Browsing:** [GPT triggers a search](https://openai.com/blog/chatgpt-plugins#browsing), evaluates the results, and modifies the search query if necessary. It can also follow up on specific search results to form a chain of thought, much like a human user would do.\n2. **Retrieval with Embeddings:** Calculate [embeddings](https://platform.openai.com/docs/guides/embeddings) for your content and a user query, and then [retrieve the content](Question_answering_using_embeddings.ipynb) most related as measured by cosine similarity. This technique is [used heavily](https://blog.google/products/search/search-language-understanding-bert/) by search engines like Google.\n\nThese approaches are both promising, but each has their shortcomings: the first one can be slow due to its iterative nature and the second one requires embedding your entire knowledge base in advance, continuously embedding new content and maintaining a vector database.\n\nBy combining these approaches, and drawing inspiration from [re-ranking](https://www.sbert.net/examples/applications/retrieve_rerank/README.html) methods, we identify an approach that sits in the middle. **This approach can be implemented on top of any existing search system, like the Slack search API, or an internal ElasticSearch instance with private data**. Here\u2019s how it works:\n\n![search_augmented_by_query_generation_and_embeddings_reranking.png](../images/search_rerank_answer.png)\n\n**Step 1: Search**\n\n1.  User asks a question.\n2.  GPT generates a list of potential queries.\n3.  Search queries are executed in parallel.\n\n**Step 2: Re-rank**\n\n1.  Embeddings for each result are used to calculate semantic similarity to a generated hypothetical ideal answer to the user question.\n2.  Results are ranked and filtered based on this similarity metric.\n\n**Step 3: Answer**\n\n1.  Given the top search results, the model generates an answer to the user\u2019s question, including references and links.\n\nThis hybrid approach offers relatively low latency and can be integrated into any existing search endpoint, without requiring the upkeep of a vector database. Let's dive into it! We will use the [News API](https://newsapi.org/) as an example domain to search over.\n\n## Setup\n\nIn addition to your `OPENAI_API_KEY`, you'll have to include a `NEWS_API_KEY` in your environment. You can get an API key [here](https://newsapi.org/).\n\n\n\n```python\n%%capture\n%env NEWS_API_KEY = YOUR_NEWS_API_KEY\n\n```"}


created_at: 2024-07-28 18:59:18
topic: persistent://default/default/4bfc3c11-fb71-4cc9-8c12-01ed076a0e01
id: ae9947c7-0208-4053-95a8-164ee6480bbe
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/Question_answering_using_a_search_API.ipynb", "title": "Question answering using a search API and re-ranking", "tokens": 4009, "retrieve_doc": true, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"ae9947c7-0208-4053-95a8-164ee6480bbe\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Question_answering_using_a_search_API.ipynb\", \"title\": \"Question answering using a search API and re-ranking\", \"tokens\": 4009, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"9c08ddb4-205b-4eb3-a84d-c5b7ffe5abf3\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Question_answering_using_a_search_API.ipynb\", \"title\": \"Question answering using a search API and re-ranking\", \"tokens\": 4009, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"e5f4c9e0edabd0a6096b78edba4264943f81a6402b6a4b458c9b133c6f4b48bc\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"c8552af3-b2a9-4615-99be-e7e5bebbc181\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Question_answering_using_a_search_API.ipynb\", \"title\": \"Question answering using a search API and re-ranking\", \"tokens\": 4009, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"56bc523ca19b457691a16fd1be45bcb82be3dab3a4a0b4513c1c2b6ec2814e15\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"e78d0d84-72f1-47eb-8247-69a8a1a07eaa\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"ed9d4b732ef247f18cba6b0c12366e7e1a84df9d7dc3bb4c031147fceb797ccf\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 2787, \"end_char_idx\": 5980, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "9c08ddb4-205b-4eb3-a84d-c5b7ffe5abf3", "doc_id": "9c08ddb4-205b-4eb3-a84d-c5b7ffe5abf3", "ref_doc_id": "9c08ddb4-205b-4eb3-a84d-c5b7ffe5abf3", "chroma:document": "```python\n%%capture\n%env NEWS_API_KEY = YOUR_NEWS_API_KEY\n\n```\n\n\n```python\n# Dependencies\nfrom datetime import date, timedelta  # date handling for fetching recent news\nfrom IPython import display  # for pretty printing\nimport json  # for parsing the JSON api responses and model outputs\nfrom numpy import dot  # for cosine similarity\nfrom openai import OpenAI\nimport os  # for loading environment variables\nimport requests  # for making the API requests\nfrom tqdm.notebook import tqdm  # for printing progress bars\n\nclient = OpenAI(api_key=os.environ.get(\"OPENAI_API_KEY\", \"<your OpenAI API key if not set as env var>\"))\n\n# Load environment variables\nnews_api_key = os.getenv(\"NEWS_API_KEY\")\n\nGPT_MODEL = \"gpt-3.5-turbo\"\n\n\n# Helper functions\ndef json_gpt(input: str):\n    completion = client.chat.completions.create(model=GPT_MODEL,\n    messages=[\n        {\"role\": \"system\", \"content\": \"Output only valid JSON\"},\n        {\"role\": \"user\", \"content\": input},\n    ],\n    temperature=0.5)\n\n    text = completion.choices[0].message.content\n    parsed = json.loads(text)\n\n    return parsed\n\n\ndef embeddings(input: list[str]) -> list[list[str]]:\n    response = client.embeddings.create(model=\"text-embedding-3-small\", input=input)\n    return [data.embedding for data in response.data]\n```\n\n## 1. Search\n\nIt all starts with a user question.\n\n\n\n```python\n# User asks a question\nUSER_QUESTION = \"Who won the NBA championship? And who was the MVP? Tell me a bit about the last game.\"\n```\n\nNow, in order to be as exhaustive as possible, we use the model to generate a list of diverse queries based on this question.\n\n\n\n```python\nQUERIES_INPUT = f\"\"\"\nYou have access to a search API that returns recent news articles.\nGenerate an array of search queries that are relevant to this question.\nUse a variation of related keywords for the queries, trying to be as general as possible.\nInclude as many queries as you can think of, including and excluding terms.\nFor example, include queries like ['keyword_1 keyword_2', 'keyword_1', 'keyword_2'].\nBe creative. The more queries you include, the more likely you are to find relevant results.\n\nUser question: {USER_QUESTION}\n\nFormat: {{\"queries\": [\"query_1\", \"query_2\", \"query_3\"]}}\n\"\"\"\n\nqueries = json_gpt(QUERIES_INPUT)[\"queries\"]\n\n# Let's include the original question as well for good measure\nqueries.append(USER_QUESTION)\n\nqueries\n```\n\n\n\n\n    ['NBA championship winner',\n     'MVP of NBA championship',\n     'Last game of NBA championship',\n     'NBA finals winner',\n     'Most valuable player of NBA championship',\n     'Finals game of NBA',\n     'Who won the NBA finals',\n     'NBA championship game summary',\n     'NBA finals MVP',\n     'Champion of NBA playoffs',\n     'NBA finals last game highlights',\n     'NBA championship series result',\n     'NBA finals game score',\n     'NBA finals game recap',\n     'NBA champion team and player',\n     'NBA finals statistics',\n     'NBA championship final score',\n     'NBA finals best player',\n     'NBA playoffs champion and MVP',\n     'NBA finals game analysis',\n     'Who won the NBA championship? And who was the MVP? Tell me a bit about the last game.']\n\n\n\nThe queries look good, so let's run the searches."}


created_at: 2024-07-28 18:59:18
topic: persistent://default/default/4bfc3c11-fb71-4cc9-8c12-01ed076a0e01
id: e78d0d84-72f1-47eb-8247-69a8a1a07eaa
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/Question_answering_using_a_search_API.ipynb", "title": "Question answering using a search API and re-ranking", "tokens": 4009, "retrieve_doc": true, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"e78d0d84-72f1-47eb-8247-69a8a1a07eaa\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Question_answering_using_a_search_API.ipynb\", \"title\": \"Question answering using a search API and re-ranking\", \"tokens\": 4009, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"9c08ddb4-205b-4eb3-a84d-c5b7ffe5abf3\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Question_answering_using_a_search_API.ipynb\", \"title\": \"Question answering using a search API and re-ranking\", \"tokens\": 4009, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"e5f4c9e0edabd0a6096b78edba4264943f81a6402b6a4b458c9b133c6f4b48bc\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"ae9947c7-0208-4053-95a8-164ee6480bbe\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Question_answering_using_a_search_API.ipynb\", \"title\": \"Question answering using a search API and re-ranking\", \"tokens\": 4009, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"be84bdd4e7fdd3fc40c69cbdff1bcc766e94841454c53c6594e1f64b2f7d1db5\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"dbbd30f5-d3a4-428a-a031-f2db7442fa5c\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"aeb0caee2ade7eac44215e7ed07742a4daf74ee655d796dee1294b507b632be2\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 4395, \"end_char_idx\": 7202, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "9c08ddb4-205b-4eb3-a84d-c5b7ffe5abf3", "doc_id": "9c08ddb4-205b-4eb3-a84d-c5b7ffe5abf3", "ref_doc_id": "9c08ddb4-205b-4eb3-a84d-c5b7ffe5abf3", "chroma:document": "```python\nQUERIES_INPUT = f\"\"\"\nYou have access to a search API that returns recent news articles.\nGenerate an array of search queries that are relevant to this question.\nUse a variation of related keywords for the queries, trying to be as general as possible.\nInclude as many queries as you can think of, including and excluding terms.\nFor example, include queries like ['keyword_1 keyword_2', 'keyword_1', 'keyword_2'].\nBe creative. The more queries you include, the more likely you are to find relevant results.\n\nUser question: {USER_QUESTION}\n\nFormat: {{\"queries\": [\"query_1\", \"query_2\", \"query_3\"]}}\n\"\"\"\n\nqueries = json_gpt(QUERIES_INPUT)[\"queries\"]\n\n# Let's include the original question as well for good measure\nqueries.append(USER_QUESTION)\n\nqueries\n```\n\n\n\n\n    ['NBA championship winner',\n     'MVP of NBA championship',\n     'Last game of NBA championship',\n     'NBA finals winner',\n     'Most valuable player of NBA championship',\n     'Finals game of NBA',\n     'Who won the NBA finals',\n     'NBA championship game summary',\n     'NBA finals MVP',\n     'Champion of NBA playoffs',\n     'NBA finals last game highlights',\n     'NBA championship series result',\n     'NBA finals game score',\n     'NBA finals game recap',\n     'NBA champion team and player',\n     'NBA finals statistics',\n     'NBA championship final score',\n     'NBA finals best player',\n     'NBA playoffs champion and MVP',\n     'NBA finals game analysis',\n     'Who won the NBA championship? And who was the MVP? Tell me a bit about the last game.']\n\n\n\nThe queries look good, so let's run the searches.\n\n\n\n```python\ndef search_news(\n    query: str,\n    news_api_key: str = news_api_key,\n    num_articles: int = 50,\n    from_datetime: str = \"2023-06-01\",  # the 2023 NBA finals were played in June 2023\n    to_datetime: str = \"2023-06-30\",\n) -> dict:\n    response = requests.get(\n        \"https://newsapi.org/v2/everything\",\n        params={\n            \"q\": query,\n            \"apiKey\": news_api_key,\n            \"pageSize\": num_articles,\n            \"sortBy\": \"relevancy\",\n            \"from\": from_datetime,\n            \"to\": to_datetime,\n        },\n    )\n\n    return response.json()\n\n\narticles = []\n\nfor query in tqdm(queries):\n    result = search_news(query)\n    if result[\"status\"] == \"ok\":\n        articles = articles + result[\"articles\"]\n    else:\n        raise Exception(result[\"message\"])\n\n# remove duplicates\narticles = list({article[\"url\"]: article for article in articles}.values())\n\nprint(\"Total number of articles:\", len(articles))\nprint(\"Top 5 articles of query 1:\", \"\\n\")\n\nfor article in articles[0:5]:\n    print(\"Title:\", article[\"title\"])\n    print(\"Description:\", article[\"description\"])\n    print(\"Content:\", article[\"content\"][0:100] + \"...\")\n    print()\n\n```\n\n\n      0%|          | 0/21 [00:00<?, ?it/s]"}


created_at: 2024-07-28 18:59:18
topic: persistent://default/default/4bfc3c11-fb71-4cc9-8c12-01ed076a0e01
id: dbbd30f5-d3a4-428a-a031-f2db7442fa5c
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/Question_answering_using_a_search_API.ipynb", "title": "Question answering using a search API and re-ranking", "tokens": 4009, "retrieve_doc": true, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"dbbd30f5-d3a4-428a-a031-f2db7442fa5c\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Question_answering_using_a_search_API.ipynb\", \"title\": \"Question answering using a search API and re-ranking\", \"tokens\": 4009, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"9c08ddb4-205b-4eb3-a84d-c5b7ffe5abf3\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Question_answering_using_a_search_API.ipynb\", \"title\": \"Question answering using a search API and re-ranking\", \"tokens\": 4009, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"e5f4c9e0edabd0a6096b78edba4264943f81a6402b6a4b458c9b133c6f4b48bc\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"e78d0d84-72f1-47eb-8247-69a8a1a07eaa\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Question_answering_using_a_search_API.ipynb\", \"title\": \"Question answering using a search API and re-ranking\", \"tokens\": 4009, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"95dda123d329dc8963a7b011c9ac48603182a2033f96d1bacf44a48be0464c3b\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"b34f3bc3-179c-4734-bb65-2f11262de124\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"4925777faecc5576431ca759e371dfac1edc1e951f5c6a42f16d812accbc3b01\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 5931, \"end_char_idx\": 9828, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "9c08ddb4-205b-4eb3-a84d-c5b7ffe5abf3", "doc_id": "9c08ddb4-205b-4eb3-a84d-c5b7ffe5abf3", "ref_doc_id": "9c08ddb4-205b-4eb3-a84d-c5b7ffe5abf3", "chroma:document": "The queries look good, so let's run the searches.\n\n\n\n```python\ndef search_news(\n    query: str,\n    news_api_key: str = news_api_key,\n    num_articles: int = 50,\n    from_datetime: str = \"2023-06-01\",  # the 2023 NBA finals were played in June 2023\n    to_datetime: str = \"2023-06-30\",\n) -> dict:\n    response = requests.get(\n        \"https://newsapi.org/v2/everything\",\n        params={\n            \"q\": query,\n            \"apiKey\": news_api_key,\n            \"pageSize\": num_articles,\n            \"sortBy\": \"relevancy\",\n            \"from\": from_datetime,\n            \"to\": to_datetime,\n        },\n    )\n\n    return response.json()\n\n\narticles = []\n\nfor query in tqdm(queries):\n    result = search_news(query)\n    if result[\"status\"] == \"ok\":\n        articles = articles + result[\"articles\"]\n    else:\n        raise Exception(result[\"message\"])\n\n# remove duplicates\narticles = list({article[\"url\"]: article for article in articles}.values())\n\nprint(\"Total number of articles:\", len(articles))\nprint(\"Top 5 articles of query 1:\", \"\\n\")\n\nfor article in articles[0:5]:\n    print(\"Title:\", article[\"title\"])\n    print(\"Description:\", article[\"description\"])\n    print(\"Content:\", article[\"content\"][0:100] + \"...\")\n    print()\n\n```\n\n\n      0%|          | 0/21 [00:00<?, ?it/s]\n\n\n    Total number of articles: 554\n    Top 5 articles of query 1: \n    \n    Title: Nascar takes on Le Mans as LeBron James gets centenary race under way\n    Description: <ul><li>Nascar has presence at iconic race for first time since 1976</li><li>NBA superstar LeBron James waves flag as honorary starter</li></ul>The crowd chanted \u201cU-S-A! U-S-A!\u201d as Nascar driver lineup for the 24 Hours of Le Mans passed through the city cente\u2026\n    Content: The crowd chanted U-S-A! U-S-A! as Nascar driver lineup for the 24 Hours of Le Mans passed through t...\n    \n    Title: NBA finals predictions: Nuggets or Heat? Our writers share their picks\n    Description: Denver or Miami? Our contributors pick the winner, key players and dark horses before the NBA\u2019s grand finale tips offA lot has been made of the importance of a balanced roster with continuity, but, somehow, still not enough. The Nuggets are the prime example \u2026\n    Content: The Nuggets are here because \n    A lot has been made of the importance of a balanced roster with conti...\n    \n    Title: Unboxing: Michelob ULTRA and Artist Futura Enshrine the NBA Championship In Custom Hand-Painted Bottles\n    Description: As the 2022-2023 NBA Championship nears the end, Michelob ULTRA brings joy to sports fans who will gather to watch the showdown between the Denver Nuggets and Miami Heat. The beermaker teamed up with artist Futura to remix its newly-designed 2023 Champ Bottle\u2026\n    Content: As the 2022-2023 NBA Championship nears the end, Michelob ULTRA brings joy to sports fans who will g...\n    \n    Title: Futura and Michelob ULTRA Toast to the NBA Finals With Abstract Artwork Crafted From the Brand\u2019s 2023 Limited-Edition Championship Bottles\n    Description: The sun is out to play, and so is Michelob ULTRA. With the 2022-2023 NBA Finals underway, the beermaker is back with its celebratory NBA Champ Bottles. This year, the self-proclaimed MVP of joy is dropping a limited-edition bottle made in collaboration with a\u2026\n    Content: The sun is out to play, and so is Michelob ULTRA. With the 2022-2023 NBA Finals underway, the beerma...\n    \n    Title: Signed and Delivered, Futura and Michelob ULTRA Will Gift Hand-Painted Bottles to This Year\u2019s NBA Championship Team\n    Description: Michelob ULTRA, the MVP of joy and official beer sponsor of the NBA is back to celebrate with basketball lovers and sports fans around the globe as the NBA 2022-2023 season comes to a nail-biting close. In collaboration with artist Futura, Michelob ULTRA will\u2026\n    Content: Michelob ULTRA, the MVP of joy and official beer sponsor of the NBA is back to celebrate with basket..."}


created_at: 2024-07-28 18:59:18
topic: persistent://default/default/4bfc3c11-fb71-4cc9-8c12-01ed076a0e01
id: b34f3bc3-179c-4734-bb65-2f11262de124
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/Question_answering_using_a_search_API.ipynb", "title": "Question answering using a search API and re-ranking", "tokens": 4009, "retrieve_doc": true, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"b34f3bc3-179c-4734-bb65-2f11262de124\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Question_answering_using_a_search_API.ipynb\", \"title\": \"Question answering using a search API and re-ranking\", \"tokens\": 4009, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"9c08ddb4-205b-4eb3-a84d-c5b7ffe5abf3\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Question_answering_using_a_search_API.ipynb\", \"title\": \"Question answering using a search API and re-ranking\", \"tokens\": 4009, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"e5f4c9e0edabd0a6096b78edba4264943f81a6402b6a4b458c9b133c6f4b48bc\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"dbbd30f5-d3a4-428a-a031-f2db7442fa5c\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Question_answering_using_a_search_API.ipynb\", \"title\": \"Question answering using a search API and re-ranking\", \"tokens\": 4009, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"bc92a8ac8cc3f2ade2d0ff2bcda308017f9f4142da0520beed75e1b421c8a9c0\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"2ca351d5-d137-4850-95a7-afc8261e84cb\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"943746c439027f798ce77ace1d780f4e946f3f4546acfa84311cbaf7d3eddc71\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 9836, \"end_char_idx\": 12345, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "9c08ddb4-205b-4eb3-a84d-c5b7ffe5abf3", "doc_id": "9c08ddb4-205b-4eb3-a84d-c5b7ffe5abf3", "ref_doc_id": "9c08ddb4-205b-4eb3-a84d-c5b7ffe5abf3", "chroma:document": "As we can see, oftentimes, the search queries will return a large number of results, many of which are not relevant to the original question asked by the user. In order to improve the quality of the final answer, we use embeddings to re-rank and filter the results.\n\n## 2. Re-rank\n\nDrawing inspiration from [HyDE (Gao et al.)](https://arxiv.org/abs/2212.10496), we first generate a hypothetical ideal answer to rerank our compare our results against. This helps prioritize results that look like good answers, rather than those similar to our question. Here\u2019s the prompt we use to generate our hypothetical answer.\n\n\n\n```python\nHA_INPUT = f\"\"\"\nGenerate a hypothetical answer to the user's question. This answer will be used to rank search results. \nPretend you have all the information you need to answer, but don't use any actual facts. Instead, use placeholders\nlike NAME did something, or NAME said something at PLACE. \n\nUser question: {USER_QUESTION}\n\nFormat: {{\"hypotheticalAnswer\": \"hypothetical answer text\"}}\n\"\"\"\n\nhypothetical_answer = json_gpt(HA_INPUT)[\"hypotheticalAnswer\"]\n\nhypothetical_answer\n\n```\n\n\n\n\n    'The NBA championship was won by TEAM NAME. The MVP was awarded to PLAYER NAME. The last game was held at STADIUM NAME, where both teams played with great energy and enthusiasm. It was a close game, but in the end, TEAM NAME emerged victorious.'\n\n\n\nNow, let's generate embeddings for the search results and the hypothetical answer. We then calculate the cosine distance between these embeddings, giving us a semantic similarity metric. Note that we can simply calculate the dot product in lieu of doing a full cosine similarity calculation since the OpenAI embeddings are returned normalized in our API.\n\n\n\n```python\nhypothetical_answer_embedding = embeddings(hypothetical_answer)[0]\narticle_embeddings = embeddings(\n    [\n        f\"{article['title']} {article['description']} {article['content'][0:100]}\"\n        for article in articles\n    ]\n)\n\n# Calculate cosine similarity\ncosine_similarities = []\nfor article_embedding in article_embeddings:\n    cosine_similarities.append(dot(hypothetical_answer_embedding, article_embedding))\n\ncosine_similarities[0:10]\n\n```\n\n\n\n\n    [0.7854456526852069,\n     0.8086023500072106,\n     0.8002998147018501,\n     0.7961229569526956,\n     0.798354506673743,\n     0.758216458795653,\n     0.7753754083127359,\n     0.7494958338411927,\n     0.804733946801739,\n     0.8405965885235218]\n\n\n\nFinally, we use these similarity scores to sort and filter the results."}


created_at: 2024-07-28 18:59:18
topic: persistent://default/default/4bfc3c11-fb71-4cc9-8c12-01ed076a0e01
id: 2ca351d5-d137-4850-95a7-afc8261e84cb
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/Question_answering_using_a_search_API.ipynb", "title": "Question answering using a search API and re-ranking", "tokens": 4009, "retrieve_doc": true, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"2ca351d5-d137-4850-95a7-afc8261e84cb\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Question_answering_using_a_search_API.ipynb\", \"title\": \"Question answering using a search API and re-ranking\", \"tokens\": 4009, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"9c08ddb4-205b-4eb3-a84d-c5b7ffe5abf3\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Question_answering_using_a_search_API.ipynb\", \"title\": \"Question answering using a search API and re-ranking\", \"tokens\": 4009, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"e5f4c9e0edabd0a6096b78edba4264943f81a6402b6a4b458c9b133c6f4b48bc\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"b34f3bc3-179c-4734-bb65-2f11262de124\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Question_answering_using_a_search_API.ipynb\", \"title\": \"Question answering using a search API and re-ranking\", \"tokens\": 4009, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"aa5960b39569e3dc8cd819d33d63f8ba93f109b8ad6b50aead983d3f5058c697\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"20e1510d-569e-4a9e-9ea9-6b7cc8bd8290\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"8928b7b99b2e7d118441c4164cf190081aa3eabe0c5e0f0478aa153ed8c50f87\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 10955, \"end_char_idx\": 14906, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "9c08ddb4-205b-4eb3-a84d-c5b7ffe5abf3", "doc_id": "9c08ddb4-205b-4eb3-a84d-c5b7ffe5abf3", "ref_doc_id": "9c08ddb4-205b-4eb3-a84d-c5b7ffe5abf3", "chroma:document": "'The NBA championship was won by TEAM NAME. The MVP was awarded to PLAYER NAME. The last game was held at STADIUM NAME, where both teams played with great energy and enthusiasm. It was a close game, but in the end, TEAM NAME emerged victorious.'\n\n\n\nNow, let's generate embeddings for the search results and the hypothetical answer. We then calculate the cosine distance between these embeddings, giving us a semantic similarity metric. Note that we can simply calculate the dot product in lieu of doing a full cosine similarity calculation since the OpenAI embeddings are returned normalized in our API.\n\n\n\n```python\nhypothetical_answer_embedding = embeddings(hypothetical_answer)[0]\narticle_embeddings = embeddings(\n    [\n        f\"{article['title']} {article['description']} {article['content'][0:100]}\"\n        for article in articles\n    ]\n)\n\n# Calculate cosine similarity\ncosine_similarities = []\nfor article_embedding in article_embeddings:\n    cosine_similarities.append(dot(hypothetical_answer_embedding, article_embedding))\n\ncosine_similarities[0:10]\n\n```\n\n\n\n\n    [0.7854456526852069,\n     0.8086023500072106,\n     0.8002998147018501,\n     0.7961229569526956,\n     0.798354506673743,\n     0.758216458795653,\n     0.7753754083127359,\n     0.7494958338411927,\n     0.804733946801739,\n     0.8405965885235218]\n\n\n\nFinally, we use these similarity scores to sort and filter the results.\n\n\n\n```python\nscored_articles = zip(articles, cosine_similarities)\n\n# Sort articles by cosine similarity\nsorted_articles = sorted(scored_articles, key=lambda x: x[1], reverse=True)\n\n# Print top 5 articles\nprint(\"Top 5 articles:\", \"\\n\")\n\nfor article, score in sorted_articles[0:5]:\n    print(\"Title:\", article[\"title\"])\n    print(\"Description:\", article[\"description\"])\n    print(\"Content:\", article[\"content\"][0:100] + \"...\")\n    print(\"Score:\", score)\n    print()\n\n```\n\n    Top 5 articles: \n    \n    Title: NBA Finals: Denver Nuggets beat Miami Hea, lift thier first-ever NBA title\n    Description: Denver Nuggets won their maiden NBA Championship trophy defeating Miami Heat 94-89 in Game 5 of the NBA Final held on Tuesday at the Ball Arena in Denver\n    Content: Denver Nuggets won their maiden NBA Championship trophy defeating Miami Heat 94-89 in Game 5 of the ...\n    Score: 0.8445817523602124\n    \n    Title: Photos: Denver Nuggets celebrate their first NBA title\n    Description: The Nuggets capped off an impressive postseason by beating the Miami Heat in the NBA Finals.\n    Content: Thousands of supporters watched along the streets of Denver, Colorado as the US National Basketball ...\n    Score: 0.842070667753606\n    \n    Title: Denver Nuggets win first NBA championship title in Game 5 victory over Miami Heat\n    Description: The Denver Nuggets won their first NBA championship Monday night, downing the Miami Heat 94-89 at Ball Arena in Denver to take Game 5 of the NBA Finals.\n    Content: The Denver Nuggets won their first NBA championship Monday night, downing the Miami Heat 94-89 at Ba...\n    Score: 0.8409346078172385\n    \n    Title: Denver Nuggets Capture Their First NBA Championship Behind Unbreakable Chemistry\n    Description: After 47 years of waiting, the Denver Nuggets are NBA champions. Led by Nikola Jokic and Jamal Murray, they reached the mountain top by staying true to themselves.\n    Content: DENVER, CO - JUNE 12: Jamal Murray (27) of the Denver Nuggets celebrates as he leaves the court ... ...\n    Score: 0.8405965885235218\n    \n    Title: NBA Finals: Nikola Jokic, Denver Nuggets survive Miami Heat to secure franchise's first NBA championship\n    Description: In a rock-fight of a Game 5, the Denver Nuggets reached the NBA mountaintop from the foothills of the Rockies, winning their first-ever championship and setting Nikola Jokic's legacy as an all-timer in stone.\n    Content: DENVER, COLORADO - JUNE 12: Jamal Murray #27 of the Denver Nuggets reacts during the fourth quarter ...\n    Score: 0.8389716330890262"}


created_at: 2024-07-28 18:59:18
topic: persistent://default/default/4bfc3c11-fb71-4cc9-8c12-01ed076a0e01
id: 20e1510d-569e-4a9e-9ea9-6b7cc8bd8290
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/Question_answering_using_a_search_API.ipynb", "title": "Question answering using a search API and re-ranking", "tokens": 4009, "retrieve_doc": true, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"20e1510d-569e-4a9e-9ea9-6b7cc8bd8290\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Question_answering_using_a_search_API.ipynb\", \"title\": \"Question answering using a search API and re-ranking\", \"tokens\": 4009, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"9c08ddb4-205b-4eb3-a84d-c5b7ffe5abf3\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Question_answering_using_a_search_API.ipynb\", \"title\": \"Question answering using a search API and re-ranking\", \"tokens\": 4009, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"e5f4c9e0edabd0a6096b78edba4264943f81a6402b6a4b458c9b133c6f4b48bc\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"2ca351d5-d137-4850-95a7-afc8261e84cb\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Question_answering_using_a_search_API.ipynb\", \"title\": \"Question answering using a search API and re-ranking\", \"tokens\": 4009, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"d68ca5d96da23fd657418ebdc2a3e16a37aed47a0705f3ece76fdc87e0809d40\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 14914, \"end_char_idx\": 17018, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "9c08ddb4-205b-4eb3-a84d-c5b7ffe5abf3", "doc_id": "9c08ddb4-205b-4eb3-a84d-c5b7ffe5abf3", "ref_doc_id": "9c08ddb4-205b-4eb3-a84d-c5b7ffe5abf3", "chroma:document": "Awesome! These results look a lot more relevant to our original query. Now, let's use the top 5 results to generate a final answer.\n\n## 3. Answer\n\n\n\n```python\nformatted_top_results = [\n    {\n        \"title\": article[\"title\"],\n        \"description\": article[\"description\"],\n        \"url\": article[\"url\"],\n    }\n    for article, _score in sorted_articles[0:5]\n]\n\nANSWER_INPUT = f\"\"\"\nGenerate an answer to the user's question based on the given search results. \nTOP_RESULTS: {formatted_top_results}\nUSER_QUESTION: {USER_QUESTION}\n\nInclude as much information as possible in the answer. Reference the relevant search result urls as markdown links.\n\"\"\"\n\ncompletion = client.chat.completions.create(\n    model=GPT_MODEL,\n    messages=[{\"role\": \"user\", \"content\": ANSWER_INPUT}],\n    temperature=0.5,\n    stream=True,\n)\n\ntext = \"\"\nfor chunk in completion:\n    text += chunk.choices[0].delta.content\n    display.clear_output(wait=True)\n    display.display(display.Markdown(text))\n```\n\n\nThe Denver Nuggets won their first-ever NBA championship by defeating the Miami Heat 94-89 in Game 5 of the NBA Finals held on Tuesday at the Ball Arena in Denver, according to this [Business Standard article](https://www.business-standard.com/sports/other-sports-news/nba-finals-denver-nuggets-beat-miami-hea-lift-thier-first-ever-nba-title-123061300285_1.html). Nikola Jokic, the Nuggets' center, was named the NBA Finals MVP. In a rock-fight of a Game 5, the Nuggets reached the NBA mountaintop, securing their franchise's first NBA championship and setting Nikola Jokic's legacy as an all-timer in stone, according to this [Yahoo Sports article](https://sports.yahoo.com/nba-finals-nikola-jokic-denver-nuggets-survive-miami-heat-to-secure-franchises-first-nba-championship-030321214.html). For more information and photos of the Nuggets' celebration, check out this [Al Jazeera article](https://www.aljazeera.com/gallery/2023/6/15/photos-denver-nuggets-celebrate-their-first-nba-title) and this [CNN article](https://www.cnn.com/2023/06/12/sport/denver-nuggets-nba-championship-spt-intl?cid=external-feeds_iluminar_yahoo)."}


created_at: 2024-07-28 18:59:18
topic: persistent://default/default/4bfc3c11-fb71-4cc9-8c12-01ed076a0e01
id: 2a66530a-02bd-4e93-a81d-e5f9a416fe4b
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/Search_reranking_with_cross-encoders.ipynb", "title": "Search reranking with cross-encoders", "tokens": 8550, "retrieve_doc": false, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"2a66530a-02bd-4e93-a81d-e5f9a416fe4b\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Search_reranking_with_cross-encoders.ipynb\", \"title\": \"Search reranking with cross-encoders\", \"tokens\": 8550, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"7fe36cde-011f-49b9-9282-b57056ad9c08\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Search_reranking_with_cross-encoders.ipynb\", \"title\": \"Search reranking with cross-encoders\", \"tokens\": 8550, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"dced2f13bcff97651066dc82958fcaa9337b1448f97481147a450ebcd8260dd3\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"ca256cf7-24f3-4be2-a17c-78225693c251\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"16a59da98549bc0110606c7cd53af1102ff09372c7b472dfbb3e335e33c89672\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 0, \"end_char_idx\": 3275, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "7fe36cde-011f-49b9-9282-b57056ad9c08", "doc_id": "7fe36cde-011f-49b9-9282-b57056ad9c08", "ref_doc_id": "7fe36cde-011f-49b9-9282-b57056ad9c08", "chroma:document": "# Search reranking with cross-encoders\n\nThis notebook takes you through examples of using a cross-encoder to re-rank search results.\n\nThis is a common use case with our customers, where you've implemented semantic search using embeddings (produced using a [bi-encoder](https://www.sbert.net/examples/applications/retrieve_rerank/README.html#retrieval-bi-encoder)) but the results are not as accurate as your use case requires. A possible cause is that there is some business rule you can use to rerank the documents such as how recent or how popular a document is. \n\nHowever, often there are subtle domain-specific rules that help determine relevancy, and this is where a cross-encoder can be useful. Cross-encoders are more accurate than bi-encoders but they don't scale well, so using them to re-order a shortened list returned by semantic search is the ideal use case.\n\n### Example\n\nConsider a search task with D documents and Q queries.\n\nThe brute force approach of computing every pairwise relevance is expensive; its cost scales as ```D * Q```. This is known as **cross-encoding**.\n\nA faster approach is **embeddings-based search**, in which an embedding is computed once for each document and query, and then re-used multiple times to cheaply compute pairwise relevance. Because embeddings are only computed once, its cost scales as ```D + Q```. This is known as **bi-encoding**.\n\nAlthough embeddings-based search is faster, the quality can be worse. To get the best of both, one common approach is to use embeddings (or another bi-encoder) to cheaply identify top candidates, and then use GPT (or another cross-encoder) to expensively re-rank those top candidates. The cost of this hybrid approach scales as ```(D + Q) * cost of embedding + (N * Q) * cost of re-ranking```, where ```N``` is the number of candidates re-ranked.\n\n### Walkthrough\n\nTo illustrate this approach we'll use ```text-davinci-003``` with ```logprobs``` enabled to build a GPT-powered cross-encoder. Our GPT models have strong general language understanding, which when tuned with some few-shot examples can provide a simple and effective cross-encoding option.\n\nThis notebook drew on this great [article](https://weaviate.io/blog/cross-encoders-as-reranker) by Weaviate, and this [excellent explanation](https://www.sbert.net/examples/applications/cross-encoder/README.html) of bi-encoders vs. cross-encoders from Sentence Transformers.\n\n\n```python\n!pip install openai\n!pip install arxiv\n!pip install tenacity\n!pip install pandas\n!pip install tiktoken\n```\n\n\n```python\nimport arxiv\nfrom math import exp\nimport openai\nimport os\nimport pandas as pd\nfrom tenacity import retry, wait_random_exponential, stop_after_attempt\nimport tiktoken\n\nclient = OpenAI(api_key=os.environ.get(\"OPENAI_API_KEY\", \"<your OpenAI API key if not set as env var>\"))\n\nOPENAI_MODEL = \"gpt-4\"\n```\n\n## Search\n\nWe'll use the arXiv search service for this example, but this step could be performed by any search service you have. The key item to consider is over-fetching slightly to capture all the potentially relevant documents, before re-sorting them.\n\n\n\n```python\nquery = \"how do bi-encoders work for sentence embeddings\"\nsearch = arxiv.Search(\n    query=query, max_results=20, sort_by=arxiv.SortCriterion.Relevance\n)\n```"}


created_at: 2024-07-28 18:59:18
topic: persistent://default/default/4bfc3c11-fb71-4cc9-8c12-01ed076a0e01
id: ca256cf7-24f3-4be2-a17c-78225693c251
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/Search_reranking_with_cross-encoders.ipynb", "title": "Search reranking with cross-encoders", "tokens": 8550, "retrieve_doc": false, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"ca256cf7-24f3-4be2-a17c-78225693c251\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Search_reranking_with_cross-encoders.ipynb\", \"title\": \"Search reranking with cross-encoders\", \"tokens\": 8550, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"7fe36cde-011f-49b9-9282-b57056ad9c08\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Search_reranking_with_cross-encoders.ipynb\", \"title\": \"Search reranking with cross-encoders\", \"tokens\": 8550, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"dced2f13bcff97651066dc82958fcaa9337b1448f97481147a450ebcd8260dd3\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"2a66530a-02bd-4e93-a81d-e5f9a416fe4b\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Search_reranking_with_cross-encoders.ipynb\", \"title\": \"Search reranking with cross-encoders\", \"tokens\": 8550, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"6888283326d02001635a0d0efefe7d765f74a37bb7108add97355b3bd22918bf\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"8b7160ec-86a6-4d81-a26a-8a746f4c7b34\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"3fdb09420e94baba44c98dfab1fd368e4cd8dce2bf4c9e74fce31e2f27fcbb49\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 2420, \"end_char_idx\": 5391, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "7fe36cde-011f-49b9-9282-b57056ad9c08", "doc_id": "7fe36cde-011f-49b9-9282-b57056ad9c08", "ref_doc_id": "7fe36cde-011f-49b9-9282-b57056ad9c08", "chroma:document": "```python\n!pip install openai\n!pip install arxiv\n!pip install tenacity\n!pip install pandas\n!pip install tiktoken\n```\n\n\n```python\nimport arxiv\nfrom math import exp\nimport openai\nimport os\nimport pandas as pd\nfrom tenacity import retry, wait_random_exponential, stop_after_attempt\nimport tiktoken\n\nclient = OpenAI(api_key=os.environ.get(\"OPENAI_API_KEY\", \"<your OpenAI API key if not set as env var>\"))\n\nOPENAI_MODEL = \"gpt-4\"\n```\n\n## Search\n\nWe'll use the arXiv search service for this example, but this step could be performed by any search service you have. The key item to consider is over-fetching slightly to capture all the potentially relevant documents, before re-sorting them.\n\n\n\n```python\nquery = \"how do bi-encoders work for sentence embeddings\"\nsearch = arxiv.Search(\n    query=query, max_results=20, sort_by=arxiv.SortCriterion.Relevance\n)\n```\n\n\n```python\nresult_list = []\n\nfor result in search.results():\n    result_dict = {}\n\n    result_dict.update({\"title\": result.title})\n    result_dict.update({\"summary\": result.summary})\n\n    # Taking the first url provided\n    result_dict.update({\"article_url\": [x.href for x in result.links][0]})\n    result_dict.update({\"pdf_url\": [x.href for x in result.links][1]})\n    result_list.append(result_dict)\n```\n\n\n```python\nresult_list[0]\n```\n\n\n\n\n    {'title': 'SBERT studies Meaning Representations: Decomposing Sentence Embeddings into Explainable Semantic Features',\n     'summary': 'Models based on large-pretrained language models, such as S(entence)BERT,\\nprovide effective and efficient sentence embeddings that show high correlation\\nto human similarity ratings, but lack interpretability. On the other hand,\\ngraph metrics for graph-based meaning representations (e.g., Abstract Meaning\\nRepresentation, AMR) can make explicit the semantic aspects in which two\\nsentences are similar. However, such metrics tend to be slow, rely on parsers,\\nand do not reach state-of-the-art performance when rating sentence similarity.\\n  In this work, we aim at the best of both worlds, by learning to induce\\n$S$emantically $S$tructured $S$entence BERT embeddings (S$^3$BERT). Our\\nS$^3$BERT embeddings are composed of explainable sub-embeddings that emphasize\\nvarious semantic sentence features (e.g., semantic roles, negation, or\\nquantification). We show how to i) learn a decomposition of the sentence\\nembeddings into semantic features, through approximation of a suite of\\ninterpretable AMR graph metrics, and how to ii) preserve the overall power of\\nthe neural embeddings by controlling the decomposition learning process with a\\nsecond objective that enforces consistency with the similarity ratings of an\\nSBERT teacher model. In our experimental studies, we show that our approach\\noffers interpretability -- while fully preserving the effectiveness and\\nefficiency of the neural sentence embeddings.',\n     'article_url': 'http://arxiv.org/abs/2206.07023v2',\n     'pdf_url': 'http://arxiv.org/pdf/2206.07023v2'}"}


created_at: 2024-07-28 18:59:18
topic: persistent://default/default/4bfc3c11-fb71-4cc9-8c12-01ed076a0e01
id: 8b7160ec-86a6-4d81-a26a-8a746f4c7b34
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/Search_reranking_with_cross-encoders.ipynb", "title": "Search reranking with cross-encoders", "tokens": 8550, "retrieve_doc": false, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"8b7160ec-86a6-4d81-a26a-8a746f4c7b34\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Search_reranking_with_cross-encoders.ipynb\", \"title\": \"Search reranking with cross-encoders\", \"tokens\": 8550, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"7fe36cde-011f-49b9-9282-b57056ad9c08\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Search_reranking_with_cross-encoders.ipynb\", \"title\": \"Search reranking with cross-encoders\", \"tokens\": 8550, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"dced2f13bcff97651066dc82958fcaa9337b1448f97481147a450ebcd8260dd3\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"ca256cf7-24f3-4be2-a17c-78225693c251\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Search_reranking_with_cross-encoders.ipynb\", \"title\": \"Search reranking with cross-encoders\", \"tokens\": 8550, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"ad925f1a88c40cf8356899a0f5b35f21d50f605d7f98d80ca99db328e9674db9\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"0ddc21ae-d489-4733-824b-73c50fa1d731\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"c69f519d93f62a0553c1392de1d6e130e8779161aea688eb237db3e36ead483f\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 3685, \"end_char_idx\": 7209, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "7fe36cde-011f-49b9-9282-b57056ad9c08", "doc_id": "7fe36cde-011f-49b9-9282-b57056ad9c08", "ref_doc_id": "7fe36cde-011f-49b9-9282-b57056ad9c08", "chroma:document": "```python\nresult_list[0]\n```\n\n\n\n\n    {'title': 'SBERT studies Meaning Representations: Decomposing Sentence Embeddings into Explainable Semantic Features',\n     'summary': 'Models based on large-pretrained language models, such as S(entence)BERT,\\nprovide effective and efficient sentence embeddings that show high correlation\\nto human similarity ratings, but lack interpretability. On the other hand,\\ngraph metrics for graph-based meaning representations (e.g., Abstract Meaning\\nRepresentation, AMR) can make explicit the semantic aspects in which two\\nsentences are similar. However, such metrics tend to be slow, rely on parsers,\\nand do not reach state-of-the-art performance when rating sentence similarity.\\n  In this work, we aim at the best of both worlds, by learning to induce\\n$S$emantically $S$tructured $S$entence BERT embeddings (S$^3$BERT). Our\\nS$^3$BERT embeddings are composed of explainable sub-embeddings that emphasize\\nvarious semantic sentence features (e.g., semantic roles, negation, or\\nquantification). We show how to i) learn a decomposition of the sentence\\nembeddings into semantic features, through approximation of a suite of\\ninterpretable AMR graph metrics, and how to ii) preserve the overall power of\\nthe neural embeddings by controlling the decomposition learning process with a\\nsecond objective that enforces consistency with the similarity ratings of an\\nSBERT teacher model. In our experimental studies, we show that our approach\\noffers interpretability -- while fully preserving the effectiveness and\\nefficiency of the neural sentence embeddings.',\n     'article_url': 'http://arxiv.org/abs/2206.07023v2',\n     'pdf_url': 'http://arxiv.org/pdf/2206.07023v2'}\n\n\n\n\n```python\nfor i, result in enumerate(result_list):\n    print(f\"{i + 1}: {result['title']}\")\n```\n\n    1: SBERT studies Meaning Representations: Decomposing Sentence Embeddings into Explainable Semantic Features\n    2: Are Classes Clusters?\n    3: Semantic Composition in Visually Grounded Language Models\n    4: Evaluating the Construct Validity of Text Embeddings with Application to Survey Questions\n    5: Learning Probabilistic Sentence Representations from Paraphrases\n    6: Exploiting Twitter as Source of Large Corpora of Weakly Similar Pairs for Semantic Sentence Embeddings\n    7: How to Probe Sentence Embeddings in Low-Resource Languages: On Structural Design Choices for Probing Task Evaluation\n    8: Clustering and Network Analysis for the Embedding Spaces of Sentences and Sub-Sentences\n    9: Vec2Sent: Probing Sentence Embeddings with Natural Language Generation\n    10: Non-Linguistic Supervision for Contrastive Learning of Sentence Embeddings\n    11: SentPWNet: A Unified Sentence Pair Weighting Network for Task-specific Sentence Embedding\n    12: Learning Joint Representations of Videos and Sentences with Web Image Search\n    13: Character-based Neural Networks for Sentence Pair Modeling\n    14: Train Once, Test Anywhere: Zero-Shot Learning for Text Classification\n    15: Hierarchical GPT with Congruent Transformers for Multi-Sentence Language Models\n    16: Sentence-T5: Scalable Sentence Encoders from Pre-trained Text-to-Text Models\n    17: In Search for Linear Relations in Sentence Embedding Spaces\n    18: Learning to Borrow -- Relation Representation for Without-Mention Entity-Pairs for Knowledge Graph Completion\n    19: Efficient and Flexible Topic Modeling using Pretrained Embeddings and Bag of Sentences\n    20: Relational Sentence Embedding for Flexible Semantic Matching"}


created_at: 2024-07-28 18:59:18
topic: persistent://default/default/4bfc3c11-fb71-4cc9-8c12-01ed076a0e01
id: 0ddc21ae-d489-4733-824b-73c50fa1d731
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/Search_reranking_with_cross-encoders.ipynb", "title": "Search reranking with cross-encoders", "tokens": 8550, "retrieve_doc": false, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"0ddc21ae-d489-4733-824b-73c50fa1d731\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Search_reranking_with_cross-encoders.ipynb\", \"title\": \"Search reranking with cross-encoders\", \"tokens\": 8550, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"7fe36cde-011f-49b9-9282-b57056ad9c08\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Search_reranking_with_cross-encoders.ipynb\", \"title\": \"Search reranking with cross-encoders\", \"tokens\": 8550, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"dced2f13bcff97651066dc82958fcaa9337b1448f97481147a450ebcd8260dd3\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"8b7160ec-86a6-4d81-a26a-8a746f4c7b34\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Search_reranking_with_cross-encoders.ipynb\", \"title\": \"Search reranking with cross-encoders\", \"tokens\": 8550, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"6c85f2e494023820356bce1e0d6cc1a2f89019d4b28399c4e1d8691ab132b065\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"5fb20ca0-b11b-4071-9bd8-7edff6fb5f4f\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"5551b0d12a201998e13de442ff7e88af66237ff9e6e8c42df97a98906f654f26\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 7212, \"end_char_idx\": 10568, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "7fe36cde-011f-49b9-9282-b57056ad9c08", "doc_id": "7fe36cde-011f-49b9-9282-b57056ad9c08", "ref_doc_id": "7fe36cde-011f-49b9-9282-b57056ad9c08", "chroma:document": "## Cross-encoder\n\nWe'll create a cross-encoder using the ```Completions``` endpoint - the key factors to consider here are:\n- Make your examples domain-specific - the strength of cross-encoders comes when you tailor them to your domain.\n- There is a trade-off between how many potential examples to re-rank vs. processing speed. Consider batching and parallel processing cross-encoder requests to process them more quickly.\n\nThe steps here are:\n- Build a prompt to assess relevance and provide few-shot examples to tune it to your domain.\n- Add a ```logit bias``` for the tokens for ``` Yes``` and ``` No``` to decrease the likelihood of any other tokens occurring.\n- Return the classification of yes/no as well as the ```logprobs```.\n- Rerank the results by the ```logprobs``` keyed on ``` Yes```.\n\n\n```python\ntokens = [\" Yes\", \" No\"]\ntokenizer = tiktoken.encoding_for_model(OPENAI_MODEL)\nids = [tokenizer.encode(token) for token in tokens]\nids[0], ids[1]\n```\n\n\n\n\n    ([3363], [1400])\n\n\n\n\n```python\nprompt = '''\nYou are an Assistant responsible for helping detect whether the retrieved document is relevant to the query. For a given input, you need to output a single token: \"Yes\" or \"No\" indicating the retrieved document is relevant to the query.\n\nQuery: How to plant a tree?\nDocument: \"\"\"Cars were invented in 1886, when German inventor Carl Benz patented his Benz Patent-Motorwagen.[3][4][5] Cars became widely available during the 20th century. One of the first cars affordable by the masses was the 1908 Model T, an American car manufactured by the Ford Motor Company. Cars were rapidly adopted in the US, where they replaced horse-drawn carriages.[6] In Europe and other parts of the world, demand for automobiles did not increase until after World War II.[7] The car is considered an essential part of the developed economy.\"\"\"\nRelevant: No\n\nQuery: Has the coronavirus vaccine been approved?\nDocument: \"\"\"The Pfizer-BioNTech COVID-19 vaccine was approved for emergency use in the United States on December 11, 2020.\"\"\"\nRelevant: Yes\n\nQuery: What is the capital of France?\nDocument: \"\"\"Paris, France's capital, is a major European city and a global center for art, fashion, gastronomy and culture. Its 19th-century cityscape is crisscrossed by wide boulevards and the River Seine. Beyond such landmarks as the Eiffel Tower and the 12th-century, Gothic Notre-Dame cathedral, the city is known for its cafe culture and designer boutiques along the Rue du Faubourg Saint-Honor\u00e9.\"\"\"\nRelevant: Yes\n\nQuery: What are some papers to learn about PPO reinforcement learning?\nDocument: \"\"\"Proximal Policy Optimization and its Dynamic Version for Sequence Generation: In sequence generation task, many works use policy gradient for model optimization to tackle the intractable backpropagation issue when maximizing the non-differentiable evaluation metrics or fooling the discriminator in adversarial learning. In this paper, we replace policy gradient with proximal policy optimization (PPO), which is a proved more efficient reinforcement learning algorithm, and propose a dynamic approach for PPO (PPO-dynamic). We demonstrate the efficacy of PPO and PPO-dynamic on conditional sequence generation tasks including synthetic experiment and chit-chat chatbot. The results show that PPO and PPO-dynamic can beat policy gradient by stability and performance.\"\"\""}


created_at: 2024-07-28 18:59:18
topic: persistent://default/default/4bfc3c11-fb71-4cc9-8c12-01ed076a0e01
id: 5fb20ca0-b11b-4071-9bd8-7edff6fb5f4f
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/Search_reranking_with_cross-encoders.ipynb", "title": "Search reranking with cross-encoders", "tokens": 8550, "retrieve_doc": false, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"5fb20ca0-b11b-4071-9bd8-7edff6fb5f4f\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Search_reranking_with_cross-encoders.ipynb\", \"title\": \"Search reranking with cross-encoders\", \"tokens\": 8550, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"7fe36cde-011f-49b9-9282-b57056ad9c08\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Search_reranking_with_cross-encoders.ipynb\", \"title\": \"Search reranking with cross-encoders\", \"tokens\": 8550, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"dced2f13bcff97651066dc82958fcaa9337b1448f97481147a450ebcd8260dd3\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"0ddc21ae-d489-4733-824b-73c50fa1d731\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Search_reranking_with_cross-encoders.ipynb\", \"title\": \"Search reranking with cross-encoders\", \"tokens\": 8550, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"9e270f76ce0ec33e201d5390232df333e62018df942f0a7333f2fc52e4483516\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"e6dd823f-1d51-47c6-b810-acf18ce8a8fe\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"409ecad44c74d085069fde984bf6542b2ffdd783ed5867f1d9ab377171fa8448\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 8788, \"end_char_idx\": 11847, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "7fe36cde-011f-49b9-9282-b57056ad9c08", "doc_id": "7fe36cde-011f-49b9-9282-b57056ad9c08", "ref_doc_id": "7fe36cde-011f-49b9-9282-b57056ad9c08", "chroma:document": "Cars were rapidly adopted in the US, where they replaced horse-drawn carriages.[6] In Europe and other parts of the world, demand for automobiles did not increase until after World War II.[7] The car is considered an essential part of the developed economy.\"\"\"\nRelevant: No\n\nQuery: Has the coronavirus vaccine been approved?\nDocument: \"\"\"The Pfizer-BioNTech COVID-19 vaccine was approved for emergency use in the United States on December 11, 2020.\"\"\"\nRelevant: Yes\n\nQuery: What is the capital of France?\nDocument: \"\"\"Paris, France's capital, is a major European city and a global center for art, fashion, gastronomy and culture. Its 19th-century cityscape is crisscrossed by wide boulevards and the River Seine. Beyond such landmarks as the Eiffel Tower and the 12th-century, Gothic Notre-Dame cathedral, the city is known for its cafe culture and designer boutiques along the Rue du Faubourg Saint-Honor\u00e9.\"\"\"\nRelevant: Yes\n\nQuery: What are some papers to learn about PPO reinforcement learning?\nDocument: \"\"\"Proximal Policy Optimization and its Dynamic Version for Sequence Generation: In sequence generation task, many works use policy gradient for model optimization to tackle the intractable backpropagation issue when maximizing the non-differentiable evaluation metrics or fooling the discriminator in adversarial learning. In this paper, we replace policy gradient with proximal policy optimization (PPO), which is a proved more efficient reinforcement learning algorithm, and propose a dynamic approach for PPO (PPO-dynamic). We demonstrate the efficacy of PPO and PPO-dynamic on conditional sequence generation tasks including synthetic experiment and chit-chat chatbot. The results show that PPO and PPO-dynamic can beat policy gradient by stability and performance.\"\"\"\nRelevant: Yes\n\nQuery: Explain sentence embeddings\nDocument: \"\"\"Inside the bubble: exploring the environments of reionisation-era Lyman-\u03b1 emitting galaxies with JADES and FRESCO: We present a study of the environments of 16 Lyman-\u03b1 emitting galaxies (LAEs) in the reionisation era (5.8<z<8) identified by JWST/NIRSpec as part of the JWST Advanced Deep Extragalactic Survey (JADES). Unless situated in sufficiently (re)ionised regions, Lyman-\u03b1 emission from these galaxies would be strongly absorbed by neutral gas in the intergalactic medium (IGM). We conservatively estimate sizes of the ionised regions required to reconcile the relatively low Lyman-\u03b1 velocity offsets (\u0394vLy\u03b1<300kms\u22121) with moderately high Lyman-\u03b1 escape fractions (fesc,Ly\u03b1>5%) observed in our sample of LAEs, indicating the presence of ionised ``bubbles'' with physical sizes of the order of 0.1pMpc\u2272Rion\u22721pMpc in a patchy reionisation scenario where the bubbles are embedded in a fully neutral IGM. Around half of the LAEs in our sample are found to coincide with large-scale galaxy overdensities seen in FRESCO at z\u223c5.8-5.9 and z\u223c7.3, suggesting Lyman-\u03b1 transmission is strongly enhanced in such overdense regions, and underlining the importance of LAEs as tracers of the first large-scale ionised bubbles."}


created_at: 2024-07-28 18:59:18
topic: persistent://default/default/4bfc3c11-fb71-4cc9-8c12-01ed076a0e01
id: e6dd823f-1d51-47c6-b810-acf18ce8a8fe
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/Search_reranking_with_cross-encoders.ipynb", "title": "Search reranking with cross-encoders", "tokens": 8550, "retrieve_doc": false, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"e6dd823f-1d51-47c6-b810-acf18ce8a8fe\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Search_reranking_with_cross-encoders.ipynb\", \"title\": \"Search reranking with cross-encoders\", \"tokens\": 8550, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"7fe36cde-011f-49b9-9282-b57056ad9c08\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Search_reranking_with_cross-encoders.ipynb\", \"title\": \"Search reranking with cross-encoders\", \"tokens\": 8550, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"dced2f13bcff97651066dc82958fcaa9337b1448f97481147a450ebcd8260dd3\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"5fb20ca0-b11b-4071-9bd8-7edff6fb5f4f\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/Search_reranking_with_cross-encoders.ipynb\", \"title\": \"Search reranking with cross-encoders\", \"tokens\": 8550, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"e539bddf44243b0954d8169c567d145a7619af44582a6e6a4f6ae40b004c28fb\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"4f3aa0f6-5f18-4e82-aa9f-fcf97740bf56\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"c5fbe626d8cacb2ca35eb6d8377665387dbf916d1d1093304e5c614c7bc72162\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 10323, \"end_char_idx\": 13361, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "7fe36cde-011f-49b9-9282-b57056ad9c08", "doc_id": "7fe36cde-011f-49b9-9282-b57056ad9c08", "ref_doc_id": "7fe36cde-011f-49b9-9282-b57056ad9c08", "chroma:document": "We demonstrate the efficacy of PPO and PPO-dynamic on conditional sequence generation tasks including synthetic experiment and chit-chat chatbot. The results show that PPO and PPO-dynamic can beat policy gradient by stability and performance.\"\"\"\nRelevant: Yes\n\nQuery: Explain sentence embeddings\nDocument: \"\"\"Inside the bubble: exploring the environments of reionisation-era Lyman-\u03b1 emitting galaxies with JADES and FRESCO: We present a study of the environments of 16 Lyman-\u03b1 emitting galaxies (LAEs) in the reionisation era (5.8<z<8) identified by JWST/NIRSpec as part of the JWST Advanced Deep Extragalactic Survey (JADES). Unless situated in sufficiently (re)ionised regions, Lyman-\u03b1 emission from these galaxies would be strongly absorbed by neutral gas in the intergalactic medium (IGM). We conservatively estimate sizes of the ionised regions required to reconcile the relatively low Lyman-\u03b1 velocity offsets (\u0394vLy\u03b1<300kms\u22121) with moderately high Lyman-\u03b1 escape fractions (fesc,Ly\u03b1>5%) observed in our sample of LAEs, indicating the presence of ionised ``bubbles'' with physical sizes of the order of 0.1pMpc\u2272Rion\u22721pMpc in a patchy reionisation scenario where the bubbles are embedded in a fully neutral IGM. Around half of the LAEs in our sample are found to coincide with large-scale galaxy overdensities seen in FRESCO at z\u223c5.8-5.9 and z\u223c7.3, suggesting Lyman-\u03b1 transmission is strongly enhanced in such overdense regions, and underlining the importance of LAEs as tracers of the first large-scale ionised bubbles. Considering only spectroscopically confirmed galaxies, we find our sample of UV-faint LAEs (MUV\u2273\u221220mag) and their direct neighbours are generally not able to produce the required ionised regions based on the Lyman-\u03b1 transmission properties, suggesting lower-luminosity sources likely play an important role in carving out these bubbles. These observations demonstrate the combined power of JWST multi-object and slitless spectroscopy in acquiring a unique view of the early stages of Cosmic Reionisation via the most distant LAEs.\"\"\"\nRelevant: No\n\nQuery: {query}\nDocument: \"\"\"{document}\"\"\"\nRelevant:\n'''\n\n\n@retry(wait=wait_random_exponential(min=1, max=40), stop=stop_after_attempt(3))\ndef document_relevance(query, document):\n    response = openai.chat.completions.create(\n        model=\"text-davinci-003\",\n        message=prompt.format(query=query, document=document),\n        temperature=0,\n        logprobs=True,\n        logit_bias={3363: 1, 1400: 1},\n    )\n\n    return (\n        query,\n        document,\n        response.choices[0].message.content,\n        response.choices[0].logprobs.token_logprobs[0],\n    )\n```\n\n\n```python\ncontent = result_list[0][\"title\"] + \": \" + result_list[0][\"summary\"]\n\n# Set logprobs to 1 so our response will include the most probable token the model identified\nresponse = openai.chat.completions.create(\n    model=OPENAI_MODEL,\n    prompt=prompt.format(query=query, document=content),\n    temperature=0,\n    logprobs=1,\n    logit_bias={3363: 1, 1400: 1},\n    max_tokens=1,\n)\n```"}


