bachephysicdun commited on
Commit
5a2b2d3
·
1 Parent(s): 20f2960

add simple stream and incomplete files

Browse files
Dockerfile CHANGED
@@ -16,4 +16,6 @@ RUN pip install --no-cache-dir --upgrade -r requirements.txt
16
  # Again, ensure the copied files are owned by 'user'
17
  COPY --chown=user . /app
18
  # Specify the command to run when the container starts
19
- CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "7860"]
 
 
 
16
  # Again, ensure the copied files are owned by 'user'
17
  COPY --chown=user . /app
18
  # Specify the command to run when the container starts
19
+ CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "7860"]
20
+ # Pass the secret variable to the application
21
+ RUN --mount=type=secret,id=HF_TOKEN,mode=0444,required=true
__init__.py ADDED
File without changes
__pycache__/app.cpython-311.pyc ADDED
Binary file (493 Bytes). View file
 
app/.ipynb_checkpoints/Untitled-checkpoint.ipynb ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [],
3
+ "metadata": {},
4
+ "nbformat": 4,
5
+ "nbformat_minor": 5
6
+ }
app/.ipynb_checkpoints/Untitled1-checkpoint.ipynb ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [],
3
+ "metadata": {},
4
+ "nbformat": 4,
5
+ "nbformat_minor": 5
6
+ }
app/.ipynb_checkpoints/Untitled2-checkpoint.ipynb ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [],
3
+ "metadata": {},
4
+ "nbformat": 4,
5
+ "nbformat_minor": 5
6
+ }
app/__init__.py ADDED
File without changes
app/__pycache__/__init__.cpython-311.pyc ADDED
Binary file (183 Bytes). View file
 
app/__pycache__/callbacks.cpython-311.pyc ADDED
Binary file (1.78 kB). View file
 
app/__pycache__/chains.cpython-311.pyc ADDED
Binary file (1.12 kB). View file
 
app/__pycache__/crud.cpython-311.pyc ADDED
Binary file (1.44 kB). View file
 
app/__pycache__/data_indexing.cpython-311.pyc ADDED
Binary file (7.12 kB). View file
 
app/__pycache__/data_indexing.cpython-312.pyc ADDED
Binary file (5.75 kB). View file
 
app/__pycache__/database.cpython-311.pyc ADDED
Binary file (705 Bytes). View file
 
app/__pycache__/database.cpython-312.pyc ADDED
Binary file (610 Bytes). View file
 
app/__pycache__/main.cpython-311.pyc ADDED
Binary file (2.7 kB). View file
 
app/__pycache__/models.cpython-311.pyc ADDED
Binary file (1.83 kB). View file
 
app/__pycache__/models.cpython-312.pyc ADDED
Binary file (1.51 kB). View file
 
app/__pycache__/prompts.cpython-311.pyc ADDED
Binary file (1.76 kB). View file
 
app/__pycache__/prompts.cpython-312.pyc ADDED
Binary file (1.59 kB). View file
 
app/__pycache__/schemas.cpython-311.pyc ADDED
Binary file (1.12 kB). View file
 
app/__pycache__/schemas.cpython-312.pyc ADDED
Binary file (908 Bytes). View file
 
