Skip to content

Commit 72d5cb5

Browse files
committed
version 3.0 first commit
1 parent b87c323 commit 72d5cb5

23 files changed

+5993
-5290
lines changed

01-Load-Data-ACogSearch.ipynb

+234-283
Large diffs are not rendered by default.

02-LoadCSVOneToMany-ACogSearch.ipynb

+217-209
Large diffs are not rendered by default.

03-Quering-AOpenAI.ipynb

+476-522
Large diffs are not rendered by default.

04-Complex-Docs.ipynb

+255-265
Large diffs are not rendered by default.

05-Adding_Memory.ipynb

+318-401
Large diffs are not rendered by default.

06-First-RAG.ipynb

+713
Large diffs are not rendered by default.

07-SQLDB_QA.ipynb

-705
This file was deleted.

06-TabularDataQA.ipynb 07-TabularDataQA.ipynb

+218-165
Large diffs are not rendered by default.

08-BingChatClone.ipynb

-492
This file was deleted.

08-SQLDB_QA.ipynb

+589
Large diffs are not rendered by default.

09-BingChatClone.ipynb

+615
Large diffs are not rendered by default.

09-API-Search.ipynb 10-API-Search.ipynb

+195-126
Large diffs are not rendered by default.

10-Smart_Agent.ipynb

-1,317
This file was deleted.

11-Smart_Agent.ipynb

+1,621
Large diffs are not rendered by default.
File renamed without changes.

README.md

