Skip to content

Commit 6595fdf

Browse files
committed
Make the grounding backend generic
1 parent 7c93eb3 commit 6595fdf

17 files changed

+95
-89
lines changed

app/backend/app.py

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -54,21 +54,21 @@
5454
from approaches.promptmanager import PromptyManager
5555
from approaches.retrievethenread import RetrieveThenReadApproach
5656
from approaches.retrievethenreadvision import RetrieveThenReadVisionApproach
57-
from bing_client import AsyncBingClient
57+
from search_client import AsyncGroundingSearchClient
5858
from chat_history.cosmosdb import chat_history_cosmosdb_bp
5959
from config import (
6060
CONFIG_ASK_APPROACH,
6161
CONFIG_ASK_VISION_APPROACH,
6262
CONFIG_AUTH_CLIENT,
63-
CONFIG_BING_SEARCH_CLIENT,
64-
CONFIG_BING_SEARCH_ENABLED,
6563
CONFIG_BLOB_CONTAINER_CLIENT,
6664
CONFIG_CHAT_APPROACH,
6765
CONFIG_CHAT_HISTORY_BROWSER_ENABLED,
6866
CONFIG_CHAT_HISTORY_COSMOS_ENABLED,
6967
CONFIG_CHAT_VISION_APPROACH,
7068
CONFIG_CREDENTIAL,
7169
CONFIG_GPT4V_DEPLOYED,
70+
CONFIG_GROUNDING_SEARCH_CLIENT,
71+
CONFIG_GROUNDING_SEARCH_ENABLED,
7272
CONFIG_INGESTER,
7373
CONFIG_LANGUAGE_PICKER_ENABLED,
7474
CONFIG_OPENAI_CLIENT,
@@ -302,7 +302,7 @@ def config():
302302
"showSpeechOutputAzure": current_app.config[CONFIG_SPEECH_OUTPUT_AZURE_ENABLED],
303303
"showChatHistoryBrowser": current_app.config[CONFIG_CHAT_HISTORY_BROWSER_ENABLED],
304304
"showChatHistoryCosmos": current_app.config[CONFIG_CHAT_HISTORY_COSMOS_ENABLED],
305-
"showBingSearchOption": current_app.config[CONFIG_BING_SEARCH_ENABLED],
305+
"showGroundingSearchOption": current_app.config[CONFIG_GROUNDING_SEARCH_ENABLED],
306306
}
307307
)
308308

@@ -470,9 +470,9 @@ async def setup_clients():
470470
USE_SPEECH_OUTPUT_AZURE = os.getenv("USE_SPEECH_OUTPUT_AZURE", "").lower() == "true"
471471
USE_CHAT_HISTORY_BROWSER = os.getenv("USE_CHAT_HISTORY_BROWSER", "").lower() == "true"
472472
USE_CHAT_HISTORY_COSMOS = os.getenv("USE_CHAT_HISTORY_COSMOS", "").lower() == "true"
473-
USE_BING_SEARCH = os.getenv("USE_BING_SEARCH", "").lower() == "true"
474-
BING_SEARCH_API_KEY = os.getenv("BING_SEARCH_API_KEY")
475-
BING_SEARCH_ENDPOINT = os.getenv("BING_SEARCH_ENDPOINT")
473+
USE_GROUNDING_SEARCH = os.getenv("USE_GROUNDING_SEARCH", "").lower() == "true"
474+
GROUNDING_SEARCH_API_KEY = os.getenv("GROUNDING_SEARCH_API_KEY")
475+
GROUNDING_SEARCH_ENDPOINT = os.getenv("GROUNDING_SEARCH_ENDPOINT")
476476

