Skip to content

Python: Added Brave search capability in SK(python) based on PR #9632 #11531

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 21 commits into from
Apr 21, 2025
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
269ad41
Python:Remove duplicate log statement in GoogleConnector search method
N-E-W-T-O-N Apr 12, 2025
425344d
Python: Add BraveConnector and BraveSettings for Brave Search API int…
N-E-W-T-O-N Apr 12, 2025
2d54af6
Python: Implement Brave Search API connector with settings and respon…
N-E-W-T-O-N Apr 13, 2025
8633977
Python: Add Brave Search plugin for Semantic Kernel chat bot integration
N-E-W-T-O-N Apr 13, 2025
2ca5f25
Python: Add BraveConnector and BraveSearch test fixtures and unit tests
N-E-W-T-O-N Apr 13, 2025
8495c86
Minor Fix
N-E-W-T-O-N Apr 13, 2025
b7c6d43
Merge branch 'microsoft:main' into pySearch
N-E-W-T-O-N Apr 15, 2025
b5296f0
Remove BraveConnector and related settings from search engine connectors
N-E-W-T-O-N Apr 15, 2025
f9e3117
PYTHON:Refactors Brave Search connector structure
N-E-W-T-O-N Apr 15, 2025
b7444a3
Python:Add Brave Text Search plugin to README and fix import path in …
N-E-W-T-O-N Apr 15, 2025
2935e71
Python:Refactor import statements in test_brave_search.py based on ne…
N-E-W-T-O-N Apr 15, 2025
db5bdd2
Python:Rename 'brave_search.py' to 'brave.py' and update the referenc…
N-E-W-T-O-N Apr 15, 2025
5061982
Python:Add BRAVE_API_KEY to .env.example for configuration
N-E-W-T-O-N Apr 15, 2025
8206388
Merge branch 'microsoft:main' into pySearch
N-E-W-T-O-N Apr 16, 2025
167b637
Merge branch 'microsoft:main' into pySearch
N-E-W-T-O-N Apr 17, 2025
76f2028
Python:Added project description in Brave Text Search plugin
N-E-W-T-O-N Apr 17, 2025
60a355a
Python:Fix typo in BraveSettings region header and improve total coun…
N-E-W-T-O-N Apr 17, 2025
4c0ed7d
Merge branch 'main' into pySearch
N-E-W-T-O-N Apr 17, 2025
d76a25a
Merge branch 'main' into pySearch
N-E-W-T-O-N Apr 17, 2025
23b825e
Merge branch 'main' into pySearch
moonbox3 Apr 18, 2025
a26bfb2
CI: retrigger
N-E-W-T-O-N Apr 18, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions python/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ POSTGRES_CONNECTION_STRING=""
WEAVIATE_URL=""
WEAVIATE_API_KEY=""
GOOGLE_SEARCH_ENGINE_ID=""
BRAVE_API_KEY=""
REDIS_CONNECTION_STRING=""
AZCOSMOS_API=""
AZCOSMOS_CONNSTR=""
Expand Down
1 change: 1 addition & 0 deletions python/samples/concepts/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,7 @@
### Search - Using [`Search`](https://github.com/microsoft/semantic-kernel/tree/main/python/semantic_kernel/connectors/search) services information

- [Bing Text Search as Plugin](./search/bing_text_search_as_plugin.py)
- [Brave Text Search as Plugin](./search/brave_text_search_as_plugin.py)
- [Google Text Search as Plugin](./search/google_text_search_as_plugin.py)

### Service Selector - Shows how to create and use a custom service selector class
Expand Down
135 changes: 135 additions & 0 deletions python/samples/concepts/search/brave_text_search_as_plugin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
# Copyright (c) Microsoft. All rights reserved.

from collections.abc import Awaitable, Callable

from semantic_kernel import Kernel
from semantic_kernel.connectors.ai import FunctionChoiceBehavior
from semantic_kernel.connectors.ai.open_ai import OpenAIChatCompletion, OpenAIChatPromptExecutionSettings
from semantic_kernel.connectors.search.brave import BraveSearch
from semantic_kernel.contents import ChatHistory
from semantic_kernel.filters import FilterTypes, FunctionInvocationContext
from semantic_kernel.functions import KernelArguments, KernelParameterMetadata, KernelPlugin

"""
This project demonstrates how to integrate the Brave Search API as a plugin into the Semantic Kernel
framework to enable conversational AI capabilities with real-time web information.

To use Brave Search, you need an API key, which can be obtained by login to
https://api-dashboard.search.brave.com/ and creating a subscription key.
After that store it under the name `BRAVE_API_KEY` in a .env file or your environment variables.
"""

kernel = Kernel()
kernel.add_service(OpenAIChatCompletion(service_id="chat"))
kernel.add_plugin(
KernelPlugin.from_text_search_with_search(
BraveSearch(),
plugin_name="brave",
description="Get details about Semantic Kernel concepts.",
parameters=[
KernelParameterMetadata(
name="query",
description="The search query.",
type="str",
is_required=True,
type_object=str,
),
KernelParameterMetadata(
name="top",
description="The number of results to return.",
type="int",
is_required=False,
default_value=2,
type_object=int,
),
KernelParameterMetadata(
name="skip",
description="The number of results to skip.",
type="int",
is_required=False,
default_value=0,
type_object=int,
),
],
)
)
chat_function = kernel.add_function(
prompt="{{$chat_history}}{{$user_input}}",
plugin_name="ChatBot",
function_name="Chat",
)
execution_settings = OpenAIChatPromptExecutionSettings(
service_id="chat",
max_tokens=2000,
temperature=0.7,
top_p=0.8,
function_choice_behavior=FunctionChoiceBehavior.Auto(auto_invoke=True),
)

history = ChatHistory()
system_message = """
You are a chat bot, specialized in Semantic Kernel, Microsoft LLM orchestration SDK.
Assume questions are related to that, and use the Brave search plugin to find answers.
"""
history.add_system_message(system_message)
history.add_user_message("Hi there, who are you?")
history.add_assistant_message("I am Mosscap, a chat bot. I'm trying to figure out what people need.")

arguments = KernelArguments(settings=execution_settings)


@kernel.filter(filter_type=FilterTypes.FUNCTION_INVOCATION)
async def log_brave_filter(
context: FunctionInvocationContext, next: Callable[[FunctionInvocationContext], Awaitable[None]]
):
if context.function.plugin_name == "brave":
print("Calling Brave search with arguments:")
if "query" in context.arguments:
print(f' Query: "{context.arguments["query"]}"')
if "count" in context.arguments:
print(f' Count: "{context.arguments["count"]}"')
if "skip" in context.arguments:
print(f' Skip: "{context.arguments["skip"]}"')
await next(context)
print("Brave search completed.")
else:
await next(context)


async def chat() -> bool:
try:
user_input = input("User:> ")
except KeyboardInterrupt:
print("\n\nExiting chat...")
return False
except EOFError:
print("\n\nExiting chat...")
return False

if user_input == "exit":
print("\n\nExiting chat...")
return False
arguments["user_input"] = user_input
arguments["chat_history"] = history
result = await kernel.invoke(chat_function, arguments=arguments)
print(f"Mosscap:> {result}")
history.add_user_message(user_input)
history.add_assistant_message(str(result))
return True


async def main():
chatting = True
print(
"Welcome to the chat bot!\
\n Type 'exit' to exit.\
\n Try to find out more about the inner workings of Semantic Kernel."
)
while chatting:
chatting = await chat()


if __name__ == "__main__":
import asyncio

asyncio.run(main())
Loading
Loading