+17-16
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
![image](https://user-images.githubusercontent.com/113465005/226238596-cc76039e-67c2-46b6-b0bb-35d037ae66e1.png)
22

3-
# 3 or 5 days POC VBD powered by: Azure Search + Azure OpenAI + Bot Framework + Langchain + Azure SQL + CosmosDB + Bing Search API
3+
# 3 or 5 days POC VBD powered by: Azure AI Search + Azure OpenAI + Bot Framework + Langchain + Azure SQL + CosmosDB + Bing Search API + Document Intelligence SDK
44
[![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MSUSAzureAccelerators/Azure-Cognitive-Search-Azure-OpenAI-Accelerator?quickstart=1)
55
[![Open in VS Code Dev Containers](https://img.shields.io/static/v1?style=for-the-badge&label=Remote%20-%20Containers&message=Open&color=blue&logo=visualstudiocode)](https://vscode.dev/redirect?url=vscode://ms-vscode-remote.remote-containers/cloneInVolume?url=https://github.com/MSUSAzureAccelerators/Azure-Cognitive-Search-Azure-OpenAI-Accelerator)
66

@@ -33,7 +33,8 @@ The repo is made to teach you step-by-step on how to build a OpenAI-based Smart
3333
* The customer team and the Microsoft team must have Contributor permissions to this resource group so they can set everything up 2 weeks prior to the workshop
3434
* A storage account must be set in place in the RG.
3535
* Customer Data/Documents must be uploaded to the blob storage account, at least two weeks prior to the workshop date
36-
* Multi-Tenant App Registration (Service Principal).
36+
* A Multi-Tenant App Registration (Service Principal) must be created by the customer (save the Client Id and Secret Value).
37+
* Customer must provide the Microsoft Team , 10-20 questions (easy to hard) that they want the bot to respond correctly.
3738
* For IDE collaboration and standarization during workshop, AML compute instances with Jupyper Lab will be used, for this, Azure Machine Learning Workspace must be deployed in the RG
3839
* Note: Please ensure you have enough core compute quota in your Azure Machine Learning workspace
3940

@@ -48,9 +49,12 @@ The repo is made to teach you step-by-step on how to build a OpenAI-based Smart
4849
* 3a. Azure SQL Database - contains COVID-related statistics in the US.
4950
* 3b. API Endpoints - RESTful OpenAPI 3.0 API containing up-to-date statistics about Covid.
5051
* 3c. Azure Bing Search API - provides access to the internet allowing scenerios like: QnA on public websites .
51-
* 3d. Azure AI Text Search - contains AI-enriched documents from Blob Storage (10k PDFs and 90k articles).
52-
* 3e. Azure AI Vector Search - contains 5 lenghty PDF books vectorized per page.
52+
* 3d. Azure AI Search - contains AI-enriched documents from Blob Storage:
53+
- 10,000 Arxiv Computer Science PDFs
54+
- 90,000 Covid publication abstracts
55+
- 5 lenghty PDF books
5356
* 3f. CSV Tabular File - contains COVID-related statistics in the US.
57+
* 3g. Kraken broker API for currencies
5458
4. The app retrieves the result from the source and crafts the answer.
5559
5. The tuple (Question and Answer) is saved to CosmosDB as persistent memory and for further analysis.
5660
6. The answer is delivered to the user.
@@ -68,9 +72,8 @@ https://gptsmartsearch.azurewebsites.net/
6872

6973
- Uses [Bot Framework](https://dev.botframework.com/) and [Bot Service](https://azure.microsoft.com/en-us/products/bot-services/) to Host the Bot API Backend and to expose it to multiple channels including MS Teams.
7074
- 100% Python.
71-
- Uses [Azure Cognitive Services](https://azure.microsoft.com/en-us/products/cognitive-services/) to index and enrich unstructured documents: Detect Language, OCR images, Key-phrases extraction, entity recognition (persons, emails, addresses, organizations, urls).
72-
- Uses Vector Search Capabilities of Azure Cognitive Search to provide the best semantic answer.
73-
- Creates vectors on-demand as users interact with the system. (versus vectorizing the whole datalake at the beginning)
75+
- Uses [Azure Cognitive Services](https://azure.microsoft.com/en-us/products/cognitive-services/) to index and enrich unstructured documents: OCR over images, Chunking and automated vectorization.
76+
- Uses Hybrid Search Capabilities of Azure AI Search to provide the best semantic answer (Text and Vector search combined).
7477
- Uses [LangChain](https://langchain.readthedocs.io/en/latest/) as a wrapper for interacting with Azure OpenAI , vector stores, constructing prompts and creating agents.
7578
- Multi-Lingual (ingests, indexes and understand any language)
7679
- Multi-Index -> multiple search indexes
@@ -89,22 +92,20 @@ https://gptsmartsearch.azurewebsites.net/
8992
Note: (Pre-requisite) You need to have an Azure OpenAI service already created
9093

9194
1. Fork this repo to your Github account.
92-
2. In Azure OpenAI studio, deploy these models: **Make sure that the deployment name is the same as the model name.**
93-
- "gpt-35-turbo"
94-
- "gpt-35-turbo-16k"
95-
- "gpt-4"
96-
- "gpt-4-32k"
97-
- "text-embedding-ada-002"
95+
2. In Azure OpenAI studio, deploy these models (older models than the ones stated below won't work):
96+
- "gpt-35-turbo-1106 (or newer)"
97+
- "gpt-4-turbo-1106 (or newer)"
98+
- "text-embedding-ada-002 (or newer)"
9899
3. Create a Resource Group where all the assets of this accelerator are going to be. Azure OpenAI can be in different RG or a different Subscription.
99-
4. ClICK BELOW to create all the Azure Infrastructure needed to run the Notebooks (Azure Cognitive Search, Cognitive Services, etc):
100+
4. ClICK BELOW to create all the Azure Infrastructure needed to run the Notebooks (Azure AI Search, Cognitive Services, etc):
100101

101102
[![Deploy To Azure](https://aka.ms/deploytoazurebutton)](https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2Fpablomarin%2FGPT-Azure-Search-Engine%2Fmain%2Fazuredeploy.json)
102103

103104
**Note**: If you have never created a `Azure AI Services Multi-Service account` before, please create one manually in the azure portal to read and accept the Responsible AI terms. Once this is deployed, delete this and then use the above deployment button.
104105

105106
5. Clone your Forked repo to your AML Compute Instance. If your repo is private, see below in Troubleshooting section how to clone a private repo.
106107

107-
6. Make sure you run the notebooks on a **Python 3.10 conda enviroment**
108+
6. Make sure you run the notebooks on a **Python 3.10 conda enviroment** or newer
108109
7. Install the dependencies on your machine (make sure you do the below pip comand on the same conda environment that you are going to run the notebooks. For example, in AZML compute instance run:
109110
```
110111
conda activate azureml_py310_sdkv2
@@ -124,7 +125,7 @@ You might get some pip dependancies errors, but that is ok, the libraries were i
124125

125126
## **FAQs**
126127

127-
1. **Why use Azure Cognitive Search engine to provide the context for the LLM and not fine tune the LLM instead?**
128+
1. **Why use Azure AI Search engine to provide the context for the LLM and not fine tune the LLM instead?**
128129

129130
A: Quoting the [OpenAI documentation](https://platform.openai.com/docs/guides/fine-tuning): "GPT-3 has been pre-trained on a vast amount of text from the open internet. When given a prompt with just a few examples, it can often intuit what task you are trying to perform and generate a plausible completion. This is often called "few-shot learning.
130131
Fine-tuning improves on few-shot learning by training on many more examples than can fit in the prompt, letting you achieve better results on a wide number of tasks. Once a model has been fine-tuned, you won't need to provide examples in the prompt anymore. This **saves costs and enables lower-latency requests**"

apps/backend/backend.zip

3.24 KB
Binary file not shown.

apps/backend/bot.py

+69-43
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,30 @@
77
import requests
88
import json
99
from concurrent.futures import ThreadPoolExecutor
10-
from langchain.chat_models import AzureChatOpenAI
10+
from langchain_openai import AzureChatOpenAI
1111
from langchain.utilities import BingSearchAPIWrapper
12-
from langchain.memory import ConversationBufferWindowMemory
1312
from langchain.memory import CosmosDBChatMessageHistory
13+
from langchain.agents import AgentExecutor, create_openai_tools_agent
14+
from langchain_core.runnables import ConfigurableField, ConfigurableFieldSpec
15+
from langchain_core.chat_history import BaseChatMessageHistory
16+
from langchain_community.chat_message_histories import ChatMessageHistory, CosmosDBChatMessageHistory
1417
from langchain.agents import ConversationalChatAgent, AgentExecutor, Tool
1518
from typing import Any, Dict, List, Optional, Union
1619
from langchain.callbacks.base import BaseCallbackHandler
1720
from langchain.callbacks.manager import CallbackManager
1821
from langchain.schema import AgentAction, AgentFinish, LLMResult
22+
from langchain_community.chat_message_histories import ChatMessageHistory
23+
from langchain_core.runnables.history import RunnableWithMessageHistory
1924

2025
#custom libraries that we will use later in the app
21-
from utils import DocSearchAgent, CSVTabularAgent, SQLSearchAgent, ChatGPTTool, BingSearchAgent, APISearchAgent, run_agent, reduce_openapi_spec
22-
from prompts import WELCOME_MESSAGE, CUSTOM_CHATBOT_PREFIX, CUSTOM_CHATBOT_SUFFIX
26+
from utils import (
27+
DocSearchAgent,
28+
CSVTabularAgent,
29+
SQLSearchAgent,
30+
ChatGPTTool,
31+
BingSearchAgent
32+
)
33+
from prompts import CUSTOM_CHATBOT_PROMPT, WELCOME_MESSAGE
2334

2435
from botbuilder.core import ActivityHandler, TurnContext
2536
from botbuilder.schema import ChannelAccount, Activity, ActivityTypes
@@ -53,6 +64,20 @@ class MyBot(ActivityHandler):
5364

5465
def __init__(self):
5566
self.model_name = os.environ.get("AZURE_OPENAI_MODEL_NAME")
67+
68+
def get_session_history(self, session_id: str, user_id: str) -> CosmosDBChatMessageHistory:
69+
cosmos = CosmosDBChatMessageHistory(
70+
cosmos_endpoint=os.environ['AZURE_COSMOSDB_ENDPOINT'],
71+
cosmos_database=os.environ['AZURE_COSMOSDB_NAME'],
72+
cosmos_container=os.environ['AZURE_COSMOSDB_CONTAINER_NAME'],
73+
connection_string=os.environ['AZURE_COMOSDB_CONNECTION_STRING'],
74+
session_id=session_id,
75+
user_id=user_id
76+
)
77+
78+
# prepare the cosmosdb instance
79+
cosmos.prepare_cosmos()
80+
return cosmos
5681

5782
# Function to show welcome message to new users
5883
async def on_members_added_activity(self, members_added: ChannelAccount, turn_context: TurnContext):
@@ -67,6 +92,7 @@ async def on_message_activity(self, turn_context: TurnContext):
6792
# Extract info from TurnContext - You can change this to whatever , this is just one option
6893
session_id = turn_context.activity.conversation.id
6994
user_id = turn_context.activity.from_property.id + "-" + turn_context.activity.channel_id
95+
7096
input_text_metadata = dict()
7197
input_text_metadata["local_timestamp"] = turn_context.activity.local_timestamp.strftime("%I:%M:%S %p, %A, %B %d of %Y")
7298
input_text_metadata["local_timezone"] = turn_context.activity.local_timezone
@@ -80,55 +106,55 @@ async def on_message_activity(self, turn_context: TurnContext):
80106
cb_manager = CallbackManager(handlers=[cb_handler])
81107

82108
# Set LLM
83-
llm = AzureChatOpenAI(deployment_name=self.model_name, temperature=0.5, max_tokens=1000, callback_manager=cb_manager)
109+
llm = AzureChatOpenAI(deployment_name=self.model_name, temperature=0.5,
110+
max_tokens=1500, callback_manager=cb_manager, streaming=True)
84111

85112
# Initialize our Tools/Experts
86-
text_indexes = ["cogsrch-index-files", "cogsrch-index-csv"]
113+
indexes = ["cogsrch-index-files", "cogsrch-index-csv", "cogsrch-index-books"]
114+
87115
doc_search = DocSearchAgent(llm=llm, indexes=text_indexes,
88-
k=10, similarity_k=4, reranker_th=1,
89-
sas_token=os.environ['BLOB_SAS_TOKEN'],
90-
callback_manager=cb_manager, return_direct=True)
91-
vector_only_indexes = ["cogsrch-index-books-vector"]
92-
book_search = DocSearchAgent(llm=llm, vector_only_indexes = vector_only_indexes,
93-
k=10, similarity_k=10, reranker_th=1,
116+
k=6, reranker_th=1,
94117
sas_token=os.environ['BLOB_SAS_TOKEN'],
95-
callback_manager=cb_manager, return_direct=True,
96-
name="@booksearch",
97-
description="useful when the questions includes the term: @booksearch.\n")
98-
www_search = BingSearchAgent(llm=llm, k=5, callback_manager=cb_manager, return_direct=True)
99-
sql_search = SQLSearchAgent(llm=llm, k=10, callback_manager=cb_manager, return_direct=True)
100-
chatgpt_search = ChatGPTTool(llm=llm, callback_manager=cb_manager, return_direct=True)
118+
callback_manager=cb_manager, verbose=False)
101119

102-
url = 'https://disease.sh/apidocs/swagger_v3.json'
103-
spec = requests.get(url).json()
104-
105-
api_search = APISearchAgent(llm=llm,
106-
llm_search=AzureChatOpenAI(deployment_name="gpt-35-turbo-16k", temperature=0, max_tokens=1000),
107-
api_spec=str(reduce_openapi_spec(spec)),
108-
limit_to_domains=["https://disease.sh/"],
109-
callback_manager=cb_manager, return_direct=True)
110-
111-
tools = [www_search, sql_search, doc_search, chatgpt_search, book_search, api_search]
112-
113-
# Set brain Agent with persisten memory in CosmosDB
114-
cosmos = CosmosDBChatMessageHistory(
115-
cosmos_endpoint=os.environ['AZURE_COSMOSDB_ENDPOINT'],
116-
cosmos_database=os.environ['AZURE_COSMOSDB_NAME'],
117-
cosmos_container=os.environ['AZURE_COSMOSDB_CONTAINER_NAME'],
118-
connection_string=os.environ['AZURE_COMOSDB_CONNECTION_STRING'],
119-
session_id=session_id,
120-
user_id=user_id
121-
)
122-
cosmos.prepare_cosmos()
123-
memory = ConversationBufferWindowMemory(memory_key="chat_history", return_messages=True, k=30, chat_memory=cosmos)
124-
agent = ConversationalChatAgent.from_llm_and_tools(llm=llm, tools=tools,system_message=CUSTOM_CHATBOT_PREFIX,human_message=CUSTOM_CHATBOT_SUFFIX)
125-
agent_chain = AgentExecutor.from_agent_and_tools(agent=agent, tools=tools, memory=memory, handle_parsing_errors=True)
120+
www_search = BingSearchAgent(llm=llm, k=5, callback_manager=cb_manager)
121+
sql_search = SQLSearchAgent(llm=llm, k=30, callback_manager=cb_manager)
122+
chatgpt_search = ChatGPTTool(llm=llm, callback_manager=cb_manager)
123+
124+
tools = [doc_search, www_search, sql_search, chatgpt_search]
125+
126+
agent = create_openai_tools_agent(llm, tools, CUSTOM_CHATBOT_PROMPT)
127+
agent_executor = AgentExecutor(agent=agent, tools=tools)
128+
brain_agent_executor = RunnableWithMessageHistory(
129+
agent_executor,
130+
get_session_history,
131+
input_messages_key="question",
132+
history_messages_key="history",
133+
history_factory_config=[
134+
ConfigurableFieldSpec(
135+
id="user_id",
136+
annotation=str,
137+
name="User ID",
138+
description="Unique identifier for the user.",
139+
default="",
140+
is_shared=True,
141+
),
142+
ConfigurableFieldSpec(
143+
id="session_id",
144+
annotation=str,
145+
name="Session ID",
146+
description="Unique identifier for the conversation.",
147+
default="",
148+
is_shared=True,
149+
),
150+
],
151+
)
126152

127153
await turn_context.send_activity(Activity(type=ActivityTypes.typing))
128154

129155
# Please note below that running a non-async function like run_agent in a separate thread won't make it truly asynchronous. It allows the function to be called without blocking the event loop, but it may still have synchronous behavior internally.
130156
loop = asyncio.get_event_loop()
131-
answer = await loop.run_in_executor(ThreadPoolExecutor(), run_agent, input_text, agent_chain)
157+
answer = brain_agent_executor.invoke({"question": input_text}, config=config)["output"]
132158

133159
await turn_context.send_activity(answer)
134160

common/callbacks.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,13 @@ def on_llm_error(self, error: Union[Exception, KeyboardInterrupt], **kwargs: Any
2020
"""Run when LLM errors."""
2121
sys.stdout.write(f"LLM Error: {error}\n")
2222

23-
def on_chain_start(self, serialized: Dict[str, Any], inputs: Dict[str, Any], **kwargs: Any) -> Any:
24-
"""Print out that we are entering a chain."""
25-
2623
def on_tool_start(self, serialized: Dict[str, Any], input_str: str, **kwargs: Any) -> Any:
2724
sys.stdout.write(f"Tool: {serialized['name']}\n")
28-
25+
26+
def on_retriever_start(self, serialized: Dict[str, Any], query: str) -> Any:
27+
sys.stdout.write(f"Retriever: {serialized}\n")
28+
2929
def on_agent_action(self, action: AgentAction, **kwargs: Any) -> Any:
30-
sys.stdout.write(f"{action.log}\n")
30+
sys.stdout.write(f"Agent Action: {action.log}\n")
3131

3232

0 commit comments

Comments
 (0)