|
2 | 2 | "cells": [
|
3 | 3 | {
|
4 | 4 | "cell_type": "code",
|
5 |
| - "execution_count": null, |
| 5 | + "execution_count": 10, |
6 | 6 | "metadata": {},
|
7 | 7 | "outputs": [],
|
8 | 8 | "source": [
|
|
20 | 20 | "AZURE_OPENAI_SERVICE = os.environ.get(\"AZURE_OPENAI_SERVICE\") or \"myopenai\"\n",
|
21 | 21 | "AZURE_OPENAI_GPT_DEPLOYMENT = os.environ.get(\"AZURE_OPENAI_GPT_DEPLOYMENT\") or \"davinci\"\n",
|
22 | 22 | "AZURE_OPENAI_CHATGPT_DEPLOYMENT = os.environ.get(\"AZURE_OPENAI_CHATGPT_DEPLOYMENT\") or \"chat\"\n",
|
23 |
| - "\n", |
24 |
| - "KB_FIELDS_CONTENT = os.environ.get(\"KB_FIELDS_CONTENT\") or \"content\"\n", |
25 |
| - "KB_FIELDS_CATEGORY = os.environ.get(\"KB_FIELDS_CATEGORY\") or \"category\"\n", |
26 |
| - "KB_FIELDS_SOURCEPAGE = os.environ.get(\"KB_FIELDS_SOURCEPAGE\") or \"sourcepage\"\n", |
| 23 | + "AZURE_OPENAI_CHATGPT_MODEL = os.environ.get(\"AZURE_OPENAI_CHATGPT_MODEL\") or \"gpt-35-turbo\"\n", |
27 | 24 | "\n",
|
28 | 25 | "# Use the current user identity to authenticate with Azure OpenAI, Cognitive Search and Blob Storage (no secrets needed, \n",
|
29 | 26 | "# just use 'az login' locally, and managed identity when deployed on Azure). If you need to use keys, use separate AzureKeyCredential instances with the \n",
|
|
33 | 30 | "# Used by the OpenAI SDK\n",
|
34 | 31 | "openai.api_type = \"azure\"\n",
|
35 | 32 | "openai.api_base = f\"https://{AZURE_OPENAI_SERVICE}.openai.azure.com\"\n",
|
36 |
| - "openai.api_version = \"2022-12-01\"\n", |
| 33 | + "openai.api_version = \"2023-05-15\"\n", |
37 | 34 | "\n",
|
38 | 35 | "# Comment these two lines out if using keys, set your API key in the OPENAI_API_KEY environment variable instead\n",
|
39 | 36 | "openai.api_type = \"azure_ad\"\n",
|
|
48 | 45 | },
|
49 | 46 | {
|
50 | 47 | "cell_type": "code",
|
51 |
| - "execution_count": null, |
| 48 | + "execution_count": 11, |
52 | 49 | "metadata": {},
|
53 | 50 | "outputs": [],
|
54 | 51 | "source": [
|
55 |
| - "# ChatGPT uses a particular set of tokens to indicate turns in conversations\n", |
56 |
| - "prompt_prefix = \"\"\"<|im_start|>system\n", |
57 |
| - "Assistant helps the company employees with their healthcare plan questions and employee handbook questions. \n", |
58 |
| - "Answer ONLY with the facts listed in the list of sources below. If there isn't enough information below, say you don't know. Do not generate answers that don't use the sources below. If asking a clarifying question to the user would help, ask the question. \n", |
59 |
| - "Each source has a name followed by colon and the actual information, always include the source name for each fact you use in the response. Use square brakets to reference the source, e.g. [info1.txt]. Don't combine sources, list each source separately, e.g. [info1.txt][info2.pdf].\n", |
60 |
| - "\n", |
61 |
| - "Sources:\n", |
62 |
| - "{sources}\n", |
63 |
| - "\n", |
64 |
| - "<|im_end|>\"\"\"\n", |
65 |
| - "\n", |
66 |
| - "turn_prefix = \"\"\"\n", |
67 |
| - "<|im_start|>user\n", |
68 |
| - "\"\"\"\n", |
69 |
| - "\n", |
70 |
| - "turn_suffix = \"\"\"\n", |
71 |
| - "<|im_end|>\n", |
72 |
| - "<|im_start|>assistant\n", |
| 52 | + "# Chat roles\n", |
| 53 | + "SYSTEM = \"system\"\n", |
| 54 | + "USER = \"user\"\n", |
| 55 | + "ASSISTANT = \"assistant\"\n", |
| 56 | + "\n", |
| 57 | + "system_message_chat_conversation = \"\"\"Assistant helps the company employees with their healthcare plan questions, and questions about the employee handbook. Be brief in your answers.\n", |
| 58 | + "Answer ONLY with the facts listed in the list of sources below. If there isn't enough information below, say you don't know. Do not generate answers that don't use the sources below. If asking a clarifying question to the user would help, ask the question.\n", |
| 59 | + "Each source has a name followed by colon and the actual information, always include the source name for each fact you use in the response. Use square brackets to reference the source, e.g. [info1.txt]. Don't combine sources, list each source separately, e.g. [info1.txt][info2.pdf].\n", |
73 | 60 | "\"\"\"\n",
|
74 |
| - "\n", |
75 |
| - "prompt_history = turn_prefix\n", |
76 |
| - "\n", |
77 |
| - "history = []\n", |
| 61 | + "chat_conversations = [{\"role\" : SYSTEM, \"content\" : system_message_chat_conversation}]\n", |
78 | 62 | "\n",
|
79 | 63 | "summary_prompt_template = \"\"\"Below is a summary of the conversation so far, and a new question asked by the user that needs to be answered by searching in a knowledge base. Generate a search query based on the conversation and the new question. Source names are not good search terms to include in the search query.\n",
|
80 | 64 | "\n",
|
|
85 | 69 | "{question}\n",
|
86 | 70 | "\n",
|
87 | 71 | "Search query:\n",
|
88 |
| - "\"\"\"" |
| 72 | + "\"\"\"\n" |
89 | 73 | ]
|
90 | 74 | },
|
91 | 75 | {
|
92 | 76 | "cell_type": "code",
|
93 |
| - "execution_count": null, |
| 77 | + "execution_count": 17, |
94 | 78 | "metadata": {},
|
95 |
| - "outputs": [], |
| 79 | + "outputs": [ |
| 80 | + { |
| 81 | + "name": "stdout", |
| 82 | + "output_type": "stream", |
| 83 | + "text": [ |
| 84 | + "Searching: \"copay\" \"Northwind Health Plus\" \"Northwind Standard\" benefits details -source name\n", |
| 85 | + "-------------------\n", |
| 86 | + "\n", |
| 87 | + "-------------------\n", |
| 88 | + "\n", |
| 89 | + "{'role': 'system', 'content': \"Assistant helps the company employees with their healthcare plan questions, and questions about the employee handbook. Be brief in your answers.\\nAnswer ONLY with the facts listed in the list of sources below. If there isn't enough information below, say you don't know. Do not generate answers that don't use the sources below. If asking a clarifying question to the user would help, ask the question.\\nEach source has a name followed by colon and the actual information, always include the source name for each fact you use in the response. Use square brackets to reference the source, e.g. [info1.txt]. Don't combine sources, list each source separately, e.g. [info1.txt][info2.pdf].\\n\"}\n", |
| 90 | + "{'role': 'user', 'content': 'does my plan cover eye exam'}\n", |
| 91 | + "{'role': 'assistant', 'content': 'Yes, Northwind Health Plus plan covers vision exams, glasses, and contact lenses. However, Northwind Standard only covers vision and hearing screenings and certain preventive services such as routine physical exams, immunizations, and screenings for certain diseases such as cancer and diabetes. [Benefit_Options-2.pdf][Northwind_Standard_Benefits_Details-44.pdf]'}\n", |
| 92 | + "{'role': 'user', 'content': 'does my plan cover eye exam'}\n", |
| 93 | + "{'role': 'assistant', 'content': 'Yes, Northwind Health Plus plan covers vision exams, glasses, and contact lenses. [Benefit_Options-2.pdf][Northwind_Health_Plus_Benefits_Details-25.pdf]'}\n", |
| 94 | + "{'role': 'user', 'content': 'does my plan cover vision'}\n", |
| 95 | + "{'role': 'assistant', 'content': 'Yes, both Northwind Health Plus and Northwind Standard plans offer coverage for vision services. Northwind Health Plus plan offers coverage for vision exams, glasses, and contact lenses, whereas Northwind Standard plan only offers coverage for vision exams and glasses. [Benefit_Options-2.pdf][Northwind_Standard_Benefits_Details-97.pdf]'}\n", |
| 96 | + "{'role': 'user', 'content': 'does my plan cover cardio'}\n", |
| 97 | + "{'role': 'assistant', 'content': 'Unfortunately, I cannot find information about whether Northwind Health Plus or Northwind Standard plans cover cardio specifically. However, both plans offer coverage for medical services like hospital stays and doctor visits. [Benefit_Options-2.pdf]'}\n", |
| 98 | + "{'role': 'user', 'content': 'does my plan cover dental'}\n", |
| 99 | + "{'role': 'assistant', 'content': 'Yes, Northwind Standard plan offers coverage for dental services. This coverage includes medically necessary services for the relief of pain resulting from dental injury, as well as services for the administration of anesthesia in a facility. However, this plan does not offer coverage for emergency services, mental health and substance abuse coverage, or out-of-network services. [Benefit_Options-2.pdf][Northwind_Standard_Benefits_Details-23.pdf]'}\n", |
| 100 | + "{'role': 'user', 'content': 'how much is copay'}\n", |
| 101 | + "{'role': 'assistant', 'content': 'The amount of copay for Northwind Standard plan varies depending on the type of service you receive, and copays may also vary from provider to provider and from state to state. Northwind Health Plus plan also has copays for certain services, and the amount of copayment varies based on the type of service received, whether the service is rendered by an in-network or out-of-network provider, and other factors. For in-network services, copays for Northwind Health Plus plan are generally lower than for out-of-network services. The copayment for primary care visits is typically around $20, while specialist visits have a copayment of around $50. [Northwind_Standard_Benefits_Details-9.pdf][Northwind_Standard_Benefits_Details-10.pdf][Northwind_Health_Plus_Benefits_Details-9.pdf]'}\n" |
| 102 | + ] |
| 103 | + }, |
| 104 | + { |
| 105 | + "data": { |
| 106 | + "text/plain": [ |
| 107 | + "[None, None, None, None, None, None, None, None, None, None, None, None, None]" |
| 108 | + ] |
| 109 | + }, |
| 110 | + "execution_count": 17, |
| 111 | + "metadata": {}, |
| 112 | + "output_type": "execute_result" |
| 113 | + } |
| 114 | + ], |
96 | 115 | "source": [
|
97 | 116 | "# Execute this cell multiple times updating user_input to accumulate chat history\n",
|
98 |
| - "user_input = \"Does my plan cover annual eye exams?\"\n", |
| 117 | + "user_input = \"how much is copay\"\n", |
99 | 118 | "\n",
|
100 | 119 | "# Exclude category, to simulate scenarios where there's a set of docs you can't see\n",
|
101 | 120 | "exclude_category = None\n",
|
102 | 121 | "\n",
|
103 |
| - "if len(history) > 0:\n", |
104 |
| - " completion = openai.Completion.create(\n", |
| 122 | + "if len(chat_conversations) > 1:\n", |
| 123 | + " query_completion = openai.Completion.create(\n", |
105 | 124 | " engine=AZURE_OPENAI_GPT_DEPLOYMENT,\n",
|
106 |
| - " prompt=summary_prompt_template.format(summary=\"\\n\".join(history), question=user_input),\n", |
| 125 | + " prompt=summary_prompt_template.format(summary=str(chat_conversations), question=user_input),\n", |
107 | 126 | " temperature=0.7,\n",
|
108 | 127 | " max_tokens=32,\n",
|
109 | 128 | " stop=[\"\\n\"])\n",
|
110 |
| - " search = completion.choices[0].text\n", |
| 129 | + " search = query_completion.choices[0].text\n", |
111 | 130 | "else:\n",
|
112 | 131 | " search = user_input\n",
|
113 | 132 | "\n",
|
|
125 | 144 | "results = [doc[KB_FIELDS_SOURCEPAGE] + \": \" + doc[KB_FIELDS_CONTENT].replace(\"\\n\", \"\").replace(\"\\r\", \"\") for doc in r]\n",
|
126 | 145 | "content = \"\\n\".join(results)\n",
|
127 | 146 | "\n",
|
128 |
| - "prompt = prompt_prefix.format(sources=content) + prompt_history + user_input + turn_suffix\n", |
| 147 | + "user_content = user_input + \" \\nSOURCES:\\n\" + content\n", |
129 | 148 | "\n",
|
130 |
| - "completion = openai.Completion.create(\n", |
131 |
| - " engine=AZURE_OPENAI_CHATGPT_DEPLOYMENT, \n", |
132 |
| - " prompt=prompt, \n", |
133 |
| - " temperature=0.7, \n", |
134 |
| - " max_tokens=1024,\n", |
135 |
| - " stop=[\"<|im_end|>\", \"<|im_start|>\"])\n", |
136 |
| - "\n", |
137 |
| - "prompt_history += user_input + turn_suffix + completion.choices[0].text + \"\\n<|im_end|>\" + turn_prefix\n", |
138 |
| - "history.append(\"user: \" + user_input)\n", |
139 |
| - "history.append(\"assistant: \" + completion.choices[0].text)\n", |
| 149 | + "chat_conversations.append({\"role\": USER, \"content\": user_content })\n", |
140 | 150 | "\n",
|
141 |
| - "print(\"\\n-------------------\\n\".join(history))\n", |
142 |
| - "print(\"\\n-------------------\\nPrompt:\\n\" + prompt)" |
| 151 | + "chat_completion = openai.ChatCompletion.create(\n", |
| 152 | + " deployment_id=AZURE_OPENAI_CHATGPT_DEPLOYMENT,\n", |
| 153 | + " model=AZURE_OPENAI_CHATGPT_MODEL,\n", |
| 154 | + " messages=chat_conversations, \n", |
| 155 | + " temperature=0.7, \n", |
| 156 | + " max_tokens=1024, \n", |
| 157 | + " n=1)\n", |
| 158 | + "chat_content = chat_completion.choices[0].message.content\n", |
| 159 | + "'''\n", |
| 160 | + "reset user content to avoid sources in conversation history\n", |
| 161 | + "add source as a single shot in query conversation\n", |
| 162 | + "'''\n", |
| 163 | + "chat_conversations[-1][\"content\"] = user_input\n", |
| 164 | + "chat_conversations.append({\"role\":ASSISTANT, \"content\": chat_content})\n", |
| 165 | + "\n", |
| 166 | + "print(\"\\n-------------------\\n\")\n", |
| 167 | + "[print(conversation) for conversation in chat_conversations]" |
143 | 168 | ]
|
144 | 169 | }
|
145 | 170 | ],
|
|
159 | 184 | "name": "python",
|
160 | 185 | "nbconvert_exporter": "python",
|
161 | 186 | "pygments_lexer": "ipython3",
|
162 |
| - "version": "3.10.10" |
| 187 | + "version": "3.11.4" |
163 | 188 | },
|
164 | 189 | "orig_nbformat": 4,
|
165 | 190 | "vscode": {
|
|
0 commit comments