diff --git a/examples/conversational_retrieval_chain/client.ipynb b/examples/conversational_retrieval_chain/client.ipynb index f4320e0d..5c2749a0 100644 --- a/examples/conversational_retrieval_chain/client.ipynb +++ b/examples/conversational_retrieval_chain/client.ipynb @@ -18,7 +18,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": 11, "metadata": { "tags": [] }, @@ -26,10 +26,15 @@ { "data": { "text/plain": [ - "{'output': {'answer': 'Cats like fish.'}, 'callback_events': []}" + "{'output': {'content': 'Based on the given context, the information we have about Harrison is that he worked at Kensho.',\n", + " 'additional_kwargs': {},\n", + " 'type': 'ai',\n", + " 'example': False},\n", + " 'callback_events': [],\n", + " 'metadata': {'run_id': '3455df2b-93f8-4e67-b1a3-27f90670cf7b'}}" ] }, - "execution_count": 1, + "execution_count": 11, "metadata": {}, "output_type": "execute_result" } @@ -37,7 +42,7 @@ "source": [ "import requests\n", "\n", - "inputs = {\"input\": {\"question\": \"what do cats like?\", \"chat_history\": []}}\n", + "inputs = {\"input\": {\"question\": \"what do you know about harrison\", \"chat_history\": []}}\n", "response = requests.post(\"http://localhost:8000/invoke\", json=inputs)\n", "\n", "response.json()" @@ -52,7 +57,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 12, "metadata": { "tags": [] }, @@ -72,7 +77,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 13, "metadata": { "tags": [] }, @@ -80,21 +85,21 @@ { "data": { "text/plain": [ - "{'answer': 'Cats like fish.'}" + "AIMessage(content='Based on the given context, the only information we have about Harrison is that he worked at Kensho.')" ] }, - "execution_count": 3, + "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "await remote_runnable.ainvoke({\"question\": \"what do cats like?\", \"chat_history\": []})" + "await remote_runnable.ainvoke({\"question\": \"what do you know about harrison\", \"chat_history\": []})" ] }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 14, "metadata": { "tags": [] }, @@ -102,26 +107,501 @@ { "data": { "text/plain": [ - "{'answer': 'Cats like fish.'}" + "AIMessage(content='Harrison worked at Kensho.')" ] }, - "execution_count": 6, + "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "await remote_runnable.ainvoke(\n", - " {\"question\": \"what do cats like?\", \"chat_history\": [(\"hi\", \"hi\")]}\n", + " {\"question\": \"what do you know about harrison\", \"chat_history\": [(\"hi\", \"hi\")]}\n", ")" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 16, + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "content=''\n", + "content='H'\n", + "content='arrison'\n", + "content=' worked'\n", + "content=' at'\n", + "content=' Kens'\n", + "content='ho'\n", + "content='.'\n", + "content=''\n" + ] + } + ], + "source": [ + "async for chunk in remote_runnable.astream(\n", + " {\"question\": \"what do you know about harrison\", \"chat_history\": [(\"hi\", \"hi\")]}\n", + "):\n", + " print(chunk)" + ] + }, + { + "cell_type": "markdown", "metadata": {}, - "outputs": [], - "source": [] + "source": [ + "stream log shows all intermediate steps as well!" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "RunLogPatch({'op': 'replace',\n", + " 'path': '',\n", + " 'value': {'final_output': None,\n", + " 'id': '2ff5a98d-49f0-40ae-92fe-489c3047d1c3',\n", + " 'logs': {},\n", + " 'streamed_output': []}})\n", + "RunLogPatch({'op': 'add',\n", + " 'path': '/logs/RunnableParallel',\n", + " 'value': {'end_time': None,\n", + " 'final_output': None,\n", + " 'id': 'ffdda3c9-a0ba-49a6-af18-c01748c31801',\n", + " 'metadata': {},\n", + " 'name': 'RunnableParallel',\n", + " 'start_time': '2023-11-16T15:59:23.348',\n", + " 'streamed_output_str': [],\n", + " 'tags': ['seq:step:1'],\n", + " 'type': 'chain'}})\n", + "RunLogPatch({'op': 'add',\n", + " 'path': '/logs/RunnableSequence',\n", + " 'value': {'end_time': None,\n", + " 'final_output': None,\n", + " 'id': 'a9da3f2c-f3ae-44c1-a2f4-1035faa0d1c2',\n", + " 'metadata': {},\n", + " 'name': 'RunnableSequence',\n", + " 'start_time': '2023-11-16T15:59:23.349',\n", + " 'streamed_output_str': [],\n", + " 'tags': ['map:key:standalone_question'],\n", + " 'type': 'chain'}})\n", + "RunLogPatch({'op': 'add',\n", + " 'path': '/logs/RunnableParallel:2',\n", + " 'value': {'end_time': None,\n", + " 'final_output': None,\n", + " 'id': '4d32b08f-a989-4c01-8068-479bed506d99',\n", + " 'metadata': {},\n", + " 'name': 'RunnableParallel',\n", + " 'start_time': '2023-11-16T15:59:23.349',\n", + " 'streamed_output_str': [],\n", + " 'tags': ['seq:step:1'],\n", + " 'type': 'chain'}})\n", + "RunLogPatch({'op': 'add',\n", + " 'path': '/logs/',\n", + " 'value': {'end_time': None,\n", + " 'final_output': None,\n", + " 'id': 'c7b9bd78-cbb4-41f9-b31a-50a5f8940a8d',\n", + " 'metadata': {},\n", + " 'name': '',\n", + " 'start_time': '2023-11-16T15:59:23.350',\n", + " 'streamed_output_str': [],\n", + " 'tags': ['map:key:chat_history'],\n", + " 'type': 'chain'}})\n", + "RunLogPatch({'op': 'add',\n", + " 'path': '/logs//final_output',\n", + " 'value': {'output': '\\nHuman: hi\\nAssistant: hi'}},\n", + " {'op': 'add',\n", + " 'path': '/logs//end_time',\n", + " 'value': '2023-11-16T15:59:23.350'})\n", + "RunLogPatch({'op': 'add',\n", + " 'path': '/logs/RunnableParallel:2/final_output',\n", + " 'value': {'chat_history': '\\nHuman: hi\\nAssistant: hi'}},\n", + " {'op': 'add',\n", + " 'path': '/logs/RunnableParallel:2/end_time',\n", + " 'value': '2023-11-16T15:59:23.351'})\n", + "RunLogPatch({'op': 'add',\n", + " 'path': '/logs/PromptTemplate',\n", + " 'value': {'end_time': None,\n", + " 'final_output': None,\n", + " 'id': 'ef9f8729-2d4a-4887-86a8-a284d64f5882',\n", + " 'metadata': {},\n", + " 'name': 'PromptTemplate',\n", + " 'start_time': '2023-11-16T15:59:23.351',\n", + " 'streamed_output_str': [],\n", + " 'tags': ['seq:step:2'],\n", + " 'type': 'prompt'}})\n", + "RunLogPatch({'op': 'add',\n", + " 'path': '/logs/PromptTemplate/final_output',\n", + " 'value': StringPromptValue(text='Given the following conversation and a follow up question, rephrase the \\nfollow up question to be a standalone question, in its original language.\\n\\nChat History:\\n\\nHuman: hi\\nAssistant: hi\\nFollow Up Input: what do you know about harrison\\nStandalone question:')},\n", + " {'op': 'add',\n", + " 'path': '/logs/PromptTemplate/end_time',\n", + " 'value': '2023-11-16T15:59:23.351'})\n", + "RunLogPatch({'op': 'add',\n", + " 'path': '/logs/ChatOpenAI',\n", + " 'value': {'end_time': None,\n", + " 'final_output': None,\n", + " 'id': '7cda5923-ed2a-42ea-aee7-a2391371ff2f',\n", + " 'metadata': {},\n", + " 'name': 'ChatOpenAI',\n", + " 'start_time': '2023-11-16T15:59:23.352',\n", + " 'streamed_output_str': [],\n", + " 'tags': ['seq:step:3'],\n", + " 'type': 'llm'}})\n", + "RunLogPatch({'op': 'add',\n", + " 'path': '/logs/StrOutputParser',\n", + " 'value': {'end_time': None,\n", + " 'final_output': None,\n", + " 'id': '6a0e199d-51fa-4306-8a7d-054444c6855f',\n", + " 'metadata': {},\n", + " 'name': 'StrOutputParser',\n", + " 'start_time': '2023-11-16T15:59:24.613',\n", + " 'streamed_output_str': [],\n", + " 'tags': ['seq:step:4'],\n", + " 'type': 'parser'}})\n", + "RunLogPatch({'op': 'add',\n", + " 'path': '/logs/RunnableParallel:3',\n", + " 'value': {'end_time': None,\n", + " 'final_output': None,\n", + " 'id': '74a13de1-c2d1-43c0-813a-7ce0246118b3',\n", + " 'metadata': {},\n", + " 'name': 'RunnableParallel',\n", + " 'start_time': '2023-11-16T15:59:24.616',\n", + " 'streamed_output_str': [],\n", + " 'tags': ['seq:step:2'],\n", + " 'type': 'chain'}})\n", + "RunLogPatch({'op': 'add',\n", + " 'path': '/logs/RunnableSequence:2',\n", + " 'value': {'end_time': None,\n", + " 'final_output': None,\n", + " 'id': '625e2183-7ee5-4f1f-8f47-56541afc96ee',\n", + " 'metadata': {},\n", + " 'name': 'RunnableSequence',\n", + " 'start_time': '2023-11-16T15:59:24.619',\n", + " 'streamed_output_str': [],\n", + " 'tags': ['map:key:context'],\n", + " 'type': 'chain'}})\n", + "RunLogPatch({'op': 'add', 'path': '/logs/ChatOpenAI/streamed_output_str/-', 'value': ''})\n", + "RunLogPatch({'op': 'add',\n", + " 'path': '/logs/ChatOpenAI/streamed_output_str/-',\n", + " 'value': 'What'})\n", + "RunLogPatch({'op': 'add',\n", + " 'path': '/logs/ChatOpenAI/streamed_output_str/-',\n", + " 'value': ' information'})\n", + "RunLogPatch({'op': 'add',\n", + " 'path': '/logs/ChatOpenAI/streamed_output_str/-',\n", + " 'value': ' do'})\n", + "RunLogPatch({'op': 'add',\n", + " 'path': '/logs/ChatOpenAI/streamed_output_str/-',\n", + " 'value': ' you'})\n", + "RunLogPatch({'op': 'add',\n", + " 'path': '/logs/ChatOpenAI/streamed_output_str/-',\n", + " 'value': ' have'})\n", + "RunLogPatch({'op': 'add',\n", + " 'path': '/logs/ChatOpenAI/streamed_output_str/-',\n", + " 'value': ' about'})\n", + "RunLogPatch({'op': 'add',\n", + " 'path': '/logs/ChatOpenAI/streamed_output_str/-',\n", + " 'value': ' Harrison'})\n", + "RunLogPatch({'op': 'add', 'path': '/logs/ChatOpenAI/streamed_output_str/-', 'value': '?'})\n", + "RunLogPatch({'op': 'add', 'path': '/logs/ChatOpenAI/streamed_output_str/-', 'value': ''})\n", + "RunLogPatch({'op': 'add',\n", + " 'path': '/logs/ChatOpenAI/final_output',\n", + " 'value': LLMResult(generations=[[ChatGenerationChunk(text='What information do you have about Harrison?', generation_info={'finish_reason': 'stop'}, message=AIMessageChunk(content='What information do you have about Harrison?'))]], llm_output=None, run=None)},\n", + " {'op': 'add',\n", + " 'path': '/logs/ChatOpenAI/end_time',\n", + " 'value': '2023-11-16T15:59:24.832'})\n", + "RunLogPatch({'op': 'add',\n", + " 'path': '/logs/StrOutputParser/final_output',\n", + " 'value': {'output': 'What information do you have about Harrison?'}},\n", + " {'op': 'add',\n", + " 'path': '/logs/StrOutputParser/end_time',\n", + " 'value': '2023-11-16T15:59:24.833'})\n", + "RunLogPatch({'op': 'add',\n", + " 'path': '/logs/RunnableSequence/final_output',\n", + " 'value': {'output': 'What information do you have about Harrison?'}},\n", + " {'op': 'add',\n", + " 'path': '/logs/RunnableSequence/end_time',\n", + " 'value': '2023-11-16T15:59:24.834'})\n", + "RunLogPatch({'op': 'add',\n", + " 'path': '/logs/RunnableParallel/final_output',\n", + " 'value': {'standalone_question': 'What information do you have about '\n", + " 'Harrison?'}},\n", + " {'op': 'add',\n", + " 'path': '/logs/RunnableParallel/end_time',\n", + " 'value': '2023-11-16T15:59:24.835'})\n", + "RunLogPatch({'op': 'add',\n", + " 'path': '/logs/RunnableLambda',\n", + " 'value': {'end_time': None,\n", + " 'final_output': None,\n", + " 'id': '71b2e8dc-753f-4bf2-83de-b87b26828370',\n", + " 'metadata': {},\n", + " 'name': 'RunnableLambda',\n", + " 'start_time': '2023-11-16T15:59:24.837',\n", + " 'streamed_output_str': [],\n", + " 'tags': ['seq:step:1'],\n", + " 'type': 'chain'}})\n", + "RunLogPatch({'op': 'add',\n", + " 'path': '/logs/RunnableLambda/final_output',\n", + " 'value': {'output': 'What information do you have about Harrison?'}},\n", + " {'op': 'add',\n", + " 'path': '/logs/RunnableLambda/end_time',\n", + " 'value': '2023-11-16T15:59:24.837'})\n", + "RunLogPatch({'op': 'add',\n", + " 'path': '/logs/Retriever',\n", + " 'value': {'end_time': None,\n", + " 'final_output': None,\n", + " 'id': 'd3d6254d-d073-478f-b00b-bc27eafa24fd',\n", + " 'metadata': {},\n", + " 'name': 'Retriever',\n", + " 'start_time': '2023-11-16T15:59:24.839',\n", + " 'streamed_output_str': [],\n", + " 'tags': ['seq:step:2', 'FAISS', 'OpenAIEmbeddings'],\n", + " 'type': 'retriever'}})\n", + "RunLogPatch({'op': 'add',\n", + " 'path': '/logs/:2',\n", + " 'value': {'end_time': None,\n", + " 'final_output': None,\n", + " 'id': '77f7132a-d98f-4121-89cf-10e462c26496',\n", + " 'metadata': {},\n", + " 'name': '',\n", + " 'start_time': '2023-11-16T15:59:24.839',\n", + " 'streamed_output_str': [],\n", + " 'tags': ['map:key:question'],\n", + " 'type': 'chain'}})\n", + "RunLogPatch({'op': 'add',\n", + " 'path': '/logs/:2/final_output',\n", + " 'value': {'output': 'What information do you have about Harrison?'}},\n", + " {'op': 'add',\n", + " 'path': '/logs/:2/end_time',\n", + " 'value': '2023-11-16T15:59:24.840'})\n", + "RunLogPatch({'op': 'add',\n", + " 'path': '/logs/Retriever/final_output',\n", + " 'value': {'documents': [Document(page_content='harrison worked at kensho')]}},\n", + " {'op': 'add',\n", + " 'path': '/logs/Retriever/end_time',\n", + " 'value': '2023-11-16T15:59:25.074'})\n", + "RunLogPatch({'op': 'add',\n", + " 'path': '/logs/_combine_documents',\n", + " 'value': {'end_time': None,\n", + " 'final_output': None,\n", + " 'id': '82aecf3e-ca9d-4b48-a281-03f8e834ea62',\n", + " 'metadata': {},\n", + " 'name': '_combine_documents',\n", + " 'start_time': '2023-11-16T15:59:25.075',\n", + " 'streamed_output_str': [],\n", + " 'tags': ['seq:step:3'],\n", + " 'type': 'chain'}})\n", + "RunLogPatch({'op': 'add',\n", + " 'path': '/logs/_combine_documents/final_output',\n", + " 'value': {'output': 'harrison worked at kensho'}},\n", + " {'op': 'add',\n", + " 'path': '/logs/_combine_documents/end_time',\n", + " 'value': '2023-11-16T15:59:25.075'})\n", + "RunLogPatch({'op': 'add',\n", + " 'path': '/logs/RunnableSequence:2/final_output',\n", + " 'value': {'output': 'harrison worked at kensho'}},\n", + " {'op': 'add',\n", + " 'path': '/logs/RunnableSequence:2/end_time',\n", + " 'value': '2023-11-16T15:59:25.075'})\n", + "RunLogPatch({'op': 'add',\n", + " 'path': '/logs/RunnableParallel:3/final_output',\n", + " 'value': {'context': 'harrison worked at kensho',\n", + " 'question': 'What information do you have about Harrison?'}},\n", + " {'op': 'add',\n", + " 'path': '/logs/RunnableParallel:3/end_time',\n", + " 'value': '2023-11-16T15:59:25.076'})\n", + "RunLogPatch({'op': 'add',\n", + " 'path': '/logs/ChatPromptTemplate',\n", + " 'value': {'end_time': None,\n", + " 'final_output': None,\n", + " 'id': 'b37f36ce-3a27-4402-81c4-6893f03ec179',\n", + " 'metadata': {},\n", + " 'name': 'ChatPromptTemplate',\n", + " 'start_time': '2023-11-16T15:59:25.076',\n", + " 'streamed_output_str': [],\n", + " 'tags': ['seq:step:3'],\n", + " 'type': 'prompt'}})\n", + "RunLogPatch({'op': 'add',\n", + " 'path': '/logs/ChatPromptTemplate/final_output',\n", + " 'value': {'messages': [HumanMessage(content='Answer the question based only on the following context:\\nharrison worked at kensho\\n\\nQuestion: What information do you have about Harrison?\\n')]}},\n", + " {'op': 'add',\n", + " 'path': '/logs/ChatPromptTemplate/end_time',\n", + " 'value': '2023-11-16T15:59:25.077'})\n", + "RunLogPatch({'op': 'add',\n", + " 'path': '/logs/ChatOpenAI:2',\n", + " 'value': {'end_time': None,\n", + " 'final_output': None,\n", + " 'id': 'b1179088-eb7c-49c5-af1e-bd09c48408bf',\n", + " 'metadata': {},\n", + " 'name': 'ChatOpenAI',\n", + " 'start_time': '2023-11-16T15:59:25.078',\n", + " 'streamed_output_str': [],\n", + " 'tags': ['seq:step:4'],\n", + " 'type': 'llm'}})\n", + "RunLogPatch({'op': 'add',\n", + " 'path': '/streamed_output/-',\n", + " 'value': AIMessageChunk(content='')})\n", + "RunLogPatch({'op': 'add', 'path': '/logs/ChatOpenAI:2/streamed_output_str/-', 'value': ''})\n", + "RunLogPatch({'op': 'add',\n", + " 'path': '/streamed_output/-',\n", + " 'value': AIMessageChunk(content='Based')})\n", + "RunLogPatch({'op': 'add',\n", + " 'path': '/logs/ChatOpenAI:2/streamed_output_str/-',\n", + " 'value': 'Based'})\n", + "RunLogPatch({'op': 'add',\n", + " 'path': '/streamed_output/-',\n", + " 'value': AIMessageChunk(content=' on')})\n", + "RunLogPatch({'op': 'add',\n", + " 'path': '/logs/ChatOpenAI:2/streamed_output_str/-',\n", + " 'value': ' on'})\n", + "RunLogPatch({'op': 'add',\n", + " 'path': '/streamed_output/-',\n", + " 'value': AIMessageChunk(content=' the')})\n", + "RunLogPatch({'op': 'add',\n", + " 'path': '/logs/ChatOpenAI:2/streamed_output_str/-',\n", + " 'value': ' the'})\n", + "RunLogPatch({'op': 'add',\n", + " 'path': '/streamed_output/-',\n", + " 'value': AIMessageChunk(content=' given')})\n", + "RunLogPatch({'op': 'add',\n", + " 'path': '/logs/ChatOpenAI:2/streamed_output_str/-',\n", + " 'value': ' given'})\n", + "RunLogPatch({'op': 'add',\n", + " 'path': '/streamed_output/-',\n", + " 'value': AIMessageChunk(content=' context')})\n", + "RunLogPatch({'op': 'add',\n", + " 'path': '/logs/ChatOpenAI:2/streamed_output_str/-',\n", + " 'value': ' context'})\n", + "RunLogPatch({'op': 'add',\n", + " 'path': '/streamed_output/-',\n", + " 'value': AIMessageChunk(content=',')})\n", + "RunLogPatch({'op': 'add',\n", + " 'path': '/logs/ChatOpenAI:2/streamed_output_str/-',\n", + " 'value': ','})\n", + "RunLogPatch({'op': 'add',\n", + " 'path': '/streamed_output/-',\n", + " 'value': AIMessageChunk(content=' the')})\n", + "RunLogPatch({'op': 'add',\n", + " 'path': '/logs/ChatOpenAI:2/streamed_output_str/-',\n", + " 'value': ' the'})\n", + "RunLogPatch({'op': 'add',\n", + " 'path': '/streamed_output/-',\n", + " 'value': AIMessageChunk(content=' only')})\n", + "RunLogPatch({'op': 'add',\n", + " 'path': '/logs/ChatOpenAI:2/streamed_output_str/-',\n", + " 'value': ' only'})\n", + "RunLogPatch({'op': 'add',\n", + " 'path': '/streamed_output/-',\n", + " 'value': AIMessageChunk(content=' information')})\n", + "RunLogPatch({'op': 'add',\n", + " 'path': '/logs/ChatOpenAI:2/streamed_output_str/-',\n", + " 'value': ' information'})\n", + "RunLogPatch({'op': 'add',\n", + " 'path': '/streamed_output/-',\n", + " 'value': AIMessageChunk(content=' we')})\n", + "RunLogPatch({'op': 'add',\n", + " 'path': '/logs/ChatOpenAI:2/streamed_output_str/-',\n", + " 'value': ' we'})\n", + "RunLogPatch({'op': 'add',\n", + " 'path': '/streamed_output/-',\n", + " 'value': AIMessageChunk(content=' have')})\n", + "RunLogPatch({'op': 'add',\n", + " 'path': '/logs/ChatOpenAI:2/streamed_output_str/-',\n", + " 'value': ' have'})\n", + "RunLogPatch({'op': 'add',\n", + " 'path': '/streamed_output/-',\n", + " 'value': AIMessageChunk(content=' about')})\n", + "RunLogPatch({'op': 'add',\n", + " 'path': '/logs/ChatOpenAI:2/streamed_output_str/-',\n", + " 'value': ' about'})\n", + "RunLogPatch({'op': 'add',\n", + " 'path': '/streamed_output/-',\n", + " 'value': AIMessageChunk(content=' Harrison')})\n", + "RunLogPatch({'op': 'add',\n", + " 'path': '/logs/ChatOpenAI:2/streamed_output_str/-',\n", + " 'value': ' Harrison'})\n", + "RunLogPatch({'op': 'add',\n", + " 'path': '/streamed_output/-',\n", + " 'value': AIMessageChunk(content=' is')})\n", + "RunLogPatch({'op': 'add',\n", + " 'path': '/logs/ChatOpenAI:2/streamed_output_str/-',\n", + " 'value': ' is'})\n", + "RunLogPatch({'op': 'add',\n", + " 'path': '/streamed_output/-',\n", + " 'value': AIMessageChunk(content=' that')})\n", + "RunLogPatch({'op': 'add',\n", + " 'path': '/logs/ChatOpenAI:2/streamed_output_str/-',\n", + " 'value': ' that'})\n", + "RunLogPatch({'op': 'add',\n", + " 'path': '/streamed_output/-',\n", + " 'value': AIMessageChunk(content=' he')})\n", + "RunLogPatch({'op': 'add',\n", + " 'path': '/logs/ChatOpenAI:2/streamed_output_str/-',\n", + " 'value': ' he'})\n", + "RunLogPatch({'op': 'add',\n", + " 'path': '/streamed_output/-',\n", + " 'value': AIMessageChunk(content=' worked')})\n", + "RunLogPatch({'op': 'add',\n", + " 'path': '/logs/ChatOpenAI:2/streamed_output_str/-',\n", + " 'value': ' worked'})\n", + "RunLogPatch({'op': 'add',\n", + " 'path': '/streamed_output/-',\n", + " 'value': AIMessageChunk(content=' at')})\n", + "RunLogPatch({'op': 'add',\n", + " 'path': '/logs/ChatOpenAI:2/streamed_output_str/-',\n", + " 'value': ' at'})\n", + "RunLogPatch({'op': 'add',\n", + " 'path': '/streamed_output/-',\n", + " 'value': AIMessageChunk(content=' Kens')})\n", + "RunLogPatch({'op': 'add',\n", + " 'path': '/logs/ChatOpenAI:2/streamed_output_str/-',\n", + " 'value': ' Kens'})\n", + "RunLogPatch({'op': 'add',\n", + " 'path': '/streamed_output/-',\n", + " 'value': AIMessageChunk(content='ho')})\n", + "RunLogPatch({'op': 'add',\n", + " 'path': '/logs/ChatOpenAI:2/streamed_output_str/-',\n", + " 'value': 'ho'})\n", + "RunLogPatch({'op': 'add',\n", + " 'path': '/streamed_output/-',\n", + " 'value': AIMessageChunk(content='.')})\n", + "RunLogPatch({'op': 'add',\n", + " 'path': '/logs/ChatOpenAI:2/streamed_output_str/-',\n", + " 'value': '.'})\n", + "RunLogPatch({'op': 'add',\n", + " 'path': '/streamed_output/-',\n", + " 'value': AIMessageChunk(content='')})\n", + "RunLogPatch({'op': 'add', 'path': '/logs/ChatOpenAI:2/streamed_output_str/-', 'value': ''})\n", + "RunLogPatch({'op': 'add',\n", + " 'path': '/logs/ChatOpenAI:2/final_output',\n", + " 'value': LLMResult(generations=[[ChatGenerationChunk(text='Based on the given context, the only information we have about Harrison is that he worked at Kensho.', generation_info={'finish_reason': 'stop'}, message=AIMessageChunk(content='Based on the given context, the only information we have about Harrison is that he worked at Kensho.'))]], llm_output=None, run=None)},\n", + " {'op': 'add',\n", + " 'path': '/logs/ChatOpenAI:2/end_time',\n", + " 'value': '2023-11-16T15:59:26.547'})\n", + "RunLogPatch({'op': 'replace',\n", + " 'path': '/final_output',\n", + " 'value': {'output': AIMessageChunk(content='Based on the given context, the only information we have about Harrison is that he worked at Kensho.')}})\n" + ] + } + ], + "source": [ + "async for chunk in remote_runnable.astream_log(\n", + " {\"question\": \"what do you know about harrison\", \"chat_history\": [(\"hi\", \"hi\")]}\n", + "):\n", + " print(chunk)" + ] } ], "metadata": { diff --git a/examples/conversational_retrieval_chain/server.py b/examples/conversational_retrieval_chain/server.py index f9d863d6..57428ba9 100755 --- a/examples/conversational_retrieval_chain/server.py +++ b/examples/conversational_retrieval_chain/server.py @@ -1,24 +1,84 @@ #!/usr/bin/env python -"""Example LangChain server exposes a conversational retrieval chain.""" +"""Example LangChain server exposes a conversational retrieval chain. + +Follow the reference here: + +https://python.langchain.com/docs/expression_language/cookbook/retrieval#conversational-retrieval-chain + +To run this example, you will need to install the following packages: +pip install langchain openai faiss-cpu tiktoken +""" # noqa: F401 + +from operator import itemgetter from typing import List, Tuple from fastapi import FastAPI -from langchain.chains import ConversationalRetrievalChain from langchain.chat_models import ChatOpenAI from langchain.embeddings import OpenAIEmbeddings -from langchain.pydantic_v1 import BaseModel, Field +from langchain.prompts import ChatPromptTemplate +from langchain.prompts.prompt import PromptTemplate +from langchain.schema import format_document +from langchain.schema.output_parser import StrOutputParser +from langchain.schema.runnable import RunnableMap, RunnablePassthrough from langchain.vectorstores import FAISS +from pydantic.v1 import BaseModel, Field from langserve import add_routes +_TEMPLATE = """Given the following conversation and a follow up question, rephrase the +follow up question to be a standalone question, in its original language. + +Chat History: +{chat_history} +Follow Up Input: {question} +Standalone question:""" +CONDENSE_QUESTION_PROMPT = PromptTemplate.from_template(_TEMPLATE) + +ANSWER_TEMPLATE = """Answer the question based only on the following context: +{context} + +Question: {question} +""" +ANSWER_PROMPT = ChatPromptTemplate.from_template(ANSWER_TEMPLATE) + +DEFAULT_DOCUMENT_PROMPT = PromptTemplate.from_template(template="{page_content}") + + +def _combine_documents( + docs, document_prompt=DEFAULT_DOCUMENT_PROMPT, document_separator="\n\n" +): + """Combine documents into a single string.""" + doc_strings = [format_document(doc, document_prompt) for doc in docs] + return document_separator.join(doc_strings) + + +def _format_chat_history(chat_history: List[Tuple]) -> str: + """Format chat history into a string.""" + buffer = "" + for dialogue_turn in chat_history: + human = "Human: " + dialogue_turn[0] + ai = "Assistant: " + dialogue_turn[1] + buffer += "\n" + "\n".join([human, ai]) + return buffer + + vectorstore = FAISS.from_texts( - ["cats like fish", "dogs like sticks"], embedding=OpenAIEmbeddings() + ["harrison worked at kensho"], embedding=OpenAIEmbeddings() ) retriever = vectorstore.as_retriever() -model = ChatOpenAI() - -chain = ConversationalRetrievalChain.from_llm(model, retriever) +_inputs = RunnableMap( + standalone_question=RunnablePassthrough.assign( + chat_history=lambda x: _format_chat_history(x["chat_history"]) + ) + | CONDENSE_QUESTION_PROMPT + | ChatOpenAI(temperature=0) + | StrOutputParser(), +) +_context = { + "context": itemgetter("standalone_question") | retriever | _combine_documents, + "question": lambda x: x["standalone_question"], +} # User input @@ -32,9 +92,8 @@ class ChatHistory(BaseModel): question: str -chain = ConversationalRetrievalChain.from_llm(model, retriever).with_types( - input_type=ChatHistory -) +conversational_qa_chain = _inputs | _context | ANSWER_PROMPT | ChatOpenAI() +chain = conversational_qa_chain.with_types(input_type=ChatHistory) app = FastAPI( title="LangChain Server",