app/callbacks.py ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from typing import Dict, Any, List
2
+ from langchain_core.callbacks import BaseCallbackHandler
3
+ import schemas
4
+ import crud
5
+
6
+
7
+ class LogResponseCallback(BaseCallbackHandler):
8
+
9
+ def __init__(self, user_request: schemas.UserRequest, db):
10
+ super().__init__()
11
+ self.user_request = user_request
12
+ self.db = db
13
+
14
+ def on_llm_end(self, outputs: Dict[str, Any], **kwargs: Any) -> Any:
15
+ """Run when llm ends running."""
16
+ # TODO: The function on_llm_end is going to be called when the LLM stops sending
17
+ # the response. Use the crud.add_message function to capture that response.
18
+ raise NotImplemented
19
+
20
+ def on_llm_start(
21
+ self, serialized: Dict[str, Any], prompts: List[str], **kwargs: Any
22
+ ) -> Any:
23
+ for prompt in prompts:
24
+ print(prompt)
app/chains.py ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #%%
2
+ import os
3
+ from dotenv import load_dotenv
4
+ load_dotenv('../../.env')
5
+
6
+ from langchain_huggingface import HuggingFaceEndpoint
7
+ from langchain_core.runnables import RunnablePassthrough
8
+ import schemas
9
+ from prompts import (
10
+ raw_prompt,
11
+ format_context,
12
+ tokenizer
13
+ )
14
+ from data_indexing import DataIndexer
15
+
16
+
17
+ # data_indexer = DataIndexer()
18
+
19
+ llm = HuggingFaceEndpoint(
20
+ repo_id="meta-llama/Meta-Llama-3-8B-Instruct",
21
+ huggingfacehub_api_token=os.environ['HF_TOKEN'],
22
+ max_new_tokens=512,
23
+ stop_sequences=[tokenizer.eos_token],
24
+ streaming=True,
25
+ )
26
+
27
+ simple_chain = (raw_prompt | llm).with_types(input_type=schemas.UserQuestion)
28
+ # %%
29
+
30
+ # data_indexer = DataIndexer()
31
+
32
+ # # TODO: create formatted_chain by piping raw_prompt_formatted and the LLM endpoint.
33
+ # formatted_chain = None
34
+
35
+ # # TODO: use history_prompt_formatted and HistoryInput to create the history_chain
36
+ # history_chain = None
37
+
38
+ # # TODO: Let's construct the standalone_chain by piping standalone_prompt_formatted with the LLM
39
+ # standalone_chain = None
40
+
41
+ # input_1 = RunnablePassthrough.assign(new_question=standalone_chain)
42
+ # input_2 = {
43
+ # 'context': lambda x: format_context(data_indexer.search(x['new_question'])),
44
+ # 'standalone_question': lambda x: x['new_question']
45
+ # }
46
+ # input_to_rag_chain = input_1 | input_2
47
+
48
+ # # TODO: use input_to_rag_chain, rag_prompt_formatted,
49
+ # # HistoryInput and the LLM to build the rag_chain.
50
+ # rag_chain = None
51
+
52
+ # # TODO: Implement the filtered_rag_chain. It should be the
53
+ # # same as the rag_chain but with hybrid_search = True.
54
+ # filtered_rag_chain = None
55
+
app/crud.py ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from sqlalchemy.orm import Session
2
+ import models, schemas
3
+
4
+
5
+ def get_or_create_user(db: Session, username: str):
6
+ user = db.query(models.User).filter(models.User.username == username).first()
7
+ if not user:
8
+ user = models.User(username=username)
9
+ db.add(user)
10
+ db.commit()
11
+ db.refresh(user)
12
+ return user
13
+
14
+ def add_message(db: Session, message: schemas.MessageBase, username: str):
15
+ # TODO: Implement the add_message function. It should:
16
+ # - get or create the user with the username
17
+ # - create a models.Message instance
18
+ # - pass the retrieved user to the message instance
19
+ # - save the message instance to the database
20
+ raise NotImplemented
21
+
22
+ def get_user_chat_history(db: Session, username: str):
23
+ raise NotImplemented
app/data_indexing.py ADDED
@@ -0,0 +1,150 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import uuid
3
+ from pathlib import Path
4
+ from pinecone.grpc import PineconeGRPC as Pinecone
5
+ from pinecone import ServerlessSpec
6
+ from langchain_community.vectorstores import Chroma
7
+ from langchain_openai import OpenAIEmbeddings
8
+
9
+ current_dir = Path(__file__).resolve().parent
10
+
11
+
12
+ class DataIndexer:
13
+
14
+ source_file = os.path.join(current_dir, 'sources.txt')
15
+
16
+ def __init__(self, index_name='langchain-repo') -> None:
17
+
18
+ # TODO: choose your embedding model
19
+ # self.embedding_client = InferenceClient(
20
+ # "dunzhang/stella_en_1.5B_v5",
21
+ # token=os.environ['HF_TOKEN'],
22
+ # )
23
+ self.embedding_client = OpenAIEmbeddings()
24
+ self.index_name = index_name
25
+ self.pinecone_client = Pinecone(api_key=os.environ.get('PINECONE_API_KEY'))
26
+
27
+ if index_name not in self.pinecone_client.list_indexes().names():
28
+ # TODO: create your index if it doesn't exist. Use the create_index function.
29
+ # Make sure to choose the dimension that corresponds to your embedding model
30
+ pass
31
+
32
+ self.index = self.pinecone_client.Index(self.index_name)
33
+ # TODO: make sure to build the index.
34
+ self.source_index = None
35
+
36
+ def get_source_index(self):
37
+ if not os.path.isfile(self.source_file):
38
+ print('No source file')
39
+ return None
40
+
41
+ print('create source index')
42
+
43
+ with open(self.source_file, 'r') as file:
44
+ sources = file.readlines()
45
+
46
+ sources = [s.rstrip('\n') for s in sources]
47
+ vectorstore = Chroma.from_texts(
48
+ sources, embedding=self.embedding_client
49
+ )
50
+ return vectorstore
51
+
52
+ def index_data(self, docs, batch_size=32):
53
+
54
+ with open(self.source_file, 'a') as file:
55
+ for doc in docs:
56
+ file.writelines(doc.metadata['source'] + '\n')
57
+
58
+ for i in range(0, len(docs), batch_size):
59
+ batch = docs[i: i + batch_size]
60
+
61
+ # TODO: create a list of the vector representations of each text data in the batch
62
+ # TODO: choose your embedding model
63
+ # values = self.embedding_client.embed_documents([
64
+ # doc.page_content for doc in batch
65
+ # ])
66
+
67
+ # values = self.embedding_client.feature_extraction([
68
+ # doc.page_content for doc in batch
69
+ # ])
70
+ values = None
71
+
72
+ # TODO: create a list of unique identifiers for each element in the batch with the uuid package.
73
+ vector_ids = None
74
+
75
+ # TODO: create a list of dictionaries representing the metadata. Capture the text data
76
+ # with the "text" key, and make sure to capture the rest of the doc.metadata.
77
+ metadatas = None
78
+
79
+ # create a list of dictionaries with keys "id" (the unique identifiers), "values"
80
+ # (the vector representation), and "metadata" (the metadata).
81
+ vectors = [{
82
+ 'id': vector_id,
83
+ 'values': value,
84
+ 'metadata': metadata
85
+ } for vector_id, value, metadata in zip(vector_ids, values, metadatas)]
86
+
87
+ try:
88
+ # TODO: Use the function upsert to upload the data to the database.
89
+ upsert_response = None
90
+ print(upsert_response)
91
+ except Exception as e:
92
+ print(e)
93
+
94
+ def search(self, text_query, top_k=5, hybrid_search=False):
95
+
96
+ filter = None
97
+ if hybrid_search and self.source_index:
98
+ # I implemented the filtering process to pull the 50 most relevant file names
99
+ # to the question. Make sure to adjust this number as you see fit.
100
+ source_docs = self.source_index.similarity_search(text_query, 50)
101
+ filter = {"source": {"$in":[doc.page_content for doc in source_docs]}}
102
+
103
+ # TODO: embed the text_query by using the embedding model
104
+ # TODO: choose your embedding model
105
+ # vector = self.embedding_client.feature_extraction(text_query)
106
+ # vector = self.embedding_client.embed_query(text_query)
107
+ vector = None
108
+
109
+ # TODO: use the vector representation of the text_query to
110
+ # search the database by using the query function.
111
+ result = None
112
+
113
+ docs = []
114
+ for res in result["matches"]:
115
+ # TODO: From the result's metadata, extract the "text" element.
116
+ pass
117
+
118
+ return docs
119
+
120
+
121
+ if __name__ == '__main__':
122
+
123
+ from langchain_community.document_loaders import GitLoader
124
+ from langchain_text_splitters import (
125
+ Language,
126
+ RecursiveCharacterTextSplitter,
127
+ )
128
+
129
+ loader = GitLoader(
130
+ clone_url="https://github.com/langchain-ai/langchain",
131
+ repo_path="./code_data/langchain_repo/",
132
+ branch="master",
133
+ )
134
+
135
+ python_splitter = RecursiveCharacterTextSplitter.from_language(
136
+ language=Language.PYTHON, chunk_size=10000, chunk_overlap=100
137
+ )
138
+
139
+ docs = loader.load()
140
+ docs = [doc for doc in docs if doc.metadata['file_type'] in ['.py', '.md']]
141
+ docs = [doc for doc in docs if len(doc.page_content) < 50000]
142
+ docs = python_splitter.split_documents(docs)
143
+ for doc in docs:
144
+ doc.page_content = '# {}\n\n'.format(doc.metadata['source']) + doc.page_content
145
+
146
+ indexer = DataIndexer()
147
+ with open('/app/sources.txt', 'a') as file:
148
+ for doc in docs:
149
+ file.writelines(doc.metadata['source'] + '\n')
150
+ indexer.index_data(docs)
app/database.py ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #%%
2
+
3
+ # create_engine: This function creates a new SQLAlchemy “engine,”
4
+ # which is an interface to the database. It acts as the core connection to
5
+ # your database and manages the communication between your Python code and the database.
6
+ from sqlalchemy import create_engine
7
+
8
+ # declarative_base: This function is used to create a base class for our ORM models.
9
+ # All of your database table classes (models) will inherit from this base class.
10
+ # This base class also ties each model to a corresponding table in the database.
11
+ from sqlalchemy.ext.declarative import declarative_base
12
+
13
+ # sessionmaker: This is a factory function for creating new Session objects.
14
+ # Sessions are used to manage the operations (queries, updates, etc.) on
15
+ # the database in a transaction-safe way. They provide an interface for
16
+ # interacting with the database.
17
+ from sqlalchemy.orm import sessionmaker
18
+
19
+ # This line defines the URL for your database connection.
20
+ # SQLAlchemy uses this URL to determine what type of database you’re
21
+ # connecting to, and where it’s located.
22
+ # sqlite:// tells SQLAlchemy that you are using SQLite as the database engine.
23
+ # ./test.db specifies the relative path to the database file (test.db) in the
24
+ # current directory (./). SQLite stores the entire database as a single file on disk
25
+ SQLALCHEMY_DATABASE_URL = "sqlite:///./test.db"
26
+
27
+ # This line creates the database engine by passing the SQLALCHEMY_DATABASE_URL to the
28
+ # create_engine function. The engine is responsible for managing the connection to the database.
29
+ # connect_args={"check_same_thread": False}: This argument is specific to SQLite. By default,
30
+ # SQLite does not allow multiple threads to interact with the database. The check_same_thread
31
+ # argument disables this check, allowing the engine to be used in a multi-threaded environment.
32
+ # This is necessary for many web applications (like FastAPI) that might have multiple requests
33
+ # hitting the database simultaneously.
34
+ engine = create_engine(
35
+ SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False}
36
+ )
37
+
38
+ # you create a factory for database sessions. SessionLocal will be used to create individual sessions,
39
+ # which are needed to interact with the database (querying data, inserting/updating records, etc.).
40
+ # 1. autocommit=False: This means that changes (inserts, updates, deletes) to the database will not be
41
+ # committed automatically. You will need to explicitly commit transactions using session.commit().
42
+ # This gives you better control over when data is saved.
43
+ # 2. autoflush=False: This disables automatic flushing. Flushing is the process of sending any pending
44
+ # changes to the database before executing queries. With autoflush=False, the session will not
45
+ # automatically send updates to the database unless you explicitly tell it to by calling flush() or commit().
46
+ # It prevents unexpected database updates.
47
+ # 3. bind=engine: This ties the session to the database engine. Any session created with SessionLocal()
48
+ # will use the engine to communicate with the database.
49
+ SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
50
+
51
+ # This line creates a base class for all of your ORM models (i.e., classes that represent database tables).
52
+ # Each model (class) will inherit from Base, and SQLAlchemy will use this base class to generate the
53
+ # necessary SQL statements to create tables and handle CRUD operations (Create, Read, Update, Delete).
54
+ Base = declarative_base()
55
+ # %%
app/main.py ADDED
@@ -0,0 +1,94 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from langchain_core.runnables import Runnable
2
+ from langchain_core.callbacks import BaseCallbackHandler
3
+ from fastapi import FastAPI, Request, Depends
4
+ from sse_starlette.sse import EventSourceResponse
5
+ from langserve.serialization import WellKnownLCSerializer
6
+ from typing import List
7
+ from sqlalchemy.orm import Session
8
+
9
+ import schemas
10
+ from chains import simple_chain
11
+ import crud, models, schemas
12
+ from database import SessionLocal, engine
13
+ from callbacks import LogResponseCallback
14
+
15
+
16
+ models.Base.metadata.create_all(bind=engine)
17
+
18
+ app = FastAPI()
19
+
20
+ # def get_db():
21
+ # db = SessionLocal()
22
+ # try:
23
+ # yield db
24
+ # finally:
25
+ # db.close()
26
+
27
+
28
+ async def generate_stream(input_data: schemas.BaseModel, runnable: Runnable, callbacks: List[BaseCallbackHandler]=[]):
29
+ for output in runnable.stream(input_data.dict(), config={"callbacks": callbacks}):
30
+ data = WellKnownLCSerializer().dumps(output).decode("utf-8")
31
+ yield {'data': data, "event": "data"}
32
+ yield {"event": "end"}
33
+
34
+
35
+ @app.post("/simple/stream")
36
+ async def simple_stream(request: Request):
37
+ data = await request.json()
38
+ user_question = schemas.UserQuestion(**data['input'])
39
+ return EventSourceResponse(generate_stream(user_question, simple_chain))
40
+
41
+
42
+ # @app.post("/formatted/stream")
43
+ # async def formatted_stream(request: Request):
44
+ # # TODO: use the formatted_chain to implement the "/formatted/stream" endpoint.
45
+ # raise NotImplemented
46
+
47
+
48
+ # def get_db():
49
+ # db = SessionLocal()
50
+ # try:
51
+ # yield db
52
+ # finally:
53
+ # db.close()
54
+
55
+ # @app.post("/history/stream")
56
+ # async def history_stream(request: Request, db: Session = Depends(get_db)):
57
+ # # TODO: Let's implement the "/history/stream" endpoint. The endpoint should follow those steps:
58
+ # # - The endpoint receives the request
59
+ # # - The request is parsed into a user request
60
+ # # - The user request is used to pull the chat history of the user
61
+ # # - We add as part of the user history the current question by using add_message.
62
+ # # - We create an instance of HistoryInput by using format_chat_history.
63
+ # # - We use the history input within the history chain.
64
+ # raise NotImplemented
65
+
66
+
67
+ # @app.post("/rag/stream")
68
+ # async def rag_stream(request: Request, db: Session = Depends(get_db)):
69
+ # # TODO: Let's implement the "/rag/stream" endpoint. The endpoint should follow those steps:
70
+ # # - The endpoint receives the request
71
+ # # - The request is parsed into a user request
72
+ # # - The user request is used to pull the chat history of the user
73
+ # # - We add as part of the user history the current question by using add_message.
74
+ # # - We create an instance of HistoryInput by using format_chat_history.
75
+ # # - We use the history input within the rag chain.
76
+ # raise NotImplemented
77
+
78
+
79
+ # @app.post("/filtered_rag/stream")
80
+ # async def filtered_rag_stream(request: Request, db: Session = Depends(get_db)):
81
+ # # TODO: Let's implement the "/filtered_rag/stream" endpoint. The endpoint should follow those steps:
82
+ # # - The endpoint receives the request
83
+ # # - The request is parsed into a user request
84
+ # # - The user request is used to pull the chat history of the user
85
+ # # - We add as part of the user history the current question by using add_message.
86
+ # # - We create an instance of HistoryInput by using format_chat_history.
87
+ # # - We use the history input within the filtered rag chain.
88
+ # raise NotImplemented
89
+
90
+
91
+
92
+ if __name__ == "__main__":
93
+ import uvicorn
94
+ uvicorn.run("main:app", host="localhost", reload=True, port=8000)
app/models.py ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from sqlalchemy import Column, ForeignKey, Integer, String, DateTime
2
+ from sqlalchemy.orm import relationship
3
+
4
+ from datetime import datetime
5
+
6
+ from database import Base
7
+
8
+ class User(Base):
9
+
10
+ # This defines the name of the table in the database.
11
+ # Here, the class User is mapped to a table called users.
12
+ __tablename__ = "users"
13
+ __table_args__ = {'extend_existing': True}
14
+
15
+ # This line defines a column called id in the users table.
16
+ # Integer: The data type of this column is an integer.
17
+ # primary_key=True: This makes the id column the primary key
18
+ # for the users table, meaning each row will have a unique id.
19
+ # index=True: This creates an index on the id column, making
20
+ # lookups by id faster.
21
+ id = Column(Integer, primary_key=True, index=True)
22
+
23
+ # This line defines a column called username.
24
+ username = Column(String, unique=True, index=True)
25
+
26
+ # This establishes a relationship between the User model
27
+ # and a related model called Message.
28
+ # relationship("Message"): This creates a one-to-many relationship between User and Message.
29
+ # It indicates that each user can have many associated messages
30
+ # (the relationship is “one user to many messages”).
31
+ # back_populates="user": This specifies that the relationship is bidirectional,
32
+ # meaning the Message model will also have a corresponding relationship with User.
33
+ # The back_populates="user" part tells SQLAlchemy to link the relationship on the
34
+ # Message side back to the user field, creating a mutual relationship.
35
+ messages = relationship("Message", back_populates="user")
36
+
37
+
38
+ # TODO: Implement the Message SQLAlchemy model. Message should have a primary key,
39
+ # a message attribute to store the content of messages, a type, AI or Human,
40
+ # depending on if it is a user question or an AI response, a timestamp to
41
+ # order by time and a user attribute to get the user instance associated
42
+ # with the message. We also need a user_id that will use the User.id
43
+ # attribute as a foreign key.
44
+
45
+ class Message(Base):
46
+ __tablename__ = "messages"
47
+ __table_args__ = {'extend_existing': True}
48
+
49
+ id = id = Column(Integer, primary_key=True, index=True)
50
+ message = Column(String, nullable=False)
51
+ type = Column(String(50), nullable=False)
52
+ timestamp = Column(DateTime, default=datetime.utcnow, nullable=False)
53
+ user_id = Column(Integer, ForeignKey("users.id"), nullable=False)
54
+
55
+ user = relationship("User", back_populates="messages")
app/prompts.py ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #%%
2
+ import os
3
+ # from dotenv import load_dotenv
4
+ # load_dotenv('../../.env')
5
+
6
+ from langchain_core.prompts import PromptTemplate
7
+ from typing import List
8
+
9
+ from transformers import AutoTokenizer
10
+ from huggingface_hub import login
11
+
12
+ import models
13
+
14
+
15
+ login(os.environ['HF_TOKEN'])
16
+ tokenizer = AutoTokenizer.from_pretrained("meta-llama/Meta-Llama-3-8B-Instruct")
17
+
18
+ def format_prompt(prompt) -> PromptTemplate:
19
+ # TODO: format the input prompt by using the model specific instruction template
20
+ # TODO: return a langchain PromptTemplate
21
+ raise NotImplemented
22
+
23
+ def format_chat_history(messages: List[models.Message]):
24
+ # TODO: implement format_chat_history to format
25
+ # the list of Message into a text of chat history.
26
+ raise NotImplemented
27
+
28
+ def format_context(docs: List[str]):
29
+ # TODO: the output of the DataIndexer.search is a list of text,
30
+ # so we need to concatenate that list into a text that can fit into
31
+ # the rag_prompt_formatted. Implement format_context that takes a
32
+ # like of strings and returns the context as one string.
33
+ raise NotImplemented
34
+
35
+ raw_prompt = "{question}"
36
+
37
+ # TODO: Create the history_prompt prompt that will capture the question and the conversation history.
38
+ # The history_prompt needs a {chat_history} placeholder and a {question} placeholder.
39
+ history_prompt: str = None
40
+
41
+ # TODO: Create the standalone_prompt prompt that will capture the question and the chat history
42
+ # to generate a standalone question. It needs a {chat_history} placeholder and a {question} placeholder,
43
+ standalone_prompt: str = None
44
+
45
+ # TODO: Create the rag_prompt that will capture the context and the standalone question to generate
46
+ # a final answer to the question.
47
+ rag_prompt: str = None
48
+
49
+ # TODO: create raw_prompt_formatted by using format_prompt
50
+ raw_prompt_formatted = None
51
+ raw_prompt = PromptTemplate.from_template(raw_prompt)
52
+
53
+ # TODO: use format_prompt to create history_prompt_formatted
54
+ history_prompt_formatted: PromptTemplate = None
55
+ # TODO: use format_prompt to create standalone_prompt_formatted
56
+ standalone_prompt_formatted: PromptTemplate = None
57
+ # TODO: use format_prompt to create rag_prompt_formatted
58
+ rag_prompt_formatted: PromptTemplate = None
app/schemas.py ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from pydantic import BaseModel
2
+
3
+ class UserQuestion(BaseModel):
4
+ question: str
5
+
6
+ # TODO: create a HistoryInput data model with a chat_history and question attributes.
7
+ class HistoryInput(BaseModel):
8
+ pass
9
+
10
+ # TODO: let's create a UserRequest data model with a question and username attribute.
11
+ # This will be used to parse the input request.
12
+ class UserRequest(BaseModel):
13
+ username: str
14
+
15
+ # TODO: implement MessageBase as a schema mapping from the database model to the
16
+ # FastAPI data model. Basically MessageBase should have the same attributes as models.Message
17
+ class MessageBase(BaseModel):
18
+ pass
app/test.db ADDED
Binary file (24.6 kB). View file
 
