Skip to content

Commit

Permalink
Merge pull request #253 from amosproj/function-int
Browse files Browse the repository at this point in the history
Integration of Firebase Functions
  • Loading branch information
preetvadaliya authored Jul 10, 2024
2 parents 69f9872 + d7921ac commit a7253d4
Show file tree
Hide file tree
Showing 12 changed files with 246 additions and 226 deletions.
73 changes: 41 additions & 32 deletions functions/main.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
# Welcome to Cloud Functions for Firebase for Python!
# To get started, simply uncomment the below code or create your own.
# Deploy with `firebase deploy`

from firebase_admin import initialize_app
from firebase_functions import https_fn
from firebase_functions import https_fn, options
from langchain.chains.query_constructor.base import AttributeInfo
from langchain.retrievers.self_query.base import SelfQueryRetriever
from langchain_astradb import AstraDBVectorStore
Expand All @@ -16,16 +12,15 @@


# Initialize embeddings and vector store
def initialize_vector_store(api_key, token):
embeddings = OpenAIEmbeddings(api_key=api_key)
vstore = AstraDBVectorStore(
def initialize_vector_store(token):
embeddings = OpenAIEmbeddings(api_key='')
return AstraDBVectorStore(
embedding=embeddings,
collection_name='test_collection_2',
api_endpoint='',
token=token,
namespace='test',
)
return vstore


# Metadata field info
Expand Down Expand Up @@ -140,22 +135,16 @@ def initialize_vector_store(api_key, token):


# Create a function to get response from the chain
def get_health_ai_response(question):
api_key = ''
def get_health_ai_response(question, llm):
token = ''

vstore = initialize_vector_store(api_key, token)

llm = ChatOpenAI(api_key=api_key, temperature=0)
vector_store = initialize_vector_store(token)
retriever = SelfQueryRetriever.from_llm(
llm=llm,
vectorstore=vstore,
vectorstore=vector_store,
document_content_description=document_content_description,
metadata_field_info=metadata_field_info,
document_contents='',
)

# Prompt Template for Health AI Agent
health_ai_template = """
You are a health AI agent equipped with access to diverse sources of health data,
including research articles, nutritional information, medical archives, and more.
Expand All @@ -171,28 +160,48 @@ def get_health_ai_response(question):
YOUR ANSWER:
"""

# Create a ChatPromptTemplate instance from the template
health_ai_prompt = ChatPromptTemplate.from_template(health_ai_template)

# Integration example:
# In your retrieval and generation pipeline, integrate this prompt template
# Replace 'retriever' and 'llm' with appropriate retrieval and language models

chain = (
{'context': retriever, 'question': RunnablePassthrough()}
| health_ai_prompt
| llm
| StrOutputParser()
)

response = chain.invoke(question)
return response


@https_fn.on_request()
def on_request_example(req: https_fn.Request) -> https_fn.Response:
response = get_health_ai_response(
'What are the key points of the nutrition article on healthy eating?'
)
return https_fn.Response([response])
def get_response_from_llm(query, llm):
api_key = ''
llm_model = None
if llm == 'gpt-4':
llm_model = ChatOpenAI(api_key=api_key, temperature=0)
if llm == 'gpt-3.5-turbo-instruct':
llm_model = ChatOpenAI(name='gpt-3.5-turbo-instruct', api_key=api_key, temperature=0)
if llm_model is not None:
response = get_health_ai_response(query, llm_model)
return response
else:
return 'Model Not Found'


@https_fn.on_request(cors=options.CorsOptions(cors_origins=['*'], cors_methods=['get', 'post']))
def get_response_url(req: https_fn.Request) -> https_fn.Response:
query = req.get_json().get('query', '')
llms = req.get_json().get('llms', ['gpt-4'])
responses = []
for llm in llms:
response = get_response_from_llm(query, llm)
responses.append(response)
return https_fn.Response(responses)


@https_fn.on_call()
def get_response(req: https_fn.CallableRequest):
query = req.data.get('query', '')
llms = req.data.get('llms', ['gpt-4'])
responses = []
for llm in llms:
response = get_response_from_llm(query, llm)
responses.append(response)
return response
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
"@react-native-firebase/app": "^20.1.0",
"@react-native-firebase/auth": "^20.1.0",
"@react-native-firebase/dynamic-links": "^20.1.0",
"@react-native-firebase/functions": "^20.1.0",
"@react-native-google-signin/google-signin": "^12.2.0",
"@react-native-voice/voice": "^3.2.4",
"@react-navigation/drawer": "^7.0.0-alpha.21",
Expand Down Expand Up @@ -57,6 +58,7 @@
"react-native-fs": "^2.20.0",
"react-native-gesture-handler": "~2.16.1",
"react-native-keyboard-aware-scroll-view": "^0.9.5",
"react-native-markdown-display": "^7.0.2",
"react-native-paper": "^5.12.3",
"react-native-reanimated": "~3.10.1",
"react-native-safe-area-context": "4.10.1",
Expand Down
12 changes: 8 additions & 4 deletions src/frontend/components/FirebaseProvider/index.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import AsyncStorage from '@react-native-async-storage/async-storage';
import Constants from 'expo-constants';
import { type FirebaseOptions, getApps, initializeApp } from 'firebase/app';
import { initializeApp } from 'firebase/app';
import { initializeAuth as getAuth, getReactNativePersistence as store } from 'firebase/auth';
import { getFirestore } from 'firebase/firestore';
import { type ReactNode, useMemo } from 'react';
import { AuthProvider, FirebaseAppProvider, FirestoreProvider } from 'reactfire';
import { getFunctions } from 'firebase/functions';
import { type ReactNode, useEffect, useMemo } from 'react';
import { AuthProvider, FirebaseAppProvider, FirestoreProvider, FunctionsProvider } from 'reactfire';

type FirebaseProviderProps = {
children: ReactNode;
Expand All @@ -16,14 +17,17 @@ export function FirebaseProvider(props: FirebaseProviderProps) {
const fireApp = useMemo(() => initializeApp(Constants.expoConfig?.extra?.firebase), []);
const fireAuth = useMemo(() => getAuth(fireApp, { persistence: store(AsyncStorage) }), [fireApp]);
const fireStore = useMemo(() => getFirestore(fireApp, 'ailixir-users'), [fireApp]);
const fireFunction = useMemo(() => getFunctions(fireApp), [fireApp]);

return (
<FirebaseAppProvider
firebaseConfig={Constants.expoConfig?.extra?.firebase}
firebaseApp={fireApp}
>
<AuthProvider sdk={fireAuth}>
<FirestoreProvider sdk={fireStore}>{children}</FirestoreProvider>
<FirestoreProvider sdk={fireStore}>
<FunctionsProvider sdk={fireFunction}>{children}</FunctionsProvider>
</FirestoreProvider>
</AuthProvider>
</FirebaseAppProvider>
);
Expand Down
13 changes: 4 additions & 9 deletions src/frontend/components/Header/index.tsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,21 @@
import type { DrawerHeaderProps } from '@react-navigation/drawer';
import { DrawerActions, type RouteProp, useRoute } from '@react-navigation/native';
import { DrawerActions } from '@react-navigation/native';
import * as Clipboard from 'expo-clipboard';
import * as FileSystem from 'expo-file-system';
import * as MediaLibrary from 'expo-media-library';
import React, { useEffect } from 'react';
import { Alert, Platform, Pressable, View } from 'react-native';
import RNFS from 'react-native-fs';
import { IconButton, Surface, Text, useTheme } from 'react-native-paper';
import { useActiveChatId, useGetChat, useLLMs } from 'src/frontend/hooks';
import { useActiveChatId, useGetChat } from 'src/frontend/hooks';
import { AilixirLogo } from 'src/frontend/icons';
import type { MainDrawerParams } from 'src/frontend/routes/MainRoutes';
import { styles } from 'src/frontend/screens/ChatUI/style';
import { DropdownMenu } from '../DropdownMenu';
import { Style } from './style';

export function Header(props: DrawerHeaderProps) {
const { colors } = useTheme();
const { navigation } = props;

const { activeChatId, setActiveChatId } = useActiveChatId();
const { activeLLMs, toggleLLM } = useLLMs(activeChatId || 'default');
const { chat, status, error } = useGetChat(activeChatId);
const { activeChatId } = useActiveChatId();
const { chat } = useGetChat(activeChatId);

// Determine if the button should be disabled
const isButtonDisabled = chat === undefined;
Expand Down
43 changes: 43 additions & 0 deletions src/frontend/components/RenderChat/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import React from 'react';
import { Text, View } from 'react-native';
import Markdown from 'react-native-markdown-display';
import { ActivityIndicator, Avatar, useTheme } from 'react-native-paper';
import { useUser } from 'reactfire';
import { useActiveChatId, useGetChat } from 'src/frontend/hooks';
import type { conversationMessage } from 'src/frontend/types';
import { Style } from './style';

export function RenderChat() {
const { activeChatId } = useActiveChatId();
const { chat, status } = useGetChat(activeChatId);
const { colors } = useTheme();
const { data: user } = useUser();

if (status === 'loading') return <ActivityIndicator />;

return (
<>
{chat?.conversation.map((item: conversationMessage) => {
const { type, message } = item;
return (
<View
key={message}
style={[Style.bubble, { backgroundColor: colors.surfaceVariant, marginBottom: 16 }]}
>
<View style={{ flexDirection: 'row', alignItems: 'center' }}>
<Avatar.Text
size={20}
label={type === 'AI' ? 'A' : user?.displayName?.charAt(0) || 'U'}
style={{ backgroundColor: colors.primary, marginRight: 4 }}
/>
<Text style={{ color: colors.primary, fontWeight: 700 }}>
{type === 'AI' ? 'AiLixir' : user?.displayName || 'User'}
</Text>
</View>
<Markdown>{message}</Markdown>
</View>
);
})}
</>
);
}
11 changes: 11 additions & 0 deletions src/frontend/components/RenderChat/style.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { StyleSheet } from "react-native";

export const Style = StyleSheet.create({
bubble: {
maxWidth: '80%',
borderRadius: 4,
padding: 8,
display: 'flex',
flexDirection: 'column'
}
})
1 change: 1 addition & 0 deletions src/frontend/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ export * from './DropdownMenu';
export * from './Header';
export * from './ActiveChatProvider';
export * from './ChatBubble';
export * from './RenderChat';
1 change: 1 addition & 0 deletions src/frontend/hooks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ export * from './useLLMs';
export * from './useActiveChatId';
export * from './useCreateChat';
export * from './useLLMsTypes';
export * from './useGetResponse';
7 changes: 7 additions & 0 deletions src/frontend/hooks/useGetResponse.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { httpsCallable } from 'firebase/functions';
import { useFunctions } from 'reactfire';

export function useGetResponse() {
const fireFunction = useFunctions();
return httpsCallable(fireFunction, 'get_response');
}
Loading

0 comments on commit a7253d4

Please sign in to comment.