From 7ff18e0a93abc99494fe1cd6577c0fd409501219 Mon Sep 17 00:00:00 2001 From: Skylar Kesselring Date: Tue, 5 Nov 2024 19:28:57 -0500 Subject: [PATCH] Create connector --- backend/danswer/configs/constants.py | 1 + backend/danswer/connectors/factory.py | 2 + .../danswer/connectors/fireflies/__init__.py | 0 .../danswer/connectors/fireflies/connector.py | 179 ++++++++++++++++++ backend/model_server/main.py | 3 +- web/public/Fireflies.png | Bin 0 -> 10432 bytes web/src/app/api/[...path]/route.ts | 6 +- web/src/components/icons/icons.tsx | 9 + web/src/lib/connectors/connectors.tsx | 7 +- web/src/lib/connectors/credentials.ts | 11 ++ web/src/lib/sources.ts | 7 + web/src/lib/types.ts | 1 + 12 files changed, 223 insertions(+), 3 deletions(-) create mode 100644 backend/danswer/connectors/fireflies/__init__.py create mode 100644 backend/danswer/connectors/fireflies/connector.py create mode 100644 web/public/Fireflies.png diff --git a/backend/danswer/configs/constants.py b/backend/danswer/configs/constants.py index 36b9a8bf3..fb32fc12a 100644 --- a/backend/danswer/configs/constants.py +++ b/backend/danswer/configs/constants.py @@ -126,6 +126,7 @@ class DocumentSource(str, Enum): XENFORO = "xenforo" NOT_APPLICABLE = "not_applicable" FRESHDESK = "freshdesk" + FIREFLIES = "fireflies" DocumentSourceRequiringTenantContext: list[DocumentSource] = [DocumentSource.FILE] diff --git a/backend/danswer/connectors/factory.py b/backend/danswer/connectors/factory.py index bc9196eec..40f926b31 100644 --- a/backend/danswer/connectors/factory.py +++ b/backend/danswer/connectors/factory.py @@ -16,6 +16,7 @@ from danswer.connectors.discourse.connector import DiscourseConnector from danswer.connectors.document360.connector import Document360Connector from danswer.connectors.dropbox.connector import DropboxConnector from danswer.connectors.file.connector import LocalFileConnector +from danswer.connectors.fireflies.connector import FirefliesConnector from danswer.connectors.freshdesk.connector import FreshdeskConnector from danswer.connectors.github.connector import GithubConnector from danswer.connectors.gitlab.connector import GitlabConnector @@ -101,6 +102,7 @@ def identify_connector_class( DocumentSource.OCI_STORAGE: BlobStorageConnector, DocumentSource.XENFORO: XenforoConnector, DocumentSource.FRESHDESK: FreshdeskConnector, + DocumentSource.FIREFLIES: FirefliesConnector, } connector_by_source = connector_map.get(source, {}) diff --git a/backend/danswer/connectors/fireflies/__init__.py b/backend/danswer/connectors/fireflies/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/backend/danswer/connectors/fireflies/connector.py b/backend/danswer/connectors/fireflies/connector.py new file mode 100644 index 000000000..7e2eae326 --- /dev/null +++ b/backend/danswer/connectors/fireflies/connector.py @@ -0,0 +1,179 @@ +# TODO: Fix the transcript text parsing for the document +# TODO: Remove the host email from the secondary owners +# TODO: Figure out if to use semantic identifier or title +# TODO: Fix date parsing in graphql query +# TODO: Fix credentials loading +from collections.abc import Iterator +from datetime import datetime +from datetime import timezone +from typing import List + +import requests + +from danswer.configs.app_configs import INDEX_BATCH_SIZE +from danswer.configs.constants import DocumentSource +from danswer.connectors.interfaces import GenerateDocumentsOutput +from danswer.connectors.interfaces import LoadConnector +from danswer.connectors.interfaces import PollConnector +from danswer.connectors.interfaces import SecondsSinceUnixEpoch +from danswer.connectors.models import BasicExpertInfo +from danswer.connectors.models import ConnectorMissingCredentialError +from danswer.connectors.models import Document +from danswer.connectors.models import Section +from danswer.utils.logger import setup_logger + +logger = setup_logger() + +_FIREFLIES_ID_PREFIX = "FIREFLIES_" + +_FIREFLIES_API_URL = "https://api.fireflies.ai/graphql" + +_FIREFLIES_API_HEADERS = {"Content-Type": "application/json", "Authorization": ""} + + +def _create_doc_from_transcript(transcript: dict) -> Document: + meeting_text = "" + sentences = transcript.get("sentences", []) + meeting_text = str(sentences) + # for sentence in sentences: + # meeting_text += ( + # sentence.get("speaker_name", "Unknown Speaker") + # + ": " + # + sentence.get("text", "") + # + "\n\n" + # ) + + link = transcript.get("transcript_url", "") + + id = _FIREFLIES_ID_PREFIX + transcript.get("id", "") + + title = transcript.get("title", "") + + meeting_date_unix = transcript.get("date", "") + meeting_date = datetime.fromtimestamp(meeting_date_unix / 1000, tz=timezone.utc) + + meeting_host_email = [BasicExpertInfo(email=transcript.get("host_email", ""))] + + meeting_participants_emails = [] + for participant in transcript.get("participants", []): + meeting_participants_emails.append(BasicExpertInfo(email=participant)) + + return Document( + id=id, + sections=[ + Section( + link=link, + text=meeting_text, + ) + ], + source=DocumentSource.FIREFLIES, + semantic_identifier=title, + metadata={}, + doc_updated_at=meeting_date, + primary_owners=meeting_host_email, + secondary_owners=meeting_participants_emails, + ) + + +class FirefliesConnector(PollConnector, LoadConnector): + def __init__(self, batch_size: int = INDEX_BATCH_SIZE) -> None: + self.batch_size = batch_size + + def load_credentials(self, credentials: dict[str, str | int]) -> None: + api_key = credentials.get("fireflies_api_key") + + if not isinstance(api_key, str): + raise ConnectorMissingCredentialError( + "The Fireflies API key must be a string" + ) + + self.api_key = str(api_key) + + def _fetch_transcripts( + self, start: datetime | None = None, end: datetime | None = None + ) -> Iterator[List[dict]]: + if self.api_key is None: + raise ConnectorMissingCredentialError("Missing API key") + + headers = _FIREFLIES_API_HEADERS.copy() + headers["Authorization"] = "Bearer 790bc814-e2f8-4349-af78-2d0b5affdaa5" + + limit = 4 + skip = 0 + date_filters = "" + if start: + date_filters = f"fromDate: {start.isoformat()}," + if end: + date_filters += f"toDate: {end.isoformat()}" + + api_query = { + "query": f""" + query {{ + transcripts( + limit: {limit}, + skip: {skip} + ) {{ + title + id + date + host_email + participants + transcript_url + sentences {{ + text + speaker_name + }} + }} + }} + """ + } + + while True: + response = requests.post( + _FIREFLIES_API_URL, headers=headers, json=api_query + ) + + response.raise_for_status() + + if response.status_code == 204: + break + + transcripts = response.json().get("data", {}).get("transcripts", []) + + if not transcripts: + break + + yield transcripts + + if len(transcripts) < limit: + break + + skip += limit + + def _process_transcripts( + self, start: datetime | None = None, end: datetime | None = None + ) -> GenerateDocumentsOutput: + doc_batch: List[Document] = [] + + for transcript_batch in self._fetch_transcripts(start, end): + for transcript in transcript_batch: + print(transcript) + doc_batch.append(_create_doc_from_transcript(transcript)) + + if len(doc_batch) >= self.batch_size: + yield doc_batch + doc_batch = [] + + if doc_batch: + yield doc_batch + + def load_from_state(self) -> GenerateDocumentsOutput: + return self._process_transcripts() + + def poll_source( + self, start: SecondsSinceUnixEpoch, end: SecondsSinceUnixEpoch + ) -> GenerateDocumentsOutput: + start_datetime = datetime.fromtimestamp(start, tz=timezone.utc) + end_datetime = datetime.fromtimestamp(end, tz=timezone.utc) + + yield from self._process_transcripts(start_datetime, end_datetime) diff --git a/backend/model_server/main.py b/backend/model_server/main.py index ce9cc724a..c2cb0ef2d 100644 --- a/backend/model_server/main.py +++ b/backend/model_server/main.py @@ -28,7 +28,8 @@ os.environ["TOKENIZERS_PARALLELISM"] = "false" os.environ["HF_HUB_DISABLE_TELEMETRY"] = "1" HF_CACHE_PATH = Path("/root/.cache/huggingface/") -TEMP_HF_CACHE_PATH = Path("/root/.cache/temp_huggingface/") +# Changed this to be compatible with Linux +TEMP_HF_CACHE_PATH = Path.home() / ".cache" / "temp_huggingface" transformer_logging.set_verbosity_error() diff --git a/web/public/Fireflies.png b/web/public/Fireflies.png new file mode 100644 index 0000000000000000000000000000000000000000..19374c4f558f4f90369ae8200f04213dfbd9b0de GIT binary patch literal 10432 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 ); +export const FirefliesIcon = ({ + size = 16, + className = defaultTailwindCSS, +}: IconProps) => ( + +); + /* EE Icons */ diff --git a/web/src/lib/connectors/connectors.tsx b/web/src/lib/connectors/connectors.tsx index 1ec265049..89dca2f28 100644 --- a/web/src/lib/connectors/connectors.tsx +++ b/web/src/lib/connectors/connectors.tsx @@ -950,7 +950,11 @@ For example, specifying .*-support.* as a "channel" will cause the connector to values: [], advanced_values: [], }, - + fireflies: { + description: "Configure Fireflies connector", + values: [], + advanced_values: [], + }, }; export function createConnectorInitialValues( connector: ConfigurableSources @@ -1210,6 +1214,7 @@ export interface AsanaConfig { export interface FreshdeskConfig {} +export interface FirefliesConfig {} export interface MediaWikiConfig extends MediaWikiBaseConfig { hostname: string; diff --git a/web/src/lib/connectors/credentials.ts b/web/src/lib/connectors/credentials.ts index c6da2c5f6..d452789a9 100644 --- a/web/src/lib/connectors/credentials.ts +++ b/web/src/lib/connectors/credentials.ts @@ -187,6 +187,10 @@ export interface FreshdeskCredentialJson { freshdesk_api_key: string; } +export interface FirefliesCredentialJson { + fireflies_api_key: string; +} + export interface MediaWikiCredentialJson {} export interface WikipediaCredentialJson extends MediaWikiCredentialJson {} @@ -290,6 +294,9 @@ export const credentialTemplates: Record = { freshdesk_password: "", freshdesk_api_key: "", } as FreshdeskCredentialJson, + fireflies: { + fireflies_api_key: "", + } as FirefliesCredentialJson, xenforo: null, google_sites: null, file: null, @@ -435,7 +442,11 @@ export const credentialDisplayNames: Record = { freshdesk_domain: "Freshdesk Domain", freshdesk_password: "Freshdesk Password", freshdesk_api_key: "Freshdesk API Key", + + // Fireflies + fireflies_api_key: "Fireflies API Key", }; + export function getDisplayNameForCredentialKey(key: string): string { return credentialDisplayNames[key] || key; } diff --git a/web/src/lib/sources.ts b/web/src/lib/sources.ts index fe71f6b09..230ec9b5d 100644 --- a/web/src/lib/sources.ts +++ b/web/src/lib/sources.ts @@ -37,6 +37,7 @@ import { ColorSlackIcon, XenforoIcon, FreshdeskIcon, + FirefliesIcon, } from "@/components/icons/icons"; import { ValidSources } from "./types"; import { @@ -289,6 +290,12 @@ const SOURCE_METADATA_MAP: SourceMap = { category: SourceCategory.CustomerSupport, docs: "https://docs.danswer.dev/connectors/freshdesk", }, + fireflies: { + icon: FirefliesIcon, + displayName: "Fireflies", + category: SourceCategory.CustomerSupport, + docs: "https://docs.danswer.dev/connectors/fireflies", + }, // currently used for the Internet Search tool docs, which is why // a globe is used not_applicable: { diff --git a/web/src/lib/types.ts b/web/src/lib/types.ts index f532a09ee..ce3e59f89 100644 --- a/web/src/lib/types.ts +++ b/web/src/lib/types.ts @@ -265,6 +265,7 @@ const validSources = [ "not_applicable", "ingestion_api", "freshdesk", + "fireflies", ] as const; export type ValidSources = (typeof validSources)[number];