richlai commited on
Commit
7781557
·
0 Parent(s):
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .env.example +11 -0
  2. .gitignore +71 -0
  3. Dockerfile +39 -0
  4. README.md +73 -0
  5. aimakerspace/__init__.py +0 -0
  6. aimakerspace/openai_utils/__init__.py +0 -0
  7. aimakerspace/openai_utils/chatmodel.py +45 -0
  8. aimakerspace/openai_utils/embedding.py +59 -0
  9. aimakerspace/openai_utils/prompts.py +78 -0
  10. aimakerspace/text_utils.py +77 -0
  11. aimakerspace/vectordatabase.py +81 -0
  12. backend/__init__.py +0 -0
  13. backend/app/__init__.py +0 -0
  14. backend/app/agents/__init__.py +0 -0
  15. backend/app/auth.py +56 -0
  16. backend/app/classes.py +160 -0
  17. backend/app/data/AIE4_SalesBuddy_QandA.csv +93 -0
  18. backend/app/data/BetterTech Lending Analytics Solution.pdf +0 -0
  19. backend/app/data/BetterTechLendingAnalyticsSolution.txt +39 -0
  20. backend/app/data/HSBC Opportunity Information.docx +0 -0
  21. backend/app/data/HSBC_background.txt +47 -0
  22. backend/app/data/Opportunity_Information.csv +3 -0
  23. backend/app/data/salesbud_examples.csv +93 -0
  24. backend/app/data/user_response_20241014_110603.csv +21 -0
  25. backend/app/db/__init__.py +0 -0
  26. backend/app/db/database.py +17 -0
  27. backend/app/db/database_dynamodb.py +57 -0
  28. backend/app/db/database_mongodb.py +194 -0
  29. backend/app/db/models.py +27 -0
  30. backend/app/llm_models.py +48 -0
  31. backend/app/main.py +151 -0
  32. backend/app/prompts.py +8 -0
  33. backend/app/reports/HSBC Opportunity Review Report.md +71 -0
  34. backend/app/reports/HSBC Quarterly Report 2024-10-16 00-39-38.pdf +0 -0
  35. backend/app/reports/HSBC Quarterly Report 2024-10-16 09_36_43.pdf +0 -0
  36. backend/app/reports/HSBC Quarterly Report 2024-10-16.md +29 -0
  37. backend/app/reports/HSBC Quarterly Report 2024-10-16.pdf +0 -0
  38. backend/app/reports/HSBC Quarterly Report 2024-10-19.md +33 -0
  39. backend/app/reports/HSBC Quarterly Report 2024-10-19.pdf +0 -0
  40. backend/app/utils/__init__.py +0 -0
  41. backend/app/utils/images/salesbuddy_logo.jpg +0 -0
  42. backend/app/utils/utils_actions.py +21 -0
  43. backend/app/utils/utils_callbacks.py +99 -0
  44. backend/app/utils/utils_chain_parameters.py +82 -0
  45. backend/app/utils/utils_control_messages.py +26 -0
  46. backend/app/utils/utils_customer_research.py +341 -0
  47. backend/app/utils/utils_data.py +186 -0
  48. backend/app/utils/utils_evaluate.py +100 -0
  49. backend/app/utils/utils_evaluate_objections.py +152 -0
  50. backend/app/utils/utils_objections.py +201 -0
