-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 9a2cf73
Showing
8 changed files
with
5,079 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
## Version 0.0.1 | ||
- Initial Version |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
<!-- | ||
This file provides your users an overview of how to use your extension after they've installed it. All content is optional, but this is the recommended format. Your users will see the contents of this file in the Firebase console after they install the extension. | ||
Include instructions for using the extension and any important functional details. Also include **detailed descriptions** for any additional post-installation setup required by the user. | ||
Reference values for the extension instance using the ${param:PARAMETER_NAME} or ${function:VARIABLE_NAME} syntax. | ||
Learn more in the docs: https://firebase.google.com/docs/extensions/publishers/user-documentation#reference-in-postinstall | ||
Learn more about writing a POSTINSTALL.md file in the docs: | ||
https://firebase.google.com/docs/extensions/publishers/user-documentation#writing-postinstall | ||
--> | ||
|
||
# See it in action | ||
|
||
You can test your Extension from the deployed Cloud Function Trigger by navgating to the Cloud Function -> Deployed service name -> Triggers. | ||
|
||
# Using the extension | ||
|
||
To use this extesnion you need to import the trigger/https endpoint to your Application Logic. | ||
|
||
To learn more about HTTP functions, visit the [functions documentation](https://firebase.google.com/docs/functions/http-events). | ||
|
||
<!-- We recommend keeping the following section to explain how to monitor extensions with Firebase --> | ||
# Monitoring | ||
|
||
As a best practice, you can [monitor the activity](https://firebase.google.com/docs/extensions/manage-installed-extensions#monitor) of your installed extension, including checks on its health, usage, and logs. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
<!-- | ||
This file provides your users an overview of your extension. All content is optional, but this is the recommended format. Your users will see the contents of this file when they run the `firebase ext:info` command. | ||
Include any important functional details as well as a brief description for any additional setup required by the user (both pre- and post-installation). | ||
Learn more about writing a PREINSTALL.md file in the docs: | ||
https://firebase.google.com/docs/extensions/publishers/user-documentation#writing-preinstall | ||
--> | ||
|
||
# MongoDB Atlas Extension | ||
|
||
This firebase extension is a v1 for MongoDB Atlas. It can perform the following operations | ||
|
||
1. /findOne | ||
* requires user to pass filter in the format {"filter":{"name":"sample"}} | ||
2. /insertOne | ||
* requires the user to pass document in JSON format. | ||
3. /vectorSearch | ||
* requires the user to pass the query in the format {"query": "Tell me about Firebase extensions"} | ||
|
||
### The parameters that can be configures at the time of installation are below: | ||
* Connection String: The Mongodb SRV string from Atlas -> connect | ||
* Database Name: name of the database | ||
* Collection Name: Name of the collection you want to connect to. | ||
* Embedding Model Name | ||
* LLM Model Name | ||
* Index Name | ||
* Vector Index Name | ||
* Vector Field Name | ||
* Vector return Name | ||
|
||
<!-- We recommend keeping the following section to explain how billing for Firebase Extensions works --> | ||
# Billing | ||
|
||
This extension uses other Firebase or Google Cloud Platform services which may have associated charges: | ||
|
||
<!-- List all products the extension interacts with --> | ||
- Cloud Functions | ||
|
||
When you use Firebase Extensions, you're only charged for the underlying resources that you use. A paid-tier billing plan is only required if the extension uses a service that requires a paid-tier plan, for example calling to a Google Cloud Platform API or making outbound network requests to non-Google services. All Firebase services offer a free tier of usage. [Learn more about Firebase billing.](https://firebase.google.com/pricing) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
name: mongodb-functions | ||
version: 0.0.1 | ||
specVersion: v1beta # Firebase Extensions specification version; don't change | ||
|
||
# Friendly display name for your extension (~3-5 words) | ||
displayName: MongoDB Atlas | ||
|
||
# Brief description of the task your extension performs (~1 sentence) | ||
description: >- | ||
Perform basic operations like findOne, InsertOne and vectorSearch on MongoDB Atlas | ||
author: | ||
authorName: Venkatesh Shanbhag | ||
url: https://mongodb.com | ||
|
||
license: Apache-2.0 # Required license | ||
|
||
# Public URL for the source code of your extension | ||
sourceUrl: https://github.com/your-name/your-repo | ||
|
||
resources: | ||
# - name: mongodbcrud | ||
# type: ev | ||
# properties: | ||
# eventTrigger: | ||
# eventType: providers/google.firebase.database/eventTypes/ref.create | ||
# # DATABASE_INSTANCE (project's default instance) is an auto-populated | ||
# # parameter value. You can also specify an instance. | ||
# resource: projects/_/instances/${DATABASE_INSTANCE}/refs/messages/{pushId}/original | ||
# runtime: "nodejs18" | ||
- name: mongodbcrud | ||
type: firebaseextensions.v1beta.function | ||
properties: | ||
runtime: nodejs18 | ||
httpsTrigger: {} | ||
|
||
params: | ||
- param: CONNECTION_STRING | ||
label: MongoDB Connection String of your cluster | ||
description: >- | ||
MongoDB connection String | ||
type: string | ||
default: mongodb+srv:// | ||
required: true | ||
immutable: false | ||
- param: DATABASE_NAME | ||
label: Mongodb Database name | ||
description: >- | ||
Mongodb Database name | ||
type: string | ||
default: test | ||
required: true | ||
immutable: false | ||
- param: COLLECTION_NAME | ||
label: Mongodb Collection name | ||
description: >- | ||
Mongodb Collection name | ||
type: string | ||
default: test | ||
required: true | ||
immutable: false | ||
- param: EMBEDDING_MODEL_NAME | ||
label: Googel VertexAI Model name | ||
description: >- | ||
Mongodb Model name | ||
type: string | ||
default: text-embedding-004 | ||
required: true | ||
immutable: false | ||
- param: LLM_MODEL_NAME | ||
label: Googel VertexAI Model name | ||
description: >- | ||
Mongodb Model name | ||
type: string | ||
default: "gemini-1.5-pro" | ||
required: true | ||
immutable: false | ||
- param: INDEX_NAME | ||
label: Mongodb Index name | ||
description: >- | ||
Mongodb Index name | ||
type: string | ||
default: vector_index | ||
required: true | ||
immutable: false | ||
- param: INDEX_FIELD | ||
label: Mongodb Index field | ||
description: >- | ||
Mongodb Index field | ||
type: string | ||
default: text | ||
required: true | ||
immutable: false | ||
- param: EMBEDDING_FIELD | ||
label: Mongodb Embedding field | ||
description: >- | ||
Mongodb Embedding field | ||
type: string | ||
default: embedding | ||
required: true | ||
immutable: false | ||
- param: LLM_PROMPT | ||
label: LLM Prompt | ||
description: >- | ||
LLM Prompt | ||
type: string | ||
default: "You are a Chatbot. respond the the user only with the context you have from the input provided to you. Don't return anything that is irrelevant to the context." | ||
required: true | ||
immutable: false | ||
|
||
events: | ||
- type: test-publisher.mongodb-functions.v1.complete | ||
description: >- | ||
Occurs with MongoDB function execution is complete | ||
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
node_modules/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
import { MongoClient } from 'mongodb'; | ||
import { initializeApp } from "firebase-admin/app"; | ||
import { https } from 'firebase-functions/v1'; | ||
import { VertexAIEmbeddings, ChatVertexAI } from "@langchain/google-vertexai"; | ||
|
||
import { MongoDBAtlasVectorSearch } from "@langchain/mongodb"; | ||
|
||
|
||
const app = initializeApp(); | ||
|
||
|
||
export const mongodbcrud = https.onRequest(async (req, res) => { | ||
|
||
const route = req.path; | ||
const payload = req.body; | ||
const client = new MongoClient(process.env.CONNECTION_STRING); | ||
const db = client.db(process.env.DATABASE_NAME); | ||
const collection = db.collection(process.env.COLLECTION_NAME); | ||
|
||
const llm = new ChatVertexAI({ | ||
model: process.env.LLM_MODEL_NAME, | ||
temperature: 0.2, | ||
maxRetries: 2, | ||
// For web, authOptions.credentials | ||
// authOptions: { ... } | ||
// other params... | ||
}); | ||
const embeddings = new VertexAIEmbeddings({ | ||
model: process.env.EMBEDDING_MODEL_NAME, | ||
location: process.env.LOCATION, | ||
// ... | ||
}); | ||
|
||
const vectorStore = new MongoDBAtlasVectorSearch(embeddings, { | ||
collection: collection, | ||
indexName: process.env.INDEX_NAME, // The name of the Atlas search index. Defaults to "default" | ||
textKey: process.env.INDEX_FIELD, // The name of the collection field containing the raw content. Defaults to "text" | ||
embeddingKey: process.env.EMBEDDING_FIELD, // The name of the collection field containing the embedded text. Defaults to "embedding" | ||
}); | ||
|
||
try { | ||
console.log('Connected successfully to MongoDB'); | ||
if (route === "/findOne") { | ||
const filter = payload.filter || {}; | ||
const projection = payload.projection || {}; | ||
try{ | ||
const result = { | ||
document: await collection.findOne(filter, projection) | ||
}; | ||
return res.status(200).send(result); | ||
} | ||
finally{ | ||
await client.close(); | ||
} | ||
} | ||
// else if(route === '/find'){ | ||
// const aggQuery = []; | ||
// const filter = payload.filter || {}; | ||
// const sort = payload.sort || {}; | ||
// try { | ||
// const result = await collection.findOne(query); | ||
// console.log('Found document:', result); | ||
// return res.status(200).send(result); | ||
// } | ||
// finally{ | ||
// await client.close(); | ||
// } | ||
|
||
// } | ||
else if(route === '/insertOne'){ | ||
const document = payload.document || {}; | ||
if (!document) { | ||
return res.status(400).send('Document is required'); | ||
} | ||
const result = await collection.insertOne(document); | ||
console.log('Inserted document:', result.insertedId); | ||
return res.status(200).send(result); | ||
} | ||
// else if(route === '/insertMany'){ | ||
// const documents = payload.documents || []; | ||
// if (!documents.length) { | ||
// return res.status(400).send('Documents are required'); | ||
// } | ||
|
||
// collection.updateOne({ name: 'John Doe' }, { $set: { name: 'Jane Doe' } }); | ||
// } | ||
else if(route === '/vectorSearch'){ | ||
const query = payload.query || {}; | ||
if (!query) { | ||
return res.status(400).send('Query is required'); | ||
} | ||
try{ | ||
// const singleVector = await embeddings.embedQuery(query); | ||
// console.log(singleVector); | ||
const similaritySearchResults = await vectorStore.similaritySearch( | ||
query, | ||
1 | ||
); | ||
for (const doc of similaritySearchResults) { | ||
console.log(`* ${doc.pageContent} [${JSON.stringify(doc.metadata, null)}]`); | ||
} | ||
|
||
const aiMsg = await llm.invoke([ | ||
[ | ||
"system", | ||
process.env.LLM_PROMPT, | ||
], | ||
similaritySearchResults[0].pageContent, | ||
]); | ||
|
||
return res.status(200).send(aiMsg.content); | ||
|
||
} | ||
finally{ | ||
await client.close(); | ||
} | ||
|
||
} | ||
} | ||
catch (error) { | ||
// Handle the error here | ||
console.error(error); | ||
} | ||
|
||
|
||
}) |
Oops, something went wrong.