477477
# WEBSITE_HOSTNAME is always set by App Service, RUNNING_IN_PRODUCTION is set in main.bicep
478478
RUNNING_ON_AZURE = os.getenv("WEBSITE_HOSTNAME") is not None or os.getenv("RUNNING_IN_PRODUCTION") is not None
@@ -595,18 +595,18 @@ async def setup_clients():
595595
# Wait until token is needed to fetch for the first time
596596
current_app.config[CONFIG_SPEECH_SERVICE_TOKEN] = None
597597

598-
if USE_BING_SEARCH:
599-
current_app.logger.info("USE_BING_SEARCH is true, setting up Bing search client")
600-
if not BING_SEARCH_API_KEY:
601-
raise ValueError("BING_SEARCH_API_KEY must be set when USE_BING_SEARCH is true")
602-
if BING_SEARCH_ENDPOINT:
603-
bing_search_client = AsyncBingClient(BING_SEARCH_API_KEY, BING_SEARCH_ENDPOINT)
598+
if USE_GROUNDING_SEARCH:
599+
current_app.logger.info("USE_GROUNDING_SEARCH is true, setting up search client")
600+
if not GROUNDING_SEARCH_API_KEY:
601+
raise ValueError("GROUNDING_SEARCH_API_KEY must be set when USE_GROUNDING_SEARCH is true")
602+
if GROUNDING_SEARCH_ENDPOINT:
603+
grounding_search_client = AsyncGroundingSearchClient(GROUNDING_SEARCH_API_KEY, GROUNDING_SEARCH_ENDPOINT)
604604
else:
605-
bing_search_client = AsyncBingClient(BING_SEARCH_API_KEY)
606-
current_app.config[CONFIG_BING_SEARCH_CLIENT] = bing_search_client
605+
grounding_search_client = AsyncGroundingSearchClient(GROUNDING_SEARCH_API_KEY)
606+
current_app.config[CONFIG_GROUNDING_SEARCH_CLIENT] = grounding_search_client
607607
else:
608-
current_app.logger.info("USE_BING_SEARCH is false, Bing search client not set up")
609-
bing_search_client = None
608+
current_app.logger.info("USE_GROUNDING_SEARCH is false, search client not set up")
609+
grounding_search_client = None
610610

611611
if OPENAI_HOST.startswith("azure"):
612612
if OPENAI_HOST == "azure_custom":
@@ -662,7 +662,7 @@ async def setup_clients():
662662
current_app.config[CONFIG_SPEECH_OUTPUT_AZURE_ENABLED] = USE_SPEECH_OUTPUT_AZURE
663663
current_app.config[CONFIG_CHAT_HISTORY_BROWSER_ENABLED] = USE_CHAT_HISTORY_BROWSER
664664
current_app.config[CONFIG_CHAT_HISTORY_COSMOS_ENABLED] = USE_CHAT_HISTORY_COSMOS
665-
current_app.config[CONFIG_BING_SEARCH_ENABLED] = USE_BING_SEARCH
665+
current_app.config[CONFIG_GROUNDING_SEARCH_ENABLED] = USE_GROUNDING_SEARCH
666666

667667
prompt_manager = PromptyManager()
668668

@@ -699,7 +699,7 @@ async def setup_clients():
699699
query_language=AZURE_SEARCH_QUERY_LANGUAGE,
700700
query_speller=AZURE_SEARCH_QUERY_SPELLER,
701701
prompt_manager=prompt_manager,
702-
bing_client=bing_search_client,
702+
grounding_search_client=grounding_search_client,
703703
)
704704

705705
if USE_GPT4V:
@@ -746,7 +746,7 @@ async def setup_clients():
746746
query_language=AZURE_SEARCH_QUERY_LANGUAGE,
747747
query_speller=AZURE_SEARCH_QUERY_SPELLER,
748748
prompt_manager=prompt_manager,
749-
bing_client=bing_search_client,
749+
grounding_search_client=grounding_search_client,
750750
)
751751

752752

app/backend/approaches/approach.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
from openai.types.chat import ChatCompletionMessageParam
2626

