palexis3 commited on
Commit
417abff
1 Parent(s): 107b48d

Completed transactions answering query

Browse files
app/api/routers/transaction.py CHANGED
@@ -6,6 +6,10 @@ from app.model.transaction import Transaction as TransactionModel
6
  from app.schema.index import TransactionResponse
7
  from app.engine.postgresdb import get_db_session
8
 
 
 
 
 
9
  transaction_router = r = APIRouter(prefix="/api/v1/transactions", tags=["transactions"])
10
 
11
 
@@ -59,11 +63,14 @@ async def answer_transactions_query(user_id: int, query: str, db: AsyncSession =
59
  """
60
  Retrieve all transactions.
61
  """
62
- result = await TransactionModel.get_by_user(db, user_id)
63
- all_rows = result.all()
64
- print(f"answer_transactions_query: \n type: {type(all_rows)}\nall_rows: {all_rows}")
65
- # TODO: Pass all rows to answer_query method in transaction_query_rag and get result that will be the
66
- # string param in TransactionRagResponse
67
- if len(all_rows) == 0:
68
- raise HTTPException(status_code=500, detail="No transactions found for this user")
69
- return all_rows
 
 
 
 
6
  from app.schema.index import TransactionResponse
7
  from app.engine.postgresdb import get_db_session
8
 
9
+ from app.service.query_rag import answer_query, fetch_transaction_documents
10
+
11
+ import pandas as pd
12
+
13
  transaction_router = r = APIRouter(prefix="/api/v1/transactions", tags=["transactions"])
14
 
15
 
 
63
  """
64
  Retrieve all transactions.
65
  """
66
+ try:
67
+ result = await TransactionModel.get_by_user(db, user_id)
68
+ all_rows = result.all()
69
+ if len(all_rows) == 0:
70
+ raise HTTPException(status_code=500, detail="No transactions found for this user")
71
+ document_splits = await fetch_transaction_documents(all_rows)
72
+ answer = await answer_query(document_splits, query, user_id)
73
+ return answer
74
+
75
+ except Exception as e:
76
+ raise HTTPException(status_code=500, detail=f"answer_transactions_query error: {str(e)}")
app/api/routers/user.py CHANGED
@@ -28,14 +28,17 @@ logger = logging.getLogger(__name__)
28
  async def create_user(user: UserCreate, db: AsyncSession = Depends(get_db_session)):
29
  try:
30
  db_user = await UserModel.get(db, email=user.email)
 
31
  if db_user and not db_user.is_deleted:
32
  raise HTTPException(status_code=409, detail="User already exists")
33
 
34
  await UserModel.create(db, **user.model_dump())
35
  user = await UserModel.get(db, email=user.email)
 
36
 
37
  fake_transactions = get_fake_transactions(user.id)
38
  await TransactionModel.bulk_create(db, fake_transactions)
 
39
 
40
  return user
41
 
 
28
  async def create_user(user: UserCreate, db: AsyncSession = Depends(get_db_session)):
29
  try:
30
  db_user = await UserModel.get(db, email=user.email)
31
+ print(f"db_user: {db_user}")
32
  if db_user and not db_user.is_deleted:
33
  raise HTTPException(status_code=409, detail="User already exists")
34
 
35
  await UserModel.create(db, **user.model_dump())
36
  user = await UserModel.get(db, email=user.email)
37
+ print(f"user: {user}")
38
 
39
  fake_transactions = get_fake_transactions(user.id)
40
  await TransactionModel.bulk_create(db, fake_transactions)
41
+ print(f"fake_transactions: {fake_transactions}")
42
 
43
  return user
44
 
app/model/transaction.py CHANGED
@@ -23,6 +23,15 @@ class Transaction(Base, BaseModel):
23
 
24
  def __str__(self) -> str:
25
  return f"{self.transaction_date}, {self.category}, {self.name_description}, {self.amount}, {self.type}"
 
 
 
 
 
 
 
 
 
26
 
27
  @classmethod
28
  async def create(cls: "type[Transaction]", db: AsyncSession, **kwargs) -> "Transaction":
 
23
 
24
  def __str__(self) -> str:
25
  return f"{self.transaction_date}, {self.category}, {self.name_description}, {self.amount}, {self.type}"
26
+
27
+ def to_dict(self):
28
+ return {
29
+ 'transaction_date': self.transaction_date,
30
+ 'category': self.category,
31
+ 'name_description': self.name_description,
32
+ 'amount': self.amount,
33
+ 'type': self.type
34
+ }
35
 
36
  @classmethod
37
  async def create(cls: "type[Transaction]", db: AsyncSession, **kwargs) -> "Transaction":
app/service/query_rag.py ADDED
@@ -0,0 +1,142 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from pinecone import Pinecone, ServerlessSpec
2
+ from langchain.text_splitter import RecursiveCharacterTextSplitter, CharacterTextSplitter
3
+ from langchain_openai import OpenAIEmbeddings, ChatOpenAI
4
+ from langchain_pinecone import PineconeVectorStore
5
+ from langchain.vectorstores import Chroma
6
+ from langchain.chains import RetrievalQA
7
+ from langchain.prompts import PromptTemplate
8
+ from langchain_core.documents import Document
9
+
10
+ from fastapi import HTTPException
11
+
12
+ from typing import List
13
+ from app.model.transaction import Transaction
14
+
15
+ import os
16
+
17
+ async def fetch_transaction_documents(transactions: List[Transaction]) -> List[Document]:
18
+ try:
19
+ document = ''.join(str(row)+'\n' for row in transactions)
20
+
21
+ page_splitter = CharacterTextSplitter(chunk_size=100, chunk_overlap=0)
22
+ pages = page_splitter.split_text(document)
23
+
24
+ text_splitter = RecursiveCharacterTextSplitter(chunk_size=100, chunk_overlap=10)
25
+ document_splits = text_splitter.create_documents(pages)
26
+
27
+ return document_splits
28
+ except Exception as e:
29
+ raise HTTPException(status_code = 500, detail=f"fetch_transaction_documents error: {str(e)}")
30
+
31
+
32
+ async def answer_query(document_splits: List[Document], query: str, user_id: int) -> str:
33
+ """Creates an embedding of the transactions table and then returns the answer for the given query.
34
+ Args:
35
+ df (pd.DataFrame): DataFrame containing the transactions that a user has entered
36
+ query (str): The query the user will ask against said embedding
37
+
38
+ Returns:
39
+ str: Response to query
40
+ """
41
+ try:
42
+ openai_api_key = os.environ['OPENAI_API_KEY']
43
+
44
+ embeddings = OpenAIEmbeddings(
45
+ model="text-embedding-3-small",
46
+ openai_api_key=openai_api_key
47
+ )
48
+
49
+ print(f"answer_transactions_query: \n document_splits: {type(document_splits)}\n")
50
+
51
+ llm = ChatOpenAI(
52
+ openai_api_key=openai_api_key,
53
+ model_name="gpt-3.5-turbo",
54
+ temperature=0.0
55
+ )
56
+
57
+ prompt_template = """
58
+ Use the following pieces of context to answer the question at the end.
59
+ If you don't know the answer, please think rationally answer from your own knowledge base
60
+
61
+ {context}
62
+
63
+ Question: {question}
64
+ """
65
+ prompt = PromptTemplate(
66
+ template=prompt_template, input_variables=["context", "question"]
67
+ )
68
+
69
+ chain_type_kwargs = {"prompt": prompt}
70
+
71
+ vectorestore = Chroma.from_documents(documents=document_splits,embedding=embeddings)
72
+
73
+ qa = RetrievalQA.from_chain_type(
74
+ llm=llm,
75
+ retriever=vectorestore.as_retriever(),
76
+ chain_type_kwargs=chain_type_kwargs
77
+ )
78
+
79
+ print(f"answer_transactions_query: \n qa: {qa}\n")
80
+
81
+ answer = qa({"query": query})
82
+
83
+ print(f"answer_transactions_query: \n answer: {answer['result']}\n")
84
+
85
+ result_split = answer['result'].split("\n")
86
+ result = ''.join(item for item in result_split)
87
+
88
+ return result
89
+
90
+ except Exception as e:
91
+ raise HTTPException(status_code = 500, detail=f"answer_query error: {str(e)}")
92
+
93
+
94
+ # Note: Attempted to use Pinecone however it failed to learn from documents so settled for Chroma
95
+
96
+ # batch_limit = 20
97
+
98
+ # pinecone_api_key = os.environ['PINECONE_API_KEY']
99
+
100
+ # namespace = "transactionsvector"
101
+ # index_name = "transactionsrag"
102
+
103
+ # pc = Pinecone(api_key=pinecone_api_key)
104
+ # if index_name in pc.list_indexes().names():
105
+ # pc.delete_index(index_name)
106
+
107
+ # pc.create_index(
108
+ # name=index_name,
109
+ # dimension=1536,
110
+ # metric="cosine",
111
+ # spec=ServerlessSpec(
112
+ # cloud="aws", region="us-east-1"
113
+ # )
114
+ # )
115
+
116
+ # index = pc.Index(index_name)
117
+ # transactions_search = PineconeVectorStore.from_documents(
118
+ # documents=document_splits,
119
+ # index_name=index_name,
120
+ # embedding=embeddings,
121
+ # namespace=namespace
122
+ # )
123
+
124
+ # print(f"answer_transactions_query: \n transactions_search: {transactions_search}\n")
125
+
126
+ # for ids in index.list(namespace=namespace):
127
+ # query_item = index.query(
128
+ # id=ids[0],
129
+ # namespace=namespace,
130
+ # top_k=1,
131
+ # include_values=True,
132
+ # include_metadata=True
133
+ # )
134
+ # print(f"answer_transactions_query: \n query_item: {query_item}\n")
135
+
136
+ # qa = RetrievalQA.from_chain_type(
137
+ # llm=llm,
138
+ # chain_type="stuff",
139
+ # retriever=transactions_search.as_retriever(),
140
+ # chain_type_kwargs=chain_type_kwargs
141
+ # )
142
+
app/service/transactions_query_rag.py DELETED
@@ -1,116 +0,0 @@
1
- from pinecone import Pinecone, ServerlessSpec
2
- from langchain.text_splitter import RecursiveCharacterTextSplitter
3
- from langchain_openai import OpenAIEmbeddings
4
- from langchain_pinecone import PineconeVectorStore
5
- from langchain_openai import ChatOpenAI
6
- from langchain.chains import RetrievalQA
7
-
8
- from fastapi import HTTPException
9
-
10
-
11
- import os
12
- import pandas as pd
13
- from uuid import uuid4
14
-
15
- async def answer_query(df: pd.DataFrame, query: str) -> str:
16
- """Creates an embedding of the transactions table and then returns the answer for the given query.
17
- Args:
18
- df (pd.DataFrame): DataFrame containing the transactions that a user has entered
19
- query (str): The query the user will ask against said embedding
20
-
21
- Returns:
22
- str: Response to query
23
- """
24
- try:
25
- batch_limit = 100
26
- pinecone_api_key = os.environ['PINECONE_API_KEY']
27
- openai_api_key = os.environ['OPENAI_API_KEY']
28
- namespace = "transactionsvector"
29
-
30
- pc = Pinecone(api_key=pinecone_api_key)
31
-
32
- embeddings = OpenAIEmbeddings(
33
- model="text-embedding-3-small",
34
- openai_api_key=openai_api_key
35
- )
36
-
37
- index_name = "transactions_rag"
38
-
39
- if index_name in pc.list_indexes().names():
40
- pc.delete_index(index_name)
41
-
42
- pc.create_index(
43
- name=index_name,
44
- dimension=1536,
45
- metric="cosine",
46
- spec=ServerlessSpec(
47
- cloud="aws",
48
- region="us-east-1"
49
- )
50
- )
51
-
52
- index = pc.Index(index_name)
53
-
54
- texts = []
55
- all_texts = []
56
- metadatas = []
57
-
58
- text_splitter = RecursiveCharacterTextSplitter(
59
- chunk_size=1000,
60
- chunk_overlap=100
61
- )
62
-
63
- for _, record in df.iterrows():
64
- content_texts = text_splitter.split_text(record['content'])
65
-
66
- metadata = {
67
- 'user_id': str(record['user_id'])
68
- }
69
- content_metadata = [{
70
- "chunk": j, "text": text, **metadata
71
- } for j, text in enumerate(content_texts)]
72
-
73
- texts.extend(content_texts)
74
- all_texts.extend(content_texts)
75
- metadatas.extend(content_metadata)
76
-
77
- # If we have reached the batch limit, then add the texts and reset
78
- if len(texts) >= batch_limit:
79
- ids = [str(uuid4()) for _ in range(len(texts))]
80
- embeds = embeddings.embed_documents(texts)
81
- index.upsert(vectors=zip(ids, embeds, metadatas))
82
- texts = []
83
- metadatas = []
84
-
85
- if len(texts) > 0:
86
- ids = [str(uuid4()) for _ in range(len(texts))]
87
- embeds = embeddings.embed_documents(texts)
88
- index.upsert(vectors=zip(ids, embeds, metadatas))
89
-
90
-
91
-
92
- transactions_search = PineconeVectorStore.from_documents(
93
- documents=all_texts,
94
- index_name=index_name,
95
- embedding=embeddings,
96
- namespace=namespace
97
- )
98
-
99
- llm = ChatOpenAI(
100
- openai_api_key=openai_api_key,
101
- model_name="gpt-3.5-turbo",
102
- temperature=0.0
103
- )
104
-
105
- qa = RetrievalQA.from_llm(
106
- llm=llm,
107
- retriever=transactions_search.as_retriever()
108
- )
109
-
110
- answer = qa.invoke(query)
111
-
112
- return answer
113
-
114
- except Exception as e:
115
- raise HTTPException(status_code = 500, detail=f"fetch_pinecone_service error: {str(e)}")
116
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
tests/utils.py CHANGED
@@ -8,80 +8,240 @@ def get_fake_transactions(user_id: int) -> List[TransactionCreate]:
8
  TransactionCreate(
9
  user_id=user_id,
10
  transaction_date=datetime(2022, 1, 1),
11
- category="category1",
12
- name_description="name_description",
13
- amount=1.0,
14
  type=TransactionType.EXPENSE,
15
  ),
16
  TransactionCreate(
17
  user_id=user_id,
18
  transaction_date=datetime(2022, 1, 2),
19
- category="category2",
20
- name_description="name_description",
21
- amount=2.0,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22
  type=TransactionType.EXPENSE,
23
  ),
24
  TransactionCreate(
25
  user_id=user_id,
26
  transaction_date=datetime(2022, 1, 3),
27
- category="category3",
28
- name_description="name_description",
29
  amount=3.0,
30
  type=TransactionType.INCOME,
31
  ),
32
  TransactionCreate(
33
  user_id=user_id,
34
  transaction_date=datetime(2022, 1, 4),
35
- category="category1",
36
- name_description="name_description",
37
  amount=4.0,
38
  type=TransactionType.INCOME,
39
  ),
40
  TransactionCreate(
41
  user_id=user_id,
42
  transaction_date=datetime(2022, 1, 5),
43
- category="category2",
44
- name_description="name_description",
45
  amount=5.0,
46
  type=TransactionType.EXPENSE,
47
  ),
48
  TransactionCreate(
49
  user_id=user_id,
50
  transaction_date=datetime(2022, 1, 6),
51
- category="category3",
52
- name_description="name_description",
53
  amount=6.0,
54
  type=TransactionType.EXPENSE,
55
  ),
56
  TransactionCreate(
57
  user_id=user_id,
58
  transaction_date=datetime(2022, 1, 7),
59
- category="category1",
60
- name_description="name_description",
61
  amount=7.0,
62
  type=TransactionType.INCOME,
63
  ),
64
  TransactionCreate(
65
  user_id=user_id,
66
  transaction_date=datetime(2022, 1, 8),
67
- category="category2",
68
- name_description="name_description",
69
  amount=8.0,
70
  type=TransactionType.INCOME,
71
  ),
72
  TransactionCreate(
73
  user_id=user_id,
74
  transaction_date=datetime(2022, 1, 9),
75
- category="category3",
76
- name_description="name_description",
77
  amount=9.0,
78
  type=TransactionType.EXPENSE,
79
  ),
80
  TransactionCreate(
81
  user_id=user_id,
82
  transaction_date=datetime(2022, 1, 10),
83
- category="category1",
84
- name_description="name_description",
85
  amount=10.0,
86
  type=TransactionType.EXPENSE,
87
  ),
 
8
  TransactionCreate(
9
  user_id=user_id,
10
  transaction_date=datetime(2022, 1, 1),
11
+ category="shopping",
12
+ name_description="Amazon",
13
+ amount=11.0,
14
  type=TransactionType.EXPENSE,
15
  ),
16
  TransactionCreate(
17
  user_id=user_id,
18
  transaction_date=datetime(2022, 1, 2),
19
+ category="Streaming",
20
+ name_description="Netflix",
21
+ amount=4.0,
22
+ type=TransactionType.EXPENSE,
23
+ ),
24
+ TransactionCreate(
25
+ user_id=user_id,
26
+ transaction_date=datetime(2022, 1, 3),
27
+ category="Other",
28
+ name_description="Consulting",
29
+ amount=3.0,
30
+ type=TransactionType.INCOME,
31
+ ),
32
+ TransactionCreate(
33
+ user_id=user_id,
34
+ transaction_date=datetime(2022, 1, 4),
35
+ category="Other",
36
+ name_description="Selling Paintings",
37
+ amount=4.0,
38
+ type=TransactionType.INCOME,
39
+ ),
40
+ TransactionCreate(
41
+ user_id=user_id,
42
+ transaction_date=datetime(2022, 1, 5),
43
+ category="Gym",
44
+ name_description="Gym membership",
45
+ amount=5.0,
46
+ type=TransactionType.EXPENSE,
47
+ ),
48
+ TransactionCreate(
49
+ user_id=user_id,
50
+ transaction_date=datetime(2022, 1, 6),
51
+ category="Transportation",
52
+ name_description="Uber Taxi",
53
+ amount=6.0,
54
+ type=TransactionType.EXPENSE,
55
+ ),
56
+ TransactionCreate(
57
+ user_id=user_id,
58
+ transaction_date=datetime(2022, 1, 7),
59
+ category="Other",
60
+ name_description="Freelancing",
61
+ amount=7.0,
62
+ type=TransactionType.INCOME,
63
+ ),
64
+ TransactionCreate(
65
+ user_id=user_id,
66
+ transaction_date=datetime(2022, 1, 8),
67
+ category="Income",
68
+ name_description="Salary",
69
+ amount=8.0,
70
+ type=TransactionType.INCOME,
71
+ ),
72
+ TransactionCreate(
73
+ user_id=user_id,
74
+ transaction_date=datetime(2022, 1, 9),
75
+ category="Shopping",
76
+ name_description="Amazon Lux",
77
+ amount=9.0,
78
+ type=TransactionType.EXPENSE,
79
+ ),
80
+ TransactionCreate(
81
+ user_id=user_id,
82
+ transaction_date=datetime(2022, 1, 10),
83
+ category="Taxes",
84
+ name_description="CA Property Tax",
85
+ amount=10.0,
86
+ type=TransactionType.EXPENSE,
87
+ ),
88
+ TransactionCreate(
89
+ user_id=user_id,
90
+ transaction_date=datetime(2022, 1, 1),
91
+ category="shopping",
92
+ name_description="Amazon",
93
+ amount=11.0,
94
+ type=TransactionType.EXPENSE,
95
+ ),
96
+ TransactionCreate(
97
+ user_id=user_id,
98
+ transaction_date=datetime(2022, 1, 2),
99
+ category="Streaming",
100
+ name_description="Netflix",
101
+ amount=4.0,
102
+ type=TransactionType.EXPENSE,
103
+ ),
104
+ TransactionCreate(
105
+ user_id=user_id,
106
+ transaction_date=datetime(2022, 1, 3),
107
+ category="Other",
108
+ name_description="Consulting",
109
+ amount=3.0,
110
+ type=TransactionType.INCOME,
111
+ ),
112
+ TransactionCreate(
113
+ user_id=user_id,
114
+ transaction_date=datetime(2022, 1, 4),
115
+ category="Other",
116
+ name_description="Selling Paintings",
117
+ amount=4.0,
118
+ type=TransactionType.INCOME,
119
+ ),
120
+ TransactionCreate(
121
+ user_id=user_id,
122
+ transaction_date=datetime(2022, 1, 5),
123
+ category="Gym",
124
+ name_description="Gym membership",
125
+ amount=5.0,
126
+ type=TransactionType.EXPENSE,
127
+ ),
128
+ TransactionCreate(
129
+ user_id=user_id,
130
+ transaction_date=datetime(2022, 1, 6),
131
+ category="Transportation",
132
+ name_description="Uber Taxi",
133
+ amount=6.0,
134
+ type=TransactionType.EXPENSE,
135
+ ),
136
+ TransactionCreate(
137
+ user_id=user_id,
138
+ transaction_date=datetime(2022, 1, 7),
139
+ category="Other",
140
+ name_description="Freelancing",
141
+ amount=7.0,
142
+ type=TransactionType.INCOME,
143
+ ),
144
+ TransactionCreate(
145
+ user_id=user_id,
146
+ transaction_date=datetime(2022, 1, 8),
147
+ category="Income",
148
+ name_description="Salary",
149
+ amount=8.0,
150
+ type=TransactionType.INCOME,
151
+ ),
152
+ TransactionCreate(
153
+ user_id=user_id,
154
+ transaction_date=datetime(2022, 1, 9),
155
+ category="Shopping",
156
+ name_description="Amazon Lux",
157
+ amount=9.0,
158
+ type=TransactionType.EXPENSE,
159
+ ),
160
+ TransactionCreate(
161
+ user_id=user_id,
162
+ transaction_date=datetime(2022, 1, 10),
163
+ category="Taxes",
164
+ name_description="CA Property Tax",
165
+ amount=10.0,
166
+ type=TransactionType.EXPENSE,
167
+ ),
168
+ TransactionCreate(
169
+ user_id=user_id,
170
+ transaction_date=datetime(2022, 1, 1),
171
+ category="shopping",
172
+ name_description="Amazon",
173
+ amount=11.0,
174
+ type=TransactionType.EXPENSE,
175
+ ),
176
+ TransactionCreate(
177
+ user_id=user_id,
178
+ transaction_date=datetime(2022, 1, 2),
179
+ category="Streaming",
180
+ name_description="Netflix",
181
+ amount=4.0,
182
  type=TransactionType.EXPENSE,
183
  ),
184
  TransactionCreate(
185
  user_id=user_id,
186
  transaction_date=datetime(2022, 1, 3),
187
+ category="Other",
188
+ name_description="Consulting",
189
  amount=3.0,
190
  type=TransactionType.INCOME,
191
  ),
192
  TransactionCreate(
193
  user_id=user_id,
194
  transaction_date=datetime(2022, 1, 4),
195
+ category="Other",
196
+ name_description="Selling Paintings",
197
  amount=4.0,
198
  type=TransactionType.INCOME,
199
  ),
200
  TransactionCreate(
201
  user_id=user_id,
202
  transaction_date=datetime(2022, 1, 5),
203
+ category="Gym",
204
+ name_description="Gym membership",
205
  amount=5.0,
206
  type=TransactionType.EXPENSE,
207
  ),
208
  TransactionCreate(
209
  user_id=user_id,
210
  transaction_date=datetime(2022, 1, 6),
211
+ category="Transportation",
212
+ name_description="Uber Taxi",
213
  amount=6.0,
214
  type=TransactionType.EXPENSE,
215
  ),
216
  TransactionCreate(
217
  user_id=user_id,
218
  transaction_date=datetime(2022, 1, 7),
219
+ category="Other",
220
+ name_description="Freelancing",
221
  amount=7.0,
222
  type=TransactionType.INCOME,
223
  ),
224
  TransactionCreate(
225
  user_id=user_id,
226
  transaction_date=datetime(2022, 1, 8),
227
+ category="Income",
228
+ name_description="Salary",
229
  amount=8.0,
230
  type=TransactionType.INCOME,
231
  ),
232
  TransactionCreate(
233
  user_id=user_id,
234
  transaction_date=datetime(2022, 1, 9),
235
+ category="Shopping",
236
+ name_description="Amazon Lux",
237
  amount=9.0,
238
  type=TransactionType.EXPENSE,
239
  ),
240
  TransactionCreate(
241
  user_id=user_id,
242
  transaction_date=datetime(2022, 1, 10),
243
+ category="Taxes",
244
+ name_description="CA Property Tax",
245
  amount=10.0,
246
  type=TransactionType.EXPENSE,
247
  ),