.env.example ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ OPENAI_API_KEY=
2
+ TAVILY_API_KEY=
3
+ LANGCHAIN_API_KEY=
4
+ PPLX_API_KEY=
5
+ AWS_ACCESS_KEY_ID=
6
+ AWS_SECRET_ACCESS_KEY=
7
+ AWS_REGION=
8
+ SECRET_KEY=
9
+ DB_TYPE=
10
+ MONGODB_URI=
11
+ MONGODB_DB=
.gitignore ADDED
@@ -0,0 +1,71 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .env
2
+ .DS_Store
3
+ node_modules/
4
+
5
+ dist/
6
+ *.tsbuildinfo
7
+
8
+ # Python
9
+ __pycache__/
10
+ *.py[cod]
11
+ *$py.class
12
+ *.so
13
+ .Python
14
+ build/
15
+ develop-eggs/
16
+ dist/
17
+ downloads/
18
+ eggs/
19
+ .eggs/
20
+ lib64/
21
+ parts/
22
+ sdist/
23
+ var/
24
+ wheels/
25
+ share/python-wheels/
26
+ *.egg-info/
27
+ .installed.cfg
28
+ *.egg
29
+
30
+ # Virtual Environment
31
+ venv/
32
+ env/
33
+ ENV/
34
+
35
+ # IDEs and Editors
36
+ .vscode/
37
+ .idea/
38
+ *.swp
39
+ *.swo
40
+ *~
41
+
42
+ # OS generated files
43
+ .DS_Store
44
+ .DS_Store?
45
+ ._*
46
+ .Spotlight-V100
47
+ .Trashes
48
+ ehthumbs.db
49
+ Thumbs.db
50
+
51
+ # Logs
52
+ *.log
53
+ npm-debug.log*
54
+ yarn-debug.log*
55
+ yarn-error.log*
56
+
57
+ # Testing
58
+ coverage/
59
+ .nyc_output
60
+ .pytest_cache/
61
+
62
+ # Miscellaneous
63
+ .env
64
+ .env.local
65
+ .env.development.local
66
+ .env.test.local
67
+ .env.production.local
68
+
69
+ .ipynb_checkpoints/
70
+
71
+ .files/
Dockerfile ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.11
2
+
3
+ RUN apt-get update && apt-get install -y \
4
+ curl \
5
+ && curl -fsSL https://deb.nodesource.com/setup_lts.20.15.1| bash - \
6
+ && apt-get install -y nodejs \
7
+ && apt-get clean \
8
+ && rm -rf /var/lib/apt/lists/*
9
+
10
+ RUN apt-get update && apt-get install -y npm
11
+
12
+ # Verify installation
13
+ RUN node --version
14
+ RUN npm --version
15
+ RUN useradd -m -u 1000 user
16
+ USER user
17
+ ENV HOME=/home/user \
18
+ PATH=/home/user/.local/bin:$PATH
19
+ WORKDIR $HOME/app
20
+ COPY --chown=user . $HOME/app
21
+ COPY ./requirements.txt ~/app/requirements.txt
22
+ RUN pip install -r requirements.txt
23
+ COPY . .
24
+
25
+ USER root
26
+ WORKDIR $HOME/app/frontend
27
+ RUN npm install -g pnpm
28
+ RUN npm install
29
+ RUN npm audit fix
30
+ RUN pnpm run build
31
+ RUN chown -R user:user $HOME/app/frontend
32
+ RUN chown -R user:user $HOME/app/backend
33
+ USER user
34
+
35
+ # Change back to app directory
36
+ WORKDIR $HOME/app
37
+ EXPOSE 5173
38
+ EXPOSE 8080
39
+ CMD ["/bin/bash", "-c", "./run.sh"]
README.md ADDED
@@ -0,0 +1,73 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ title: SalesBuddy for BetterTech
3
+ emoji: 👁
4
+ colorFrom: pink
5
+ colorTo: blue
6
+ sdk: docker
7
+ pinned: false
8
+ license: mit
9
+ short_description: AIE4 Project - SalesBuddy for BetterTech
10
+ ---
11
+
12
+ # SalesBuddy for BetterTech
13
+
14
+ ## Description
15
+ SalesBuddy for BetterTech
16
+
17
+ ## Prerequisites
18
+ - Python 3.11
19
+ - pip
20
+
21
+ ## Steps to Setup and Run the Project Locally
22
+
23
+ ### 1. Clone the Remote Repository Locally
24
+
25
+ Assuming that you are in the directory where you want to clone the repository (`project-directory`), run the following command to clone the repository locally:
26
+ ```bash
27
+ git clone [email protected]:aithon-ai/SalesBuddy.git .
28
+ cd <project-directory>
29
+ ```
30
+
31
+ ### 2. Create a Virtual Environment
32
+
33
+ Create a virtual environment with python 3.11 for compatibility.
34
+
35
+ If not familiar with creating virtual environments, follow the steps below:
36
+ ```bash
37
+ python3.11 -m venv venv
38
+ source venv/bin/activate # For Linux
39
+ venv\Scripts\activate # For Windows
40
+ ```
41
+
42
+ ### 3. Install Required Libraries
43
+ ```bash
44
+ pip install -r requirements.txt
45
+ ```
46
+
47
+ ### 4. Add your API Keys to the `.env` file
48
+ Copy the .env.sample file to .env and add your API keys to the file.
49
+
50
+
51
+ ## Local Development
52
+
53
+ We recommend using node version 20.11.0 and pnpm version 9.1.0.
54
+
55
+ Go to the frontend directory and install the dependencies:
56
+
57
+ ```bash
58
+ cd frontend
59
+ pnpm install
60
+ ```
61
+
62
+ You must build the frontend before running the application:
63
+ ```bash
64
+ cd frontend
65
+ pnpm run build
66
+ ```
67
+
68
+ To run the application locally, at the main folder, run the following command in the terminal:
69
+ ```bash
70
+ ./run.sh
71
+ ```
72
+
73
+ The application will be available at http://localhost:8080 and http://localhost:8080/chainlit. The latter uses the Chainlit UI. The former is the React.js version in progress
aimakerspace/__init__.py ADDED
File without changes
aimakerspace/openai_utils/__init__.py ADDED
File without changes
aimakerspace/openai_utils/chatmodel.py ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from openai import OpenAI, AsyncOpenAI
2
+ from dotenv import load_dotenv
3
+ import os
4
+
5
+ load_dotenv()
6
+
7
+
8
+ class ChatOpenAI:
9
+ def __init__(self, model_name: str = "gpt-4o-mini"):
10
+ self.model_name = model_name
11
+ self.openai_api_key = os.getenv("OPENAI_API_KEY")
12
+ if self.openai_api_key is None:
13
+ raise ValueError("OPENAI_API_KEY is not set")
14
+
15
+ def run(self, messages, text_only: bool = True, **kwargs):
16
+ if not isinstance(messages, list):
17
+ raise ValueError("messages must be a list")
18
+
19
+ client = OpenAI()
20
+ response = client.chat.completions.create(
21
+ model=self.model_name, messages=messages, **kwargs
22
+ )
23
+
24
+ if text_only:
25
+ return response.choices[0].message.content
26
+
27
+ return response
28
+
29
+ async def astream(self, messages, **kwargs):
30
+ if not isinstance(messages, list):
31
+ raise ValueError("messages must be a list")
32
+
33
+ client = AsyncOpenAI()
34
+
35
+ stream = await client.chat.completions.create(
36
+ model=self.model_name,
37
+ messages=messages,
38
+ stream=True,
39
+ **kwargs
40
+ )
41
+
42
+ async for chunk in stream:
43
+ content = chunk.choices[0].delta.content
44
+ if content is not None:
45
+ yield content
aimakerspace/openai_utils/embedding.py ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from dotenv import load_dotenv
2
+ from openai import AsyncOpenAI, OpenAI
3
+ import openai
4
+ from typing import List
5
+ import os
6
+ import asyncio
7
+
8
+
9
+ class EmbeddingModel:
10
+ def __init__(self, embeddings_model_name: str = "text-embedding-3-small"):
11
+ load_dotenv()
12
+ self.openai_api_key = os.getenv("OPENAI_API_KEY")
13
+ self.async_client = AsyncOpenAI()
14
+ self.client = OpenAI()
15
+
16
+ if self.openai_api_key is None:
17
+ raise ValueError(
18
+ "OPENAI_API_KEY environment variable is not set. Please set it to your OpenAI API key."
19
+ )
20
+ openai.api_key = self.openai_api_key
21
+ self.embeddings_model_name = embeddings_model_name
22
+
23
+ async def async_get_embeddings(self, list_of_text: List[str]) -> List[List[float]]:
24
+ embedding_response = await self.async_client.embeddings.create(
25
+ input=list_of_text, model=self.embeddings_model_name
26
+ )
27
+
28
+ return [embeddings.embedding for embeddings in embedding_response.data]
29
+
30
+ async def async_get_embedding(self, text: str) -> List[float]:
31
+ embedding = await self.async_client.embeddings.create(
32
+ input=text, model=self.embeddings_model_name
33
+ )
34
+
35
+ return embedding.data[0].embedding
36
+
37
+ def get_embeddings(self, list_of_text: List[str]) -> List[List[float]]:
38
+ embedding_response = self.client.embeddings.create(
39
+ input=list_of_text, model=self.embeddings_model_name
40
+ )
41
+
42
+ return [embeddings.embedding for embeddings in embedding_response.data]
43
+
44
+ def get_embedding(self, text: str) -> List[float]:
45
+ embedding = self.client.embeddings.create(
46
+ input=text, model=self.embeddings_model_name
47
+ )
48
+
49
+ return embedding.data[0].embedding
50
+
51
+
52
+ if __name__ == "__main__":
53
+ embedding_model = EmbeddingModel()
54
+ print(asyncio.run(embedding_model.async_get_embedding("Hello, world!")))
55
+ print(
56
+ asyncio.run(
57
+ embedding_model.async_get_embeddings(["Hello, world!", "Goodbye, world!"])
58
+ )
59
+ )
aimakerspace/openai_utils/prompts.py ADDED
@@ -0,0 +1,78 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import re
2
+
3
+
4
+ class BasePrompt:
5
+ def __init__(self, prompt):
6
+ """
7
+ Initializes the BasePrompt object with a prompt template.
8
+
9
+ :param prompt: A string that can contain placeholders within curly braces
10
+ """
11
+ self.prompt = prompt
12
+ self._pattern = re.compile(r"\{([^}]+)\}")
13
+
14
+ def format_prompt(self, **kwargs):
15
+ """
16
+ Formats the prompt string using the keyword arguments provided.
17
+
18
+ :param kwargs: The values to substitute into the prompt string
19
+ :return: The formatted prompt string
20
+ """
21
+ matches = self._pattern.findall(self.prompt)
22
+ return self.prompt.format(**{match: kwargs.get(match, "") for match in matches})
23
+
24
+ def get_input_variables(self):
25
+ """
26
+ Gets the list of input variable names from the prompt string.
27
+
28
+ :return: List of input variable names
29
+ """
30
+ return self._pattern.findall(self.prompt)
31
+
32
+
33
+ class RolePrompt(BasePrompt):
34
+ def __init__(self, prompt, role: str):
35
+ """
36
+ Initializes the RolePrompt object with a prompt template and a role.
37
+
38
+ :param prompt: A string that can contain placeholders within curly braces
39
+ :param role: The role for the message ('system', 'user', or 'assistant')
40
+ """
41
+ super().__init__(prompt)
42
+ self.role = role
43
+
44
+ def create_message(self, format=True, **kwargs):
45
+ """
46
+ Creates a message dictionary with a role and a formatted message.
47
+
48
+ :param kwargs: The values to substitute into the prompt string
49
+ :return: Dictionary containing the role and the formatted message
50
+ """
51
+ if format:
52
+ return {"role": self.role, "content": self.format_prompt(**kwargs)}
53
+
54
+ return {"role": self.role, "content": self.prompt}
55
+
56
+
57
+ class SystemRolePrompt(RolePrompt):
58
+ def __init__(self, prompt: str):
59
+ super().__init__(prompt, "system")
60
+
61
+
62
+ class UserRolePrompt(RolePrompt):
63
+ def __init__(self, prompt: str):
64
+ super().__init__(prompt, "user")
65
+
66
+
67
+ class AssistantRolePrompt(RolePrompt):
68
+ def __init__(self, prompt: str):
69
+ super().__init__(prompt, "assistant")
70
+
71
+
72
+ if __name__ == "__main__":
73
+ prompt = BasePrompt("Hello {name}, you are {age} years old")
74
+ print(prompt.format_prompt(name="John", age=30))
75
+
76
+ prompt = SystemRolePrompt("Hello {name}, you are {age} years old")
77
+ print(prompt.create_message(name="John", age=30))
78
+ print(prompt.get_input_variables())
aimakerspace/text_utils.py ADDED
@@ -0,0 +1,77 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ from typing import List
3
+
4
+
5
+ class TextFileLoader:
6
+ def __init__(self, path: str, encoding: str = "utf-8"):
7
+ self.documents = []
8
+ self.path = path
9
+ self.encoding = encoding
10
+
11
+ def load(self):
12
+ if os.path.isdir(self.path):
13
+ self.load_directory()
14
+ elif os.path.isfile(self.path) and self.path.endswith(".txt"):
15
+ self.load_file()
16
+ else:
17
+ raise ValueError(
18
+ "Provided path is neither a valid directory nor a .txt file."
19
+ )
20
+
21
+ def load_file(self):
22
+ with open(self.path, "r", encoding=self.encoding) as f:
23
+ self.documents.append(f.read())
24
+
25
+ def load_directory(self):
26
+ for root, _, files in os.walk(self.path):
27
+ for file in files:
28
+ if file.endswith(".txt"):
29
+ with open(
30
+ os.path.join(root, file), "r", encoding=self.encoding
31
+ ) as f:
32
+ self.documents.append(f.read())
33
+
34
+ def load_documents(self):
35
+ self.load()
36
+ return self.documents
37
+
38
+
39
+ class CharacterTextSplitter:
40
+ def __init__(
41
+ self,
42
+ chunk_size: int = 1000,
43
+ chunk_overlap: int = 200,
44
+ ):
45
+ assert (
46
+ chunk_size > chunk_overlap
47
+ ), "Chunk size must be greater than chunk overlap"
48
+
49
+ self.chunk_size = chunk_size
50
+ self.chunk_overlap = chunk_overlap
51
+
52
+ def split(self, text: str) -> List[str]:
53
+ chunks = []
54
+ for i in range(0, len(text), self.chunk_size - self.chunk_overlap):
55
+ chunks.append(text[i : i + self.chunk_size])
56
+ return chunks
57
+
58
+ def split_texts(self, texts: List[str]) -> List[str]:
59
+ chunks = []
60
+ for text in texts:
61
+ chunks.extend(self.split(text))
62
+ return chunks
63
+
64
+
65
+ if __name__ == "__main__":
66
+ loader = TextFileLoader("data/KingLear.txt")
67
+ loader.load()
68
+ splitter = CharacterTextSplitter()
69
+ chunks = splitter.split_texts(loader.documents)
70
+ print(len(chunks))
71
+ print(chunks[0])
72
+ print("--------")
73
+ print(chunks[1])
74
+ print("--------")
75
+ print(chunks[-2])
76
+ print("--------")
77
+ print(chunks[-1])
aimakerspace/vectordatabase.py ADDED
@@ -0,0 +1,81 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+ from collections import defaultdict
3
+ from typing import List, Tuple, Callable
4
+ from aimakerspace.openai_utils.embedding import EmbeddingModel
5
+ import asyncio
6
+
7
+
8
+ def cosine_similarity(vector_a: np.array, vector_b: np.array) -> float:
9
+ """Computes the cosine similarity between two vectors."""
10
+ dot_product = np.dot(vector_a, vector_b)
11
+ norm_a = np.linalg.norm(vector_a)
12
+ norm_b = np.linalg.norm(vector_b)
13
+ return dot_product / (norm_a * norm_b)
14
+
15
+
16
+ class VectorDatabase:
17
+ def __init__(self, embedding_model: EmbeddingModel = None):
18
+ self.vectors = defaultdict(np.array)
19
+ self.embedding_model = embedding_model or EmbeddingModel()
20
+
21
+ def insert(self, key: str, vector: np.array) -> None:
22
+ self.vectors[key] = vector
23
+
24
+ def search(
25
+ self,
26
+ query_vector: np.array,
27
+ k: int,
28
+ distance_measure: Callable = cosine_similarity,
29
+ ) -> List[Tuple[str, float]]:
30
+ scores = [
31
+ (key, distance_measure(query_vector, vector))
32
+ for key, vector in self.vectors.items()
33
+ ]
34
+ return sorted(scores, key=lambda x: x[1], reverse=True)[:k]
35
+
36
+ def search_by_text(
37
+ self,
38
+ query_text: str,
39
+ k: int,
40
+ distance_measure: Callable = cosine_similarity,
41
+ return_as_text: bool = False,
42
+ ) -> List[Tuple[str, float]]:
43
+ query_vector = self.embedding_model.get_embedding(query_text)
44
+ results = self.search(query_vector, k, distance_measure)
45
+ return [result[0] for result in results] if return_as_text else results
46
+
47
+ def retrieve_from_key(self, key: str) -> np.array:
48
+ return self.vectors.get(key, None)
49
+
50
+ async def abuild_from_list(self, list_of_text: List[str]) -> "VectorDatabase":
51
+ embeddings = await self.embedding_model.async_get_embeddings(list_of_text)
52
+ for text, embedding in zip(list_of_text, embeddings):
53
+ self.insert(text, np.array(embedding))
54
+ return self
55
+
56
+
57
+ if __name__ == "__main__":
58
+ list_of_text = [
59
+ "I like to eat broccoli and bananas.",
60
+ "I ate a banana and spinach smoothie for breakfast.",
61
+ "Chinchillas and kittens are cute.",
62
+ "My sister adopted a kitten yesterday.",
63
+ "Look at this cute hamster munching on a piece of broccoli.",
64
+ ]
65
+
66
+ vector_db = VectorDatabase()
67
+ vector_db = asyncio.run(vector_db.abuild_from_list(list_of_text))
68
+ k = 2
69
+
70
+ searched_vector = vector_db.search_by_text("I think fruit is awesome!", k=k)
71
+ print(f"Closest {k} vector(s):", searched_vector)
72
+
73
+ retrieved_vector = vector_db.retrieve_from_key(
74
+ "I like to eat broccoli and bananas."
75
+ )
76
+ print("Retrieved vector:", retrieved_vector)
77
+
78
+ relevant_texts = vector_db.search_by_text(
79
+ "I think fruit is awesome!", k=k, return_as_text=True
80
+ )
81
+ print(f"Closest {k} text(s):", relevant_texts)
backend/__init__.py ADDED
File without changes
backend/app/__init__.py ADDED
File without changes
backend/app/agents/__init__.py ADDED
File without changes
backend/app/auth.py ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ from dotenv import load_dotenv
3
+ import datetime
4
+ from datetime import timedelta
5
+ from typing import Optional
6
+ from jose import JWTError, jwt
7
+ from passlib.context import CryptContext
8
+ from fastapi import Depends, HTTPException, status
9
+ from fastapi.security import OAuth2PasswordBearer
10
+ from .db.database import get_user_by_username
11
+ from .db.models import User, TokenData
12
+
13
+ load_dotenv()
14
+
15
+ SECRET_KEY = os.getenv("SECRET_KEY") or "aithon-secret-1108"
16
+ ALGORITHM = "HS256"
17
+ ACCESS_TOKEN_EXPIRE_MINUTES = 30
18
+
19
+ pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
20
+ oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
21
+
22
+ def verify_password(plain_password: str, hashed_password: str) -> bool:
23
+ return pwd_context.verify(plain_password, hashed_password)
24
+
25
+ def get_password_hash(password: str) -> str:
26
+ return pwd_context.hash(password)
27
+
28
+ def create_access_token(data: dict, expires_delta: Optional[timedelta] = None):
29
+ to_encode = data.copy()
30
+ if expires_delta:
31
+ expire = datetime.datetime.now(datetime.UTC) + expires_delta
32
+ else:
33
+ expire = datetime.datetime.now(datetime.UTC) + timedelta(minutes=15)
34
+ to_encode.update({"exp": expire})
35
+ encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
36
+ return encoded_jwt
37
+
38
+ async def get_current_user(token: str = Depends(oauth2_scheme)) -> User:
39
+ credentials_exception = HTTPException(
40
+ status_code=status.HTTP_401_UNAUTHORIZED,
41
+ detail="Could not validate credentials",
42
+ headers={"WWW-Authenticate": "Bearer"},
43
+ )
44
+ try:
45
+ payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
46
+ username: str = payload.get("sub")
47
+ if username is None:
48
+ raise credentials_exception
49
+ token_data = TokenData(username=username)
50
+ except JWTError:
51
+ raise credentials_exception
52
+
53
+ user = await get_user_by_username(token_data.username)
54
+ if user is None:
55
+ raise credentials_exception
56
+ return user
backend/app/classes.py ADDED
@@ -0,0 +1,160 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ class SessionState:
2
+ session_stage = ""
3
+ do_evaluation = False
4
+ do_opportunity_analysis = False
5
+ do_customer_research = False
6
+ do_objections = False
7
+ add_objections_to_analysis = True
8
+ ask_objections = True
9
+ use_objection_cache = True
10
+ do_ragas_evaluation = False
11
+ customer_research_report_md = "HSBC Quarterly Report 2024-10-19.md"
12
+ customer_research_report_pdf = "HSBC Quarterly Report 2024-10-19.pdf"
13
+ bettetech_value_proposition_pdf = "BetterTech Lending Analytics Solution.pdf"
14
+ do_voice = True
15
+ status = "active"
16
+ scenario = None
17
+ qa_mode = "single"
18
+ questions = []
19
+ start_time = None
20
+ end_time = None
21
+ duration_minutes = None
22
+ attitude = "Happy"
23
+ mood_score = 5
24
+ num_questions = 2
25
+ current_question_index = 0
26
+ previous_answer = None
27
+ question = ""
28
+ ground_truth = ""
29
+ rep_answer = ""
30
+ responses = []
31
+ queries = []
32
+ llm_responses = []
33
+ command = ""
34
+ scores = []
35
+ llm_next_steps = ""
36
+ opportunity_review_results = None
37
+ opportunity_review_report = None
38
+ def __init__(self):
39
+ self.company = None
40
+ self.customer = None
41
+ self.opportunity = None
42
+ self.scenario = None
43
+ self.session_stage = "research"
44
+ self.do_evaluation = False
45
+ self.do_opportunity_analysis = False
46
+ self.do_customer_research = False
47
+ self.do_objections = False
48
+ self.add_objections_to_analysis = True
49
+ self.ask_objections = True
50
+ self.use_objection_cache = True
51
+ self.do_ragas_evaluation = False
52
+ self.customer_research_report_md = "HSBC Quarterly Report 2024-10-19.md"
53
+ self.customer_research_report_pdf = "HSBC Quarterly Report 2024-10-19.pdf"
54
+ self.bettetech_value_proposition_pdf = "BetterTech Lending Analytics Solution.pdf"
55
+ self.do_voice = True
56
+ self.status = "active"
57
+ self.scenario = None
58
+ self.qa_mode = "single"
59
+ self.questions = []
60
+ self.start_time = None
61
+ self.end_time = None
62
+ self.duration_minutes = None
63
+ self.attitude = "Happy"
64
+ self.mood_score = 5
65
+ self.num_questions = 2
66
+ self.current_question_index = 0
67
+ self.previous_answer = None
68
+ self.question = ""
69
+ self.ground_truth = ""
70
+ self.rep_answer = ""
71
+ self.responses = []
72
+ self.queries = []
73
+ self.llm_responses = []
74
+ self.command = ""
75
+ self.scores = []
76
+ self.llm_next_steps = ""
77
+ self.company = None
78
+ self.customer = None
79
+ self.opportunity = None
80
+ self.scenario = None
81
+ self.opportunity_review_results = None
82
+ self.opportunity_review_report = None
83
+ class Company:
84
+ def __init__(self, name, description, product, product_summary, product_description):
85
+ self.name = name
86
+ self.description = description
87
+ self.product = product
88
+ self.product_summary = product_summary
89
+ self.product_description = product_description
90
+
91
+ class Customer:
92
+ def __init__(self, name, contact_name, contact_role):
93
+ self.name = name
94
+ self.contact_name = contact_name
95
+ self.contact_role = contact_role
96
+ self.background = None
97
+
98
+
99
+ class Opportunity:
100
+ def __init__(self, id, name, stage, description, value, close_date, activity, next_steps):
101
+ self.id = id
102
+ self.name = name
103
+ self.stage = stage
104
+ self.description = description
105
+ self.value = value
106
+ self.close_date = close_date
107
+ self.activity = activity
108
+ self.next_steps = next_steps
109
+
110
+
111
+
112
+ def add_company_info(self, name, description, product, product_summary, product_description):
113
+ self.company = self.Company(name, description, product, product_summary, product_description)
114
+
115
+ def add_customer_info(self, name, contact_name, contact_role):
116
+ self.customer = self.Customer(name, contact_name, contact_role)
117
+
118
+ def add_opportunity_info(self, id, name, stage, description, value, close_date, activity, next_steps):
119
+ self.opportunity = self.Opportunity(id, name, stage, description, value, close_date, activity, next_steps)
120
+
121
+ def add_scenario_info(self, scenario_data):
122
+ self.scenario = scenario_data
123
+ self.add_opportunity_info(
124
+ id=scenario_data['Opportunity ID'],
125
+ name=scenario_data['Opportunity Name'],
126
+ stage=scenario_data['Opportunity Stage'],
127
+ description=scenario_data['Opportunity Description'],
128
+ value=scenario_data['Opportunity Value'],
129
+ close_date=scenario_data['Close Date'],
130
+ activity=scenario_data['Activity'],
131
+ next_steps=scenario_data['Next Steps']
132
+ )
133
+ self.add_customer_info(
134
+ name=scenario_data['Customer Name'],
135
+ contact_name=scenario_data['Customer Contact'],
136
+ contact_role=scenario_data['Customer Contact Role']
137
+ )
138
+
139
+ def get_opening(self):
140
+ output_lines = [
141
+ "**Simulation Scenario**",
142
+ f"**Customer:** {self.customer.name if self.customer else 'Unknown'}",
143
+ f"**Opportunity:** {self.opportunity.name if self.opportunity else 'Unknown'}",
144
+ f"**Value:** {self.opportunity.value if self.opportunity and hasattr(self.opportunity, 'value') else 'Unknown'}",
145
+ f"**Stage:** {self.opportunity.stage if self.opportunity else 'N/A'}",
146
+ f"**Target Close Date:** {self.opportunity.close_date if self.opportunity and hasattr(self.opportunity, 'close_date') else 'Unknown'}",
147
+ f"**Opportunity Description:** {self.opportunity.description if self.opportunity else 'Unknown'}",
148
+ f"**Meeting with:** {self.customer.contact_name} ({self.customer.contact_role})",
149
+ f"**Activity:** {self.opportunity.activity if self.opportunity and hasattr(self.opportunity, 'activity') else 'Unknown'}",
150
+ f"**Current Meeting:** {self.opportunity.next_steps if self.opportunity and hasattr(self.opportunity, 'next_steps') else 'Unknown'}"
151
+ ]
152
+ output = "\n".join(output_lines)
153
+ return output
154
+
155
+ def __str__(self):
156
+ company_info = f"{self.company.name} - " if self.company else ""
157
+ customer_info = f"for {self.customer.name}" if self.customer else "No Customer"
158
+ opportunity_info = f"{self.opportunity.name} ({self.opportunity.stage})" if self.opportunity else "No opportunity set"
159
+ return f"{company_info}SessionState: {customer_info} {opportunity_info}".strip()
160
+
backend/app/data/AIE4_SalesBuddy_QandA.csv ADDED
@@ -0,0 +1,93 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Stage,Customer Question (Provided by Claude),Salesperson Response (Provided by Claude),Ground Truth (Provided by Nitin). Marked as Salesperson 2 by Claude,Rating of Salesperson response (per Claude),Rating of Groundtruth (per Claude),Comments (per Claude)
2
+ Discovery,What exactly does your software do?,"""Our software is a comprehensive financial data analytics platform. It aggregates data from multiple sources, provides real-time insights, and helps financial institutions make data-driven decisions more efficiently.""","Our software is a comprehensive financial data analytics platform. It aggregates data from multiple sources, provides real-time insights, and helps financial institutions make data-driven decisions.
3
+ Our customer list includes 15 of the Fortune 100 companies. PNC bank is one of our customers and they aggregated data from their different loan systems to reduce charge-offs by 17%, and costs by 30%.
4
+ Can you share a little about your data challenges in your organization?",7,9,Salesperson 2 provides more specific details and examples
5
+ Discovery,How is your solution different from what we're currently using?,"""I'd love to learn more about your current system. Our solution stands out with its AI-powered predictive analytics and ability to integrate seamlessly with a wide range of financial systems. Could you tell me about your current pain points?""","The main reasons cited by our customers for selecting our software are the AI-powered predictive analytics and ability to integrate seamlessly with a wide range of financial systems. A large credit union customer said that our AI capabilities were far superior than what they would have developed internally.
6
+ It will be super helpful for me to learn about your current system and your pain points to explore if there is a fit",8,9,Salesperson 2 offers concrete examples and asks about pain points
7
+ Discovery,Can your software handle the volume of transactions we process daily?,"Absolutely. Our platform is designed to handle high-volume, high-frequency data. We currently serve clients processing millions of transactions daily. May I ask what volume you're dealing with so I can provide more specific information?""","Absolutely. Our platform is designed to handle high-volume, high-frequency data. PNC bank processes 3.5 million deposit and payment transactions every hour with our systems. May I ask what volume you're dealing with so I can provide more specific information?""",7,9,Salesperson 2 gives a specific example with numbers
8
+ Discovery,Does your solution comply with financial regulations like GDPR and CCPA?,"""Yes, regulatory compliance is a top priority for us. Our solution is fully compliant with GDPR, CCPA, and other major financial regulations. We also regularly update our system to adapt to new regulations. Are there any specific compliance concerns you have?""","Regulatory compliance is a top priority for us. Our solution is fully compliant with GDPR, CCPA, and other major financial regulations. We also regularly update our system to adapt to new regulations. We produce the detailed compliance findings in the SOC2 report that I am happy to share with you.
9
+ Can you share the compliance requirements for your firm?",8,9,Salesperson 2 mentions SOC2 report and asks about specific requirements
10
+ Discovery,How does your software integrate with legacy systems?,"""We have extensive experience integrating with legacy systems common in the financial sector. Our platform uses APIs and custom connectors to ensure smooth data flow. Could you share what systems you're currently using? This will help me explain how we'd approach integration in your specific case.""",We offer many integration options for our software. Most customers feed data into our software from their internal system via APIs. Others build customer connectors to ensure smooth data flows. Can you share what systems you're currently using? This will help me explain how we'd approach integration in your specific case.,8,7,Salesperson 1 provides more detailed integration options
11
+ Discovery,What kind of support do you offer for implementation and ongoing use?,"""We provide comprehensive support throughout the journey. This includes a dedicated implementation team, 24/7 technical support, regular training sessions, and a customer success manager. How hands-on would you like the support to be?""","For implementation, our customers use a combination of our professional services team and resources from our certified SI partners.
12
+ For ongoing support, we offer a couple of support options, ranging from developer support to enterprise support. How do you typically implement and support software within your organization?",7,9,Salesperson 2 gives more specific implementation and support options
13
+ Discovery,Can your solution help us with risk management and fraud detection?,"""Definitely. Our AI algorithms are particularly strong in risk assessment and fraud detection. They can identify unusual patterns and potential risks in real-time. What are your current challenges in risk management and fraud detection?""","Some of our customers have used the aggregation and analytics capabilities of our solution to ascertain supplier and vendor risk in their organization. A large retail customer aggregated all their supplier data sources including shipping, land transportation etc to review risk to the shipping timelines to determine appropriate inventory levels.
14
+ Can you tell me more about the risk and fraud use cases you are thinking about so we can determine if our solution is a fit?",7,9,Salesperson 2 provides a specific example and asks about use cases
15
+ Discovery,How scalable is your solution?,"""Our solution is highly scalable, designed to grow with your business. We use cloud infrastructure that can easily expand to handle increased data volume and user base. What kind of growth are you anticipating in the next few years?""","One of the reasons customers choose our solution is because it can be scaled up or down depending on their business needs. During the pandemic, some of our large online retail customers had to scale overnight as the ecommerce volumes went up 10X. They depended on our platform for their analytics needs.
16
+ As you think about scalability, can you give me some idea of the data volumes within your org?",8,9,Salesperson 2 gives a concrete example of scalability during the pandemic
17
+ Discovery,Do you have experience working with companies of our size?,"""Yes, we work with several large financial institutions. While I can't name them due to confidentiality, I can share that we serve three of the top 10 banks in the country. Would you be interested in case studies or speaking with references in your industry?""","Our customers range from large Fortune 100 enterprises to young startups innovating on a business idea.
18
+ Can you tell me more about some of the intended use cases and things you are struggling with regarding your analytics needs?",7,8,Salesperson 2 asks about specific use cases and challenges
19
+ Discovery,How does your pricing model work?,"""Our pricing is based on the modules you choose and the volume of data processed. We aim to align our pricing with the value we provide. To give you an accurate quote, could you share more about your specific needs and usage expectations?""","We have a consumption based pricing model, based on the modules you choose and the volume of data processed. We will be providing you a dashboard so you can get a daily view of the costs incurred. You can set limits at an org level or a user level so you can keep a tab of the costs.",7,9,Salesperson 2 explains the consumption-based model and mentions a dashboard
20
+ Qualification,What's the total cost of ownership for your solution?,"""The total cost includes the software license, implementation, training, and ongoing support. For a company of your size, we estimate the first-year cost to be between $500,000 to $750,000, with annual renewals at about 20% of that. Would you like a detailed breakdown?""","Our customers have to consider annual running costs (consumption), one time implementation fee, training costs, and support costs as they come on to our platform. Customers have cited productivity gains of 25% and analytics costs going down by 30% within 18 months post implementation. ",9,8,Salesperson 1 provides specific numbers while 2 focuses on ROI
21
+ Qualification,How long does the implementation usually take?,"""For a company of your size and complexity, implementation typically takes 3-6 months. This includes system integration, data migration, and user training. Do you have any specific timeline constraints we should be aware of?""","Implementation ranges from 8-16 weeks. Our platform is modular but the key things that impact the implementation timeframe are the number of data sources we have to connect to, and the number of downstream systems we need to integrate with.
22
+ Do you have any specific timeline constraints we should be aware of?""",8,9,Salesperson 2 gives more detail on factors affecting implementation time
23
+ Qualification,What kind of ROI can we expect?,"""Based on our experience with similar clients, most see a full ROI within 12-18 months. This comes from improved efficiency, better risk management, and data-driven decision making. One client reduced operational costs by 22% in the first year. What specific metrics are most important to you?""","Customers have cited productivity gains of 25% and analytics costs going down by 30% within 18 months post implementation.
24
+ Over the long run, our customers have also been to consolidate the number of vendor systems, reducing their technical debt, seeing ROI of 75% within 3 years.",8,9,Salesperson 2 provides more detailed ROI figures and timeframes
25
+ Qualification,Who will be our main point of contact during and after implementation?,"""You'll have a dedicated project manager during implementation and a customer success manager post-launch. Both will be deeply familiar with the financial services sector. How hands-on do you prefer your points of contact to be?""","Our Customer Success and Professional services teams works with customers during the entire implementation phase. During the implementation phase, the project lead from the Professional Services team will be the main point of contact, and then they will hand over to the customer success manager who will be the POC post implementation to drive training and adoption.",8,9,Salesperson 2 provides more detailed information about the process
26
+ Qualification,What happens if we need to scale up or down?,"""Our contracts are flexible. You can easily add users or increase data processing capacity as you grow. If you need to scale down, we can adjust at your annual renewal. What kind of fluctuations do you anticipate in your usage?""","We run on a highly secure and scalable infrastructure backend which allows you to scale up or down, on-demand, depending on your business needs. During the pandemic, some of our large online retail customers had to scale overnight as the ecommerce volumes went up 10X and they needs stronger real time analytics to run their business.
27
+ They were not only able to scale up, but also scale down as the business volume decreased as they dealt with inflationary pressures last year. ",8,9,Salesperson 2 gives a specific example of scaling during the pandemic
28
+ Qualification,How often do you release updates and how disruptive are they?,"""We release major updates quarterly and minor ones monthly. Updates are scheduled during off-hours and typically take less than an hour. We always notify clients in advance and provide detailed release notes. How does this align with your change management processes?""","We have 4 major releases a year, and 8 minor releases a year. The releases are all made into the core platform and available to all customers. Updates are scheduled during off-hours and typically take less than an hour. We always notify clients in advance and provide detailed release notes.
29
+ How does this align with your change management processes?""",9,9,Both provide similar comprehensive information
30
+ Qualification,What kind of training do you provide for our staff?,"""We offer a mix of online and on-site training. This includes admin training, end-user workshops, and ongoing webinars. We also provide a comprehensive knowledge base. How many users would need training, and do you have any specific training preferences?""","We offer a mix of online and in-person trainings on our platform and solution. Prior to launch, we will conduct a half day training delivered in a hybrid environment with our team at your office so we can walk you through different functionality and how to use the platform. Post launch, there are different trainings available on-demand. We can also provide customized training at any team for your team.
31
+ What is the size and makeup of your team that will need to be trained on the solution?",8,9,Salesperson 2 offers more detailed training options and asks about team size
32
+ Qualification,Can we customize the solution to our specific needs?,"""Absolutely. While our core product is robust, we understand that every financial institution has unique needs. We offer customization services to tailor the solution to your specific workflows and requirements. What kind of customizations do you think you'd need?""","Abolutely. Our platform is highly configurable and can be tailored to meet different customer needs and use cases. To give you a couple of examples, we have retail customers running their supply chain risk analysis on our platform and we have financial services customers running loan loss forecasting analysis on their credit card portfolios.
33
+ Can you tell me more about your needs and the use case you have in mind?",8,9,Salesperson 2 provides specific examples of customization
34
+ Qualification,What security measures does your solution have in place?,"""Security is paramount for us. We use bank-grade encryption, multi-factor authentication, and regular third-party security audits. We're also SOC 2 Type II compliant. Are there any specific security protocols or certifications you require?""","Security is job zero for us. Our customers put confidential data into our platform and we need to make sure we have the right protections in place to safeguard their data. Security measures include masking of data to remove any PII, encryption of data both at rest and transit, and deleting data copies on a periodic basis. We also partner with leading security companies like Palo Alto and Crowdstrike to use their tooling to monitor our securty posture. I can share with you our security whitepaper and also share the SOC Type II report that outlines our security certifications.
35
+ Are there any specific security protocols or certifications you require?",8,10,Salesperson 2 provides extensive details on security measures and offers documentation
36
+ Qualification,"If we decide to proceed, what are the next steps?,","""Great question! The next steps would be a technical deep dive with your IT team, followed by a customized demo for your key stakeholders. Then we'd move to contract discussions and implementation planning. Does this align with your decision-making process?""","We should first identify the 1-2 use cases you want to tackle in phase 1 of the project. Following that, we will sit down with your team to understand your technical landscape and the integration requirements. We can then discuss timelines, and provide you a pricing and implementation proposal.
37
+ Does this sound reasonable to you? ",8,9,Salesperson 2 outlines a more specific action plan
38
+ Technical Assessment,Can you walk us through how your system handles data encryption?,"""Certainly. We use AES-256 encryption for data at rest and TLS 1.3 for data in transit. All encryption keys are managed through a robust key management system with regular rotation. Would you like me to go into more technical detail on any specific aspect of our encryption process?""","Security is job zero for us. Our customers put confidential data into our platform and we need to make sure we have the right protections in place to safeguard their data. Security measures include masking of data to remove any PII, encryption of data both at rest and transit, and deleting data copies on a periodic basis. We use AES-256 encryption for data at rest and TLS 1.3 for data in transit. All encryption keys are managed through a robust key management system with regular rotation. I can share with you our security whitepaper and also share the SOC1 report that outlines our security certifications.
39
+ Can you talk about your policies and compliance requirements regarding data encryption?",9,10,Salesperson 2 provides more comprehensive information on encryption and security
40
+ Technical Assessment,How does your solution integrate with our core banking system?,"""We have pre-built connectors for most major core banking systems. Our integration process typically involves setting up secure API connections, defining data mapping rules, and establishing real-time or batch data synchronization based on your needs. Which core banking system are you using? I can provide more specific integration details.""","We have pre-built connectors for most major core banking systems. Our integration process typically involves setting up secure API connections, defining data mapping rules, and establishing real-time or batch data synchronization based on your needs. We use data masking so no PII gets included in the data that gets sent to us. We will use encryption at rest and in transit when dealing with any data transfers. Our customers have integrated our analytics engine with core banking providers like FIS, Jack Henry, and Temenos.
41
+ Which core banking provider do you use?",8,9,Salesperson 2 mentions specific core banking providers and data protection measures
42
+ Technical Assessment,What's your system's average response time for complex queries?,"""Our system is optimized for performance. For complex queries involving large datasets, the average response time is under 2 seconds. This is achieved through advanced indexing, in-memory processing, and distributed computing architecture. What kind of response times are you currently experiencing with your system?""","We have designed our platform to be highly scalable and process thousands of queries per minute. One of our banking customers runs their entire credit decisioning process on our platform, getting the entire loan approval process in under 3 minutes.
43
+ What kind of response time are you looking for?",9,8,Salesperson 1 provides more specific response time information
44
+ Technical Assessment,How do you handle data backups and disaster recovery?,"""We maintain real-time replicas across multiple geographically distributed data centers. Full backups are performed daily, with incremental backups every hour. Our disaster recovery plan ensures a Recovery Time Objective (RTO) of 4 hours and a Recovery Point Objective (RPO) of 15 minutes. How do these metrics compare to your current system and requirements?""","""We maintain real-time replicas across multiple geographically distributed data centers. Full backups are performed daily, with incremental backups every hour. Our disaster recovery plan ensures SLAs for Recovery Time Objective (RTO) and a Recovery Point Objective (RPO).
45
+ What recovery metrics are you looking to meet? ",9,8,Salesperson 1 provides more specific RTO and RPO metrics
46
+ Technical Assessment,Can your system handle real-time fraud detection?,"""Yes, our system excels at real-time fraud detection. We use machine learning models that analyze transaction patterns in real-time. The system can flag suspicious activities instantly and even automate certain preventive actions. What specific fraud scenarios are you most concerned about?""","Fraud detection is a common use case for our software. Our platform can process both structured and unstructured data to make real time fraud detection better, and reduce the chances of false positives. We also use both predictive and generative AI for better pattern matching and detect fraud across our network of customers. One of our large banking customers migrated to our platform from a large legacy provider and they saw 40% reduction in false positives and 20% reduction in overall fraud cases. ",8,10,Salesperson 2 provides a specific customer example with impressive results
47
+ Technical Assessment,How flexible is your reporting module?,"""Our reporting module is highly flexible. It includes a drag-and-drop report builder, a library of pre-built financial reports, and the ability to create custom reports using SQL. Reports can be scheduled, exported in various formats, and even embedded in other applications. What are your most critical reporting needs?""","Our customers run a variety of reports on our platform. The reporting module is highly configurable allowing you to select data from different table structures. You can configure report, table, and field level permissions to ensure only the authorized users in your organization get access to the right data. Reports can be scheduled, exported in various formats, and even embedded in other applications. What are your most critical reporting needs?",9,9,Both provide comprehensive information on reporting capabilities
48
+ Technical Assessment,What APIs do you offer for extending the system's functionality?,"""We provide a comprehensive set of RESTful APIs that cover all major functionalities of our system. This includes APIs for data ingestion, analytics, reporting, and administrative functions. We also offer SDKs for popular programming languages. Are there specific integrations or extensions you're considering?""","We have existing integrations with many 3rd party systems include core banking, payment, risk, and transaction processing systems to ensure we can exchange data feeds from upstream or downstream systems. In addition, we provide a comprehensive set of RESTful APIs that cover all major functionalities of our system. This includes APIs for data ingestion, analytics, reporting, and administrative functions. We also offer SDKs for popular programming languages.
49
+ Can you share some details of your integration requirements?",8,9,Salesperson 2 mentions existing integrations in addition to APIs
50
+ Technical Assessment,How does your system handle data governance and lineage?,"""Data governance is built into our system's core. We provide full data lineage tracking, allowing you to trace any piece of data back to its source. Our governance module includes features for data classification, access control, and audit trails. How complex are your data governance requirements?""","We comply with the data governance and sovereignty requirements of different states and countries. In the insurance sector, each state has different data governance requriements and our system can be configured to ensure those requirements are always adhered to. Similarly, in the case of a country specific sovereign requirements, we will ensure that the data stays within that country only.
51
+ For lineage, we provide an audit trail so you know each step when your data was enhanced or modified, offering you complete transparency. ",8,9,Salesperson 2 provides more specific information on governance and compliance
52
+ Technical Assessment,Can you explain your approach to ensuring system scalability?,"""Our system is built on a microservices architecture deployed on cloud infrastructure. This allows us to scale individual components independently based on demand. We use auto-scaling groups to handle traffic spikes and have successfully scaled to handle over 10 million transactions per hour for some clients. What kind of growth do you anticipate in your transaction volume?""","Our system is built on a microservices architecture deployed on cloud infrastructure. This allows us to scale individual components independently based on demand. We offer deployment to multiple cloud providers including AWS, Azure, and GCP giving you choice and freedom of deployment options.
53
+ We use auto-scaling groups to handle traffic spikes and have successfully scaled to handle over 10 million transactions per hour for some clients.
54
+ What kind of growth do you anticipate in your transaction volume? ",9,9,Both provide comprehensive information on scalability
55
+ Technical Assessment,How do you ensure the accuracy of your AI/ML models in financial predictions?,"Technical Assessment,,""We take a rigorous approach to model accuracy. Our models are trained on vast amounts of anonymized financial data and are continuously refined. We use techniques like cross-validation, backtesting, and A/B testing to ensure accuracy. Models are monitored in real-time and retrained regularly. We also provide transparency reports on model performance. What specific predictive capabilities are you most interested in?""","We take a rigorous approach to model accuracy. Our models are trained on vast amounts of anonymized financial data and are continuously refined. We use techniques like cross-validation, backtesting, and A/B testing to ensure accuracy. Models are monitored in real-time and retrained regularly. We also provide transparency reports on model performance.
56
+ For unstructured data, we use a number of techniques including RAG and fine-tuning to minimize hallucinations in our predictions. Post model runs, we run different evaluations to calculate model drift, precision, and relevancy.
57
+ As we are running across hundreds of customers, we have been able to achieve very high levels of accuracy in our AI/ML models",9,10,Salesperson 2 provides more detailed information on AI/ML model accuracy and techniques
58
+ Proposal,Can you provide a detailed breakdown of the costs?,"""Certainly. For your organization, we're proposing our Enterprise plan, which includes all modules. The first-year cost breaks down as follows: Software license: $400,000, Implementation and integration: $150,000, Training: $50,000, First-year support: $100,000. This totals $700,000 for the first year, with subsequent annual costs of $500,000 for license renewal and ongoing support. Would you like me to walk you through each component in more detail?""","Our customers have to consider annual running costs (consumption), one time implementation fee, training costs, and support costs as they come on to our platform. Actual costs depend on the size of the datasets and number of use cases we are getting deployed. If you would like, we can do a business and technical assessment so I can provide you a cost proposal. Would you want that?",9,8,Salesperson 1 provides specific numbers while 2 offers to do an assessment
59
+ Proposal,What specific ROI can we expect in the first year?,",""Based on our analysis of your current processes and the efficiencies our system will bring, we project a first-year ROI of 120%. This comes from a 15% reduction in operational costs, 20% improvement in fraud detection, and 10% increase in customer retention due to improved service quality. I'd be happy to provide a detailed ROI report with all our assumptions clearly stated. Would that be helpful?""","Customers have cited productivity gains of 25% and analytics costs going down by 30% within 18 months post implementation.
60
+ Over the long run, our customers have also been to consolidate the number of vendor systems, reducing their technical debt, seeing ROI of 75% within 3 years.",9,8,Salesperson 1 provides more detailed first-year ROI projections
61
+ Proposal,How quickly can we get the system up and running?,"""Given the scope of the project, we estimate a 4-month implementation timeline. This includes 1 month for initial setup and data migration, 2 months for integration and customization, and 1 month for testing and training. We can start within two weeks of contract signing. Does this timeline align with your expectations?""","We have seen customers get up and running in as little as 8 weeks. Our platform is modular but the key things that impact the implementation timeframe are the number of data sources we have to connect to, and the number of downstream systems we need to integrate with.
62
+ We would need to do a technical assessment to provide you a good estimate. Do you have a technical lead identified for this project? If so, can you make an introduction?",9,8,Salesperson 1 provides a more detailed timeline
63
+ Proposal,What guarantees do you offer if the system doesn't perform as promised?,"""We're confident in our solution, but we also understand the need for assurances. We offer a performance guarantee in our Service Level Agreement. If we don't meet the agreed-upon performance metrics, you're entitled to service credits. Additionally, we offer a 90-day warranty period post-implementation. If you're not satisfied during this period, we'll work to resolve issues at no additional cost. Would you like to discuss specific performance metrics for your guarantee?""","We offer Service Level Agreements (SLAs) for uptime and response time. We will work with you to fine tune the data models or the underlying infrastructure if performance is not performing for any reason. Our goal is to have a long term relationship, and we want to make sure you are a happy and satisfied customer. ",9,8,Salesperson 1 offers more specific guarantees and warranty information
64
+ Proposal,Can you provide customer references in our industry?,"""Absolutely. We have several clients in the financial services sector who have agreed to serve as references. I can arrange calls with two of our clients: a large national bank and a regional credit union. They can speak to their experiences with implementation, day-to-day use, and the ROI they've seen. Would you like me to set up these reference calls?""","Absolutely. We have a number of customers across the financial services industry running mission critical workloads on our platform.
65
+ PNC bank has aggregated data from their different loan systems to reduce charge-offs by 17%, and costs by 30%. They also process 3.5 million deposit and payment transactions every hour with our systems.
66
+ One other large banking customers is running their fraud detection process on us and saw 40% reduction in false positives and 20% reduction in overall fraud cases.
67
+ What use cases did you have in mind so I can share more relevant case studies?",8,9,Salesperson 2 provides specific customer examples and results
68
+ Proposal,What kind of ongoing support and maintenance is included?,"""Our proposal includes our Premium Support package. This provides 24/7 technical support with a 1-hour response time for critical issues, quarterly system health checks, and a dedicated customer success manager. It also covers all software updates and patches. Is there any specific area of support you'd like more information about?""","For ongoing support, we offer a couple of support options, ranging from developer support to enterprise support. Depending on your needs, we can price the support option and include them into the proposal.
69
+ We maintain and update the platform on a regular basis. We have 4 major releases a year, and 8 minor releases a year. The releases are all made into the core platform and available to all customers.",8,9,Salesperson 2 provides specific customer examples and results
70
+ Proposal,How do you ensure business continuity during the transition to your system?,"""We understand the critical nature of your operations. Our implementation plan includes a phased approach with parallel running of systems to ensure no disruption. We also provide a rollback plan at each stage. Your dedicated project manager will work closely with your team to minimize any potential business impact. Would you like to review our detailed transition plan?""","We take full back-up of your data before you start the transition process. Our implementation plan includes a phased approach with parallel running of systems to ensure no disruption. Your dedicated project manager will work closely with your team to minimize any potential business impact.
71
+ Would you like to review our detailed transition plan?""",8,9,Salesperson 2 provides more options for ongoing support
72
+ Proposal,What training options are available for our team?,"""We offer a comprehensive training program tailored to different user roles. This includes on-site workshops for administrators and power users, web-based training for end-users, and a full e-learning platform with on-demand courses. We also provide train-the-trainer sessions if you prefer to manage ongoing training internally. How would you like to approach training for your team?""","We offer a mix of online and in-person trainings on our platform and solution. Prior to launch, we will conduct a half day training delivered in a hybrid environment with our team at your office so we can walk you through different functionality and how to use the platform. Post launch, there are different trainings available on-demand. We can also provide customized training at any team for your team.
73
+ What is the size and makeup of your team that will need to be trained on the solution?",9,8,Salesperson 1 provides more detailed information on the transition process
74
+ Proposal,Can you outline the key milestones in the implementation process?,"""Certainly. The key milestones in our 4-month implementation plan are: Month 1 - Project kickoff and initial setup, Month 2 - Data migration and basic integration, Month 3 - Custom feature development and advanced integration, Month 4 - User acceptance testing and staff training. We have checkpoints and sign-offs at each milestone. Would you like a more detailed project plan?""","There are 5 major checkpoints for us during the implemenation process. First is to ensure that we have done all the integrations with the data feeds and the internal systems. Second is to run a Proof of Concept for a small use case to ensure we have got the models and analytics running correctly. Third is to scale the use case to the larger organization. Fourth is User acceptance testing and staff training. And fiith and final is going into Production with the launch.
75
+ Would you like a more detailed project plan?",9,9,Both provide comprehensive information on training options
76
+ Proposal,What makes your solution the best fit for our company compared to other options?,"""Based on our discussions, I believe our solution is the best fit for three main reasons: 1) Our deep expertise in the financial sector, which means faster implementation and industry-specific features, 2) Our advanced AI capabilities, which align with your goals for improved risk management and fraud detection, and 3) Our scalable architecture, which can support your projected growth. Moreover, our commitment to ongoing innovation ensures you'll always have cutting-edge capabilities. How do these align with your decision criteria?""","Our customers cite the advanced analytics, precision of the AI models, and the configrability of the platform as the key reasons to select us. PNC bank has aggregated data from their different loan systems to reduce charge-offs by 17%, and costs by 30%. They also process 3.5 million deposit and payment transactions every hour with our systems. They went live with our system in 16 weeks. Some of the other reasons include the underlying scalability of the platform and enterprise grade security. ",9,9,Both provide strong arguments for their solution's fit
77
+ Negotiation,Your pricing seems high compared to some other solutions we've seen. Is there any flexibility?,"""I appreciate your concern about the pricing. While our initial quote reflects the comprehensive nature of our solution, we do have some flexibility. We could look at adjusting the feature set or exploring a phased implementation to reduce the initial investment. Alternatively, we could discuss a longer contract term in exchange for a discount. What approach would you prefer to explore?""",We think we have a best in class solution and have a number of customers today running varied use cases on our platform. We offer a very transparent pricing model which allows us to scale across many customers. Some of the possibilities are discounts against commitments for long term or volume commitments. ,9,8,Salesperson 1 offers more specific options for flexibility
78
+ Negotiation,Can we spread out the payments over a longer period to reduce the upfront cost?,"""Absolutely, we can discuss alternative payment structures. One option is to spread the implementation cost over the first year, combined with quarterly payments for the license fee. This would reduce your initial outlay. We could also explore a pay-as-you-go model for certain modules. How would you like to structure the payments to best fit your budgeting process?""","Potentially. I will need to understand this more before I can make any commitments. As you can understand, we are a young company and have cash flow considerations as well. Can you help me understand how you want to structure the payments?",9,7,Salesperson 1 offers more specific payment structure options
79
+ Negotiation,What kind of discount can you offer for a three-year commitment?,"""For a three-year commitment, we can offer a 15% discount on the annual license fee. This would bring your annual cost down from $500,000 to $425,000 after the first year. Additionally, we could lock in this price for the full three years, protecting you from any potential price increases. Would you like me to draw up a comparison of the one-year versus three-year terms?""","Absolutely, we do offer price reductions to customers who are willing to do a longer term commitment to us. There is a 15% discount if you were to make a three-year commitment.
80
+ Would you like me to draw up a comparison of the one-year versus three-year terms?",9,8,Salesperson 1 provides more specific discount information
81
+ Negotiation,Can we start with a smaller implementation and scale up over time?,"""That's definitely an option. We could begin with core modules like data aggregation and basic analytics, then add advanced features like AI-driven predictions in subsequent phases. This approach would reduce your initial investment to about $400,000 for the first year. We can then add modules as your needs grow and as you realize ROI from the initial implementation. How does this aligned approach sound to you?""","Absolutely. Many of our customers start with 1-2 use cases and then scale up over time. What we do suggest however that you pick a use case that is a material and challenging use case for you so you are able to get a good idea of the results.
82
+ Do you have such a use case already identified?",9,8,Salesperson 1 provides more specific information on a phased approach
83
+ Negotiation,Is there any room for negotiation on the support costs?,"""I understand your concern about the support costs. While our support is comprehensive, we could look at tailoring it more specifically to your needs. For instance, we could reduce the cost by adjusting the support hours or response times. Alternatively, if you have a strong internal IT team, we could explore a co-support model. What aspects of the support package are most valuable to you?""","I understand your concern about the support costs. While our support is comprehensive, we could look at tailoring it more specifically to your needs. For instance, we could reduce the cost by adjusting the support hours or response times. Alternatively, if you have a strong internal IT team, we could explore a co-support model. One other option available to you is a discount if you were to commit to a longer term contract.
84
+ What aspects of the support package are most valuable to you?",9,9,Both offer similar levels of flexibility on support costs
85
+ Negotiation,Can you include additional training or consulting hours in the package without increasing the price?,"""I appreciate you asking about this. While our proposed package already includes substantial training, I understand the value of additional support. I can offer an additional 20 hours of consulting time at no extra cost. This could be used for advanced training, workflow optimization, or custom report development. Would this added value address your concerns?""","I appreciate you asking about this. Our goal is to ensure you gain adoption and value from the platform within your organzation. What we have done with other customers is offered additional training linked to adoption goals within their organization.
86
+ Is that something you are willing to consider?",9,8,Salesperson 1 offers a specific number of additional hours
87
+ Negotiation,What guarantees can you offer on the implementation timeline?,"""We're confident in our 4-month implementation estimate, but I understand the importance of timely delivery. We can add a clause to our contract that provides a service credit if we exceed the agreed-upon timeline. For instance, we could offer a 5% credit for each week of delay, up to a maximum of 20%. Would this type of guarantee give you the assurance you're looking for?""","Our implementation resources are available on a T&M basis. There are many dependencies on the implementation timeline including availability of your resources and integration with your internal systems. While we have done many such integrations offer, it is hard for us to offer guarantees in this area since we do not control availability of resources to guide these decisions. ",9,7,Salesperson 1 offers specific guarantees while 2 explains limitations
88
+ Negotiation,"If we commit to becoming a reference customer, can you offer any additional incentives?","""We greatly value reference customers and would be delighted to have you as one. In exchange for agreeing to be a reference (including potential case studies and peer recommendations), we can offer an additional 5% discount on your annual license fee. We would also prioritize your feature requests in our product roadmap. How does this sound to you?""",I would be happy to discuss that. We have offered some incentives to customers who agreed to becoming lighthouse customers for us and agreed to produce case studies and participate in joint speaking sessions. Is that something you are willing to consider?,9,8,Salesperson 1 offers more specific incentives for being a reference customer
89
+ Negotiation,Can we include a performance-based pricing component?,"""That's an interesting proposal. We're open to exploring a performance-based pricing model. We could structure it so that a portion of your fee is tied to agreed-upon KPIs","We have a consumption based pricing model, based on the modules you choose and the volume of data processed. We will be providing you a dashboard so you can get a daily view of the costs incurred.
90
+ On the performance, we will work with you to fine tune the data models or the underlying infrastructure if performance is not performing for any reason. Our goal is to have a long term relationship, and we want to make sure you are a happy and satisfied customer. ",8,7,Salesperson 1 is more open to performance-based pricing
91
+ Negotiation,"The incumbent provider just offered us a 25% discount so we stay on their platform, and now your pricing is much higher than theirs. Can you match their pricing so we can reconsider you?","I understand the appeal of a 25% discount from your current provider. While we may not be able to directly match that price, I'm confident our solution offers superior value that more than justifies the cost difference. Our advanced features like AI-driven analytics and real-time fraud detection often lead to cost savings and revenue increases that far exceed the price gap.
92
+ Would you be open to a detailed ROI analysis comparing our solution to your discounted current system? We could also explore performance-based pricing to align our fees with the value we deliver. Our goal is to be a long-term partner in driving your business success, not just a low-cost provider.","Looks like we are already delivering value for you! I am definitely willing to go back to my executives to see if there are any reductions possible but I wanted you to consider a few things. 1. our customers choose us because of the the advanced analytics, precision of the AI models, and the configrability of the platform. Those were some of the things you had cited were missing from the incumbent provider and reasons for the migration. 2. we offer very transparent pricing which has allowed us to scale quickly across many customers. Offering bait and switch pricing techniques erode customer trust and slow us down in terms of pricing.
93
+ What I have seen work in terms of a discount is when are customers are willing to do a longer term contract or agree to be a reference customer. Are you willing to consider those?",8,10,Salesperson 2 provides a more strategic and value-focused response
backend/app/data/BetterTech Lending Analytics Solution.pdf ADDED
Binary file (58.4 kB). View file
 
backend/app/data/BetterTechLendingAnalyticsSolution.txt ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Real-time analysis with BetterTech Lending Analytics
2
+
3
+
4
+ While most technologies on the market are able to fulfill regulatory risk management requirements, they often fall short of meeting the team’s actual needs. What works when Lending Analytics calculations are run weekly or monthly is simply not enough on a day-to-day basis. Maintaining regulations is no longer enough
5
+
6
+
7
+ There are three functions that an efficient Lending Analytics solution must be able to fulfill: report, explain and optimize.
8
+
9
+
10
+ Reporting is what every solution made for Lending Analytics can do: calculating risk figures and generating reports at the right level of aggregation that are ready to be sent to internal and external auditors. With the data volumes involved with Lending Analytics, however, reporting alone is simply not enough. Explaining is the most critical need for business users. Regulators ask for detailed explanations of what is included in the report, request that banks test alternative stress scenarios, and demonstrate the accuracy of their models — particularly with the Internal Models Approach. With a solution that only reports, business teams end up scrambling to answer those requests as best as they can, falling back on other tools such as Excel or PowerBI, which are simply not designed to analyze data at this scale. Optimizing is where growth and profitability reside.
11
+ Lending Analytics framework creates many decision points that are crucial to improving performance:
12
+ • How best to organize or reorganize loan portfolios?
13
+ • What would be the impact of changing positions or making certain loans?
14
+ • How can we improve our models?
15
+
16
+
17
+ BetterTech Lending Analytics handles this level of analysis deftly and can quickly answer these questions. By relying on inadequate tools to perform analysis, organizations often see reduced productivity and accuracy. Inaccurate reporting negatively impacts relationships with regulators, potentially leading to fines, leading to fines. Furthermore, companies that do not have the analytical capabilities to optimize their risk management and, by extension their capital charge, risk falling behind other, better equipped organizations. How can you get ahead if you cannot efficiently simulate different scenarios to choose the best outcome, while your competitors do it dozens of times a day? A robust analytics solutions that is affordable and easy to implement
18
+
19
+
20
+ BetterTech’s Lending Analytics represents an attractive offering for any bank looking to drastically improve their analytics capabilities within a short timeframe, while keeping their costs under control. BetterTech Lending Analytics can be used to build or replace your risk analysis and reporting system top to bottom, or simply complement your existing reporting capabilities with much improved analytics. Its capabilities and flexibility adapt to your architecture and always deliver the same outcome: putting into the hands of business users and executive managers the tools they need to maximize productivity and profitability.
21
+
22
+
23
+ BetterTech Lending Analytics is in production today at many banks of all sizes around the world, including HSBC, Erste Bank, CIBC and Mizuho. It has successfully passed the ISDA Lending Analytics SA Regulatory Benchmarking Unit Test. It has even been selected by one of the most important global regulators to serve as the benchmark against which to test other banks’ architectures.
24
+
25
+
26
+ Available as SaaS or on-premise, BetterTech Lending Analytics can run on any Cloud platform or in-house hardware and be fully deployed within 4 to 6 weeks.
27
+ Runs anywhere BetterTech Lending Analytics can be deployed under several configurations that all bring the same benefits. Reach out to our team of experts to find the setup that will work best for your organization.
28
+
29
+
30
+ On-premise: BetterTech Lending Analytics can be deployed on a large variety of hardware that are able to provide the requisite capabilities. We have partnerships in place with most global providers to ensure compatibility. In the Cloud: We have extensively tested BetterTech Lending Analytics on all the main cloud platforms (Azure, AWS, Google Cloud...). In fact, it has been deployed in production on those platforms.
31
+
32
+
33
+ As SaaS: We can provide BetterTech Lending Analytics under a managed services contract. This configuration offers the fastest time-to-production while giving you complete control over your investment. The future of market risk analytics Organizations who want to outsmart the competition in their trading strategies must take the long-term view for their market risk architecture. In a sense, Lending Analytics has created a new, level playing field; simply meeting its requirements only puts you in the middle of the pack. The cloud has reached maturity for the financial industry, and makes the best technologies now not just available, but also scalable, affordable and quick to deploy. It is for this new world that BetterTech Lending Analytics was designed, not just to walk along with the rest, but to run ahead. To get ahead, the time is ripe to expand capabilities and onboard new technology. Don’t get left behind.
34
+
35
+
36
+ About BetterTech
37
+
38
+
39
+ Founded by industry experts, BetterTech understands the data analytics challenges faced by financial institutions across lending desks, risk, and compliance. BetterTech pioneered the use of high-performance analytics in finance, helping the banks and lenders make better decisions, explain results with confidence, and simulate the impact of their decisions. BetterTech’s mission is to deliver train-of-thought analysis on terabytes of data in the most cost-effective way so clients can explain their results with confidence and model the scenarios that will optimize their business. BetterTech specializes in risk data analytics for one of the fastest moving and most regulated industries with a presence in the world’s leading financial marketplaces - London, New York, Singapore, Sydney, Hong Kong, Paris and Frankfurt.
backend/app/data/HSBC Opportunity Information.docx ADDED
Binary file (292 kB). View file
 
backend/app/data/HSBC_background.txt ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ HSBC Holdings Plc (HSBC) is a provider of banking and financial solutions. Its
2
+ subsidiaries offer retail, business, and commercial banking; private banking, and wealth
3
+ management services. The group’s portfolio of offerings comprises personal and
4
+ commercial loans, deposit services, mortgages, card products, insurance solutions,
5
+ global asset management, working capital and term loans, payment services,
6
+ international trade facilitation, merger and acquisition advisory, transaction banking,
7
+ capital markets, and risk management, investment management, and trusts and estate
8
+ planning, among others. The group has a presence in Europe, Asia, the Middle East,
9
+ North Africa, North America, and Latin America. HSBC is headquartered in London, the
10
+ UK.
11
+
12
+ From the Group Chairman
13
+ Technology and sustainability are two of the trends transforming banking and the world around us. The opportunities from generative
14
+ AI are among the most transformative within my working life. We are actively exploring a number of use cases, while also working to
15
+ manage the associated risks.
16
+ From Group Chief Executive
17
+ Driving cost savings enables us to invest in technology, which is the fourth opportunity. The digitisation of our business continues to
18
+ improve customer experience and increase efficiency. Using AI to help price complex structural options in our Foreign Exchange
19
+ business has cut execution times down from hours to minutes. We have also identified hundreds of opportunities to leverage
20
+ generative AI, and will focus our efforts on use cases with tangible benefits for the Group and our customers.
21
+ Innovation also creates new avenues for growth. We recently launched Zing, which is our open market mobile platform focused on
22
+ cross-border payments, initially available in the UK. It offers similar capabilities as Global Money does to our international Wealth
23
+ and Personal Banking customers, but is targeted at non-HSBC customers and allows us to drive growth beyond our traditional
24
+ customer footprint.
25
+ From the Strategic Report 2023
26
+ HSBC Technology Priority
27
+ Digitize
28
+ Improve customer experience and efficiency while investing in innovation
29
+ In 2023, we made progress on our goal to become a digital-first bank, and our customers have been increasingly adopting our digital
30
+ services. In CMB, 83% of customers were digitally active, an increase of 5 percentage points since 2022. Our net promoter score for
31
+ onboarding wholesale international clients in the last quarter of 2023 improved by 12 points when compared with the first three
32
+ months
33
+ of the year. At 54%, more than half of WPB customers were mobile active, an increase of 6 percentage points from 2022.
34
+ Furthermore, a total of 75% of WPB’s international customer accounts were opened digitally in 2023, an increase of 30 percentage
35
+ points from 2022.
36
+ We are also focused on building future-ready business models by investing in open-market propositions. In 2023, we announced a
37
+ partnership with Tradeshift to launch a new embedded finance solution in the first half
38
+
39
+ of 2024, which will provide payment and financial services embedded into trade, e-commerce and marketplace experiences. In
40
+ January 2024, in the UK we launched Zing, a mobile platform enabling cross-border payments available to non-HSBC consumers.
41
+ We are also investing in innovative technologies for the future. In 2024, we plan to both concentrate our efforts and increase our
42
+ investment in artificial intelligence (‘Al’).
43
+ At present, we employ Al in areas such as fraud detection and transaction monitoring. We also launched Al Markets, a digital service
44
+ that utilises natural language processing to enrich the way investors interact with global markets. Additionally, we are in the process
45
+ of piloting numerous generative Al use
46
+ cases in areas like developer augmentation, creative content generation and knowledge management, and have identified
47
+ hundreds more potential opportunities.
backend/app/data/Opportunity_Information.csv ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ Opportunity ID,Customer Name,Opportunity Name,Opportunity Stage,Opportunity Description,Opportunity Value,Close Date,Customer Contact,Customer Contact Role,Activity,Next Steps
2
+ XFR0001,HSBC,Lending - Loan Origination System,Proposal,Developing analytic capabilities for the loan origination system,"$250,000",11/30/2024,John Smith,"VP, Information Technology",We have had several meetings with HSBC's lending team regarding replacing the analytics engine for their lending solution. The current system is slow and inflexible. They have the renewal coming up with the existing vendor next year so there is urgency regarding the decision process. ,"Next Steps: Meet with John on 10/26 discuss next steps in the decision-making process, potentially moving towards a pilot program or final negotiations."
3
+ XFR0002,Citi,Competitive Analysis SaaS,Negotiation,Develop SaaS for analysis of Citi's competitors in foreign markets,"$100,000",11/15/2024,Peter Branson,"CEO",Contract finally ironed out by both parties' lawyers. Have verbal agreement that this will be moving forwards.,Finalize contract with Peter and lawyers on October 25th
backend/app/data/salesbud_examples.csv ADDED
@@ -0,0 +1,93 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ objection,response,reference,satisfy,Rating of Salesperson response (per Claude),Rating of Groundtruth (per Claude),Comments (per Claude)
2
+ What exactly does your software do?,"""Our software is a comprehensive financial data analytics platform. It aggregates data from multiple sources, provides real-time insights, and helps financial institutions make data-driven decisions more efficiently.""","Our software is a comprehensive financial data analytics platform. It aggregates data from multiple sources, provides real-time insights, and helps financial institutions make data-driven decisions.
3
+ Our customer list includes 15 of the Fortune 100 companies. PNC bank is one of our customers and they aggregated data from their different loan systems to reduce charge-offs by 17%, and costs by 30%.
4
+ Can you share a little about your data challenges in your organization?",0,7,9,Salesperson 2 provides more specific details and examples
5
+ How is your solution different from what we're currently using?,"""I'd love to learn more about your current system. Our solution stands out with its AI-powered predictive analytics and ability to integrate seamlessly with a wide range of financial systems. Could you tell me about your current pain points?""","The main reasons cited by our customers for selecting our software are the AI-powered predictive analytics and ability to integrate seamlessly with a wide range of financial systems. A large credit union customer said that our AI capabilities were far superior than what they would have developed internally.
6
+ It will be super helpful for me to learn about your current system and your pain points to explore if there is a fit",0,8,9,Salesperson 2 offers concrete examples and asks about pain points
7
+ Can your software handle the volume of transactions we process daily?,"Absolutely. Our platform is designed to handle high-volume, high-frequency data. We currently serve clients processing millions of transactions daily. May I ask what volume you're dealing with so I can provide more specific information?""","Absolutely. Our platform is designed to handle high-volume, high-frequency data. PNC bank processes 3.5 million deposit and payment transactions every hour with our systems. May I ask what volume you're dealing with so I can provide more specific information?""",0,7,9,Salesperson 2 gives a specific example with numbers
8
+ Does your solution comply with financial regulations like GDPR and CCPA?,"""Yes, regulatory compliance is a top priority for us. Our solution is fully compliant with GDPR, CCPA, and other major financial regulations. We also regularly update our system to adapt to new regulations. Are there any specific compliance concerns you have?""","Regulatory compliance is a top priority for us. Our solution is fully compliant with GDPR, CCPA, and other major financial regulations. We also regularly update our system to adapt to new regulations. We produce the detailed compliance findings in the SOC2 report that I am happy to share with you.
9
+ Can you share the compliance requirements for your firm?",1,8,9,Salesperson 2 mentions SOC2 report and asks about specific requirements
10
+ How does your software integrate with legacy systems?,"""We have extensive experience integrating with legacy systems common in the financial sector. Our platform uses APIs and custom connectors to ensure smooth data flow. Could you share what systems you're currently using? This will help me explain how we'd approach integration in your specific case.""",We offer many integration options for our software. Most customers feed data into our software from their internal system via APIs. Others build customer connectors to ensure smooth data flows. Can you share what systems you're currently using? This will help me explain how we'd approach integration in your specific case.,0,8,7,Salesperson 1 provides more detailed integration options
11
+ What kind of support do you offer for implementation and ongoing use?,"""We provide comprehensive support throughout the journey. This includes a dedicated implementation team, 24/7 technical support, regular training sessions, and a customer success manager. How hands-on would you like the support to be?""","For implementation, our customers use a combination of our professional services team and resources from our certified SI partners.
12
+ For ongoing support, we offer a couple of support options, ranging from developer support to enterprise support. How do you typically implement and support software within your organization?",0,7,9,Salesperson 2 gives more specific implementation and support options
13
+ Can your solution help us with risk management and fraud detection?,"""Definitely. Our AI algorithms are particularly strong in risk assessment and fraud detection. They can identify unusual patterns and potential risks in real-time. What are your current challenges in risk management and fraud detection?""","Some of our customers have used the aggregation and analytics capabilities of our solution to ascertain supplier and vendor risk in their organization. A large retail customer aggregated all their supplier data sources including shipping, land transportation etc to review risk to the shipping timelines to determine appropriate inventory levels.
14
+ Can you tell me more about the risk and fraud use cases you are thinking about so we can determine if our solution is a fit?",0,7,9,Salesperson 2 provides a specific example and asks about use cases
15
+ How scalable is your solution?,"""Our solution is highly scalable, designed to grow with your business. We use cloud infrastructure that can easily expand to handle increased data volume and user base. What kind of growth are you anticipating in the next few years?""","One of the reasons customers choose our solution is because it can be scaled up or down depending on their business needs. During the pandemic, some of our large online retail customers had to scale overnight as the ecommerce volumes went up 10X. They depended on our platform for their analytics needs.
16
+ As you think about scalability, can you give me some idea of the data volumes within your org?",1,8,9,Salesperson 2 gives a concrete example of scalability during the pandemic
17
+ Do you have experience working with companies of our size?,"""Yes, we work with several large financial institutions. While I can't name them due to confidentiality, I can share that we serve three of the top 10 banks in the country. Would you be interested in case studies or speaking with references in your industry?""","Our customers range from large Fortune 100 enterprises to young startups innovating on a business idea.
18
+ Can you tell me more about some of the intended use cases and things you are struggling with regarding your analytics needs?",1,7,8,Salesperson 2 asks about specific use cases and challenges
19
+ How does your pricing model work?,"""Our pricing is based on the modules you choose and the volume of data processed. We aim to align our pricing with the value we provide. To give you an accurate quote, could you share more about your specific needs and usage expectations?""","We have a consumption based pricing model, based on the modules you choose and the volume of data processed. We will be providing you a dashboard so you can get a daily view of the costs incurred. You can set limits at an org level or a user level so you can keep a tab of the costs.",0,7,9,Salesperson 2 explains the consumption-based model and mentions a dashboard
20
+ What's the total cost of ownership for your solution?,"""The total cost includes the software license, implementation, training, and ongoing support. For a company of your size, we estimate the first-year cost to be between $500,000 to $750,000, with annual renewals at about 20% of that. Would you like a detailed breakdown?""","Our customers have to consider annual running costs (consumption), one time implementation fee, training costs, and support costs as they come on to our platform. Customers have cited productivity gains of 25% and analytics costs going down by 30% within 18 months post implementation. ",1,9,8,Salesperson 1 provides specific numbers while 2 focuses on ROI
21
+ How long does the implementation usually take?,"""For a company of your size and complexity, implementation typically takes 3-6 months. This includes system integration, data migration, and user training. Do you have any specific timeline constraints we should be aware of?""","Implementation ranges from 8-16 weeks. Our platform is modular but the key things that impact the implementation timeframe are the number of data sources we have to connect to, and the number of downstream systems we need to integrate with.
22
+ Do you have any specific timeline constraints we should be aware of?""",1,8,9,Salesperson 2 gives more detail on factors affecting implementation time
23
+ What kind of ROI can we expect?,"""Based on our experience with similar clients, most see a full ROI within 12-18 months. This comes from improved efficiency, better risk management, and data-driven decision making. One client reduced operational costs by 22% in the first year. What specific metrics are most important to you?""","Customers have cited productivity gains of 25% and analytics costs going down by 30% within 18 months post implementation.
24
+ Over the long run, our customers have also been to consolidate the number of vendor systems, reducing their technical debt, seeing ROI of 75% within 3 years.",1,8,9,Salesperson 2 provides more detailed ROI figures and timeframes
25
+ Who will be our main point of contact during and after implementation?,"""You'll have a dedicated project manager during implementation and a customer success manager post-launch. Both will be deeply familiar with the financial services sector. How hands-on do you prefer your points of contact to be?""","Our Customer Success and Professional services teams works with customers during the entire implementation phase. During the implementation phase, the project lead from the Professional Services team will be the main point of contact, and then they will hand over to the customer success manager who will be the POC post implementation to drive training and adoption.",1,8,9,Salesperson 2 provides more detailed information about the process
26
+ What happens if we need to scale up or down?,"""Our contracts are flexible. You can easily add users or increase data processing capacity as you grow. If you need to scale down, we can adjust at your annual renewal. What kind of fluctuations do you anticipate in your usage?""","We run on a highly secure and scalable infrastructure backend which allows you to scale up or down, on-demand, depending on your business needs. During the pandemic, some of our large online retail customers had to scale overnight as the ecommerce volumes went up 10X and they needs stronger real time analytics to run their business.
27
+ They were not only able to scale up, but also scale down as the business volume decreased as they dealt with inflationary pressures last year. ",1,8,9,Salesperson 2 gives a specific example of scaling during the pandemic
28
+ How often do you release updates and how disruptive are they?,"""We release major updates quarterly and minor ones monthly. Updates are scheduled during off-hours and typically take less than an hour. We always notify clients in advance and provide detailed release notes. How does this align with your change management processes?""","We have 4 major releases a year, and 8 minor releases a year. The releases are all made into the core platform and available to all customers. Updates are scheduled during off-hours and typically take less than an hour. We always notify clients in advance and provide detailed release notes.
29
+ How does this align with your change management processes?""",1,9,9,Both provide similar comprehensive information
30
+ What kind of training do you provide for our staff?,"""We offer a mix of online and on-site training. This includes admin training, end-user workshops, and ongoing webinars. We also provide a comprehensive knowledge base. How many users would need training, and do you have any specific training preferences?""","We offer a mix of online and in-person trainings on our platform and solution. Prior to launch, we will conduct a half day training delivered in a hybrid environment with our team at your office so we can walk you through different functionality and how to use the platform. Post launch, there are different trainings available on-demand. We can also provide customized training at any team for your team.
31
+ What is the size and makeup of your team that will need to be trained on the solution?",1,8,9,Salesperson 2 offers more detailed training options and asks about team size
32
+ Can we customize the solution to our specific needs?,"""Absolutely. While our core product is robust, we understand that every financial institution has unique needs. We offer customization services to tailor the solution to your specific workflows and requirements. What kind of customizations do you think you'd need?""","Abolutely. Our platform is highly configurable and can be tailored to meet different customer needs and use cases. To give you a couple of examples, we have retail customers running their supply chain risk analysis on our platform and we have financial services customers running loan loss forecasting analysis on their credit card portfolios.
33
+ Can you tell me more about your needs and the use case you have in mind?",1,8,9,Salesperson 2 provides specific examples of customization
34
+ What security measures does your solution have in place?,"""Security is paramount for us. We use bank-grade encryption, multi-factor authentication, and regular third-party security audits. We're also SOC 2 Type II compliant. Are there any specific security protocols or certifications you require?""","Security is job zero for us. Our customers put confidential data into our platform and we need to make sure we have the right protections in place to safeguard their data. Security measures include masking of data to remove any PII, encryption of data both at rest and transit, and deleting data copies on a periodic basis. We also partner with leading security companies like Palo Alto and Crowdstrike to use their tooling to monitor our securty posture. I can share with you our security whitepaper and also share the SOC Type II report that outlines our security certifications.
35
+ Are there any specific security protocols or certifications you require?",0,8,10,Salesperson 2 provides extensive details on security measures and offers documentation
36
+ "If we decide to proceed, what are the next steps?,","""Great question! The next steps would be a technical deep dive with your IT team, followed by a customized demo for your key stakeholders. Then we'd move to contract discussions and implementation planning. Does this align with your decision-making process?""","We should first identify the 1-2 use cases you want to tackle in phase 1 of the project. Following that, we will sit down with your team to understand your technical landscape and the integration requirements. We can then discuss timelines, and provide you a pricing and implementation proposal.
37
+ Does this sound reasonable to you? ",1,8,9,Salesperson 2 outlines a more specific action plan
38
+ Can you walk us through how your system handles data encryption?,"""Certainly. We use AES-256 encryption for data at rest and TLS 1.3 for data in transit. All encryption keys are managed through a robust key management system with regular rotation. Would you like me to go into more technical detail on any specific aspect of our encryption process?""","Security is job zero for us. Our customers put confidential data into our platform and we need to make sure we have the right protections in place to safeguard their data. Security measures include masking of data to remove any PII, encryption of data both at rest and transit, and deleting data copies on a periodic basis. We use AES-256 encryption for data at rest and TLS 1.3 for data in transit. All encryption keys are managed through a robust key management system with regular rotation. I can share with you our security whitepaper and also share the SOC1 report that outlines our security certifications.
39
+ Can you talk about your policies and compliance requirements regarding data encryption?",1,9,10,Salesperson 2 provides more comprehensive information on encryption and security
40
+ How does your solution integrate with our core banking system?,"""We have pre-built connectors for most major core banking systems. Our integration process typically involves setting up secure API connections, defining data mapping rules, and establishing real-time or batch data synchronization based on your needs. Which core banking system are you using? I can provide more specific integration details.""","We have pre-built connectors for most major core banking systems. Our integration process typically involves setting up secure API connections, defining data mapping rules, and establishing real-time or batch data synchronization based on your needs. We use data masking so no PII gets included in the data that gets sent to us. We will use encryption at rest and in transit when dealing with any data transfers. Our customers have integrated our analytics engine with core banking providers like FIS, Jack Henry, and Temenos.
41
+ Which core banking provider do you use?",1,8,9,Salesperson 2 mentions specific core banking providers and data protection measures
42
+ What's your system's average response time for complex queries?,"""Our system is optimized for performance. For complex queries involving large datasets, the average response time is under 2 seconds. This is achieved through advanced indexing, in-memory processing, and distributed computing architecture. What kind of response times are you currently experiencing with your system?""","We have designed our platform to be highly scalable and process thousands of queries per minute. One of our banking customers runs their entire credit decisioning process on our platform, getting the entire loan approval process in under 3 minutes.
43
+ What kind of response time are you looking for?",1,9,8,Salesperson 1 provides more specific response time information
44
+ How do you handle data backups and disaster recovery?,"""We maintain real-time replicas across multiple geographically distributed data centers. Full backups are performed daily, with incremental backups every hour. Our disaster recovery plan ensures a Recovery Time Objective (RTO) of 4 hours and a Recovery Point Objective (RPO) of 15 minutes. How do these metrics compare to your current system and requirements?""","""We maintain real-time replicas across multiple geographically distributed data centers. Full backups are performed daily, with incremental backups every hour. Our disaster recovery plan ensures SLAs for Recovery Time Objective (RTO) and a Recovery Point Objective (RPO).
45
+ What recovery metrics are you looking to meet? ",1,9,8,Salesperson 1 provides more specific RTO and RPO metrics
46
+ Can your system handle real-time fraud detection?,"""Yes, our system excels at real-time fraud detection. We use machine learning models that analyze transaction patterns in real-time. The system can flag suspicious activities instantly and even automate certain preventive actions. What specific fraud scenarios are you most concerned about?""","Fraud detection is a common use case for our software. Our platform can process both structured and unstructured data to make real time fraud detection better, and reduce the chances of false positives. We also use both predictive and generative AI for better pattern matching and detect fraud across our network of customers. One of our large banking customers migrated to our platform from a large legacy provider and they saw 40% reduction in false positives and 20% reduction in overall fraud cases. ",0,8,10,Salesperson 2 provides a specific customer example with impressive results
47
+ How flexible is your reporting module?,"""Our reporting module is highly flexible. It includes a drag-and-drop report builder, a library of pre-built financial reports, and the ability to create custom reports using SQL. Reports can be scheduled, exported in various formats, and even embedded in other applications. What are your most critical reporting needs?""","Our customers run a variety of reports on our platform. The reporting module is highly configurable allowing you to select data from different table structures. You can configure report, table, and field level permissions to ensure only the authorized users in your organization get access to the right data. Reports can be scheduled, exported in various formats, and even embedded in other applications. What are your most critical reporting needs?",1,9,9,Both provide comprehensive information on reporting capabilities
48
+ What APIs do you offer for extending the system's functionality?,"""We provide a comprehensive set of RESTful APIs that cover all major functionalities of our system. This includes APIs for data ingestion, analytics, reporting, and administrative functions. We also offer SDKs for popular programming languages. Are there specific integrations or extensions you're considering?""","We have existing integrations with many 3rd party systems include core banking, payment, risk, and transaction processing systems to ensure we can exchange data feeds from upstream or downstream systems. In addition, we provide a comprehensive set of RESTful APIs that cover all major functionalities of our system. This includes APIs for data ingestion, analytics, reporting, and administrative functions. We also offer SDKs for popular programming languages.
49
+ Can you share some details of your integration requirements?",1,8,9,Salesperson 2 mentions existing integrations in addition to APIs
50
+ How does your system handle data governance and lineage?,"""Data governance is built into our system's core. We provide full data lineage tracking, allowing you to trace any piece of data back to its source. Our governance module includes features for data classification, access control, and audit trails. How complex are your data governance requirements?""","We comply with the data governance and sovereignty requirements of different states and countries. In the insurance sector, each state has different data governance requriements and our system can be configured to ensure those requirements are always adhered to. Similarly, in the case of a country specific sovereign requirements, we will ensure that the data stays within that country only.
51
+ For lineage, we provide an audit trail so you know each step when your data was enhanced or modified, offering you complete transparency. ",1,8,9,Salesperson 2 provides more specific information on governance and compliance
52
+ Can you explain your approach to ensuring system scalability?,"""Our system is built on a microservices architecture deployed on cloud infrastructure. This allows us to scale individual components independently based on demand. We use auto-scaling groups to handle traffic spikes and have successfully scaled to handle over 10 million transactions per hour for some clients. What kind of growth do you anticipate in your transaction volume?""","Our system is built on a microservices architecture deployed on cloud infrastructure. This allows us to scale individual components independently based on demand. We offer deployment to multiple cloud providers including AWS, Azure, and GCP giving you choice and freedom of deployment options.
53
+ We use auto-scaling groups to handle traffic spikes and have successfully scaled to handle over 10 million transactions per hour for some clients.
54
+ What kind of growth do you anticipate in your transaction volume? ",1,9,9,Both provide comprehensive information on scalability
55
+ How do you ensure the accuracy of your AI/ML models in financial predictions?,"Technical Assessment,,""We take a rigorous approach to model accuracy. Our models are trained on vast amounts of anonymized financial data and are continuously refined. We use techniques like cross-validation, backtesting, and A/B testing to ensure accuracy. Models are monitored in real-time and retrained regularly. We also provide transparency reports on model performance. What specific predictive capabilities are you most interested in?""","We take a rigorous approach to model accuracy. Our models are trained on vast amounts of anonymized financial data and are continuously refined. We use techniques like cross-validation, backtesting, and A/B testing to ensure accuracy. Models are monitored in real-time and retrained regularly. We also provide transparency reports on model performance.
56
+ For unstructured data, we use a number of techniques including RAG and fine-tuning to minimize hallucinations in our predictions. Post model runs, we run different evaluations to calculate model drift, precision, and relevancy.
57
+ As we are running across hundreds of customers, we have been able to achieve very high levels of accuracy in our AI/ML models",1,9,10,Salesperson 2 provides more detailed information on AI/ML model accuracy and techniques
58
+ Can you provide a detailed breakdown of the costs?,"""Certainly. For your organization, we're proposing our Enterprise plan, which includes all modules. The first-year cost breaks down as follows: Software license: $400,000, Implementation and integration: $150,000, Training: $50,000, First-year support: $100,000. This totals $700,000 for the first year, with subsequent annual costs of $500,000 for license renewal and ongoing support. Would you like me to walk you through each component in more detail?""","Our customers have to consider annual running costs (consumption), one time implementation fee, training costs, and support costs as they come on to our platform. Actual costs depend on the size of the datasets and number of use cases we are getting deployed. If you would like, we can do a business and technical assessment so I can provide you a cost proposal. Would you want that?",1,9,8,Salesperson 1 provides specific numbers while 2 offers to do an assessment
59
+ What specific ROI can we expect in the first year?,",""Based on our analysis of your current processes and the efficiencies our system will bring, we project a first-year ROI of 120%. This comes from a 15% reduction in operational costs, 20% improvement in fraud detection, and 10% increase in customer retention due to improved service quality. I'd be happy to provide a detailed ROI report with all our assumptions clearly stated. Would that be helpful?""","Customers have cited productivity gains of 25% and analytics costs going down by 30% within 18 months post implementation.
60
+ Over the long run, our customers have also been to consolidate the number of vendor systems, reducing their technical debt, seeing ROI of 75% within 3 years.",1,9,8,Salesperson 1 provides more detailed first-year ROI projections
61
+ How quickly can we get the system up and running?,"""Given the scope of the project, we estimate a 4-month implementation timeline. This includes 1 month for initial setup and data migration, 2 months for integration and customization, and 1 month for testing and training. We can start within two weeks of contract signing. Does this timeline align with your expectations?""","We have seen customers get up and running in as little as 8 weeks. Our platform is modular but the key things that impact the implementation timeframe are the number of data sources we have to connect to, and the number of downstream systems we need to integrate with.
62
+ We would need to do a technical assessment to provide you a good estimate. Do you have a technical lead identified for this project? If so, can you make an introduction?",1,9,8,Salesperson 1 provides a more detailed timeline
63
+ What guarantees do you offer if the system doesn't perform as promised?,"""We're confident in our solution, but we also understand the need for assurances. We offer a performance guarantee in our Service Level Agreement. If we don't meet the agreed-upon performance metrics, you're entitled to service credits. Additionally, we offer a 90-day warranty period post-implementation. If you're not satisfied during this period, we'll work to resolve issues at no additional cost. Would you like to discuss specific performance metrics for your guarantee?""","We offer Service Level Agreements (SLAs) for uptime and response time. We will work with you to fine tune the data models or the underlying infrastructure if performance is not performing for any reason. Our goal is to have a long term relationship, and we want to make sure you are a happy and satisfied customer. ",1,9,8,Salesperson 1 offers more specific guarantees and warranty information
64
+ Can you provide customer references in our industry?,"""Absolutely. We have several clients in the financial services sector who have agreed to serve as references. I can arrange calls with two of our clients: a large national bank and a regional credit union. They can speak to their experiences with implementation, day-to-day use, and the ROI they've seen. Would you like me to set up these reference calls?""","Absolutely. We have a number of customers across the financial services industry running mission critical workloads on our platform.
65
+ PNC bank has aggregated data from their different loan systems to reduce charge-offs by 17%, and costs by 30%. They also process 3.5 million deposit and payment transactions every hour with our systems.
66
+ One other large banking customers is running their fraud detection process on us and saw 40% reduction in false positives and 20% reduction in overall fraud cases.
67
+ What use cases did you have in mind so I can share more relevant case studies?",1,8,9,Salesperson 2 provides specific customer examples and results
68
+ What kind of ongoing support and maintenance is included?,"""Our proposal includes our Premium Support package. This provides 24/7 technical support with a 1-hour response time for critical issues, quarterly system health checks, and a dedicated customer success manager. It also covers all software updates and patches. Is there any specific area of support you'd like more information about?""","For ongoing support, we offer a couple of support options, ranging from developer support to enterprise support. Depending on your needs, we can price the support option and include them into the proposal.
69
+ We maintain and update the platform on a regular basis. We have 4 major releases a year, and 8 minor releases a year. The releases are all made into the core platform and available to all customers.",1,8,9,Salesperson 2 provides specific customer examples and results
70
+ How do you ensure business continuity during the transition to your system?,"""We understand the critical nature of your operations. Our implementation plan includes a phased approach with parallel running of systems to ensure no disruption. We also provide a rollback plan at each stage. Your dedicated project manager will work closely with your team to minimize any potential business impact. Would you like to review our detailed transition plan?""","We take full back-up of your data before you start the transition process. Our implementation plan includes a phased approach with parallel running of systems to ensure no disruption. Your dedicated project manager will work closely with your team to minimize any potential business impact.
71
+ Would you like to review our detailed transition plan?""",1,8,9,Salesperson 2 provides more options for ongoing support
72
+ What training options are available for our team?,"""We offer a comprehensive training program tailored to different user roles. This includes on-site workshops for administrators and power users, web-based training for end-users, and a full e-learning platform with on-demand courses. We also provide train-the-trainer sessions if you prefer to manage ongoing training internally. How would you like to approach training for your team?""","We offer a mix of online and in-person trainings on our platform and solution. Prior to launch, we will conduct a half day training delivered in a hybrid environment with our team at your office so we can walk you through different functionality and how to use the platform. Post launch, there are different trainings available on-demand. We can also provide customized training at any team for your team.
73
+ What is the size and makeup of your team that will need to be trained on the solution?",1,9,8,Salesperson 1 provides more detailed information on the transition process
74
+ Can you outline the key milestones in the implementation process?,"""Certainly. The key milestones in our 4-month implementation plan are: Month 1 - Project kickoff and initial setup, Month 2 - Data migration and basic integration, Month 3 - Custom feature development and advanced integration, Month 4 - User acceptance testing and staff training. We have checkpoints and sign-offs at each milestone. Would you like a more detailed project plan?""","There are 5 major checkpoints for us during the implemenation process. First is to ensure that we have done all the integrations with the data feeds and the internal systems. Second is to run a Proof of Concept for a small use case to ensure we have got the models and analytics running correctly. Third is to scale the use case to the larger organization. Fourth is User acceptance testing and staff training. And fiith and final is going into Production with the launch.
75
+ Would you like a more detailed project plan?",1,9,9,Both provide comprehensive information on training options
76
+ What makes your solution the best fit for our company compared to other options?,"""Based on our discussions, I believe our solution is the best fit for three main reasons: 1) Our deep expertise in the financial sector, which means faster implementation and industry-specific features, 2) Our advanced AI capabilities, which align with your goals for improved risk management and fraud detection, and 3) Our scalable architecture, which can support your projected growth. Moreover, our commitment to ongoing innovation ensures you'll always have cutting-edge capabilities. How do these align with your decision criteria?""","Our customers cite the advanced analytics, precision of the AI models, and the configrability of the platform as the key reasons to select us. PNC bank has aggregated data from their different loan systems to reduce charge-offs by 17%, and costs by 30%. They also process 3.5 million deposit and payment transactions every hour with our systems. They went live with our system in 16 weeks. Some of the other reasons include the underlying scalability of the platform and enterprise grade security. ",1,9,9,Both provide strong arguments for their solution's fit
77
+ Your pricing seems high compared to some other solutions we've seen. Is there any flexibility?,"""I appreciate your concern about the pricing. While our initial quote reflects the comprehensive nature of our solution, we do have some flexibility. We could look at adjusting the feature set or exploring a phased implementation to reduce the initial investment. Alternatively, we could discuss a longer contract term in exchange for a discount. What approach would you prefer to explore?""",We think we have a best in class solution and have a number of customers today running varied use cases on our platform. We offer a very transparent pricing model which allows us to scale across many customers. Some of the possibilities are discounts against commitments for long term or volume commitments. ,1,9,8,Salesperson 1 offers more specific options for flexibility
78
+ Can we spread out the payments over a longer period to reduce the upfront cost?,"""Absolutely, we can discuss alternative payment structures. One option is to spread the implementation cost over the first year, combined with quarterly payments for the license fee. This would reduce your initial outlay. We could also explore a pay-as-you-go model for certain modules. How would you like to structure the payments to best fit your budgeting process?""","Potentially. I will need to understand this more before I can make any commitments. As you can understand, we are a young company and have cash flow considerations as well. Can you help me understand how you want to structure the payments?",0,9,7,Salesperson 1 offers more specific payment structure options
79
+ What kind of discount can you offer for a three-year commitment?,"""For a three-year commitment, we can offer a 15% discount on the annual license fee. This would bring your annual cost down from $500,000 to $425,000 after the first year. Additionally, we could lock in this price for the full three years, protecting you from any potential price increases. Would you like me to draw up a comparison of the one-year versus three-year terms?""","Absolutely, we do offer price reductions to customers who are willing to do a longer term commitment to us. There is a 15% discount if you were to make a three-year commitment.
80
+ Would you like me to draw up a comparison of the one-year versus three-year terms?",1,9,8,Salesperson 1 provides more specific discount information
81
+ Can we start with a smaller implementation and scale up over time?,"""That's definitely an option. We could begin with core modules like data aggregation and basic analytics, then add advanced features like AI-driven predictions in subsequent phases. This approach would reduce your initial investment to about $400,000 for the first year. We can then add modules as your needs grow and as you realize ROI from the initial implementation. How does this aligned approach sound to you?""","Absolutely. Many of our customers start with 1-2 use cases and then scale up over time. What we do suggest however that you pick a use case that is a material and challenging use case for you so you are able to get a good idea of the results.
82
+ Do you have such a use case already identified?",0,9,8,Salesperson 1 provides more specific information on a phased approach
83
+ Is there any room for negotiation on the support costs?,"""I understand your concern about the support costs. While our support is comprehensive, we could look at tailoring it more specifically to your needs. For instance, we could reduce the cost by adjusting the support hours or response times. Alternatively, if you have a strong internal IT team, we could explore a co-support model. What aspects of the support package are most valuable to you?""","I understand your concern about the support costs. While our support is comprehensive, we could look at tailoring it more specifically to your needs. For instance, we could reduce the cost by adjusting the support hours or response times. Alternatively, if you have a strong internal IT team, we could explore a co-support model. One other option available to you is a discount if you were to commit to a longer term contract.
84
+ What aspects of the support package are most valuable to you?",1,9,9,Both offer similar levels of flexibility on support costs
85
+ Can you include additional training or consulting hours in the package without increasing the price?,"""I appreciate you asking about this. While our proposed package already includes substantial training, I understand the value of additional support. I can offer an additional 20 hours of consulting time at no extra cost. This could be used for advanced training, workflow optimization, or custom report development. Would this added value address your concerns?""","I appreciate you asking about this. Our goal is to ensure you gain adoption and value from the platform within your organzation. What we have done with other customers is offered additional training linked to adoption goals within their organization.
86
+ Is that something you are willing to consider?",1,9,8,Salesperson 1 offers a specific number of additional hours
87
+ What guarantees can you offer on the implementation timeline?,"""We're confident in our 4-month implementation estimate, but I understand the importance of timely delivery. We can add a clause to our contract that provides a service credit if we exceed the agreed-upon timeline. For instance, we could offer a 5% credit for each week of delay, up to a maximum of 20%. Would this type of guarantee give you the assurance you're looking for?""","Our implementation resources are available on a T&M basis. There are many dependencies on the implementation timeline including availability of your resources and integration with your internal systems. While we have done many such integrations offer, it is hard for us to offer guarantees in this area since we do not control availability of resources to guide these decisions. ",0,9,7,Salesperson 1 offers specific guarantees while 2 explains limitations
88
+ "If we commit to becoming a reference customer, can you offer any additional incentives?","""We greatly value reference customers and would be delighted to have you as one. In exchange for agreeing to be a reference (including potential case studies and peer recommendations), we can offer an additional 5% discount on your annual license fee. We would also prioritize your feature requests in our product roadmap. How does this sound to you?""",I would be happy to discuss that. We have offered some incentives to customers who agreed to becoming lighthouse customers for us and agreed to produce case studies and participate in joint speaking sessions. Is that something you are willing to consider?,1,9,8,Salesperson 1 offers more specific incentives for being a reference customer
89
+ Can we include a performance-based pricing component?,"""That's an interesting proposal. We're open to exploring a performance-based pricing model. We could structure it so that a portion of your fee is tied to agreed-upon KPIs","We have a consumption based pricing model, based on the modules you choose and the volume of data processed. We will be providing you a dashboard so you can get a daily view of the costs incurred.
90
+ On the performance, we will work with you to fine tune the data models or the underlying infrastructure if performance is not performing for any reason. Our goal is to have a long term relationship, and we want to make sure you are a happy and satisfied customer. ",0,8,7,Salesperson 1 is more open to performance-based pricing
91
+ "The incumbent provider just offered us a 25% discount so we stay on their platform, and now your pricing is much higher than theirs. Can you match their pricing so we can reconsider you?","I understand the appeal of a 25% discount from your current provider. While we may not be able to directly match that price, I'm confident our solution offers superior value that more than justifies the cost difference. Our advanced features like AI-driven analytics and real-time fraud detection often lead to cost savings and revenue increases that far exceed the price gap.
92
+ Would you be open to a detailed ROI analysis comparing our solution to your discounted current system? We could also explore performance-based pricing to align our fees with the value we deliver. Our goal is to be a long-term partner in driving your business success, not just a low-cost provider.","Looks like we are already delivering value for you! I am definitely willing to go back to my executives to see if there are any reductions possible but I wanted you to consider a few things. 1. our customers choose us because of the the advanced analytics, precision of the AI models, and the configrability of the platform. Those were some of the things you had cited were missing from the incumbent provider and reasons for the migration. 2. we offer very transparent pricing which has allowed us to scale quickly across many customers. Offering bait and switch pricing techniques erode customer trust and slow us down in terms of pricing.
93
+ What I have seen work in terms of a discount is when are customers are willing to do a longer term contract or agree to be a reference customer. Are you willing to consider those?",0,8,10,Salesperson 2 provides a more strategic and value-focused response
backend/app/data/user_response_20241014_110603.csv ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ timestamp,objection,response
2
+ 2024-10-14 11:06:03.482416,1. What guarantees do you offer for real-time issue resolution?,asdf
3
+ 2024-10-14 11:06:03.482430,2. Can you provide more details on the transparent pricing models?,adsf
4
+ 2024-10-14 11:06:03.482431,3. How do you ensure regulatory compliance for industry-specific solutions?,adsfa
5
+ 2024-10-14 11:06:03.482433,4. Can you elaborate on the process of seamless integration with existing cloud services?,asdfasd
6
+ 2024-10-14 11:06:03.482434,5. What specific measures do you take to ensure your data centers are eco-friendly?,asdfasd
7
+ 2024-10-14 11:06:03.482435,6. How do you handle data security concerns for clients?,asdfads
8
+ 2024-10-14 11:06:03.482436,7. What kind of support services do you offer for your cloud storage solutions?,adsfas
9
+ 2024-10-14 11:06:03.482438,8. Can you explain the scalability options available for businesses?,adsfas
10
+ 2024-10-14 11:06:03.482439,9. What level of customization is possible for tailored storage solutions?,adsfas
11
+ 2024-10-14 11:06:03.482440,10. How do you address concerns about data privacy and confidentiality?,asdfas
12
+ 2024-10-14 11:06:03.482441,11. What sets your platform apart from other cloud storage providers?,asdfads
13
+ 2024-10-14 11:06:03.482443,12. Can you provide case studies or testimonials from satisfied clients?,asdfsad
14
+ 2024-10-14 11:06:03.482444,13. Are there any hidden fees or additional costs that may arise?,asdfasd
15
+ 2024-10-14 11:06:03.482445,14. How do you handle data migration from existing systems to your platform?,asdfasd
16
+ 2024-10-14 11:06:03.482447,15. What measures do you have in place for disaster recovery and data backup?,asdfas
17
+ 2024-10-14 11:06:03.482448,16. Can you guarantee uptime and performance levels for the cloud storage?,asdfasd
18
+ 2024-10-14 11:06:03.482450,17. How do you stay up-to-date with the latest technology trends in cloud storage?,asdfsad
19
+ 2024-10-14 11:06:03.482451,18. What happens in case of a service outage or technical issue on your end?,asdfasd
20
+ 2024-10-14 11:06:03.482453,19. How do you ensure data encryption and protection during transmission and storage?,asdfsadf
21
+ 2024-10-14 11:06:03.482454,20. Can you provide a demo or trial period for us to test your cloud storage solutions before committing?,asdf
backend/app/db/__init__.py ADDED
File without changes
backend/app/db/database.py ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ from dotenv import load_dotenv
3
+
4
+ load_dotenv()
5
+
6
+ db_type = os.getenv("DB_TYPE")
7
+
8
+
9
+ if db_type == "mongodb":
10
+ from .database_mongodb import get_user_by_username, create_user, save_file, get_user_files
11
+ else:
12
+ from .database_dynamodb import get_user_by_username, create_user, save_file, get_user_files
13
+
14
+ get_user_by_username
15
+ create_user
16
+ save_file
17
+ get_user_files
backend/app/db/database_dynamodb.py ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import boto3
2
+ from botocore.exceptions import ClientError
3
+ from datetime import datetime
4
+ from typing import Optional, List
5
+ from .models import User, FileUpload
6
+
7
+ dynamodb = boto3.resource('dynamodb')
8
+ users_table = dynamodb.Table('Users')
9
+ files_table = dynamodb.Table('Files')
10
+
11
+ async def get_user_by_username(username: str) -> Optional[User]:
12
+ try:
13
+ response = users_table.get_item(Key={'username': username})
14
+ if 'Item' in response:
15
+ return User(**response['Item'])
16
+ return None
17
+ except ClientError:
18
+ return None
19
+
20
+ async def create_user(user: User) -> bool:
21
+ try:
22
+ users_table.put_item(
23
+ Item={
24
+ 'username': user.username,
25
+ 'email': user.email,
26
+ 'password': user.password,
27
+ },
28
+ ConditionExpression='attribute_not_exists(username)'
29
+ )
30
+ return True
31
+ except ClientError:
32
+ return False
33
+
34
+ async def save_file(username: str, file_upload: FileUpload) -> bool:
35
+ try:
36
+ files_table.put_item(
37
+ Item={
38
+ 'username': username,
39
+ 'filename': file_upload.filename,
40
+ 'content': file_upload.content,
41
+ 'created_at': datetime.utcnow().isoformat(),
42
+ 'updated_at': datetime.utcnow().isoformat()
43
+ }
44
+ )
45
+ return True
46
+ except ClientError:
47
+ return False
48
+
49
+ async def get_user_files(username: str) -> List[FileUpload]:
50
+ try:
51
+ response = files_table.query(
52
+ KeyConditionExpression='username = :username',
53
+ ExpressionAttributeValues={':username': username}
54
+ )
55
+ return [FileUpload(**item) for item in response.get('Items', [])]
56
+ except ClientError:
57
+ return []
backend/app/db/database_mongodb.py ADDED
@@ -0,0 +1,194 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # backend/app/database.py
2
+ from motor.motor_asyncio import AsyncIOMotorClient
3
+ import datetime
4
+ from typing import Optional, List
5
+ from .models import User, FileUpload
6
+ from bson import Binary
7
+ import os
8
+
9
+ # Get MongoDB connection string from environment variable
10
+ MONGO_URI = os.getenv("MONGODB_URI", "mongodb://localhost:27017")
11
+ DB_NAME = os.getenv("MONGODB_DB", "aithon")
12
+
13
+ client = AsyncIOMotorClient(MONGO_URI)
14
+ db = client[DB_NAME]
15
+
16
+ # Collections
17
+ users_collection = db.users
18
+ files_collection = db.files
19
+
20
+ async def get_user_by_username(username: str) -> Optional[User]:
21
+ """
22
+ Retrieve a user by username
23
+ """
24
+ user_doc = await users_collection.find_one({"username": username})
25
+ if user_doc:
26
+ return User(
27
+ username=user_doc["username"],
28
+ email=user_doc["email"],
29
+ password=user_doc["password"]
30
+ )
31
+ return None
32
+
33
+ async def get_user_by_email(email: str) -> Optional[User]:
34
+ """
35
+ Retrieve a user by email
36
+ """
37
+ user_doc = await users_collection.find_one({"email": email})
38
+ if user_doc:
39
+ return User(
40
+ username=user_doc["username"],
41
+ email=user_doc["email"],
42
+ password=user_doc["password"]
43
+ )
44
+ return None
45
+
46
+ async def create_user(user: User) -> bool:
47
+ """
48
+ Create a new user
49
+ Returns True if successful, False if user already exists
50
+ """
51
+ try:
52
+ # Check if username or email already exists
53
+ if await get_user_by_username(user.username) or await get_user_by_email(user.email):
54
+ return False
55
+
56
+ user_doc = {
57
+ "username": user.username,
58
+ "email": user.email,
59
+ "password": user.password,
60
+ "created_at": datetime.utcnow()
61
+ }
62
+
63
+ await users_collection.insert_one(user_doc)
64
+ return True
65
+ except Exception as e:
66
+ print(f"Error creating user: {e}")
67
+ return False
68
+
69
+ async def save_file(username: str, records: any, filename: str) -> bool:
70
+ """
71
+ Save a file to the database
72
+ """
73
+ try:
74
+ current_time = datetime.datetime.now(datetime.UTC)
75
+ file_doc = {
76
+ "username": username,
77
+ "filename": filename,
78
+ "content": records,
79
+ "created_at": current_time,
80
+ "updated_at": current_time,
81
+ "file_type": filename.split('.')[-1] if '.' in filename else 'unknown'
82
+ }
83
+
84
+ # Update if exists, insert if not
85
+ result = await files_collection.update_one(
86
+ {"username": username, "filename": filename},
87
+ {"$set": {
88
+ **file_doc,
89
+ "updated_at": current_time
90
+ }},
91
+ upsert=True
92
+ )
93
+
94
+ return bool(result.modified_count or result.upserted_id)
95
+ except Exception as e:
96
+ print(f"Error saving file: {e}")
97
+ return False
98
+
99
+ async def get_user_files(username: str) -> List[FileUpload]:
100
+ """
101
+ Retrieve all files belonging to a user
102
+ """
103
+ try:
104
+ cursor = files_collection.find({"username": username})
105
+ files = []
106
+ async for doc in cursor:
107
+ files.append(
108
+ FileUpload(
109
+ filename=doc["filename"],
110
+ content=doc["content"],
111
+ created_at=doc["created_at"],
112
+ updated_at=doc["updated_at"]
113
+ )
114
+ )
115
+ return files
116
+ except Exception as e:
117
+ print(f"Error retrieving files: {e}")
118
+ return []
119
+
120
+ async def delete_file(username: str, filename: str) -> bool:
121
+ """
122
+ Delete a file from the database
123
+ """
124
+ try:
125
+ result = await files_collection.delete_one({
126
+ "username": username,
127
+ "filename": filename
128
+ })
129
+ return bool(result.deleted_count)
130
+ except Exception as e:
131
+ print(f"Error deleting file: {e}")
132
+ return False
133
+
134
+ async def get_file_by_name(username: str, filename: str) -> Optional[FileUpload]:
135
+ """
136
+ Retrieve a specific file by username and filename
137
+ """
138
+ try:
139
+ doc = await files_collection.find_one({
140
+ "username": username,
141
+ "filename": filename
142
+ })
143
+ if doc:
144
+ return FileUpload(
145
+ filename=doc["filename"],
146
+ content=doc["content"].decode() if isinstance(doc["content"], Binary) else str(doc["content"]),
147
+ created_at=doc["created_at"],
148
+ updated_at=doc["updated_at"]
149
+ )
150
+ return None
151
+ except Exception as e:
152
+ print(f"Error retrieving file: {e}")
153
+ return None
154
+
155
+ async def update_user(username: str, update_data: dict) -> bool:
156
+ """
157
+ Update user information
158
+ """
159
+ try:
160
+ result = await users_collection.update_one(
161
+ {"username": username},
162
+ {"$set": {
163
+ **update_data,
164
+ "updated_at": datetime.utcnow()
165
+ }}
166
+ )
167
+ return bool(result.modified_count)
168
+ except Exception as e:
169
+ print(f"Error updating user: {e}")
170
+ return False
171
+
172
+ # Index creation function - call this during application startup
173
+ async def create_indexes():
174
+ """
175
+ Create necessary indexes for the collections
176
+ """
177
+ try:
178
+ # Users indexes
179
+ await users_collection.create_index("username", unique=True)
180
+ await users_collection.create_index("email", unique=True)
181
+
182
+ # Files indexes
183
+ await files_collection.create_index([("username", 1), ("filename", 1)], unique=True)
184
+ await files_collection.create_index("created_at")
185
+ await files_collection.create_index("updated_at")
186
+
187
+ return True
188
+ except Exception as e:
189
+ print(f"Error creating indexes: {e}")
190
+ return False
191
+
192
+ # Optional: Add these to your requirements.txt
193
+ # motor==3.3.1
194
+ # pymongo==4.5.0
backend/app/db/models.py ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from pydantic import BaseModel, EmailStr
2
+
3
+ from typing import Optional
4
+ from datetime import datetime
5
+
6
+ class User(BaseModel):
7
+ username: str
8
+ email: EmailStr
9
+ password: str
10
+
11
+ class TokenData(BaseModel):
12
+ username: Optional[str] = None
13
+
14
+ class Token(BaseModel):
15
+ access_token: str
16
+ token_type: str
17
+
18
+ class FileUpload(BaseModel):
19
+ filename: str
20
+ content: list[dict]
21
+ created_at: Optional[datetime] = None
22
+ updated_at: Optional[datetime] = None
23
+
24
+ class ChatMessage(BaseModel):
25
+ message: str
26
+ timestamp: datetime
27
+ sender: str
backend/app/llm_models.py ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from langchain_core.messages import HumanMessage, SystemMessage, BaseMessage
2
+ from langchain_community.chat_models import ChatPerplexity
3
+ from langchain_openai import ChatOpenAI
4
+
5
+ from .prompts import general_model_prompt, opportunity_search_prompt
6
+
7
+
8
+ def invoke_general_model(user_question: str) -> BaseMessage:
9
+ """Function to invoke the general model, to answer general questions related to sales."""
10
+ model = ChatOpenAI(model="gpt-4o-mini")
11
+ system_message = SystemMessage(content=general_model_prompt)
12
+ human_message = HumanMessage(content=user_question)
13
+ response = model.invoke([system_message, human_message])
14
+ return response
15
+
16
+
17
+ def invoke_customer_search(customer_name: str) -> BaseMessage:
18
+ """Function to invoke a Perplexity search on the customer name."""
19
+ model = ChatPerplexity()
20
+ message = HumanMessage(content=opportunity_search_prompt.format(customer_name))
21
+ response = model.invoke([message])
22
+ return response
23
+
24
+
25
+ if __name__ == "__main__":
26
+ from dotenv import load_dotenv
27
+
28
+ load_dotenv()
29
+
30
+ def test_invoke_general_model():
31
+ # Test that the general model can answer general questions related to sales processes.
32
+ response = invoke_general_model("What is MEDDPICC?")
33
+ assert "MEDDPIC" in response.content
34
+ assert len(response.content) > 10
35
+
36
+ # Test that the general model can politely decline to answer questions not related to sales processes.
37
+ response = invoke_general_model("What is the weather like today?")
38
+ assert "weather" not in response.content
39
+ assert "I'm only here to assist you with sales processes and closing deals." in response.content
40
+
41
+ def test_invoke_customer_search():
42
+ # Test that the customer search model can find information about a specific company.
43
+ response = invoke_customer_search("Datadog")
44
+ assert "Datadog" in response.content
45
+ assert len(response.content) > 10
46
+
47
+ test_invoke_general_model()
48
+ test_invoke_customer_search()
backend/app/main.py ADDED
@@ -0,0 +1,151 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import base64
3
+ import io
4
+ import csv
5
+ import json
6
+ import datetime
7
+ import pandas as pd
8
+ from datetime import timedelta
9
+ from fastapi import FastAPI,WebSocket, Depends, HTTPException, status, UploadFile, File
10
+ from fastapi.responses import FileResponse, JSONResponse
11
+ from fastapi.requests import Request
12
+ from fastapi.staticfiles import StaticFiles
13
+ from fastapi.middleware.cors import CORSMiddleware
14
+ from fastapi.security import OAuth2PasswordRequestForm
15
+ from .auth import (
16
+ get_current_user,
17
+ create_access_token,
18
+ verify_password,
19
+ get_password_hash,
20
+ )
21
+ from .db.models import User, Token, FileUpload
22
+ from .db.database import get_user_by_username, create_user, save_file, get_user_files
23
+ from .websocket import handle_websocket
24
+ from .llm_models import invoke_general_model, invoke_customer_search
25
+
26
+ app = FastAPI()
27
+
28
+ app.add_middleware(
29
+ CORSMiddleware,
30
+ allow_origins=["*"],
31
+ allow_credentials=True,
32
+ allow_methods=["*"],
33
+ allow_headers=["*"],
34
+ )
35
+
36
+ # Get the directory of the current file
37
+ current_dir = os.path.dirname(os.path.realpath(__file__))
38
+
39
+ # Construct the path to the frontend dist directory
40
+ frontend_dir = os.path.join(current_dir, "..", "..", "frontend", "dist")
41
+
42
+ @app.get("/")
43
+ async def serve_react_root() -> FileResponse:
44
+ return FileResponse(os.path.join(frontend_dir, "index.html"))
45
+
46
+ @app.post("/register", response_model=Token)
47
+ async def register(user: User) -> Token:
48
+ if await get_user_by_username(user.username):
49
+ raise HTTPException(
50
+ status_code=status.HTTP_400_BAD_REQUEST,
51
+ detail="Username already registered"
52
+ )
53
+
54
+ hashed_password = get_password_hash(user.password)
55
+ user.password = hashed_password
56
+
57
+ if not await create_user(user):
58
+ raise HTTPException(
59
+ status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
60
+ detail="Could not create user"
61
+ )
62
+
63
+ access_token = create_access_token(
64
+ data={"sub": user.username},
65
+ expires_delta=timedelta(minutes=30)
66
+ )
67
+ return Token(access_token=access_token, token_type="bearer")
68
+
69
+ @app.post("/token", response_model=Token)
70
+ async def login(form_data: OAuth2PasswordRequestForm = Depends()) -> Token:
71
+ user = await get_user_by_username(form_data.username)
72
+ if not user or not verify_password(form_data.password, user.password):
73
+ raise HTTPException(
74
+ status_code=status.HTTP_401_UNAUTHORIZED,
75
+ detail="Incorrect username or password",
76
+ headers={"WWW-Authenticate": "Bearer"},
77
+ )
78
+
79
+ access_token = create_access_token(
80
+ data={"sub": user.username},
81
+ expires_delta=timedelta(minutes=30)
82
+ )
83
+ return Token(access_token=access_token, token_type="bearer")
84
+
85
+ @app.post("/upload")
86
+ async def upload_file(
87
+ file: UploadFile = File(...),
88
+ current_user: User = Depends(get_current_user)
89
+ ) -> dict:
90
+ contents = await file.read()
91
+ # Convert to pandas DataFrame
92
+ df = pd.read_csv(io.StringIO(contents.decode('utf-8')))
93
+
94
+ # Convert DataFrame to list of dictionaries
95
+ records = json.loads(df.to_json(orient='records'))
96
+
97
+
98
+ # Insert into MongoDB
99
+
100
+
101
+ if not await save_file(current_user.username, records, file.filename):
102
+ raise HTTPException(
103
+ status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
104
+ detail="Could not save file"
105
+ )
106
+
107
+ return {"message": "File uploaded successfully"}
108
+
109
+ @app.get("/api/opportunities")
110
+ async def get_opportunities(request: Request, current_user: User = Depends(get_current_user)) -> dict:
111
+ records = await get_user_files(current_user.username)
112
+ print("records", records)
113
+ all_records = []
114
+ for record in records:
115
+ all_records.extend(record.content)
116
+
117
+
118
+ return {"records": all_records , "success": len(all_records) > 0}
119
+
120
+ @app.websocket("/ws")
121
+ async def websocket_endpoint(websocket: WebSocket) -> None:
122
+ await handle_websocket(websocket)
123
+
124
+ @app.post("/api/message")
125
+ async def message(obj: dict, current_user: User = Depends(get_current_user)) -> JSONResponse:
126
+ """Endpoint to handle general incoming messages from the frontend."""
127
+ answer = invoke_general_model(obj["message"])
128
+ return JSONResponse(content={"message": answer.model_dump_json()})
129
+
130
+
131
+ @app.post("/api/customer_insights")
132
+ async def customer_insights(obj: dict) -> JSONResponse:
133
+ """Endpoint to launch a customer insight search."""
134
+ answer = invoke_customer_search(obj["message"])
135
+ return JSONResponse(content={"AIMessage": answer.model_dump_json()})
136
+
137
+ app.mount("/assets", StaticFiles(directory=os.path.join(frontend_dir, "assets")), name="static")
138
+
139
+ if __name__ == "__main__":
140
+ from fastapi.testclient import TestClient
141
+
142
+ client = TestClient(app)
143
+
144
+ def test_message_endpoint():
145
+ # Test that the message endpoint returns answers to questions.
146
+ response = client.post("/api/message", json={"message": "What is MEDDPICC?"})
147
+ print(response.json())
148
+ assert response.status_code == 200
149
+ assert "AIMessage" in response.json()
150
+
151
+ test_message_endpoint()
backend/app/prompts.py ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ general_model_prompt = """
2
+ You are a helpful assistant, expert in sales processes. Your task is to help other salesperson as well as possible.
3
+ You are only allowed to answer questions related to sales processes and provide guidance on how to close deals.
4
+ If the user asks you a question that is not related to sales processes or closing deals, you should politely decline to answer.
5
+ In this case, your answer should contain 'I'm only here to assist you with sales processes and closing deals.' and you should add a continuation to invite the user to ask a relevant question.
6
+ """
7
+
8
+ opportunity_search_prompt = "Search for all the latest news and information about the company {}."
backend/app/reports/HSBC Opportunity Review Report.md ADDED
@@ -0,0 +1,71 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ **Analysis Results**
2
+
3
+ **Opportunity ID:** XFR0001
4
+ **Opportunity Name:** Lending - Loan Origination System
5
+ **Opportunity Stage:** Proposal
6
+ **Opportunity Description:** Developing analytic capabilities for the loan origination system
7
+ **Opportunity Value:** $250,000
8
+ **Opportunity Close Date:** 11/30/2024
9
+ **Customer Contact:** John Smith
10
+ **Customer Contact Role:** VP, Information Technology
11
+
12
+ **Summary:** The opportunity with HSBC involves providing a new analytics engine for their loan origination system, aimed at improving speed and flexibility. The urgency is driven by an upcoming renewal with their current vendor. Multiple meetings have been held, leading to a proposal review. A follow-up with the VP of IT is planned to discuss next steps, possibly moving towards a pilot or negotiations.
13
+
14
+ **Score:** 78
15
+
16
+ **MEDDIC Evaluation:**
17
+
18
+ **Metrics:** 80 - The proposal includes discussions on ROI and expected performance improvements, indicating a strong understanding of the quantitative benefits HSBC expects.
19
+ **Economic Buyer:** 75 - John Smith, the VP of IT, is a high-level contact, but the involvement of the CFO in discussions suggests that the economic buyer might be higher up or require broader agreement.
20
+ **Decision Criteria:** 70 - The decision criteria have been explored through customization discussions and integration options, but further clarity on the specific decision-making factors within HSBC is needed.
21
+ **Decision Process:** 85 - The decision process appears structured with a series of meetings leading to proposal review and further internal review. Upcoming discussions with John Smith indicate a clear path forward.
22
+ **Identify Pain:** 90 - HSBC's need for a faster, more flexible system is well understood, with urgency added by the upcoming vendor renewal, showing a strong identification of pain points.
23
+ **Champion:** 70 - John Smith appears to be a potential champion, engaging in most meetings, but more explicit support or advocacy from him would strengthen this position.
24
+
25
+ **Next Steps**
26
+
27
+ Prepare for the meeting with John Smith by developing a detailed pilot proposal that aligns with HSBC's decision criteria and showcases the value of the analytics engine. Aim to secure a commitment to move forward with a pilot program.
28
+
29
+ **Talking Points:**
30
+
31
+ 1. Highlight the ROI and performance improvements expected from the new analytics engine, emphasizing how it addresses HSBC's pain points for speed and flexibility in the loan origination process
32
+ 2. Discuss the customization and integration options explored so far, and seek clarity on any additional decision-making factors or criteria that need to be addressed to align with HSBC's expectations
33
+ 3. Reinforce the urgency of transitioning to a more advanced solution by outlining the potential risks and downsides of continuing with the current vendor, especially in light of the upcoming renewal
34
+
35
+ **Opportunity History:**
36
+
37
+ **Meeting 1:** Initial Discovery Call
38
+ - Date: August 15, 2024
39
+ - Attendees:
40
+ - HSBC: John Smith (VP, IT), Sarah Johnson (Head of Lending)
41
+ - Our Company: Michael Brown (Account Executive), Emily Davis (Solutions Architect)
42
+ - Duration: 60 minutes
43
+ - Key Points Discussed:
44
+ - HSBC's current challenges with their loan origination system
45
+ - High-level overview of our analytics capabilities
46
+ - Initial discussion on potential integration points
47
+ - Outcome: HSBC expressed interest in a follow-up meeting for a deeper dive into our solution
48
+
49
+ **Meeting 2:** Technical Deep Dive
50
+ - Date: September 3, 2024
51
+ - Attendees:
52
+ - HSBC: John Smith (VP, IT), Mark Wilson (Senior Systems Analyst), Lisa Chen (Data Scientist)
53
+ - Our Company: Emily Davis (Solutions Architect), Alex Rodriguez (Technical Lead)
54
+ - Duration: 90 minutes
55
+ - Key Points Discussed:
56
+ - Detailed walkthrough of our analytics engine architecture
57
+ - Discussion on data migration and integration processes
58
+ - Exploration of customization options to meet HSBC's specific needs
59
+ - Outcome: HSBC requested a proposal outlining potential implementation scenarios
60
+
61
+ **Meeting 3:** Proposal Review and Q&A
62
+ - Date: September 25, 2024
63
+ - Attendees:
64
+ - HSBC: John Smith (VP, IT), Sarah Johnson (Head of Lending), David Thompson (CFO)
65
+ - Our Company: Michael Brown (Account Executive), Emily Davis (Solutions Architect), Rachel Kim (Client Success Manager)
66
+ - Duration: 75 minutes
67
+ - Key Points Discussed:
68
+ - Presentation of our proposed solution and implementation plan
69
+ - Discussion on ROI and expected performance improvements
70
+ - Clarification on pricing structure and contract terms
71
+ - Outcome: HSBC team to review internally and schedule a follow-up for any additional questions before moving to the next stage
backend/app/reports/HSBC Quarterly Report 2024-10-16 00-39-38.pdf ADDED
Binary file (7.34 kB). View file
 
backend/app/reports/HSBC Quarterly Report 2024-10-16 09_36_43.pdf ADDED
Binary file (6.66 kB). View file
 
backend/app/reports/HSBC Quarterly Report 2024-10-16.md ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ### HSBC Quarterly Report - Q3 2024
2
+
3
+ #### Overview
4
+ HSBC Holdings plc, one of the world's largest banking and financial services organizations, has been navigating a transformative period marked by strategic shifts, leadership changes, and a focus on digital innovation. As of October 2024, the bank is actively pursuing cost-cutting measures, expanding its wealth management services, and launching new ventures in embedded finance.
5
+
6
+ #### Key Developments
7
+ 1. **Cost-Cutting Initiatives**: HSBC is reportedly considering a cost-cutting plan aimed at saving up to $300 million, primarily targeting senior management positions. This move is part of a broader strategy to enhance operational efficiency and respond to changing market conditions ([Reuters](https://www.reuters.com/business/finance/hsbc-mulls-cost-cutting-plan-save-up-300-mln-ft-reports-2024-10-10/)).
8
+
9
+ 2. **Leadership Changes**: The bank has seen significant leadership transitions, with Noel Quinn announcing his retirement as Group Chief Executive after nearly five years. Georges Elhedery has been appointed as his successor, tasked with leading HSBC through its next phase of development ([HSBC News](https://www.hsbc.com/news-and-views/news)).
10
+
11
+ 3. **Expansion of Wealth Management**: HSBC aims to double its assets under management in the UK wealth business to £100 billion ($131 billion) over the next five years. This initiative is part of a strategy to target the 'mass affluent' market, which is increasingly becoming a focus for major banks ([Financial Express](https://today.thefinancialexpress.com.bd/trade-market/hsbc-looks-to-double-uk-wealth-business-as-banks-target-mass-affluent-1724516994)).
12
+
13
+ 4. **Launch of Embedded Finance Venture**: In October 2024, HSBC launched a joint venture called SemFi with Tradeshift, aimed at providing embedded finance solutions to business clients. This venture will initially operate in the UK and is designed to integrate HSBC's financial services into e-commerce platforms, enhancing accessibility for SMEs ([Finextra](https://www.finextra.com/newsarticle/44827/hsbc-launches-embedded-finance-venture)).
14
+
15
+ 5. **Market Outlook and Economic Implications**: As the US elections approach, HSBC's market insights suggest that while election outcomes may introduce volatility, historical trends indicate that US equity markets tend to perform positively in the six months following elections, regardless of the political party in power ([HSBC UK](https://www.hsbc.co.uk/wealth/insights/market-outlook/special-coverage/2024-10-14/)).
16
+
17
+ 6. **Write-Offs and Strategic Divestments**: HSBC has also been restructuring its portfolio, including writing off its remaining $5.8 million stake in UK fintech Monese and considering the sale of its South African business to focus on more lucrative markets ([FinTech Futures](https://www.fintechfutures.com/2024/10/hsbc-reportedly-writes-off-remaining-5-8m-stake-in-uk-fintech-monese/), [FinTech Futures](https://www.fintechfutures.com/2024/08/hsbc-reportedly-considering-sale-of-its-south-african-business/)).
18
+
19
+ #### Conclusion
20
+ HSBC is positioning itself for future growth through strategic cost management, leadership renewal, and a focus on digital transformation. The bank's initiatives in wealth management and embedded finance reflect its commitment to adapting to the evolving financial landscape while maintaining a strong operational foundation. As it navigates these changes, HSBC remains focused on delivering value to its shareholders and clients alike.
21
+
22
+ ### Citations
23
+ - [HSBC mulls cost-cutting plan of up to $300 mln, targeting top ranks, FT ...](https://www.reuters.com/business/finance/hsbc-mulls-cost-cutting-plan-save-up-300-mln-ft-reports-2024-10-10/): "HSBC mulls cost-cutting plan of up to $300 mln, targeting top ranks."
24
+ - [News: Latest Articles and Media Releases | HSBC Holdings plc](https://www.hsbc.com/news-and-views/news): "Georges Elhedery becomes our new Group Chief Executive."
25
+ - [HSBC looks to double UK wealth business as banks target 'mass affluent' - Finance News: Latest Financial News, Finance News today in Bangladesh](https://today.thefinancialexpress.com.bd/trade-market/hsbc-looks-to-double-uk-wealth-business-as-banks-target-mass-affluent-1724516994): "HSBC aims to double the assets under management in its British wealth business to 100 billion pounds ($131 billion) in the next five years."
26
+ - [HSBC launches embedded finance venture - Finextra](https://www.finextra.com/newsarticle/44827/hsbc-launches-embedded-finance-venture): "HSBC launches embedded finance venture."
27
+ - [Special Coverage | Market and Economic News | HSBC UK](https://www.hsbc.co.uk/wealth/insights/market-outlook/special-coverage/2024-10-14/): "For the overall market direction, the election result may matter less than is sometimes assumed."
28
+ - [HSBC reportedly writes off remaining $5.8m stake in UK fintech Monese - FinTech Futures](https://www.fintechfutures.com/2024/10/hsbc-reportedly-writes-off-remaining-5-8m-stake-in-uk-fintech-monese/): "HSBC reportedly writes off remaining $5.8m stake in UK fintech Monese."
29
+ - [HSBC reportedly considering sale of its South African business - FinTech Futures](https://www.fintechfutures.com/2024/08/hsbc-reportedly-considering-sale-of-its-south-african-business/): "HSBC reportedly considering sale of its South African business."
backend/app/reports/HSBC Quarterly Report 2024-10-16.pdf ADDED
Binary file (7.65 kB). View file
 
backend/app/reports/HSBC Quarterly Report 2024-10-19.md ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ## HSBC Quarterly Report - Q3 2024
2
+
3
+ ### Overview
4
+ HSBC Holdings plc, one of the world's largest banking and financial services organizations, has demonstrated robust performance in the first half of 2024, continuing its strategic focus on wealth management and digital innovation. The bank reported a profit before tax of $21.7 billion for the first half of 2024, up from $21.7 billion in the same period last year, with revenues reaching $36.9 billion. This performance underscores the effectiveness of HSBC's strategic initiatives, particularly in wealth management and digital banking.
5
+
6
+ ### Financial Performance
7
+ - **Profit Before Tax**: $21.7 billion (1H23: $21.7 billion)
8
+ - **Revenue**: $36.9 billion (1H23: $36.9 billion)
9
+ - **Return on Tangible Equity (RoTE)**: Targeting mid-teens for 2024 and 2025, excluding notable items.
10
+ - **Net Interest Income**: Expected to be around $43 billion in 2024, influenced by global interest rate trends.
11
+ - **Loan Growth**: 1% in 1H24, with expectations of mid-single digit growth in customer lending over the medium to long term.
12
+ - **Dividend Payout Ratio**: Targeting 50% for 2024, excluding notable items.
13
+
14
+ ### Strategic Initiatives
15
+ 1. **Wealth Management Expansion**: HSBC is aggressively expanding its wealth management services, particularly in Canada and the UK. The bank aims to double its private client business in Canada and increase its assets under management in the UK to £100 billion ($131 billion) over the next five years. This strategy is aimed at capturing a larger share of the growing mass affluent market, which is increasingly targeted by major banks ([Yahoo Finance](https://finance.yahoo.com/news/hsbc-plans-expand-private-wealth-141500759.html), [Financial Express](https://today.thefinancialexpress.com.bd/trade-market/hsbc-looks-to-double-uk-wealth-business-as-banks-target-mass-affluent-1724516994)).
16
+
17
+ 2. **Digital Innovation**: HSBC is pioneering digital banking solutions, as highlighted in its Digital Horizons Report. The bank is leveraging advancements in AI and automation to enhance customer experience and operational efficiency. This includes the launch of its embedded finance venture, SemFi, in partnership with Tradeshift, which aims to provide integrated financial solutions for SMEs in e-commerce ([Finextra](https://www.finextra.com/newsarticle/44827/hsbc-launches-embedded-finance-venture), [HSBC UK](https://www.business.hsbc.uk/en-gb/insights/running-a-business/steering-the-future)).
18
+
19
+ 3. **Global Wealth Centers**: HSBC has opened a flagship wealth center in Hudson Yards, New York, as part of its strategy to enhance wealth management services in the U.S. This center is designed to cater to high-net-worth individuals and families with international ties, providing a comprehensive suite of banking and wealth management services ([Yahoo Finance](https://finance.yahoo.com/news/hsbc-accelerates-wealth-management-strategy-140000206.html)).
20
+
21
+ ### Outlook
22
+ HSBC's outlook remains positive, with a focus on achieving a mid-teens RoTE and continued growth in wealth management and digital banking. The bank is well-positioned to capitalize on the increasing demand for personalized financial services and the ongoing digital transformation in the banking sector. The strategic initiatives in wealth management and digital innovation are expected to drive future growth and enhance HSBC's competitive advantage in the global market.
23
+
24
+ ### Conclusion
25
+ HSBC's strong financial performance in the first half of 2024, coupled with its strategic focus on wealth management and digital innovation, positions the bank for continued success. The initiatives to expand its wealth management services and enhance digital offerings reflect HSBC's commitment to meeting the evolving needs of its clients in a rapidly changing financial landscape.
26
+
27
+ ### Citations
28
+ - [Interim Results 2024 quick read | HSBC Holdings plc](https://www.hsbc.com/investors/results-and-announcements/all-reporting/interim-results-2024-quick-read): "We had another strong profit performance in the first half of 2024, which is further evidence that our strategy is working."
29
+ - [HSBC Plans to Expand Private Wealth Management Business in Canada](https://finance.yahoo.com/news/hsbc-plans-expand-private-wealth-141500759.html): "HSBC aims to double its private client business in Canada as the Canadian private wealth management market offers an attractive opportunity for the company."
30
+ - [HSBC looks to double UK wealth business as banks target 'mass affluent' - Finance News: Latest Financial News, Finance News today in Bangladesh](https://today.thefinancialexpress.com.bd/trade-market/hsbc-looks-to-double-uk-wealth-business-as-banks-target-mass-affluent-1724516994): "HSBC aims to double the assets under management in its British wealth business to 100 billion pounds ($131 billion) in the next five years."
31
+ - [HSBC launches embedded finance venture - Finextra](https://www.finextra.com/newsarticle/44827/hsbc-launches-embedded-finance-venture): "HSBC has partnered B2B global trade network Tradeshift on a joint venture offering embedded finance solutions to business clients."
32
+ - [HSBC UK | Pioneering the Next Wave of Digital Innovation](https://www.business.hsbc.uk/en-gb/insights/running-a-business/steering-the-future): "The banking sector is already embracing this transition – leveraging digitalisation to deliver both operational benefits and a greater customer experience."
33
+ - [HSBC Accelerates Wealth Management Strategy in U.S. with Opening of ...](https://finance.yahoo.com/news/hsbc-accelerates-wealth-management-strategy-140000206.html): "HSBC announced the launch of its new wealth center at Hudson Yards, a key part of its wealth management strategy in the U.S."
backend/app/reports/HSBC Quarterly Report 2024-10-19.pdf ADDED
Binary file (7.45 kB). View file
 
backend/app/utils/__init__.py ADDED
File without changes
backend/app/utils/images/salesbuddy_logo.jpg ADDED
backend/app/utils/utils_actions.py ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import chainlit as cl
2
+
3
+ async def offer_initial_actions():
4
+ actions = [
5
+ cl.Action(name="Deal Analysis", value="deal-analysis", description="Deal Analysis"),
6
+ cl.Action(name="Customer Research", value="customer-research", description="Customer Research"),
7
+ cl.Action(name="Sales Simulation", value="sales-simulation", description="Sales Simulation"),
8
+ ]
9
+ await cl.Message(content=" ", actions=actions).send()
10
+ await cl.Message(content="\n\n").send()
11
+
12
+ async def offer_actions():
13
+ await cl.Message(content="\n\n").send()
14
+ actions = [
15
+ cl.Action(name="Get Latest News on this Customer", value="HSBC", description="Get Latest News"),
16
+ cl.Action(name="Enter Meeting Simulation", value="enter-meeting-simulation", description="Enter Meeting Simulation"),
17
+ cl.Action(name="Review Another Opportunity", value="review-another-opportunity", description="Review Another Opportunity"),
18
+ ]
19
+ await cl.Message(content="Select an action", actions=actions).send()
20
+ await cl.Message(content="\n\n").send()
21
+
backend/app/utils/utils_callbacks.py ADDED
@@ -0,0 +1,99 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ import asyncio
3
+ import chainlit as cl
4
+ from datetime import datetime
5
+ from .utils_data import get_company_data, get_opportunities, get_questions, get_customer_background
6
+ from .utils_output import display_evaluation_results, display_llm_responses
7
+ from .utils_objections import create_objections
8
+ # async def callback_show_scenarios():
9
+ # scenarios = get_opportunities()
10
+ # cl.user_session.set("scenarios", scenarios)
11
+ # scenarios = cl.user_session.get("scenarios", None)
12
+ # if scenarios is None:
13
+ # await cl.Message(content="No scenarios found.").send()
14
+ # return
15
+
16
+ # scenario_actions = []
17
+ # for idx, row in scenarios.iterrows():
18
+ # if row['Opportunity Description'] != "":
19
+ # scenario_action = cl.Action(
20
+ # name="Scenario",
21
+ # value=f"{idx}", # Send the row index as value
22
+ # description=f"{row['Customer Name']}: {row['Opportunity Name']} ({row['Opportunity Stage']}) "
23
+ # f"Value: {row['Opportunity Value']}. Meeting with {row['Customer Contact']} "
24
+ # f"({row['Customer Contact Role']})"
25
+ # )
26
+ # scenario_actions.append(scenario_action)
27
+ # await cl.Message(content="Select a scenario (hover for details):", actions=scenario_actions).send()
28
+
29
+
30
+ async def callback_run_scenario(action):
31
+ await cl.Message(content="*Preparing simulation - please wait ...*").send()
32
+ index = 0
33
+ opportunities = cl.user_session.get("opportunities", None)
34
+ if opportunities is None:
35
+ await cl.Message(content="No scenarios found.").send()
36
+ return
37
+ await cl.Message(content="*Gathering opportunity information ...*").send()
38
+ await asyncio.sleep(1)
39
+
40
+ await cl.Message(content="*Customizing questions for this opportunity ...*").send()
41
+ await asyncio.sleep(1)
42
+
43
+ selected_opportunity = opportunities.iloc[index]
44
+ session_state = cl.user_session.get("session_state", None)
45
+ session_state.add_scenario_info(selected_opportunity)
46
+ get_customer_background(session_state, selected_opportunity['Customer Name'])
47
+ if session_state.ask_objections:
48
+ print("creating objections")
49
+ session_state.objections = await create_objections(session_state)
50
+ questions = []
51
+ for obj in session_state.objections:
52
+ print(obj)
53
+ q = {"stage": session_state.opportunity.stage, "question": obj[3:], "ground_truth": ""}
54
+ questions.append(q)
55
+ session_state.questions = questions
56
+ else:
57
+ print("questions created")
58
+ session_state.questions = get_questions(session_state.opportunity.stage, session_state.num_questions)
59
+ for q in session_state.questions:
60
+ print(q)
61
+ opening_message = session_state.get_opening()
62
+ await cl.Message(content=opening_message).send()
63
+ start_actions = [
64
+ cl.Action(name="Start Simulation", value="start_simulation", description="Start Simulation"),
65
+ ]
66
+ await cl.Message(content="Click to start simulation", actions=start_actions).send()
67
+
68
+ async def callback_start_scenario():
69
+ print("callback_start_scenario()")
70
+ session_state = cl.user_session.get("session_state", None)
71
+ await cl.Message(content="3...").send()
72
+ await asyncio.sleep(1)
73
+ await cl.Message(content="2...").send()
74
+ await asyncio.sleep(1)
75
+ await cl.Message(content="1...").send()
76
+ await asyncio.sleep(1)
77
+ await cl.Message(content="**Simulation Starting**").send()
78
+ await cl.Message(content="\n\n").send()
79
+ start_time = datetime.now()
80
+ print("setting start time")
81
+ session_state.start_time = start_time
82
+ output = f"{session_state.customer.contact_name} joins the zoom call"
83
+ print(output)
84
+ await cl.Message(content=output).send()
85
+ await cl.Message(content="\n\n").send()
86
+
87
+ async def callback_evaluate_performance():
88
+ session_state = cl.user_session.get("session_state", None)
89
+ if session_state is None:
90
+ await cl.Message(content="No session found.").send()
91
+ return
92
+ await display_evaluation_results(cl, session_state)
93
+
94
+ async def callback_display_queries_responses():
95
+ session_state = cl.user_session.get("session_state", None)
96
+ if session_state is None:
97
+ await cl.Message(content="No session found.").send()
98
+ return
99
+ await display_llm_responses(cl, session_state)
backend/app/utils/utils_chain_parameters.py ADDED
@@ -0,0 +1,82 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ def prepare_chain_parameters(session_state, message, history):
2
+ message = message.content
3
+ previous_question = ""
4
+ rep_answer = ""
5
+ next_question = ""
6
+ ground_truth = ""
7
+ command = ""
8
+ all_questions_answers = ""
9
+ print(f"Index: {session_state.current_question_index}")
10
+ if session_state.current_question_index == 0:
11
+ previous_question = ""
12
+ rep_answer = ""
13
+ ground_truth = ""
14
+ next_question = session_state.questions[session_state.current_question_index]["question"]
15
+ all_questions_answers = ""
16
+ command = "You should greet the salesrep"
17
+ elif session_state.current_question_index >= len(session_state.questions):
18
+ next_question = ""
19
+ previous_question = session_state.questions[session_state.current_question_index - 1]["question"]
20
+ rep_answer = session_state.previous_answer
21
+ ground_truth = session_state.questions[session_state.current_question_index - 1]["ground_truth"]
22
+ for response in session_state.responses:
23
+ all_questions_answers += f"Question: {response['question']}\nAnswer: {response['response']}\n\n"
24
+ command = """Offer a comment on their last answer. Then conclude the conversation with a polite farewell
25
+ and a suggestion for the next step.
26
+ """
27
+ else:
28
+ previous_question = session_state.questions[session_state.current_question_index - 1]["question"]
29
+ rep_answer = session_state.previous_answer
30
+ next_question = session_state.questions[session_state.current_question_index]["question"]
31
+ ground_truth = session_state.questions[session_state.current_question_index]["ground_truth"]
32
+ all_questions_answers = ""
33
+ command = "You should respond to the answer based on how well the rep answered the previous question."
34
+ session_state.ground_truth = ground_truth
35
+ session_state.question = previous_question
36
+ session_state.rep_answer = rep_answer
37
+ print("--------------------------------")
38
+ print(f"Message: {message}")
39
+ print("Sending the following:")
40
+ print(f"Command: {command}")
41
+ print(f"Previous question: {previous_question}")
42
+ print(f"Rep answer: {rep_answer}")
43
+ print(f"Next question: {next_question}")
44
+
45
+ rep_company_details = f"""
46
+ Name: {session_state.company.name}
47
+ Description: {session_state.company.description}
48
+ Product: {session_state.company.product}
49
+ Product Summary: {session_state.company.product_summary}
50
+ Product Description: {session_state.company.product_description}
51
+ """
52
+ company_details = f"""
53
+ Name: {session_state.customer.name}
54
+ Description: {session_state.customer.background}
55
+ """
56
+ scenario = f"""
57
+ Opportunity Name: {session_state.opportunity.name}
58
+ Opportunity Description: {session_state.opportunity.description}
59
+ Opportunity Stage: {session_state.opportunity.stage}
60
+ Opportunity Value: {session_state.opportunity.value}
61
+ Opportunity Close Date: {session_state.opportunity.close_date}
62
+ """
63
+ parm = {"conversation_mode": session_state.qa_mode,
64
+ "message": message,
65
+ "name": session_state.customer.contact_name,
66
+ "company": company_details,
67
+ "role": session_state.customer.contact_role,
68
+ "sales_rep": "Tony Snell",
69
+ "rep_company": rep_company_details,
70
+ "attitude": session_state.attitude,
71
+ "mood_score": session_state.mood_score,
72
+ "scenario": scenario,
73
+ "stage": session_state.opportunity.stage,
74
+ "previous_question": previous_question,
75
+ "next_question": next_question,
76
+ "rep_answer": rep_answer,
77
+ "conversation_history": history,
78
+ "command": command,
79
+ "all_questions_answers": all_questions_answers
80
+ }
81
+ return parm
82
+
backend/app/utils/utils_control_messages.py ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ async def handle_control_message(cl, command):
2
+ command_parts = command.split()
3
+ main_command = command_parts[0].lower()
4
+
5
+ if main_command == 'start':
6
+ await cl.Message(content="Starting new session...").send()
7
+
8
+ elif main_command == 'stop':
9
+ session_state = cl.user_session.get("session_state")
10
+ end_time = datetime.now()
11
+ duration = end_time - session_state.start_time
12
+ duration_minutes = round(duration.total_seconds() / 60)
13
+ session_state.end_time = end_time
14
+ session_state.duration_minutes = duration_minutes
15
+
16
+ await cl.Message(content=f"Ending current session after {session_state.duration_minutes} minutes").send()
17
+ elif main_command == 'pause':
18
+ await cl.Message(content="Ending current session...").send()
19
+
20
+ elif main_command == 'time':
21
+ session_state = cl.user_session.get("session_state")
22
+ duration = session_state.get_session_duration()
23
+ await cl.Message(content=f"Current session duration: {duration}").send()
24
+
25
+ else:
26
+ await cl.Message(content=f"Unknown command: {main_command}").send()
backend/app/utils/utils_customer_research.py ADDED
@@ -0,0 +1,341 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import asyncio
2
+ import chainlit as cl
3
+ import json
4
+ import operator
5
+ import os
6
+
7
+ from typing import TypedDict, List, Annotated, Literal, Dict, Union, Optional
8
+ from datetime import datetime
9
+
10
+
11
+
12
+ from langchain_core.tools import tool
13
+ from langchain_core.messages import AnyMessage, AIMessage, SystemMessage, HumanMessage, ToolMessage
14
+ from langchain_core.pydantic_v1 import BaseModel, Field, conlist
15
+ from langchain_openai import ChatOpenAI
16
+ from langgraph.graph import StateGraph, START, END, add_messages
17
+
18
+ from tavily import AsyncTavilyClient, TavilyClient
19
+
20
+ from .utils_actions import offer_actions
21
+ from .utils_pdf import generate_pdf_from_md
22
+
23
+
24
+ async def get_latest_news(customer):
25
+
26
+ session_state = cl.user_session.get("session_state", None)
27
+
28
+ await cl.Message(content=f"*Researching Latest News on {customer}*").send()
29
+
30
+ if session_state.do_customer_research:
31
+ print("Searching for news items ...")
32
+ workflow = StateGraph(ResearchState)
33
+
34
+ # Add nodes
35
+ workflow.add_node("research", research_model)
36
+ workflow.add_node("tools", tool_node)
37
+ workflow.add_node("curate", select_and_process)
38
+ workflow.add_node("write", write_report)
39
+ workflow.add_node("publish", generete_pdf)
40
+ # Set the entrypoint as route_query
41
+ workflow.set_entry_point("research")
42
+
43
+ # Determine which node is called next
44
+ workflow.add_conditional_edges(
45
+ "research",
46
+ # Next, we pass in the function that will determine which node is called next.
47
+ should_continue,
48
+ )
49
+
50
+ # Add a normal edge from `tools` to `research`.
51
+ # This means that after `tools` is called, `research` node is called next in order to determine if we should keep or move to the 'curate' step
52
+ workflow.add_edge("tools", "research")
53
+ workflow.add_edge("curate","write")
54
+ workflow.add_edge("write", "publish") # Option in the future, to add another step and filter the documents retrieved using rerhank before writing the report
55
+ workflow.add_edge("publish", END) # Option in the future, to add another step and filter the documents retrieved using rerhank before writing the report
56
+
57
+ app = workflow.compile()
58
+
59
+ company = "HSBC"
60
+ company_keywords = "banking, financial services, investment, wealth management, digital banking"
61
+ # (Optional) exclude_keywords: Use this field when you need to differentiate the company from others with the same name in a different industry
62
+ # or when you want to exclude specific types of documents or information. Leave it as an empty string ("") if not needed.
63
+ exclude_keywords = "insurance"
64
+ # You may uncomment your_additional_guidelines and HumanMessage and update the content with some guidelines of your own
65
+ # your_additional_guidelines=f"Note that the {company} is ... / focus on ...."
66
+ messages = [
67
+ SystemMessage(content="You are an expert researcher ready to begin the information gathering process.")
68
+ # ,HumanMessage(content=your_additional_guidelines)
69
+ ]
70
+ async for s in app.astream({"company": company, "company_keywords": company_keywords, "exclude_keywords": exclude_keywords, "messages":messages}, stream_mode="values"):
71
+ message = s["messages"][-1]
72
+ if isinstance(message, tuple):
73
+ print(message)
74
+ else:
75
+ message.pretty_print()
76
+ else:
77
+ await cl.Message(content="*Searching for news items ...*").send()
78
+ await asyncio.sleep(2)
79
+
80
+ await cl.Message(content="*Curating 8 documents ...*").send()
81
+ await asyncio.sleep(3)
82
+
83
+ await cl.Message(content="*Research complete. Generating report*").send()
84
+ await asyncio.sleep(1)
85
+
86
+ app_folder = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
87
+ markdown_file_path = os.path.abspath(os.path.join(app_folder, 'reports', session_state.customer_research_report_md))
88
+
89
+ await cl.Message(content=read_markdown_file(markdown_file_path)).send()
90
+
91
+ await offer_actions()
92
+
93
+
94
+ def read_markdown_file(file_path):
95
+ try:
96
+ print(file_path)
97
+ with open(file_path, 'r', encoding='utf-8') as file:
98
+ content = file.read()
99
+ return content
100
+ except FileNotFoundError:
101
+ return f"Error: The file {file_path} was not found."
102
+ except Exception as e:
103
+ return f"An error occurred while reading the file: {str(e)}"
104
+
105
+
106
+ # Define the research state
107
+ class ResearchState(TypedDict):
108
+ company: str
109
+ company_keywords: str
110
+ exclude_keywords: str
111
+ report: str
112
+ # Declare a dictionary where:
113
+ # - The outer dictionary has string keys.
114
+ # - The inner dictionary can have keys of different types (e.g., str, int).
115
+ # - The inner dictionary values can be of different types (e.g., str, float).
116
+ documents: Dict[str, Dict[Union[str, int], Union[str, float]]]
117
+ RAG_docs: Dict[str, Dict[Union[str, int], Union[str, float]]]
118
+ messages: Annotated[list[AnyMessage], add_messages]
119
+
120
+ # Define the structure for the model's response, which includes citations.
121
+ class Citation(BaseModel):
122
+ source_id: str = Field(
123
+ ...,
124
+ description="The url of a SPECIFIC source which justifies the answer.",
125
+ )
126
+ quote: str = Field(
127
+ ...,
128
+ description="The VERBATIM quote from the specified source that justifies the answer.",
129
+ )
130
+
131
+
132
+ class QuotedAnswer(BaseModel):
133
+ """Answer the user question based only on the given sources, and cite the sources used."""
134
+ answer: str = Field(
135
+ ...,
136
+ description="The answer to the user question, which is based only on the given sources. Include any relevant sources in the answer as markdown hyperlinks. For example: 'This is a sample text ([url website](url))'"
137
+ )
138
+ citations: List[Citation] = Field(
139
+ ..., description="Citations from the given sources that justify the answer."
140
+ )
141
+
142
+ # Add Tavily's arguments to enhance the web search tool's capabilities
143
+ class TavilyQuery(BaseModel):
144
+ query: str = Field(description="web search query")
145
+ topic: str = Field(description="type of search, should be 'general' or 'news'. Choose 'news' ONLY when the company you searching is publicly traded and is likely to be featured on popular news")
146
+ days: int = Field(description="number of days back to run 'news' search")
147
+ # raw_content: bool = Field(description="include raw content from found sources, use it ONLY if you need more information besides the summary content provided")
148
+ domains: Optional[List[str]] = Field(default=None, description="list of domains to include in the research. Useful when trying to gather information from trusted and relevant domains")
149
+
150
+
151
+ # Define the args_schema for the tavily_search tool using a multi-query approach, enabling more precise queries for Tavily.
152
+ class TavilySearchInput(BaseModel):
153
+ sub_queries: List[TavilyQuery] = Field(description="set of sub-queries that can be answered in isolation")
154
+
155
+
156
+ class TavilyExtractInput(BaseModel):
157
+ urls: List[str] = Field(description="list of a single or several URLs for extracting raw content to gather additional information")
158
+
159
+
160
+ @tool("tavily_search", args_schema=TavilySearchInput, return_direct=True)
161
+ async def tavily_search(sub_queries: List[TavilyQuery]):
162
+ """Perform searches for each sub-query using the Tavily search tool concurrently."""
163
+ # Define a coroutine function to perform a single search with error handling
164
+ async def perform_search(itm):
165
+ try:
166
+ # Add date to the query as we need the most recent results
167
+ query_with_date = f"{itm.query} {datetime.now().strftime('%m-%Y')}"
168
+ # Attempt to perform the search, hardcoding days to 90 (days will be used only when topic is news)
169
+ response = await tavily_client.search(query=query_with_date, topic=itm.topic, days=itm.days, max_results=1)
170
+ return response['results']
171
+ except Exception as e:
172
+ # Handle any exceptions, log them, and return an empty list
173
+ print(f"Error occurred during search for query '{itm.query}': {str(e)}")
174
+ return []
175
+
176
+ # Run all the search tasks in parallel
177
+ search_tasks = [perform_search(itm) for itm in sub_queries]
178
+ search_responses = await asyncio.gather(*search_tasks)
179
+
180
+ # Combine the results from all the responses
181
+ search_results = []
182
+ for response in search_responses:
183
+ search_results.extend(response)
184
+ await cl.Message(content=f"Searching for news items ...").send()
185
+ return search_results
186
+
187
+ # Code for adding Tavily Extract as a tool (found it more useful to use Tavily Extract in a separate node)
188
+ # @tool("tavily_extract", args_schema=TavilyExtractInput, return_direct=True)
189
+ # async def tavily_extract(urls: TavilyExtractInput):
190
+ # """Extract raw content from urls to gather additional information."""
191
+ # try:
192
+ # response = await tavily_client.extract(urls=urls)
193
+ # return response['results']
194
+ # except Exception as e:
195
+ # # Handle any exceptions, log them, and return an empty list
196
+ # print(f"Error occurred during extract: {str(e)}")
197
+ # return []
198
+
199
+
200
+ tools = [tavily_search]
201
+ tools_by_name = {tool.name: tool for tool in tools}
202
+ tavily_client = AsyncTavilyClient()
203
+
204
+
205
+ # Define an async custom research tool node to store Tavily's search results for improved processing and later on filtering
206
+ async def tool_node(state: ResearchState):
207
+ docs = state.get('documents',{})
208
+ docs_str = ""
209
+ msgs = []
210
+ for tool_call in state["messages"][-1].tool_calls:
211
+ tool = tools_by_name[tool_call["name"]]
212
+ new_docs = await tool.ainvoke(tool_call["args"])
213
+ for doc in new_docs:
214
+ # Make sure that this document was not retrieved before
215
+ if not docs or doc['url'] not in docs:
216
+ docs[doc['url']] = doc
217
+ docs_str += json.dumps(doc)
218
+ # For Tavily Extract tool, checking if raw_content was retrieved a document
219
+ # if doc.get('raw_content', None) and doc['url'] in docs:
220
+ # docs[doc['url']]['raw_content'] = doc['raw_content'] # add raw content retrieved by extract
221
+ # docs_str += json.dumps(doc)
222
+ msgs.append(ToolMessage(content=f"Found the following new documents/information: {docs_str}", tool_call_id=tool_call["id"]))
223
+ return {"messages": msgs, "documents": docs}
224
+
225
+ # Invoke a model with research tools to gather data about the company
226
+ def research_model(state: ResearchState):
227
+ prompt = f"""Today's date is {datetime.now().strftime('%d/%m/%Y')}.\n
228
+ You are an expert researcher tasked with gathering information for a quarterly report on recent developments in portfolio companies.\n
229
+ Your current objective is to gather documents about any significant events that occurred in the past quarter for the following company: {state['company']}.\n
230
+ The user has provided the following company keywords: {state['company_keywords']} to help you find documents relevant to the correct company.\n
231
+ **Instructions:**\n
232
+ - Use the 'tavily_search' tool to search for relevant documents
233
+ - Focus on gathering documents by making appropriate tool calls
234
+ - If you believe you have gathered enough information, state 'I have gathered enough information and am ready to proceed.'
235
+ """
236
+ messages = state['messages'] + [SystemMessage(content=prompt)]
237
+ model = ChatOpenAI(model="gpt-4o-mini",temperature=0)
238
+ response = model.bind_tools(tools).invoke(messages)
239
+ return {"messages": [response]}
240
+
241
+
242
+ # Define the function that decides whether to continue research using tools or proceed to writing the report
243
+ def should_continue(state: ResearchState) -> Literal["tools", "curate"]:
244
+ messages = state['messages']
245
+ last_message = messages[-1]
246
+ # If the LLM makes a tool call, then we route to the "tools" node
247
+ if last_message.tool_calls:
248
+ return "tools"
249
+ # Otherwise, we stop (reply to the user with citations)
250
+ return "curate"
251
+
252
+ async def select_and_process(state: ResearchState):
253
+ msg = "Curating Documents ...\n"
254
+ prompt = f"""You are an expert researcher specializing in analyzing portfolio companies.\n
255
+ Your current task is to review a list of documents and select the most relevant URLs related to recent developments for the following company: {state['company']}.\n
256
+ Be aware that some documents may refer to other companies with similar or identical names, potentially leading to conflicting information.\n
257
+ Your objective is to choose the documents that pertain to the correct company and provide the most consistent and synchronized information, using the following keywords provided by the user to help identify the correct company as a guide:{state['company_keywords']}.\n"""
258
+ # Optionally include exclusion keywords if provided by the user
259
+ if state['exclude_keywords'] != "":
260
+ prompt += f"""Additionally, if any form of the following exclusion words are present in the documents, do not include them and filter out those documents: {state['exclude_keywords']}.\n"""
261
+ # Append the list of gathered documents to the prompt
262
+ prompt += f"""\nHere is the list of documents gathered for your review:\n{state['documents']}\n\n"""
263
+
264
+ # Use the model to filter documents and obtain relevant URLs structured as TavilyExtractInput
265
+ messages = [SystemMessage(content=prompt)]
266
+ model = ChatOpenAI(model="gpt-4o-mini",temperature=0)
267
+ relevant_urls = model.with_structured_output(TavilyExtractInput).invoke(messages)
268
+
269
+ # Create a dictionary of relevant documents based on the URLs returned by the model
270
+ RAG_docs = {url: state['documents'][url] for url in relevant_urls.urls if url in state['documents']}
271
+
272
+ try:
273
+ # Extract raw content from the selected URLs using the Tavily client
274
+ response = await tavily_client.extract(urls=relevant_urls.urls)
275
+
276
+ # Save the raw content into the RAG_docs dictionary for each URL
277
+ msg += "Extracted raw content for:\n"
278
+ for itm in response['results']:
279
+ url = itm['url']
280
+ msg += f"{url}\n"
281
+ raw_content = itm['raw_content']
282
+ RAG_docs[url]['raw_content'] = raw_content
283
+ except Exception as e:
284
+ print(f"Error occurred during Tavily Extract request")
285
+
286
+ msg += f"ֿֿ\n\nState of RAG documents that will be used for the report:\n\n{RAG_docs}"
287
+
288
+ return {"messages": [AIMessage(content=msg)],"RAG_docs": RAG_docs}
289
+
290
+ # Define the function to write the report based on the retrieved documents.
291
+ async def write_report(state: ResearchState):
292
+ # Create the prompt
293
+ prompt = f"""Today's date is {datetime.now().strftime('%d/%m/%Y')}\n.
294
+ You are an expert researcher, writing a quarterly report about recent events in portfolio companies.\n
295
+ Your task is to write an in-depth, well-written, and detailed report on the following company: {state['company']}. in markdown syntax\n
296
+ Here are all the documents you should base your answer on:\n{state['RAG_docs']}\n"""
297
+ # messages = [state['messages'][-1]] + [SystemMessage(content=prompt)]
298
+ # Create a system message with the constructed prompt (no need to include entire chat history)
299
+ messages = [SystemMessage(content=prompt)]
300
+ model = ChatOpenAI(model="gpt-4o-mini",temperature=0)
301
+ response = model.with_structured_output(QuotedAnswer).invoke(messages)
302
+ full_report = response.answer
303
+ msg = "Curating Documents ...\n"
304
+ await cl.Message(content=f"*Curating {len(response.citations)} documents ...*").send()
305
+ # Add Citations Section to the report
306
+ full_report += "\n\n### Citations\n"
307
+ for citation in response.citations:
308
+ doc = state['RAG_docs'].get(citation.source_id)
309
+ full_report += f"- [{doc.get('title',citation.source_id)}]({citation.source_id}): \"{citation.quote}\"\n"
310
+ # We return a list, because this will get added to the existing list
311
+ return {"messages": [AIMessage(content=f"Generated Report:\n{full_report}")], "report": full_report}
312
+
313
+ async def generete_pdf(state: ResearchState):
314
+ await cl.Message(content=f"*Research complete. Generating report*").send()
315
+ directory = "reports"
316
+ file_name = f"{state['company']} Quarterly Report {datetime.now().strftime('%Y-%m-%d')}"
317
+ # Check if the directory exists
318
+ if not os.path.exists(directory):
319
+ # Create the directory
320
+ os.makedirs(directory)
321
+
322
+ markdown_file_path = f'{directory}/{file_name}.md'
323
+ pdf_file_path = f'{directory}/{file_name}.pdf'
324
+
325
+ session_state = cl.user_session.get("session_state", None)
326
+ session_state.customer_research_report_md = f"{file_name}.md"
327
+ session_state.customer_research_report_pdf = f"{file_name}.pdf"
328
+
329
+ for file_path in [markdown_file_path, pdf_file_path]:
330
+ if os.path.exists(file_path):
331
+ os.remove(file_path)
332
+ print(f"Existing file deleted: {file_path}")
333
+ with open(markdown_file_path, 'w', encoding='utf-8') as md_file:
334
+ md_file.write(state['report'])
335
+
336
+ await cl.Message(content=state['report']).send()
337
+
338
+ msg = generate_pdf_from_md(state['report'], filename=pdf_file_path)
339
+
340
+ return {"messages": [AIMessage(content=msg)]}
341
+
backend/app/utils/utils_data.py ADDED
@@ -0,0 +1,186 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import pandas as pd
2
+ import os
3
+ import sqlite3
4
+
5
+ def get_questions(stage=None, num_questions=0):
6
+ q_and_a_filename = "AIE4_SalesBuddy_QandA.csv"
7
+ data = read_csv_from_data_folder(q_and_a_filename)
8
+ if data is None:
9
+ print(f"Error: Failed to read {q_and_a_filename}")
10
+ return []
11
+ questions = []
12
+ for index, row in data.iterrows():
13
+ if stage is not None and row['Stage'] != stage:
14
+ continue
15
+ question = {
16
+ 'stage': row['Stage'],
17
+ 'question': row['Customer Question (Provided by Claude)'],
18
+ 'ground_truth': row['Ground Truth (Provided by Nitin). Marked as Salesperson 2 by Claude'],
19
+ }
20
+ if num_questions == 0 or num_questions > len(questions):
21
+ print(f"Adding question: {question['question']}")
22
+ questions.append(question)
23
+ print(f"Returned {len(questions)} questions for stage {stage}")
24
+ return questions
25
+
26
+ def get_customer_background(scenario, customer_name="HSBC" ):
27
+ background_filename = f"{customer_name}_background.txt"
28
+ data = read_txt_from_data_folder(background_filename)
29
+ scenario.customer.background = data
30
+ print(f"Read background for {customer_name} - {background_filename}")
31
+
32
+ def get_company_data(scenario):
33
+ company = {
34
+ "name": "BetterTech",
35
+ "description": """
36
+ Founded by industry experts, BetterTech understands the data analytics challenges faced by financial
37
+ institutions across lending desks, risk, and compliance.
38
+ BetterTech pioneered the use of high-performance analytics in finance, helping the banks and lenders
39
+ make better decisions, explain results with confidence, and simulate the impact of their decisions.
40
+ BetterTech’s mission is to deliver train-of-thought analysis on terabytes of data in the most
41
+ cost-effective way so clients can explain their results with confidence and model the scenarios
42
+ that will optimize their business. BetterTech specializes in risk data analytics for one of the
43
+ fastest moving and most regulated industries with a presence in the world’s leading
44
+ financial marketplaces - London, New York, Singapore, Sydney, Hong Kong, Paris and Frankfurt.
45
+ """,
46
+ "product": "BetterTech Lending Analytics Solution",
47
+ "product_summary": """
48
+ A comprehensive solution for real-time analysis in lending, surpassing basic regulatory compliance
49
+ by enabling reporting, explaining, and optimizing. Deployed as SaaS, on-premise, or in the cloud, it
50
+ empowers organizations to improve performance, enhance decision-making, and stay competitive by
51
+ simulating various scenarios efficiently and accurately.
52
+ """,
53
+ "product_description": """
54
+ Real-time analysis with BetterTech Lending Analytics
55
+ While most technologies on the market are able to fulfill regulatory risk management requirements,
56
+ they often fall short of meeting the team’s actual needs. What works when Lending Analytics calculations
57
+ are run weekly or monthly is simply not enough on a day-to-day basis. Maintaining regulations is no
58
+ longer enough
59
+
60
+ There are three functions that an efficient Lending Analytics solution must be able to fulfill:
61
+ report, explain and optimize.
62
+
63
+ Reporting is what every solution made for Lending Analytics can do: calculating risk figures and
64
+ generating reports at the right level of aggregation that are ready to be sent to internal and
65
+ external auditors. With the data volumes involved with Lending Analytics, however, reporting alone
66
+ is simply not enough. Explaining is the most critical need for business users. Regulators ask for
67
+ detailed explanations of what is included in the report, request that banks test alternative stress
68
+ scenarios, and demonstrate the accuracy of their models — particularly with the Internal Models Approach.
69
+ With a solution that only reports, business teams end up scrambling to answer those requests as best
70
+ as they can, falling back on other tools such as Excel or PowerBI, which are simply not designed to
71
+ analyze data at this scale. Optimizing is where growth and profitability reside.
72
+ Lending Analytics framework creates many decision points that are crucial to improving performance:
73
+ • How best to organize or reorganize loan portfolios?
74
+ • What would be the impact of changing positions or making certain loans?
75
+ • How can we improve our models?
76
+
77
+ BetterTech Lending Analytics handles this level of analysis deftly and can quickly answer these questions.
78
+ By relying on inadequate tools to perform analysis, organizations often see reduced productivity and
79
+ accuracy. Inaccurate reporting negatively impacts relationships with regulators, potentially leading
80
+ to fines, leading to fines. Furthermore, companies that do not have the analytical capabilities to
81
+ optimize their risk management and, by extension their capital charge, risk falling behind other,
82
+ better equipped organizations. How can you get ahead if you cannot efficiently simulate different
83
+ scenarios to choose the best outcome, while your competitors do it dozens of times a day?
84
+
85
+ A robust analytics solutions that is affordable and easy to implement
86
+
87
+ BetterTech Lending Analytics is in production today at many banks of all sizes around the world,
88
+ including HSBC, Erste Bank, CIBC and Mizuho. It has successfully passed the ISDA Lending Analytics
89
+ SA Regulatory Benchmarking Unit Test. It has even been selected by one of the most important global
90
+ regulators to serve as the benchmark against which to test other banks’ architectures.
91
+
92
+ Available as SaaS or on-premise, BetterTech Lending Analytics can run on any Cloud platform or
93
+ in-house hardware and be fully deployed within 4 to 6 weeks.
94
+
95
+ Runs anywhere BetterTech Lending Analytics can be deployed under several configurations that all
96
+ bring the same benefits. Reach out to our team of experts to find the setup that will work best for
97
+ your organization.
98
+
99
+ On-premise: BetterTech Lending Analytics can be deployed on a large variety of hardware that are
100
+ able to provide the requisite capabilities. We have partnerships in place with most global providers
101
+ to ensure compatibility. In the Cloud: We have extensively tested BetterTech Lending Analytics on
102
+ all the main cloud platforms (Azure, AWS, Google Cloud...). In fact, it has been deployed in production
103
+ on those platforms.
104
+
105
+ As SaaS: We can provide BetterTech Lending Analytics under a managed services contract. This
106
+ configuration offers the fastest time-to-production while giving you complete control over your
107
+ investment. The future of market risk analytics Organizations who want to outsmart the competition
108
+ """,
109
+ }
110
+ scenario.add_company_info(
111
+ name=company['name'],
112
+ description=company['description'],
113
+ product=company['product'],
114
+ product_summary=company['product_summary'],
115
+ product_description=company['product_description']
116
+ )
117
+
118
+ def get_q_and_a():
119
+ q_and_a_filename = "AIE4_SalesBuddy_QandA.csv"
120
+ data = read_csv_from_data_folder(q_and_a_filename)
121
+ return data
122
+
123
+ def get_opportunities():
124
+ opportunities_filename = "Opportunity_Information.csv"
125
+ data = read_csv_from_data_folder(opportunities_filename)
126
+ return data
127
+
128
+ def get_opportunities_from_db(username, filename=None):
129
+ data = retrieve_objections(username, filename)
130
+ return data
131
+
132
+ def read_csv_from_data_folder(filename, handle_nan='drop'):
133
+ app_folder = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
134
+ file_path = os.path.abspath(os.path.join(app_folder, 'data', filename))
135
+
136
+ try:
137
+ df = pd.read_csv(file_path)
138
+ print(f"Successfully read {filename}")
139
+ # Handle NaN values
140
+ if handle_nan == 'drop':
141
+ df = df.dropna()
142
+ elif handle_nan == 'fill_na':
143
+ df = df.fillna('N/A')
144
+ elif handle_nan == 'fill_empty':
145
+ df = df.fillna('')
146
+ else:
147
+ print(f"Warning: Unknown NaN handling method '{handle_nan}'. NaN values were not processed.")
148
+
149
+ # Reset index if rows were dropped
150
+ df = df.reset_index(drop=True)
151
+ return df
152
+ except FileNotFoundError:
153
+ print(f"Error: File '{filename}' not found in the data folder.")
154
+ return None
155
+ except pd.errors.EmptyDataError:
156
+ print(f"Error: File '{filename}' is empty.")
157
+ return None
158
+ except Exception as e:
159
+ print(f"An error occurred while reading '{filename}': {str(e)}")
160
+ return None
161
+
162
+ def read_txt_from_data_folder(filename):
163
+ app_folder = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
164
+ file_path = os.path.abspath(os.path.join(app_folder, 'data', filename))
165
+
166
+ try:
167
+ with open(file_path, 'r', encoding='utf-8') as file:
168
+ data = file.read()
169
+ print(f"Successfully read {filename}")
170
+ return data
171
+ except FileNotFoundError:
172
+ print(f"Error: File '{filename}' not found in the data folder.")
173
+ return None
174
+ except Exception as e:
175
+ print(f"An error occurred while reading '{filename}': {str(e)}")
176
+ return None
177
+
178
+ def retrieve_objections(username, filename=None):
179
+ conn = sqlite3.connect('users.db')
180
+ cur = conn.cursor()
181
+ if filename:
182
+ cur.execute("SELECT FIRST * FROM files WHERE username=? and filename=?", (username, filename))
183
+ else:
184
+ cur.execute("SELECT FIRST * FROM files WHERE username=?", (username,))
185
+ return cur.fetchall()
186
+
backend/app/utils/utils_evaluate.py ADDED
@@ -0,0 +1,100 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import pandas as pd
2
+ from datasets import Dataset
3
+ from nltk.translate.bleu_score import sentence_bleu
4
+
5
+ from ragas import evaluate
6
+ from ragas.metrics import (
7
+ answer_relevancy,
8
+ answer_correctness,
9
+ )
10
+ from rouge_score import rouge_scorer
11
+ from sentence_transformers import SentenceTransformer, util
12
+
13
+ from .utils_evaluate_objections import generate_objection_score
14
+
15
+
16
+ async def evaluate_objections(session):
17
+ print("evaluate_objections()")
18
+
19
+ for response in session.responses:
20
+ question = response.get("question", "")
21
+ answer = response.get("response", "")
22
+ print(f"Question: {question}")
23
+ print(f"Answer: {answer}")
24
+
25
+ q_and_a = {
26
+ "objection": question,
27
+ "answer": answer
28
+ }
29
+ print(q_and_a)
30
+ score = await generate_objection_score(q_and_a)
31
+ print(score)
32
+ response["evaluation_score"] = score
33
+
34
+
35
+ def evaluate_answers(session):
36
+ ragas_results = evaluate_with_ragas(session)
37
+ session.ragas_results = ragas_results
38
+ scores = []
39
+ for response in session.responses:
40
+ bleu_score = calculate_bleu_score(response.get("response", ""), response.get("ground_truth", ""))
41
+ rouge_score = calculate_rouge_score(response.get("response", ""), response.get("ground_truth", ""))
42
+ semantic_similarity_score = calculate_semantic_similarity(response.get("response", ""), response.get("ground_truth", ""))
43
+ all_scores = {
44
+ "bleu_score": bleu_score,
45
+ "rouge_score": rouge_score,
46
+ "semantic_similarity_score": semantic_similarity_score
47
+ }
48
+ scores.append(all_scores)
49
+ session.scores = scores
50
+ return scores
51
+
52
+ def evaluate_with_ragas(session):
53
+ questions = []
54
+ answers = []
55
+ ground_truths = []
56
+ contexts = []
57
+ for i, response in enumerate(session.responses, 1):
58
+ questions.append(response.get("question", ""))
59
+ answers.append(response.get("response", ""))
60
+ ground_truths.append(response.get("ground_truth", ""))
61
+ contexts.append([session.company.product_description])
62
+
63
+ evaluation_dataset = Dataset.from_dict({
64
+ "question" : questions,
65
+ "answer" : answers,
66
+ "contexts" : contexts,
67
+ "ground_truth" : ground_truths
68
+ })
69
+
70
+ print(evaluation_dataset)
71
+
72
+ metrics = [
73
+ # faithfulness,
74
+ answer_relevancy,
75
+ # context_recall,
76
+ # context_precision,
77
+ answer_correctness,
78
+ ]
79
+ results = evaluate(evaluation_dataset, metrics)
80
+ print(results)
81
+ return results
82
+
83
+ def calculate_bleu_score(answer, ground_truth):
84
+ bleu_score = sentence_bleu([ground_truth.split()], answer.split())
85
+ print(f"BLEU score: {bleu_score}")
86
+ return bleu_score
87
+
88
+ def calculate_rouge_score(answer, ground_truth):
89
+ scorer = rouge_scorer.RougeScorer(['rouge1', 'rougeL'], use_stemmer=True)
90
+ rouge_scores = scorer.score(ground_truth, answer)
91
+ print(f"ROUGE score: {rouge_scores}")
92
+ return rouge_scores
93
+
94
+ def calculate_semantic_similarity(answer, ground_truth):
95
+ model = SentenceTransformer('all-MiniLM-L6-v2')
96
+ answer_embedding = model.encode(answer)
97
+ ground_truth_embedding = model.encode(ground_truth)
98
+ similarity_score = util.cos_sim(answer_embedding, ground_truth_embedding)
99
+ print(f"Semantic Similarity: {similarity_score.item()}")
100
+ return similarity_score.item()
backend/app/utils/utils_evaluate_objections.py ADDED
@@ -0,0 +1,152 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import asyncio
2
+ import dotenv
3
+ import os
4
+ import pandas as pd
5
+ import sys
6
+ import typing as t
7
+
8
+ from dataclasses import dataclass, field
9
+ from datetime import datetime
10
+ from langchain_openai import ChatOpenAI
11
+ from pydantic import BaseModel, Field
12
+ from ragas import SingleTurnSample
13
+ from ragas.llms.base import LangchainLLMWrapper
14
+ from ragas.metrics.base import MetricType
15
+ from ragas.metrics.base import MetricWithLLM, SingleTurnMetric
16
+ from ragas.prompt.pydantic_prompt import PydanticPrompt
17
+ from typing import List, Tuple
18
+
19
+
20
+ # Load environment variables from .env file
21
+ dotenv.load_dotenv()
22
+
23
+ # Access the OpenAI API key
24
+ OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
25
+
26
+ class ObjectionInput(BaseModel):
27
+ user_input: str = Field(description="The objection text")
28
+ response: str = Field(default="", description="The response to the objection")
29
+ reference: str = Field(default="", description="Any reference related to the objection")
30
+
31
+
32
+ class ObjectionOutput(BaseModel):
33
+ satisfy: bool = Field(description="Boolean indicating if the objection was satisfied")
34
+
35
+ def process_salesbud_file(file_path: str) -> List[Tuple[ObjectionInput, ObjectionOutput]]:
36
+ """
37
+ Process the salesbud CSV file and return a list of examples for ObjectionlPrompt.
38
+
39
+ Args:
40
+ file_path (str): The path to the salesbud CSV file.
41
+
42
+ Returns:
43
+ List[Tuple[ObjectionInput, ObjectionOutput]]: A list of tuples containing ObjectionInput and ObjectionOutput.
44
+ """
45
+ # Print the timestamp and the file being processed
46
+ print(f"{datetime.now()}: Processing file: salesbud_examples.csv")
47
+
48
+ # Read the CSV file into a DataFrame
49
+ _file_path = os.path.join(os.path.dirname(__file__), '../data/salesbud_examples.csv')
50
+ df = pd.read_csv(_file_path)
51
+
52
+ # List to hold the processed objections
53
+ examples = [] # List to hold examples
54
+
55
+ # Process each row in the DataFrame
56
+ for index, row in df.iterrows():
57
+ # Create an ObjectionInput instance for each row
58
+ objection_input = ObjectionInput(
59
+ user_input=row['objection'], # Assuming your CSV has a column named 'objection'
60
+ response=row.get('response', ""), # Use .get() to avoid KeyError if the column doesn't exist
61
+ reference=row.get('reference', "") # Use .get() to avoid KeyError if the column doesn't exist
62
+ )
63
+
64
+ # Create an ObjectionOutput instance (you can modify the logic for 'satisfy' as needed)
65
+ objection_output = ObjectionOutput(
66
+ satisfy= row['satisfy']
67
+ )
68
+ # Append the example tuple to the examples list
69
+ examples.append((objection_input, objection_output))
70
+ #print (examples[0])
71
+ return examples
72
+
73
+ class ObjectionlPrompt(PydanticPrompt[ObjectionInput, ObjectionOutput]):
74
+ instruction = "You are an expert technology sales rep that is tasked with judging if response satisfies potential customer's objection (user input). \
75
+ Given an user input and sales rep response, output True if the response satisfies the objection by the potential customer"
76
+
77
+ input_model = ObjectionInput
78
+ output_model = ObjectionOutput
79
+ examples = process_salesbud_file('salesbud_examples.csv')
80
+
81
+ @dataclass
82
+ class SatisfyRate(MetricWithLLM, SingleTurnMetric):
83
+ name: str = "satisfy_rate"
84
+ _required_columns: t.Dict[MetricType, t.Set[str]] = field(
85
+ default_factory=lambda: {MetricType.SINGLE_TURN: {"response", "reference"}}
86
+ )
87
+ objection_prompt: PydanticPrompt = ObjectionlPrompt()
88
+
89
+ async def _ascore(self, row):
90
+ pass
91
+
92
+ async def _single_turn_ascore(self, sample, callbacks):
93
+ prompt_input = ObjectionInput(
94
+ user_input=sample.user_input, response=sample.response
95
+ )
96
+ prompt_response = await self.objection_prompt.generate(
97
+ data=prompt_input, llm=self.llm
98
+ )
99
+ print("prompt_response")
100
+ print(prompt_response)
101
+ return int(prompt_response.satisfy)
102
+
103
+ async def generate_objection_score(question_answer):
104
+ print("generate_objection_scores()")
105
+ # user_response= pd.read_csv(file_path)
106
+ openai_model = LangchainLLMWrapper(ChatOpenAI(model_name="gpt-4o", api_key=OPENAI_API_KEY))
107
+ scorer = SatisfyRate(llm=openai_model)
108
+
109
+ sample = SingleTurnSample(user_input=question_answer['objection'], response=question_answer['answer'])
110
+
111
+ #(user_response['objection'][num], user_response['response'][num])
112
+ satisfy_0_1 = await scorer.single_turn_ascore(sample)
113
+ print(satisfy_0_1)
114
+
115
+ print (question_answer['objection'], question_answer['answer'], satisfy_0_1)
116
+ # Implement your logic to generate a response based on the user's input
117
+ return satisfy_0_1 #f"Response to your objection: {user_response['objection'][num]}, {user_response['response'][num]}, {satisfy_0_1}"
118
+
119
+
120
+ async def generate_response_to_objection(file_path, num):
121
+ from langchain_openai import ChatOpenAI
122
+ from ragas.llms.base import LangchainLLMWrapper
123
+ import pandas as pd
124
+ user_response= pd.read_csv(file_path)
125
+ openai_model = LangchainLLMWrapper(ChatOpenAI(model_name="gpt-4o", api_key=OPENAI_API_KEY))
126
+ scorer = SatisfyRate(llm=openai_model)
127
+
128
+ sample = SingleTurnSample(user_input=user_response['objection'][num], response=user_response['response'][num])
129
+
130
+ #(user_response['objection'][num], user_response['response'][num])
131
+ satisfy_0_1 = await scorer.single_turn_ascore(sample)
132
+
133
+ print (user_response['objection'][num], user_response['response'][num], satisfy_0_1)
134
+ # Implement your logic to generate a response based on the user's input
135
+ return satisfy_0_1 #f"Response to your objection: {user_response['objection'][num]}, {user_response['response'][num]}, {satisfy_0_1}"
136
+
137
+ async def main(file_path):
138
+ # Call the async function
139
+ #examples_file = process_salesbud_file()
140
+ response = await generate_response_to_objection(file_path, 0)
141
+
142
+ if __name__ == "__main__":
143
+ # Check if the file path is provided as a command-line argument
144
+ if len(sys.argv) != 2:
145
+ print("Usage: python objection_eval.py <path_to_salesbud.csv>")
146
+ sys.exit(1)
147
+
148
+ # Get the file path from the command-line argument
149
+ file_path = sys.argv[1]
150
+
151
+ # Run the main async function
152
+ asyncio.run(main(file_path))
backend/app/utils/utils_objections.py ADDED
@@ -0,0 +1,201 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import chainlit as cl
2
+ import tempfile
3
+ import uuid
4
+ from chainlit.types import AskFileResponse
5
+ from langchain_community.document_loaders import PyMuPDFLoader
6
+ from langchain_core.prompts import ChatPromptTemplate
7
+ from langchain_core.runnables.passthrough import RunnablePassthrough
8
+ from langchain_openai import ChatOpenAI
9
+ from langchain_openai.embeddings import OpenAIEmbeddings
10
+ from langchain_qdrant import QdrantVectorStore
11
+ from langchain_text_splitters import RecursiveCharacterTextSplitter
12
+ from langchain.embeddings import CacheBackedEmbeddings
13
+ from langchain.storage import LocalFileStore
14
+ from operator import itemgetter
15
+ from qdrant_client import QdrantClient
16
+ from qdrant_client.http.models import Distance, VectorParams
17
+
18
+
19
+
20
+ async def create_objections(session_state):
21
+ if session_state.use_objection_cache:
22
+
23
+ objections = [
24
+ "1. Can you provide customer references in the banking and financial services industry?",
25
+ "2. What training options are available for our team, given the number of employees and their global distribution?",
26
+ ]
27
+ # "3. Last but not least, your pricing seems high compared to some other solutions we've seen. Can you provide any flexibility with HSBC's pricing?",
28
+
29
+ else:
30
+ customer_document_file = session_state.customer_research_report_pdf
31
+ customer_file_path = "./reports/" + customer_document_file
32
+ bettertech_document_file = session_state.bettetech_value_proposition_pdf
33
+ bettertech_file_path = "data/" + bettertech_document_file
34
+ objections = await process_files(customer_file_path, bettertech_file_path)
35
+ return objections
36
+
37
+
38
+
39
+ def process_value_prop_pdf(file_path) -> str:
40
+ """
41
+ Process the value proposition PDF file and return its content as a string.
42
+
43
+ Args:
44
+ file (AskFileResponse): The uploaded PDF file.
45
+
46
+ Returns:
47
+ str: The extracted content from the PDF.
48
+ """
49
+ # Create a temporary file to store the uploaded content
50
+ # with tempfile.NamedTemporaryFile(mode="wb", delete=False) as temp_file:
51
+ # temp_file.write(file.content)
52
+ # temp_file_path = temp_file.name
53
+
54
+ # Load the PDF using PyMuPDFLoader
55
+ loader = PyMuPDFLoader(file_path)
56
+ documents = loader.load()
57
+
58
+ # Combine the content of all pages into a single string
59
+ value_prop_text = "\n".join(doc.page_content for doc in documents)
60
+
61
+ # Return the text extracted from the PDF
62
+ return value_prop_text
63
+
64
+ def process_text_file(file_path: str):
65
+ # import tempfile
66
+ text_splitter = RecursiveCharacterTextSplitter(separators=["\n\n","\n"],chunk_size=200, chunk_overlap=20)
67
+ # with tempfile.NamedTemporaryFile(mode="w", delete=False) as temp_file:
68
+ # with open(temp_file.name, "wb") as f:
69
+ # f.write(file.content)
70
+
71
+ loader = PyMuPDFLoader(file_path)
72
+ documents = loader.load()
73
+ docs = text_splitter.split_documents(documents)
74
+ for i, doc in enumerate(docs):
75
+ doc.metadata["source"] = f"source_{i}"
76
+ return docs
77
+
78
+ # Function to generate a response to the user's objection
79
+ def generate_response_to_objection(user_response, num):
80
+ from langchain_openai import ChatOpenAI
81
+ from ragas.llms.base import LangchainLLMWrapper
82
+ openai_model = LangchainLLMWrapper(ChatOpenAI(model_name="gpt-4o"))
83
+ scorer = SatisfyRate(llm=openai_model)
84
+
85
+ satify_0_1 = scorer.single_turn_ascore(user_response['objection'][num], user_response['response'][num])
86
+ # Implement your logic to generate a response based on the user's input
87
+ return f"Response to your objection: {user_response['objection'][num],user_response['response'][num], satify_0_1}"
88
+
89
+
90
+ async def process_files(customer_document, bettertech_document):
91
+ objections = []
92
+ core_embeddings = OpenAIEmbeddings(model="text-embedding-3-small")
93
+ collection_name = f"pdf_to_parse_{uuid.uuid4()}"
94
+ qdrant_client = QdrantClient(":memory:")
95
+ qdrant_client.create_collection(
96
+ collection_name=collection_name,
97
+ vectors_config=VectorParams(size=1536, distance=Distance.COSINE),
98
+ )
99
+
100
+ # msg = cl.Message(
101
+ # content=f"Processing Customer Business Domain...", disable_human_feedback=True
102
+ # )
103
+ # await msg.send()
104
+ # Process the customer
105
+ texts = process_text_file(customer_document)
106
+ print(f"Processing {len(texts)} text chunks from Customer Research Report")
107
+
108
+
109
+ # Notify the user that the second file is being processed
110
+ # msg = cl.Message(
111
+ # content=f"Processing BetterTech Value Proposition...", disable_human_feedback=True
112
+ # )
113
+ # await msg.send()
114
+
115
+ # Process the second file
116
+ value_prop_content = process_value_prop_pdf(bettertech_document)
117
+ print(f"Processing {len(value_prop_content)} text chunks from BetterTech Value Proposition")
118
+
119
+
120
+ # Create a Local File Store for caching
121
+ store = LocalFileStore("./cache/")
122
+ cached_embedder = CacheBackedEmbeddings.from_bytes_store(
123
+ core_embeddings, store, namespace=core_embeddings.model
124
+ )
125
+
126
+ # QDrant Vector Store Setup
127
+ vectorstore = QdrantVectorStore(
128
+ client=qdrant_client,
129
+ collection_name=collection_name,
130
+ embedding=cached_embedder
131
+ )
132
+ vectorstore.add_documents(texts)
133
+ retriever = vectorstore.as_retriever(search_type="mmr", search_kwargs={"k": 5})
134
+
135
+ chat_openai = ChatOpenAI() #model='gpt-4o')
136
+
137
+ # RAG Chain for generating objections
138
+ objection_prompt_template = """\
139
+ Internally, review the value proposition information of sales rep's company then review your Context.
140
+ Internally, find areas where the sales' product/service could help add value and where it fails to fit.
141
+ Internally, review this final list and think step-by-step on what likely objections to buying product/service.
142
+ Using these thoughts, generate 5 Context-based sales objections.
143
+ The output is numbered objections only.
144
+ For example:
145
+ '1. Our current pricing structure is already optimized and we do not see the immediate need for AI assistance in pricing complex structural options in Foreign Exchange.'
146
+ '2. We have a dedicated team handling customer experience and efficiency, and we do not see how integrating AI for pricing options would significantly improve these aspects.',
147
+ '3. While we acknowledge the importance of technology and innovation in banking, we are currently focusing on other areas for digital transformation and do not prioritize the use of AI in pricing at this time.'
148
+ '4. Our customer base might not be ready for a shift towards AI-driven pricing models, and introducing such a change could potentially create confusion and resistance among our clients.',
149
+ '5. We are cautious about the potential risks and uncertainties associated with relying heavily on AI for pricing, especially in the volatile Foreign Exchange market where human expertise and judgment are highly valued.'
150
+ The output is NOT intro phrases or ** text **:
151
+ Context: {context}
152
+ Value Proposition: {{value_prop_content}}
153
+ Sales Opportunity: {{sales_opportunity}}
154
+ """
155
+
156
+ # Create a chain for generating objections with the retrieved context
157
+ objection_chain = (
158
+ {"context": itemgetter("question") | retriever}
159
+ | RunnablePassthrough.assign(context=itemgetter("context"))
160
+ | ChatPromptTemplate.from_messages([
161
+ ("system", "You a potential customer interested in the offering from this sales rep. Please use context business name and your name found in sales_opportunity."),
162
+ ("human", objection_prompt_template)
163
+ ])
164
+ | chat_openai
165
+ )
166
+
167
+ # Ask the user for the sales opportunity
168
+ # sales_opportunity = await cl.AskUserMessage(
169
+ # content="Please describe the sales opportunity you want to discuss.", timeout=300
170
+ # ).send()
171
+ sales_opportunity = "Developing analytic capabilities for the loan origination system"
172
+ #print(sales_opportunity['content'])
173
+ # Retrieve the documents based on the query (here we're simulating with the sales opportunity)
174
+ retrieved_docs = retriever.get_relevant_documents(value_prop_content)
175
+
176
+ # Extract the content of the retrieved documents (chunks)
177
+ context_chunks = [doc.page_content for doc in retrieved_docs]
178
+
179
+ # Combine the retrieved context chunks into a single string
180
+ context = "\n\n".join(context_chunks)
181
+
182
+ # Log and display the retrieved chunks to Chainlit
183
+ # await cl.Message(content=f"Retrieved context chunks:\n{context}", author="retriever").send()
184
+
185
+ #print (sales_opportunity["content"])
186
+ # Generate objections using the chain, with the context included
187
+ #print ({"question": "Generate sales objections from {{value_prop_content}}", "sales_opportunity": sales_opportunity["content"], "context": context})
188
+ objection_response = objection_chain.invoke({"question": "Generate 3 sales objections", "sales_opportunity": sales_opportunity, "context": context})
189
+
190
+ objections.extend(objection_response.content.split('\n')) # Assuming each objection is on a new line
191
+ # Remove empty strings or strings with only spaces
192
+ cleaned_objections = [objection for objection in objections if objection.strip()]
193
+
194
+ # Output the cleaned list
195
+ # print(cleaned_objections)
196
+
197
+ # Store the objection chain in user session
198
+ cl.user_session.set("objection_chain", objection_chain)
199
+ cl.user_session.set("objections", objections)
200
+ return cleaned_objections
201
+ #await cl.Message(content="We are ready to enter Sales simulation. Ok? ").send()