2727
from approaches.promptmanager import PromptManager
28-
from bing_client import WebPage
28+
from app.backend.search_client import WebPage
2929
from core.authentication import AuthenticationHelper
3030

3131

app/backend/approaches/chatreadretrieveread.py

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
from approaches.approach import Document, ThoughtStep
1515
from approaches.chatapproach import ChatApproach
1616
from approaches.promptmanager import PromptManager
17-
from bing_client import AsyncBingClient, WebPage
17+
from search_client import AsyncGroundingSearchClient, WebPage
1818
from core.authentication import AuthenticationHelper
1919

2020

@@ -41,11 +41,11 @@ def __init__(
4141
query_language: str,
4242
query_speller: str,
4343
prompt_manager: PromptManager,
44-
bing_client: Optional[AsyncBingClient] = None,
44+
grounding_search_client: Optional[AsyncGroundingSearchClient] = None,
4545
):
4646
self.search_client = search_client
4747
self.openai_client = openai_client
48-
self.bing_client = bing_client
48+
self.grounding_search_client = grounding_search_client
4949
self.auth_helper = auth_helper
5050
self.chatgpt_model = chatgpt_model
5151
self.chatgpt_deployment = chatgpt_deployment
@@ -61,9 +61,9 @@ def __init__(
6161
self.query_rewrite_prompt = self.prompt_manager.load_prompt("chat_query_rewrite.prompty")
6262
self.query_rewrite_tools = self.prompt_manager.load_tools("chat_query_rewrite_tools.json")
6363
self.answer_prompt = self.prompt_manager.load_prompt("chat_answer_question.prompty")
64-
self.bing_answer_prompt = self.prompt_manager.load_prompt("chat_bing_answer_question.prompty")
65-
self.bing_ground_rewrite_prompt = self.prompt_manager.load_prompt("chat_bing_ground_rewrite.prompty")
66-
self.bing_ground_rewrite_tools = self.prompt_manager.load_tools("chat_bing_ground_rewrite_tools.json")
64+
self.ground_answer_prompt = self.prompt_manager.load_prompt("chat_ground_answer_question.prompty")
65+
self.ground_rewrite_prompt = self.prompt_manager.load_prompt("chat_ground_rewrite.prompty")
66+
self.ground_rewrite_tools = self.prompt_manager.load_tools("chat_ground_rewrite_tools.json")
6767

6868
@overload
6969
async def run_until_final_call(
@@ -95,7 +95,7 @@ async def run_until_final_call(
9595
use_vector_search = overrides.get("retrieval_mode") in ["vectors", "hybrid", None]
9696
use_semantic_ranker = True if overrides.get("semantic_ranker") else False
9797
use_semantic_captions = True if overrides.get("semantic_captions") else False
98-
use_bing_search = True if overrides.get("use_bing_search") else False
98+
use_grounding_search = True if overrides.get("use_grounding_search") else False
9999
top = overrides.get("top", 3)
100100
minimum_search_score = overrides.get("minimum_search_score", 0.0)
101101
minimum_reranker_score = overrides.get("minimum_reranker_score", 0.0)
@@ -137,13 +137,13 @@ async def keyword_rewrite(rendered_prompt, tools):
137137
)
138138
tools: List[ChatCompletionToolParam] = self.query_rewrite_tools
139139
query_messages, query_text = await keyword_rewrite(rendered_query_prompt, tools)
140-
if use_bing_search and self.bing_client:
141-
bing_search_prompt = self.prompt_manager.render_prompt(
142-
self.bing_ground_rewrite_prompt,
140+
if use_grounding_search and self.grounding_search_client:
141+
ground_search_prompt = self.prompt_manager.render_prompt(
142+
self.ground_rewrite_prompt,
143143
{"user_query": original_user_query, "past_messages": messages[:-1]},
144144
)
145-
_, bing_query_text = await keyword_rewrite(bing_search_prompt, self.bing_ground_rewrite_tools)
146-
bing_results = await self.bing_client.search(bing_query_text, lang=self.query_language)
145+
_, ground_query_text = await keyword_rewrite(ground_search_prompt, self.ground_rewrite_tools)
146+
ground_results = await self.grounding_search_client.search(ground_query_text, lang=self.query_language)
147147

148148
# STEP 2: Retrieve relevant documents from the search index with the GPT optimized query
149149

@@ -168,12 +168,12 @@ async def keyword_rewrite(rendered_prompt, tools):
168168
# STEP 3: Generate a contextual and content specific answer using the search results and chat history
169169
text_sources = self.get_sources_content(results, use_semantic_captions, use_image_citation=False)
170170
web_sources: list[WebPage] = []
171-
if use_bing_search and bing_results.totalEstimatedMatches > 0:
172-
web_sources = bing_results.value[:2]
171+
if use_grounding_search and ground_results.totalEstimatedMatches > 0:
172+
web_sources = ground_results.value[:2]
173173
web_sources_text = self.get_links(web_sources)
174174

175175
rendered_answer_prompt = self.prompt_manager.render_prompt(
176-
self.bing_answer_prompt,
176+
self.ground_answer_prompt,
177177
self.get_system_prompt_variables(overrides.get("prompt_template"))
178178
| {
179179
"include_follow_up_questions": bool(overrides.get("suggest_followup_questions")),
@@ -217,10 +217,10 @@ async def keyword_rewrite(rendered_prompt, tools):
217217
else {"model": self.chatgpt_model}
218218
),
219219
),
220-
ThoughtStep("Bing search query", bing_query_text if use_bing_search else None, {}),
220+
ThoughtStep("Grounding search query", ground_query_text if use_grounding_search else None, {}),
221221
ThoughtStep(
222-
"Bing search results",
223-
[result.snippet for result in bing_results.value[:2]] if use_bing_search else None,
222+
"Grounding search results",
223+
[result.snippet for result in ground_results.value[:2]] if use_grounding_search else None,
224224
),
225225
ThoughtStep(
226226
"Search using generated search query",

app/backend/approaches/chatreadretrievereadvision.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
from approaches.approach import ThoughtStep
1515
from approaches.chatapproach import ChatApproach
1616
from approaches.promptmanager import PromptManager
17-
from bing_client import AsyncBingClient
17+
from search_client import AsyncGroundingSearchClient
1818
from core.authentication import AuthenticationHelper
1919
from core.imageshelper import fetch_image
2020

@@ -47,12 +47,12 @@ def __init__(
4747
vision_endpoint: str,
4848
vision_token_provider: Callable[[], Awaitable[str]],
4949
prompt_manager: PromptManager,
50-
bing_client: Optional[AsyncBingClient] = None,
50+
grounding_search_client: Optional[AsyncGroundingSearchClient] = None,
5151
):
5252
self.search_client = search_client
5353
self.blob_container_client = blob_container_client
5454
self.openai_client = openai_client
55-
self.bing_client = bing_client
55+
self.grounding_search_client = grounding_search_client
5656
self.auth_helper = auth_helper
5757
self.chatgpt_model = chatgpt_model
5858
self.chatgpt_deployment = chatgpt_deployment
@@ -85,7 +85,6 @@ async def run_until_final_call(
8585
use_vector_search = overrides.get("retrieval_mode") in ["vectors", "hybrid", None]
8686
use_semantic_ranker = True if overrides.get("semantic_ranker") else False
8787
use_semantic_captions = True if overrides.get("semantic_captions") else False
88-
# use_bing_search = True if overrides.get("use_bing_search") else False
8988
top = overrides.get("top", 3)
9089
minimum_search_score = overrides.get("minimum_search_score", 0.0)
9190
minimum_reranker_score = overrides.get("minimum_reranker_score", 0.0)
File renamed without changes.

app/backend/approaches/prompts/chat_bing_ground_rewrite.prompty renamed to app/backend/approaches/prompts/chat_ground_rewrite.prompty

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ description: Suggest the optimal search query based on the user's query, example
44
model:
55
api: chat
66
parameters:
7-
tools: ${file:chat_query_rewrite_tools.json}
7+
tools: ${file:chat_ground_rewrite_tools.json}
88
sample:
99
user_query: Does it include hearing?
1010
past_messages:
@@ -15,7 +15,7 @@ sample:
1515
---
1616
system:
1717
Below is a history of the conversation so far, and a new question asked by the user that needs to be answered by searching in a knowledge base and/or a web search.
18-
If the user question requires grounding from an Internet search, generate a Bing search query based on the conversation and the new question.
18+
If the user question requires grounding from an Internet search, generate an Internet search query based on the conversation and the new question.
1919
If you cannot generate a search query, return just the number 0.
2020

2121
user:
@@ -48,4 +48,4 @@ Microsoft headquarters address
4848
{% endfor %}
4949

5050
user:
51-
Generate Bing search query for: {{ user_query }}
51+
Generate Grounding search query for: {{ user_query }}
Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
[{
22
"type": "function",
33
"function": {
4-
"name": "search_bing",
5-
"description": "Retrieve sources from Bing",
4+
"name": "search_internet",
5+
"description": "Retrieve sources from the Internet",
66
"parameters": {
77
"type": "object",
88
"properties": {
9-
"bing_search_query": {
9+
"internet_search_query": {
1010
"type": "string",
11-
"description": "Query string to retrieve documents from bing e.g.: 'Microsoft headquarters address'"
11+
"description": "Query string to retrieve documents from an Internet search e.g.: 'Microsoft headquarters address'"
1212
}
1313
},
14-
"required": ["bing_search_query"]
14+
"required": ["internet_search_query"]
1515
}
1616
}
1717
}]

app/backend/approaches/retrievethenread.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,6 @@ async def run(
6868
use_vector_search = overrides.get("retrieval_mode") in ["vectors", "hybrid", None]
6969
use_semantic_ranker = True if overrides.get("semantic_ranker") else False
7070
use_semantic_captions = True if overrides.get("semantic_captions") else False
71-
# use_bing_search = True if overrides.get("use_bing_search") else False
7271
top = overrides.get("top", 3)
7372
minimum_search_score = overrides.get("minimum_search_score", 0.0)
7473
minimum_reranker_score = overrides.get("minimum_reranker_score", 0.0)

app/backend/approaches/retrievethenreadvision.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,6 @@ async def run(
7777
use_vector_search = overrides.get("retrieval_mode") in ["vectors", "hybrid", None]
7878
use_semantic_ranker = True if overrides.get("semantic_ranker") else False
7979
use_semantic_captions = True if overrides.get("semantic_captions") else False
80-
# use_bing_search = True if overrides.get("use_bing_search") else False
8180
top = overrides.get("top", 3)
8281
minimum_search_score = overrides.get("minimum_search_score", 0.0)
8382
minimum_reranker_score = overrides.get("minimum_reranker_score", 0.0)

app/backend/config.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,5 +26,5 @@
2626
CONFIG_CHAT_HISTORY_COSMOS_ENABLED = "chat_history_cosmos_enabled"
2727
CONFIG_COSMOS_HISTORY_CLIENT = "cosmos_history_client"
2828
CONFIG_COSMOS_HISTORY_CONTAINER = "cosmos_history_container"
29-
CONFIG_BING_SEARCH_ENABLED = "bing_search_enabled"
30-
CONFIG_BING_SEARCH_CLIENT = "bing_search_client"
29+
CONFIG_GROUNDING_SEARCH_ENABLED = "grounding_search_enabled"
30+
CONFIG_GROUNDING_SEARCH_CLIENT = "grounding_search_client"

0 commit comments

Comments
 (0)