Skip to content
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

SharePoint Plugin added #125

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
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
4 changes: 3 additions & 1 deletion app/plugins/loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from app.plugins.airtable.handler import Airtable
from app.plugins.website.handler import Website
from app.plugins.document.handler import Document
from app.plugins.sharepoint.handler import SharePoint
from loguru import logger

class DSLoader:
Expand All @@ -17,7 +18,8 @@ def load_ds(self):
"bigquery": Bigquery,
"airtable": Airtable,
"website": Website,
"document" : Document,
"document": Document,
"sharepoint": SharePoint,
}
db_type = self.config.get("type")
connection_params = self.config.get("params")
Expand Down
99 changes: 99 additions & 0 deletions app/plugins/sharepoint/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
from app.models.prompt import Prompt
from collections import OrderedDict
from app.models.request import ConnectionArgument

# Plugin Metadata
__version__ = '1.0.0'
__plugin_name__ = 'sharepoint'
__display_name__ = 'SharePoint Loader'
__description__ = 'SharePoint integration for handling SharePoint data'
__icon__ = '/assets/plugins/logos/sharepoint.svg'
__category__ = 2

# Connection arguments
__connection_args__ = OrderedDict(
sharepoint_site_url=ConnectionArgument(
type=4,
generic_name='SharePoint Site URL',
description='URL of the SharePoint site',
order=1,
required=True,
value=None,
slug="sharepoint_site_url"
),
client_id=ConnectionArgument(
type=1,
generic_name='Client ID',
description='Client ID for authentication',
order=2,
required=True,
value=None,
slug="client_id"
),
client_secret=ConnectionArgument(
type=1,
generic_name='Client Secret',
description='Client Secret for authentication',
order=3,
required=True,
value=None,
slug="client_secret"
),
tenant_id=ConnectionArgument(
type=1,
generic_name='Tenant ID',
description='Tenant ID for SharePoint',
order=4,
required=False,
value=None,
slug="tenant_id"
)
)

# Prompt
__prompt__ = Prompt(**{
"base_prompt": "{system_prompt}{user_prompt}",
"system_prompt": {
"template": """
You are a Chatbot designed to answer user questions based only on the context given to you.
Use the details enclosed in `[context][/context]` to generate answers.

[context]
{context}
[/context]

Adhere to these rules while generating queries:
- Deliberately go through the question and context word by word to appropriately answer the question.
"""
},
"user_prompt": {
"template": """
User question is "$question"
generate a JSON in the following format without any formatting.
{
"explanation": "Explain how you finalized the query using the schemas and rules provided",
"operation_kind": "none",
"general_message": "Answer to user question based on the context",
"confidence": "confidence in 100",
"main_entity": "document"
}
"""
},
"regeneration_prompt": {
"template": """
User question is "$question"
generate a JSON in the following format without any formatting.
{
"explanation": "Explain how you finalized the query using the schemas and rules provided",
"operation_kind": "none",
"general_message": "Answer to user question based on the context",
"confidence": "confidence in 100",
"main_entity": "document"
}
"""
}
})

__all__ = [
__version__, __plugin_name__, __display_name__, __description__, __icon__, __category__, __prompt__
]
30 changes: 30 additions & 0 deletions app/plugins/sharepoint/formatter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
from typing import Any, Dict
from loguru import logger

class Formatter:
"""
SharePointFormatter class to format the response based on the inference and data.
"""

def format(self, data: Dict[str, Any], inference: Dict[str, Any]) -> dict:
"""
Format the response using the given data and inference information.

:param data: The data containing records to process.
:param inference: Inference details including main entity and operation kind.
:return: Formatted response dictionary.
"""

logger.info("Processing SharePoint output using inference details")

response = {}
self.main_entity = inference.get("main_entity", "")
self.kind = inference.get("operation_kind", "")
self.general_message = inference.get("general_message", "Unable to process question, try again")

response["content"] = self.general_message
response["main_entity"] = self.main_entity
response["main_format"] = self.kind
response["role"] = "assistant"

return response
83 changes: 83 additions & 0 deletions app/plugins/sharepoint/handler.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
from .formatter import Formatter
from loguru import logger
import requests
from app.base.base_plugin import BasePlugin
from app.base.remote_data_plugin import RemoteDataPlugin
from app.base.plugin_metadata_mixin import PluginMetadataMixin
from typing import Tuple, Optional
from app.readers.base_reader import BaseReader

class SharePoint(BasePlugin, PluginMetadataMixin, RemoteDataPlugin, Formatter):
"""
SharePoint class for interacting with SharePoint data.
"""

def __init__(self, site_url: str, client_id: str, client_secret: str, tenant_id: str):
super().__init__(__name__)

self.connection = {}

# SharePoint connection parameters
self.params = {
'site_url': site_url,
'client_id': client_id,
'client_secret': client_secret,
'tenant_id': tenant_id,
}

def connect(self) -> Tuple[bool, Optional[str]]:
"""
Establish a connection to the SharePoint site using the provided credentials.

:return: Tuple containing connection status (True/False) and an error message if any.
"""
logger.info("Attempting to connect to SharePoint site")

try:
# Mocking connection setup to SharePoint
# You might need to implement OAuth authentication here to get an access token
# For example, you could use Microsoft's Authentication Library (MSAL) or similar
logger.info("Successfully connected to SharePoint")
return True, None
except Exception as e:
logger.exception(f"Failed to connect to SharePoint: {str(e)}")
return False, str(e)

def healthcheck(self) -> Tuple[bool, Optional[str]]:
"""
Perform a health check by checking if the SharePoint site is accessible.

:return: Tuple containing the health status (True/False) and error message (if any).
"""
logger.info("Performing health check for SharePoint")

site_url = self.params["site_url"]

try:
# Replace with actual SharePoint endpoint check if necessary

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

health check should also validate the credentials

response = requests.get(site_url)
if response.status_code == 200:
logger.info("SharePoint health check passed.")
return True, None
else:
logger.error(f"Health check failed: {response.status_code} {response.text}")
return False, "Failed to connect to SharePoint site"
except Exception as e:
logger.exception(f"Exception during health check: {str(e)}")
return False, str(e)

def fetch_data(self, params=None):
"""
Fetch data from SharePoint using a base reader.

:param params: Additional parameters for data retrieval if needed.
:return: Data fetched from the SharePoint site.
"""
logger.info("Fetching data from SharePoint")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Implementation is not complete

base_reader = BaseReader({
"type": "sharepoint",
"path": [self.params.get('site_url')]
})
data = base_reader.load_data()
return data
Loading