check.ipynb ADDED
@@ -0,0 +1,229 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "code",
5
+ "execution_count": 1,
6
+ "metadata": {},
7
+ "outputs": [],
8
+ "source": [
9
+ "%load_ext autoreload\n",
10
+ "%autoreload 2"
11
+ ]
12
+ },
13
+ {
14
+ "cell_type": "code",
15
+ "execution_count": 2,
16
+ "metadata": {},
17
+ "outputs": [
18
+ {
19
+ "data": {
20
+ "text/plain": [
21
+ "True"
22
+ ]
23
+ },
24
+ "execution_count": 2,
25
+ "metadata": {},
26
+ "output_type": "execute_result"
27
+ }
28
+ ],
29
+ "source": [
30
+ "import requests\n",
31
+ "import os\n",
32
+ "\n",
33
+ "from dotenv import load_dotenv\n",
34
+ "load_dotenv()"
35
+ ]
36
+ },
37
+ {
38
+ "cell_type": "code",
39
+ "execution_count": 3,
40
+ "metadata": {},
41
+ "outputs": [
42
+ {
43
+ "data": {
44
+ "text/plain": [
45
+ "'World!'"
46
+ ]
47
+ },
48
+ "execution_count": 3,
49
+ "metadata": {},
50
+ "output_type": "execute_result"
51
+ }
52
+ ],
53
+ "source": [
54
+ "url = 'https://bachephysicdun-backend.hf.space'\n",
55
+ "response = requests.get(url)\n",
56
+ "response.json()['Hello']"
57
+ ]
58
+ },
59
+ {
60
+ "cell_type": "code",
61
+ "execution_count": 4,
62
+ "metadata": {},
63
+ "outputs": [],
64
+ "source": [
65
+ "from app.data_indexing import DataIndexer"
66
+ ]
67
+ },
68
+ {
69
+ "cell_type": "code",
70
+ "execution_count": 5,
71
+ "metadata": {},
72
+ "outputs": [
73
+ {
74
+ "data": {
75
+ "text/plain": [
76
+ "sqlalchemy.orm.decl_api.Base"
77
+ ]
78
+ },
79
+ "execution_count": 5,
80
+ "metadata": {},
81
+ "output_type": "execute_result"
82
+ }
83
+ ],
84
+ "source": [
85
+ "from app.database import Base\n",
86
+ "\n",
87
+ "Base"
88
+ ]
89
+ },
90
+ {
91
+ "cell_type": "code",
92
+ "execution_count": 6,
93
+ "metadata": {},
94
+ "outputs": [],
95
+ "source": [
96
+ "import sys\n",
97
+ "sys.path.append('./app/')\n",
98
+ "from app.models import User, Message"
99
+ ]
100
+ },
101
+ {
102
+ "cell_type": "code",
103
+ "execution_count": 7,
104
+ "metadata": {},
105
+ "outputs": [
106
+ {
107
+ "name": "stdout",
108
+ "output_type": "stream",
109
+ "text": [
110
+ "The token has not been saved to the git credentials helper. Pass `add_to_git_credential=True` in this function directly or `--add-to-git-credential` if using via `huggingface-cli` if you want to set the git credential as well.\n",
111
+ "Token is valid (permission: fineGrained).\n",
112
+ "Your token has been saved to /Users/amin/.cache/huggingface/token\n",
113
+ "Login successful\n",
114
+ "{'input_ids': [128000, 9906, 11, 1268, 527, 499, 30], 'attention_mask': [1, 1, 1, 1, 1, 1, 1]}\n"
115
+ ]
116
+ }
117
+ ],
118
+ "source": [
119
+ "import os\n",
120
+ "from transformers import AutoTokenizer\n",
121
+ "from huggingface_hub import login\n",
122
+ "\n",
123
+ "login(os.environ['HF_TOKEN'])\n",
124
+ "\n",
125
+ "# Load the tokenizer for the gated model\n",
126
+ "tokenizer = AutoTokenizer.from_pretrained(\"meta-llama/Meta-Llama-3-8B-Instruct\")\n",
127
+ "\n",
128
+ "# Example usage\n",
129
+ "text = \"Hello, how are you?\"\n",
130
+ "tokens = tokenizer(text)\n",
131
+ "\n",
132
+ "print(tokens)"
133
+ ]
134
+ },
135
+ {
136
+ "cell_type": "code",
137
+ "execution_count": 8,
138
+ "metadata": {},
139
+ "outputs": [],
140
+ "source": [
141
+ "from huggingface_hub import InferenceClient\n",
142
+ "client = InferenceClient(\n",
143
+ " \"meta-llama/Meta-Llama-3-8B-Instruct\",\n",
144
+ " token=os.environ['HF_TOKEN'],\n",
145
+ ")"
146
+ ]
147
+ },
148
+ {
149
+ "cell_type": "code",
150
+ "execution_count": 11,
151
+ "metadata": {},
152
+ "outputs": [
153
+ {
154
+ "name": "stdout",
155
+ "output_type": "stream",
156
+ "text": [
157
+ " Linear regression is a statistical method that is used to create a linear equation that best predicts the relationship between two or more variables. The goal of linear regression is to create a model that can be used to make predictions about the value of the dependent variable (y) based on the value of one or more independent variables (x). Linear regression is a widely used and powerful tool for modeling the relationship between variables, and it has many applications in fields such as finance, economics, and medicine.\n",
158
+ "\n",
159
+ "How does Linear Regression work? Linear regression works by using a set of data points, where each data point represents a pair of values for the dependent and independent variables. The algorithm then finds the line that best fits the data points, by minimizing the sum of the squared errors between the predicted values and the actual values. The line that is found is called the regression line, and it is used to make predictions about the value of the dependent variable.\n",
160
+ "\n",
161
+ "There are several types of linear regression, including:\n",
162
+ "\n",
163
+ "* Simple Linear Regression: This type of linear regression involves a single independent variable and a single dependent variable.\n",
164
+ "* Multiple Linear Regression: This type of linear regression involves multiple independent variables and a single dependent variable.\n",
165
+ "* Polynomial Regression: This type of linear regression involves a polynomial equation, rather than a linear equation.\n",
166
+ "* Non-Linear Regression: This type of linear regression involves a non-linear equation, rather than a linear equation.\n",
167
+ "\n",
168
+ "What are the advantages and disadvantages of Linear Regression? The advantages of linear regression include:\n",
169
+ "\n",
170
+ "* It is a widely used and well-established statistical method.\n",
171
+ "* It is easy to interpret and understand.\n",
172
+ "* It can be used to make predictions about the value of the dependent variable.\n",
173
+ "* It can be used to identify the relationship between the independent and dependent variables.\n",
174
+ "\n",
175
+ "The disadvantages of linear regression include:\n",
176
+ "\n",
177
+ "* It assumes a linear relationship between the independent and dependent variables, which may not always be the case.\n",
178
+ "* It can be sensitive to outliers and noisy data.\n",
179
+ "* It can be difficult to interpret the results, especially for complex models.\n",
180
+ "* It can be sensitive to the choice of variables and the data used.\n",
181
+ "\n",
182
+ "What are some common applications of Linear Regression? Linear regression has many applications in fields such as:\n",
183
+ "\n",
184
+ "* Finance: Linear regression can be used to predict stock prices, interest rates, and other financial variables.\n",
185
+ "* Economics: Linear regression can be used to model the relationship between economic variables, such as GDP and unemployment rates.\n",
186
+ "* Medicine: Linear regression can be used to model the relationship between medical variables, such as blood pressure and heart rate.\n",
187
+ "* Marketing: Linear regression can"
188
+ ]
189
+ }
190
+ ],
191
+ "source": [
192
+ "from langserve import RemoteRunnable\n",
193
+ "chain = RemoteRunnable(\"http://localhost:8000/simple\")\n",
194
+ "stream = chain.stream(input={'question':'What is Linear Regression?'})\n",
195
+ "for chunk in stream:\n",
196
+ " print(chunk, end=\"\", flush=True)"
197
+ ]
198
+ },
199
+ {
200
+ "cell_type": "code",
201
+ "execution_count": null,
202
+ "metadata": {},
203
+ "outputs": [],
204
+ "source": []
205
+ }
206
+ ],
207
+ "metadata": {
208
+ "kernelspec": {
209
+ "display_name": "myenv",
210
+ "language": "python",
211
+ "name": "python3"
212
+ },
213
+ "language_info": {
214
+ "codemirror_mode": {
215
+ "name": "ipython",
216
+ "version": 3
217
+ },
218
+ "file_extension": ".py",
219
+ "mimetype": "text/x-python",
220
+ "name": "python",
221
+ "nbconvert_exporter": "python",
222
+ "pygments_lexer": "ipython3",
223
+ "version": "3.11.4"
224
+ },
225
+ "orig_nbformat": 4
226
+ },
227
+ "nbformat": 4,
228
+ "nbformat_minor": 2
229
+ }