diff --git a/audio-rag/endpoint/app.py b/audio-rag/endpoint/app.py
index aeadbb3..e7de249 100644
--- a/audio-rag/endpoint/app.py
+++ b/audio-rag/endpoint/app.py
@@ -1,6 +1,8 @@
from flask import Flask, request, redirect
from rag_set import query, load
from werkzeug.utils import secure_filename
+import mimetypes
+from datetime import datetime
import os
@@ -18,11 +20,14 @@ def index():
@app.route('/api/query', methods=['POST'])
def api_query():
json = request.json
- res = query(json['prompt'])
- context = []
- for doc in res['context']:
- context.append(doc.dict())
- return {"answer": res['answer'], "context": context}
+ try:
+ res = query(json['prompt'])
+ context = []
+ for doc in res['context']:
+ context.append(doc.dict())
+ return {"answer": res['answer'], "context": context}
+ except:
+ return {"answer": "An error occured. Make sure to upload some documents before chatting with them."}
@app.route('/upload', methods=['POST'])
@@ -33,11 +38,21 @@ def upload_file():
if file.filename == '':
raise 'No selected file'
if file:
- filename = secure_filename(file.filename)
+ filename = datetime.now().isoformat() + \
+ secure_filename(file.filename).split(
+ ".")[0] + mimetypes.guess_extension(file.mimetype)
file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
load(filename)
return redirect("/", code=302)
+@app.route("/files", methods=['GET'])
+def list_files():
+ files = []
+ for file in os.listdir("data/"):
+ files.append(file)
+ return files
+
+
if __name__ == "__main__":
app.run()
diff --git a/audio-rag/endpoint/rag_set.py b/audio-rag/endpoint/rag_set.py
index b2fd404..e370c94 100644
--- a/audio-rag/endpoint/rag_set.py
+++ b/audio-rag/endpoint/rag_set.py
@@ -1,3 +1,4 @@
+import speech_recognition as sr
from langchain_text_splitters import CharacterTextSplitter
from langchain_community.vectorstores import FAISS
from langchain_community.document_loaders import TextLoader
@@ -6,6 +7,7 @@
from langchain_community.llms import Ollama
from langchain.chains.combine_documents import create_stuff_documents_chain
from langchain.chains import create_retrieval_chain
+from langchain_core.documents import Document
from langchain import hub
import os
@@ -55,6 +57,31 @@ def load(f):
global chain
global texts
match f.split(".")[-1]:
+ case "mp3":
+ name = ".".join(f.split(".")[:-1])
+ os.system(f"ffmpeg -i data/{name}.mp3 data/{name}.wav")
+ os.remove(f"data/{name}.mp3")
+ r = sr.Recognizer()
+ file = sr.AudioFile(f"data/{name}.wav")
+ with file as source:
+ audio = r.record(source)
+ txt = str(r.recognize_sphinx(audio))
+ documents = [
+ Document(page_content=txt, metadata={"source": f"data/{name}.wav"})]
+ text_splitter = CharacterTextSplitter(
+ chunk_size=500, chunk_overlap=10)
+ texts.extend(text_splitter.split_documents(documents))
+ case "wav":
+ r = sr.Recognizer()
+ file = sr.AudioFile("data/"+f)
+ with file as source:
+ audio = r.record(source)
+ txt = str(r.recognize_sphinx(audio))
+ documents = [
+ Document(page_content=txt, metadata={"source": "data/"+f})]
+ text_splitter = CharacterTextSplitter(
+ chunk_size=500, chunk_overlap=10)
+ texts.extend(text_splitter.split_documents(documents))
case "txt":
loader = TextLoader("data/"+f)
documents = loader.load()
@@ -67,6 +94,9 @@ def load(f):
text_splitter = CharacterTextSplitter(
chunk_size=500, chunk_overlap=10)
texts.extend(text_splitter.split_documents(documents))
+ case _:
+ print(f, "not accepted")
+ os.remove("data/"+f)
db = FAISS.from_documents(texts, embeddings)
retriever = db.as_retriever()
diff --git a/audio-rag/endpoint/static/index.html b/audio-rag/endpoint/static/index.html
new file mode 100644
index 0000000..c293ed5
--- /dev/null
+++ b/audio-rag/endpoint/static/index.html
@@ -0,0 +1,34 @@
+
+
+
+
+
+ Ollama RAG with LLAMA 3
+
+
+
+
+ Files in RAG store
+ Chat
+
+
+
diff --git a/audio-rag/endpoint/static/main.js b/audio-rag/endpoint/static/main.js
new file mode 100644
index 0000000..ea6dae1
--- /dev/null
+++ b/audio-rag/endpoint/static/main.js
@@ -0,0 +1,74 @@
+document.querySelector("#send").onclick = async () => {
+ const prompt = document.querySelector("#q").value;
+ document.querySelector("#q").value = "";
+
+ document.querySelector("#spinner").classList.toggle("hidden");
+
+ const q_div = document.createElement("div");
+ q_div.className =
+ "m-4 mr-24 flex flex-col gap-2 items-start bg-emerald-400 p-4 rounded-md";
+ const user_div = document.createElement("div");
+ user_div.innerText = "User:";
+ const prompt_div = document.createElement("div");
+ prompt_div.innerText = prompt;
+ q_div.appendChild(user_div);
+ q_div.appendChild(prompt_div);
+ document.querySelector("#main").appendChild(q_div);
+
+ const req = await fetch("/api/query", {
+ body: JSON.stringify({
+ prompt,
+ }),
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ });
+ const res = await req.json();
+ console.log(res);
+ const r_div = document.createElement("div");
+ r_div.className =
+ "m-4 ml-24 flex flex-col gap-2 bg-emerald-300 p-4 rounded-md";
+ const a_div = document.createElement("div");
+ a_div.innerText = "RAG:";
+ const answer_div = document.createElement("div");
+ answer_div.innerText = res.answer;
+ const context_div = document.createElement("div");
+ res.context.forEach((elem) => {
+ const context_item = document.createElement("div");
+ context_item.className = "m-4 border-b-2";
+ const text = document.createElement("div");
+ text.innerText = elem.page_content;
+ context_item.appendChild(text);
+ const source = document.createElement("div");
+ source.innerText = elem.metadata.source;
+ source.className = "text-right font-semibold";
+ context_item.appendChild(source);
+ context_div.appendChild(context_item);
+ });
+ r_div.appendChild(a_div);
+ r_div.appendChild(answer_div);
+ r_div.appendChild(context_div);
+
+ document.querySelector("#main").appendChild(r_div);
+
+ document.querySelector("#spinner").classList.toggle("hidden");
+};
+const getFileType = (filename) => {
+ switch (filename.split('.').at(-1)) {
+ case 'txt':
+ return 'Text file';
+ case 'wav':
+ return 'WAV Sound recording';
+ case 'pdf':
+ return 'PDF document';
+ default:
+ return '<>';
+ }
+};
+
+fetch("/files").then(res=>res.json().then(json=>{
+ document.querySelector("#files").innerHTML = `Files in RAG store
` + json.map(file=>`
+ ${file}
${getFileType(file)}
+`).join("")
+}))
diff --git a/audio-rag/native/README.md b/audio-rag/native/README.md
index 12470c3..8bd066d 100644
--- a/audio-rag/native/README.md
+++ b/audio-rag/native/README.md
@@ -2,7 +2,7 @@ This is a new [**React Native**](https://reactnative.dev) project, bootstrapped
# Getting Started
->**Note**: Make sure you have completed the [React Native - Environment Setup](https://reactnative.dev/docs/environment-setup) instructions till "Creating a new application" step, before proceeding.
+> **Note**: Make sure you have completed the [React Native - Environment Setup](https://reactnative.dev/docs/environment-setup) instructions till "Creating a new application" step, before proceeding.
## Step 1: Start the Metro Server
diff --git a/audio-rag/native/__tests__/App.test.tsx b/audio-rag/native/__tests__/App.test.tsx
deleted file mode 100644
index 9eac6fb..0000000
--- a/audio-rag/native/__tests__/App.test.tsx
+++ /dev/null
@@ -1,17 +0,0 @@
-/**
- * @format
- */
-
-import 'react-native';
-import React from 'react';
-import App from '../App';
-
-// Note: import explicitly to use the types shipped with jest.
-import {it} from '@jest/globals';
-
-// Note: test renderer must be required after react-native.
-import renderer from 'react-test-renderer';
-
-it('renders correctly', () => {
- renderer.create();
-});
diff --git a/audio-rag/native/index.js b/audio-rag/native/index.js
index 752e7ee..69303b3 100644
--- a/audio-rag/native/index.js
+++ b/audio-rag/native/index.js
@@ -2,8 +2,8 @@
* @format
*/
-import { AppRegistry } from 'react-native';
+import {AppRegistry} from 'react-native';
import App from './src/App';
-import { name as appName } from './app.json';
+import {name as appName} from './app.json';
AppRegistry.registerComponent(appName, () => App);
diff --git a/audio-rag/native/ios/audiorag/Images.xcassets/AppIcon.appiconset/Contents.json b/audio-rag/native/ios/audiorag/Images.xcassets/AppIcon.appiconset/Contents.json
index 8121323..ddd7fca 100644
--- a/audio-rag/native/ios/audiorag/Images.xcassets/AppIcon.appiconset/Contents.json
+++ b/audio-rag/native/ios/audiorag/Images.xcassets/AppIcon.appiconset/Contents.json
@@ -1,53 +1,53 @@
{
- "images" : [
+ "images": [
{
- "idiom" : "iphone",
- "scale" : "2x",
- "size" : "20x20"
+ "idiom": "iphone",
+ "scale": "2x",
+ "size": "20x20"
},
{
- "idiom" : "iphone",
- "scale" : "3x",
- "size" : "20x20"
+ "idiom": "iphone",
+ "scale": "3x",
+ "size": "20x20"
},
{
- "idiom" : "iphone",
- "scale" : "2x",
- "size" : "29x29"
+ "idiom": "iphone",
+ "scale": "2x",
+ "size": "29x29"
},
{
- "idiom" : "iphone",
- "scale" : "3x",
- "size" : "29x29"
+ "idiom": "iphone",
+ "scale": "3x",
+ "size": "29x29"
},
{
- "idiom" : "iphone",
- "scale" : "2x",
- "size" : "40x40"
+ "idiom": "iphone",
+ "scale": "2x",
+ "size": "40x40"
},
{
- "idiom" : "iphone",
- "scale" : "3x",
- "size" : "40x40"
+ "idiom": "iphone",
+ "scale": "3x",
+ "size": "40x40"
},
{
- "idiom" : "iphone",
- "scale" : "2x",
- "size" : "60x60"
+ "idiom": "iphone",
+ "scale": "2x",
+ "size": "60x60"
},
{
- "idiom" : "iphone",
- "scale" : "3x",
- "size" : "60x60"
+ "idiom": "iphone",
+ "scale": "3x",
+ "size": "60x60"
},
{
- "idiom" : "ios-marketing",
- "scale" : "1x",
- "size" : "1024x1024"
+ "idiom": "ios-marketing",
+ "scale": "1x",
+ "size": "1024x1024"
}
],
- "info" : {
- "author" : "xcode",
- "version" : 1
+ "info": {
+ "author": "xcode",
+ "version": 1
}
}
diff --git a/audio-rag/native/ios/audiorag/Images.xcassets/Contents.json b/audio-rag/native/ios/audiorag/Images.xcassets/Contents.json
index 2d92bd5..97a8662 100644
--- a/audio-rag/native/ios/audiorag/Images.xcassets/Contents.json
+++ b/audio-rag/native/ios/audiorag/Images.xcassets/Contents.json
@@ -1,6 +1,6 @@
{
- "info" : {
- "version" : 1,
- "author" : "xcode"
+ "info": {
+ "version": 1,
+ "author": "xcode"
}
}
diff --git a/audio-rag/native/package.json b/audio-rag/native/package.json
index fa369cd..02a773c 100644
--- a/audio-rag/native/package.json
+++ b/audio-rag/native/package.json
@@ -29,7 +29,6 @@
"eslint": "^8.19.0",
"jest": "^29.6.3",
"prettier": "2.8.8",
- "react-test-renderer": "18.2.0",
"typescript": "5.0.4"
},
"engines": {
diff --git a/audio-rag/native/src/App.tsx b/audio-rag/native/src/App.tsx
index 50c6981..5efcfde 100644
--- a/audio-rag/native/src/App.tsx
+++ b/audio-rag/native/src/App.tsx
@@ -5,62 +5,27 @@
* @format
*/
-import React, { useCallback, useState } from 'react';
+import React, {useState} from 'react';
import {
Button,
SafeAreaView,
ScrollView,
StatusBar,
StyleSheet,
- Text,
useColorScheme,
View,
} from 'react-native';
-import { constants } from './constants';
-
-import {
- Colors,
-} from 'react-native/Libraries/NewAppScreen';
-
-
-import DocumentPicker, { DocumentPickerResponse } from 'react-native-document-picker'
-
+import {Colors} from 'react-native/Libraries/NewAppScreen';
+import {RagStore} from './RagStore';
+import {Chat} from './Chat';
+import {AppMode} from './utils';
+import {Message} from './Chat/types';
function App(): React.JSX.Element {
- const [fileResponse, setFileResponse] = useState([]);
- const [error, setError] = useState("")
-
- const handleDocumentSelection = useCallback(async () => {
- try {
- const response = await DocumentPicker.pick({
- allowMultiSelection: false,
- presentationStyle: 'fullScreen',
- });
- setFileResponse(response);
- } catch (err: any) {
- setError(err.toString())
- }
- }, []);
-
- const uploadFile = useCallback(async () => {
- try {
- let data = new FormData()
- data.append('file', { uri: fileResponse[0].uri, type: fileResponse[0].type, name: fileResponse[0].name })
- const response = await fetch(new URL("/upload", constants.ENDPOINT_URI), {
- method: 'POST',
- headers: {
- 'Content-Type': 'multipart/form-data',
- },
- body: data
- })
- throw "Uploaded"
- } catch (err: any) {
- setError(err.toString())
- }
- }, [fileResponse]);
-
+ const [mode, setMode] = useState('chat');
const isDarkMode = useColorScheme() === 'dark';
+ const [messages, setMessages] = useState([]);
const backgroundStyle = {
backgroundColor: isDarkMode ? Colors.darker : Colors.lighter,
@@ -76,39 +41,29 @@ function App(): React.JSX.Element {
contentInsetAdjustmentBehavior="automatic"
style={backgroundStyle}>
-
- {error || "No error yet."}
-
-
- {fileResponse.length == 1 ?
- <>
-
- Upload file:{fileResponse[0]?.name}
-
-
-
- > : <>>}
- {fileResponse.length > 1 ?
- Please upload just a single file!
- : <>>}
-
+
+
+ {(function () {
+ switch (mode) {
+ case 'chat':
+ return ;
+ case 'store':
+ return ;
+ }
+ })()}
-
+
);
}
-const styles = StyleSheet.create({
- highlight: {
- fontWeight: '700',
+export default App;
+
+const style = StyleSheet.create({
+ toggle: {
+ display: 'flex',
+ flexDirection: 'row',
},
});
-
-export default App;
diff --git a/audio-rag/native/src/Chat/MessageView/ContextView/index.tsx b/audio-rag/native/src/Chat/MessageView/ContextView/index.tsx
new file mode 100644
index 0000000..d042c53
--- /dev/null
+++ b/audio-rag/native/src/Chat/MessageView/ContextView/index.tsx
@@ -0,0 +1,27 @@
+import {StyleSheet, Text, View} from 'react-native';
+import React from 'react';
+import {MessageContext} from '../../types';
+
+export const ContextView = ({context}: {context: MessageContext}) => {
+ return (
+ <>
+
+ {context.source}
+ {context.content}
+
+ >
+ );
+};
+const styles = StyleSheet.create({
+ context: {
+ display: 'flex',
+ padding: 10,
+ paddingLeft: 30,
+ },
+ source: {
+ fontStyle: 'italic',
+ },
+ content: {
+ fontSize: 20,
+ },
+});
diff --git a/audio-rag/native/src/Chat/MessageView/index.tsx b/audio-rag/native/src/Chat/MessageView/index.tsx
new file mode 100644
index 0000000..8b164a2
--- /dev/null
+++ b/audio-rag/native/src/Chat/MessageView/index.tsx
@@ -0,0 +1,46 @@
+import React, {useState} from 'react';
+import {StyleSheet, Text, View} from 'react-native';
+import {Message} from '../types';
+import {ContextView} from './ContextView';
+
+export const MessageView = ({message}: {message: Message}) => {
+ const [show, setShow] = useState(false);
+ return (
+ <>
+
+ {message.author}:
+ {message.content}
+ {message.context?.length ? (
+ setShow(s => !s)}>
+ ---- {!show ? 'open' : 'close'} context ( {message.context?.length}{' '}
+ items ) ----
+
+ ) : (
+ <>>
+ )}
+ {show ? (
+ message.context?.map((item, ix) => (
+
+ ))
+ ) : (
+ <>>
+ )}
+
+ >
+ );
+};
+const styles = StyleSheet.create({
+ message: {
+ display: 'flex',
+ padding: 10,
+ },
+ author: {
+ fontStyle: 'italic',
+ },
+ context: {
+ fontStyle: 'italic',
+ },
+ content: {
+ fontSize: 20,
+ },
+});
diff --git a/audio-rag/native/src/Chat/MessagesView/index.tsx b/audio-rag/native/src/Chat/MessagesView/index.tsx
new file mode 100644
index 0000000..5e93c3d
--- /dev/null
+++ b/audio-rag/native/src/Chat/MessagesView/index.tsx
@@ -0,0 +1,20 @@
+import React from 'react';
+import {StyleSheet, View} from 'react-native';
+import {Message} from '../types';
+import {MessageView} from '../MessageView';
+
+export const MessagesView = ({messages}: {messages: Message[]}) => (
+ <>
+
+ {messages.map((message, ix) => (
+
+ ))}
+
+ >
+);
+
+const styles = StyleSheet.create({
+ list: {
+ marginTop: 10,
+ },
+});
diff --git a/audio-rag/native/src/Chat/index.tsx b/audio-rag/native/src/Chat/index.tsx
new file mode 100644
index 0000000..02ebc6c
--- /dev/null
+++ b/audio-rag/native/src/Chat/index.tsx
@@ -0,0 +1,51 @@
+import React, {Dispatch, SetStateAction, useState} from 'react';
+import {StyleSheet, Text, TextInput} from 'react-native';
+import {Message} from './types';
+import {MessagesView} from './MessagesView';
+import {queueMessage} from './utils';
+
+export const Chat = ({
+ messages,
+ setMessages,
+}: {
+ messages: Message[];
+ setMessages: Dispatch>;
+}) => {
+ const [message, setMessage] = useState('');
+ return (
+ <>
+ Chat with store
+
+
+ setMessage(text)}
+ placeholder="Send a message..."
+ onSubmitEditing={() => {
+ setMessage('');
+ setMessages(mgs => {
+ return mgs.concat([
+ {
+ author: 'User',
+ content: message,
+ },
+ ]);
+ });
+ queueMessage(message, setMessages);
+ }}
+ />
+ >
+ );
+};
+
+const styles = StyleSheet.create({
+ input: {
+ fontSize: 20,
+ padding: 10,
+ marginTop: 20,
+ },
+ title: {
+ fontSize: 32,
+ },
+});
diff --git a/audio-rag/native/src/Chat/types.ts b/audio-rag/native/src/Chat/types.ts
new file mode 100644
index 0000000..20160fd
--- /dev/null
+++ b/audio-rag/native/src/Chat/types.ts
@@ -0,0 +1,10 @@
+export interface Message {
+ author: 'RAG' | 'User';
+ content: string;
+ context?: MessageContext[];
+}
+
+export interface MessageContext {
+ source: string;
+ content: string;
+}
diff --git a/audio-rag/native/src/Chat/utils.ts b/audio-rag/native/src/Chat/utils.ts
new file mode 100644
index 0000000..342fc97
--- /dev/null
+++ b/audio-rag/native/src/Chat/utils.ts
@@ -0,0 +1,49 @@
+import {Dispatch, SetStateAction} from 'react';
+import {Message} from './types';
+import {constants} from '../constants';
+
+export interface ResponseMessage {
+ answer: string;
+ context: {
+ metadata: {
+ source: string;
+ };
+ page_content: string;
+ type: string;
+ }[];
+}
+
+export const sendMessage = async (
+ message: string,
+): Promise => {
+ const res = await fetch(new URL('/api/query', constants.ENDPOINT_URI), {
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify({
+ prompt: message,
+ }),
+ method: 'POST',
+ });
+ return await res.json();
+};
+
+export const queueMessage = (
+ message: string,
+ setMessages: Dispatch>,
+) => {
+ sendMessage(message).then((res: ResponseMessage) => {
+ setMessages(messages =>
+ messages.concat([
+ {
+ author: 'RAG',
+ content: res.answer,
+ context: res.context.map(item => ({
+ source: item.metadata.source,
+ content: item.page_content,
+ })),
+ },
+ ]),
+ );
+ });
+};
diff --git a/audio-rag/native/src/RagStore/FileDisplay/index.tsx b/audio-rag/native/src/RagStore/FileDisplay/index.tsx
new file mode 100644
index 0000000..654d05c
--- /dev/null
+++ b/audio-rag/native/src/RagStore/FileDisplay/index.tsx
@@ -0,0 +1,30 @@
+import React from 'react';
+import {StyleSheet, Text, View} from 'react-native';
+
+import {getFileType} from '../utils';
+
+export const FileDisplay = ({file}: {file: string}) => {
+ return (
+ <>
+
+ {file}
+ {getFileType(file)}
+
+ >
+ );
+};
+const styles = StyleSheet.create({
+ filename: {
+ fontWeight: '700',
+ paddingRight: 20,
+ },
+ filetype: {
+ fontStyle: 'italic',
+ fontWeight: '400',
+ },
+ file: {
+ flexDirection: 'row',
+ height: 40,
+ padding: 10,
+ },
+});
diff --git a/audio-rag/native/src/RagStore/index.tsx b/audio-rag/native/src/RagStore/index.tsx
new file mode 100644
index 0000000..2a477cb
--- /dev/null
+++ b/audio-rag/native/src/RagStore/index.tsx
@@ -0,0 +1,59 @@
+import React, {useCallback, useEffect, useState} from 'react';
+import {Button, StyleSheet, Text} from 'react-native';
+
+import DocumentPicker from 'react-native-document-picker';
+import {fetchFileList, sendFile} from './utils';
+import {FileDisplay} from './FileDisplay';
+
+export const RagStore = () => {
+ const [files, setFiles] = useState([]);
+ useEffect(() => {
+ fetchFileList().then(res => {
+ setFiles(res);
+ });
+ }, []);
+
+ const handleDocumentSelection = useCallback(async () => {
+ try {
+ const response = await DocumentPicker.pick({
+ allowMultiSelection: false,
+ presentationStyle: 'fullScreen',
+ });
+ await sendFile(response);
+ setFiles(await fetchFileList());
+ } catch (err: any) {
+ console.warn(err);
+ }
+ }, []);
+ return (
+ <>
+ RAG store
+
+ {files.map(file => (
+
+ ))}
+ >
+ );
+};
+
+const styles = StyleSheet.create({
+ filename: {
+ fontWeight: '700',
+ paddingRight: 20,
+ },
+ filetype: {
+ fontStyle: 'italic',
+ fontWeight: '400',
+ },
+ file: {
+ flexDirection: 'row',
+ height: 40,
+ padding: 10,
+ },
+ title: {
+ fontSize: 32,
+ },
+ highlight: {
+ fontWeight: '700',
+ },
+});
diff --git a/audio-rag/native/src/RagStore/utils.ts b/audio-rag/native/src/RagStore/utils.ts
new file mode 100644
index 0000000..45ce4e8
--- /dev/null
+++ b/audio-rag/native/src/RagStore/utils.ts
@@ -0,0 +1,40 @@
+import {constants} from '../constants';
+import {DocumentPickerResponse} from 'react-native-document-picker';
+
+export const fetchFileList = async () => {
+ const res = await fetch(new URL('/files', constants.ENDPOINT_URI));
+ const json = await res.json();
+ return json;
+};
+
+export const sendFile = async (response: DocumentPickerResponse[]) => {
+ if (response.length !== 1) {
+ throw 'sendFile can only be used with single files';
+ }
+ let data = new FormData();
+ data.append('file', {
+ uri: response[0].uri,
+ type: response[0].type,
+ name: response[0].name,
+ });
+ await fetch(new URL('/upload', constants.ENDPOINT_URI), {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'multipart/form-data',
+ },
+ body: data,
+ });
+};
+
+export const getFileType = (filename: string) => {
+ switch (filename.split('.').at(-1)) {
+ case 'txt':
+ return 'Text file';
+ case 'wav':
+ return 'WAV Sound recording';
+ case 'pdf':
+ return 'PDF document';
+ default:
+ return '<>';
+ }
+};
diff --git a/audio-rag/native/src/constants.ts b/audio-rag/native/src/constants.ts
index a572eb2..2005418 100644
--- a/audio-rag/native/src/constants.ts
+++ b/audio-rag/native/src/constants.ts
@@ -1,3 +1,3 @@
export const constants = {
- ENDPOINT_URI: "http://minisforum:5000"
-}
+ ENDPOINT_URI: 'http://minisforum:5000',
+};
diff --git a/audio-rag/native/src/utils.ts b/audio-rag/native/src/utils.ts
new file mode 100644
index 0000000..9c97cd9
--- /dev/null
+++ b/audio-rag/native/src/utils.ts
@@ -0,0 +1 @@
+export type AppMode = 'chat' | 'store';
diff --git a/audio-rag/native/yarn.lock b/audio-rag/native/yarn.lock
index 61951d9..320660b 100644
--- a/audio-rag/native/yarn.lock
+++ b/audio-rag/native/yarn.lock
@@ -3342,7 +3342,6 @@ __metadata:
react: 18.2.0
react-native: 0.74.1
react-native-document-picker: ^9.2.0
- react-test-renderer: 18.2.0
typescript: 5.0.4
languageName: unknown
linkType: soft
@@ -7939,7 +7938,7 @@ __metadata:
languageName: node
linkType: hard
-"react-is@npm:^16.12.0 || ^17.0.0 || ^18.0.0, react-is@npm:^18.0.0, react-is@npm:^18.2.0":
+"react-is@npm:^16.12.0 || ^17.0.0 || ^18.0.0, react-is@npm:^18.0.0":
version: 18.3.1
resolution: "react-is@npm:18.3.1"
checksum: e20fe84c86ff172fc8d898251b7cc2c43645d108bf96d0b8edf39b98f9a2cae97b40520ee7ed8ee0085ccc94736c4886294456033304151c3f94978cec03df21
@@ -8048,19 +8047,6 @@ __metadata:
languageName: node
linkType: hard
-"react-test-renderer@npm:18.2.0":
- version: 18.2.0
- resolution: "react-test-renderer@npm:18.2.0"
- dependencies:
- react-is: ^18.2.0
- react-shallow-renderer: ^16.15.0
- scheduler: ^0.23.0
- peerDependencies:
- react: ^18.2.0
- checksum: 6b6980ced93fa2b72662d5e4ab3b4896833586940047ce52ca9aca801e5432adf05fcbe28289b0af3ce6a2a7c590974e25dcc8aa43d0de658bfe8bbcd686f958
- languageName: node
- linkType: hard
-
"react@npm:18.2.0":
version: 18.2.0
resolution: "react@npm:18.2.0"
@@ -8417,15 +8403,6 @@ __metadata:
languageName: node
linkType: hard
-"scheduler@npm:^0.23.0":
- version: 0.23.2
- resolution: "scheduler@npm:0.23.2"
- dependencies:
- loose-envify: ^1.1.0
- checksum: 3e82d1f419e240ef6219d794ff29c7ee415fbdc19e038f680a10c067108e06284f1847450a210b29bbaf97b9d8a97ced5f624c31c681248ac84c80d56ad5a2c4
- languageName: node
- linkType: hard
-
"selfsigned@npm:^2.4.1":
version: 2.4.1
resolution: "selfsigned@npm:2.4.1"