Skip to content

Commit efc8c0f

Browse files
committed
Merge remote-tracking branch 'origin/main'
2 parents f5afc45 + 2d6a731 commit efc8c0f

19 files changed

+1434
-0
lines changed
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# Integrate OCI Generative AI with LangChain
2+
This repo contains all the work done to develop demos on the integration between [**LangChain**](https://www.langchain.com/) and Oracle [**OCI GenAI**](https://www.oracle.com/artificial-intelligence/generative-ai/large-language-models/) Service.
3+
4+
## OCI Generative AI Service is in GENERAL AVAILABILITY
5+
Consider that OCI Generative AI Service (based on Cohere models) is now (July )
6+
7+
## Oracle 23ai is in GENERAL AVAILABILITY
8+
Consider that Oracle 23 ai database is available now
9+
10+
## Documentation
11+
The development of the proposed integration is based on the example, from LangChain, provided [here](https://python.langchain.com/docs/modules/model_io/models/llms/custom_llm)
12+
13+
**RAG** has been first described in the following [arXiv paper](https://arxiv.org/pdf/2005.11401.pdf)
14+
15+
## Features
16+
* How-to build a complete, end-2-end RAG solution using LangChain and Oracle GenAI Service.
17+
* How-to load multiple pdf
18+
* How-to split pdf pages in smaller chuncks
19+
* How-to do semantic search using Embeddings
20+
* How-to use Cohere Embeddings
21+
* How-to use HF Embeddings
22+
* How-to setup a Retriever using Embeddings
23+
* How-to add Cohere reranker to the chain
24+
* How to integrate OCI GenAI Service with LangChain
25+
* How to define the LangChain
26+
* How to use the Oracle vector Db capabilities
27+
* How to use in-memory database capability
28+
29+
## Oracle BOT
30+
Using the script [run_oracle_bot_exp.sh](./run_oracle_bot_exp.sh) you can launch a simple ChatBot that showcase Oracle GenAI service. The demo is based on docs from Oracle Database pdf documentation.
31+
32+
You need to put in the local directory:
33+
* Trobleshooting.pdf
34+
* globally-distributed-autonomous-database.pdf
35+
* Oracle True cache.pdf
36+
* oracle-database-23c.pdf
37+
* oracle-globally-distributed-database-guide.pdf
38+
* sharding-adg-addshard-cookbook-3610618.pdf
39+
40+
You can add more pdf. Edit [config_rag.py](./config_rag.py)
41+
42+
## Video
43+
44+
45+
46+
47+
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
[DEFAULT]
2+
user = ocid1.user.oc1..aaaaaaaabjnsmmvrb6xp53xodn7mpl3tpbmp5skyeln45hpjh35kcjka3g2a
3+
fingerprint = 78:c8:06:ce:8d:ec:fa:59:11:e0:95:cb:38:cd:70:7b
4+
tenancy = ocid1.tenancy.oc1..aaaaaaaalfdcq4pjudpqet6h7hdwontdpij5qzeec5nag236it6x6arg7rsq
5+
region = us-ashburn-1
6+
key_file = /Users/pankatiw/Downloads/[email protected]_2024-05-21T09_18_17.616Z.pem
7+
COMPARTMENT_OCID = "ocid1.compartment.oc1..aaaaaaaajdyhd7dqnix2avhlckbhhkkcl3cujzyuz6jzyzonadca3i66pqjq"
8+
COHERE_API_KEY = "-----BEGIN PRIVATE KEY----- MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDSu5DgrYhdkRpx 8YLJZyd6uJmuWDMz6iqN9Yy9xxGj6XWNTk+aHMvumDJ451j2jCkaXXkBorADWcyo I7X5aJF/WdSzM9QTA71nVKshbCBPNW7NaQJEbknSOlaZIEk77eREKzuyY7XY8agv xCBVf06oJ8w5jzbOO38G8TWIUcnNyOJnFKI2VHkCI6RI8Bc39iPqQWG8qgQdzSy2 pwFqbZBU2xcQtbKB3ByvvDRS+YHen1FN3w64ZMne2ky8SDU9sT+94km+w0Y+Wl6A ibbgaG1LrRW3VCgg5QxfYKs4lHdLlGX2grWl6O5Ar4gcX8+x1XmoZQVamo0kg1s+ eAQkPxgFAgMBAAECggEANJJ+DYtFVKBtUkVP3Up6hyt0DZJr7bTq2mEKtFKsNDH7 NV42zioGd1bpao++uj1TyMPOeym40xEtVToZfSgI+lYxEebpbrf1Yci167/jnJcm NiEPI37HNGcA8TEkjAqocpg9i57EAGQjUw1RCrtYpmtNUAPKRq+BnHwDIKfU2l0i OFgIUDBatKlfZOlvX+CphVgEbIyrkinK3BYCSjCuY4bPInOwHc+YTYy9ihMpWeGj li1nDGG11y0Ui4IzX3w+W8Yhl0mIjTKQUPnPkAvsV/2mjKDmEvdX3nMtzE2s6MNW MOIJ7db3G38r/l34lntAAiOtoDrNiyEOYYFAFJeowQKBgQDo0eik9R0Xpx+9L85n xt88vavYq/AsZFrLfFNoCoOey5lPtkKmPxUIbdWfynujO4s9O/I4xHs1LiKO3xcE PmNu5L3Y0SydV0CK7Gj4LOLpIwFTb8wIntFYRET6+nkEz83fFyBrgVl0iA3xH7XW SiHxaQZWL2y1Yg2rCerf1n/BQQKBgQDntrLr1gJWZBVxQu69CByTndf+j1Y47iIf L3hQhSD5q8d2QACavggxpg0AvSM9bqMNtkHSh/HELpZrJZHxP3GsqbUY4cvaA3WK muretzmN8kCozcgs+dMeM7aqL+/4Xatujn4UxHt7O5eOqAzVfavwOXTF7bo9zVcc zWxtdIYhxQKBgQDnPh4pQX+sz4S5vrLu5lsyFF2L7nK1VNPNimW5T8AdR7G1t5yJ TNySK61jcZTNs0WAA3t5IMYTMwiGCVTuFR1jtnRN1qzOdiwYD+nOnZ6e2vLlMYRh B4V8ewpckc0Dl3auX2UHAkmcccoPNWTBO45tHdh6X85EdeiHemk7++uWQQKBgQCV hIXFuk29000mzarh3YcbFeJXh8R6beckumvngVA660aFHl2FfJQq/Vwsmt9Pd8HN SksE/+XY0rsLHq4ivu6qHMQX7zOsVUkWjEp8Njz0RFrG0iqWIwrA1VvMS6yMVl0V tOrUmciYR2bPjc7iP/qfw2N/iJwB3yuUEVYi9urKhQKBgQCDqwzMHpSC+IvNAomj HB6XY20MlkLkjZIbJwyw2SzLnrEgp7RsGH/bVmZonGiDQKl8xTTcG831I8+h8rEt tNM8a1Xl4sMpnFmHkmD0XV8DvsXwafBO9ygj87Au87tREcxX/8DgTn6tZSclmgdp vKDkErw6rpZmLZKFHck8lwZZBA== -----END PRIVATE KEY-----"
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
# configurations for the RAG
2+
3+
# to enable debugging info..
4+
DEBUG = False
5+
6+
# book to use for augmentation
7+
# BOOK1 = "APISpec.pdf"
8+
BOOK1 = "pdfFiles/sharding-adg-addshard-cookbook-3610618.pdf"
9+
BOOK2 = "pdfFiles/globally-distributed-autonomous-database.pdf"
10+
# BOOK4 = "OnBoardingGuide.pdf"
11+
# BOOK5 = "CreateWorkFlow.pdf"
12+
# BOOK6 = "Team Onboarding.pdf"
13+
# BOOK7 = "workflow.pdf"
14+
BOOK3 = "pdfFiles/oracle-database-23c.pdf"
15+
BOOK4 = "pdfFiles/oracle-globally-distributed-database-guide.pdf"
16+
BOOK5 = "pdfFiles/Oracle True cache.pdf"
17+
BOOK6 = "pdfFiles/Trobleshooting.pdf"
18+
# BOOK12 = "OsdCode.pdf"
19+
20+
BOOK_LIST = [BOOK1, BOOK2, BOOK3, BOOK4, BOOK5, BOOK6]
21+
22+
23+
# to divide docs in chunks
24+
CHUNK_SIZE = 1000
25+
CHUNK_OVERLAP = 50
26+
27+
28+
#
29+
# Vector Store (Chrome or FAISS)
30+
#
31+
# VECTOR_STORE_NAME = "FAISS"
32+
# VECTOR_STORE_NAME = "ORACLEDB"
33+
VECTOR_STORE_NAME = "CHROME"
34+
35+
36+
# type of Embedding Model. The choice has been parametrized
37+
# Local means HF
38+
EMBED_TYPE = "LOCAL"
39+
# see: https://huggingface.co/spaces/mteb/leaderboard
40+
# see also: https://github.com/FlagOpen/FlagEmbedding
41+
# base seems to work better than small
42+
# EMBED_HF_MODEL_NAME = "BAAI/bge-base-en-v1.5"
43+
# EMBED_HF_MODEL_NAME = "BAAI/bge-small-en-v1.5"
44+
EMBED_HF_MODEL_NAME = "BAAI/bge-large-en-v1.5"
45+
46+
# Cohere means the embed model from Cohere site API
47+
# EMBED_TYPE = "COHERE"
48+
EMBED_COHERE_MODEL_NAME = "embed-english-v3.0"
49+
50+
# number of docs to return from Retriever
51+
MAX_DOCS_RETRIEVED = 6
52+
53+
# to add Cohere reranker to the QA chain
54+
ADD_RERANKER = False
55+
56+
#
57+
# LLM Config
58+
#
59+
# LLM_TYPE = "COHERE"
60+
LLM_TYPE = "OCI"
61+
62+
# max tokens returned from LLM for single query
63+
MAX_TOKENS = 1000
64+
# to avoid "creativity"
65+
TEMPERATURE = 0
66+
67+
#
68+
# OCI GenAI configs
69+
#
70+
TIMEOUT = 30
71+
ENDPOINT = "https://inference.generativeai.us-chicago-1.oci.oraclecloud.com"
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
feedback_0
Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
#
2+
# This one is to be used in Notebooks
3+
#
4+
5+
# for pdf post processing
6+
import re
7+
8+
import cohere
9+
# modified to load from Pdf
10+
from langchain.document_loaders import PyPDFLoader
11+
from langchain.text_splitter import RecursiveCharacterTextSplitter
12+
13+
# two possible vector store
14+
from langchain.vectorstores import Chroma
15+
from langchain.vectorstores import FAISS
16+
17+
from langchain.schema.runnable import RunnablePassthrough
18+
19+
# removed OpenAI, using Cohere embeddings
20+
from langchain.embeddings import CohereEmbeddings
21+
from langchain.embeddings import HuggingFaceEmbeddings
22+
23+
from langchain import hub
24+
25+
import oci
26+
27+
from langchain.llms import Cohere
28+
from langchain_community.llms.oci_generative_ai import OCIGenAI
29+
from oci.generative_ai_inference import generative_ai_inference_client
30+
31+
# oci_llm is in a local file
32+
from oci_llm import OCIGenAILLM
33+
34+
# config for the RAG
35+
from config_rag import (
36+
BOOK_LIST,
37+
CHUNK_SIZE,
38+
CHUNK_OVERLAP,
39+
VECTOR_STORE_NAME,
40+
MAX_TOKENS,
41+
ENDPOINT,
42+
EMBED_TYPE,
43+
MAX_DOCS_RETRIEVED,
44+
TEMPERATURE,
45+
EMBED_HF_MODEL_NAME,
46+
TIMEOUT,
47+
LLM_TYPE,
48+
)
49+
50+
# private configs
51+
CONFIG_PROFILE = "DEFAULT"
52+
COMPARTMENT_OCID = "ocid1.compartment.oc1..aaaaaaaajdyhd7dqnix2avhlckbhhkkcl3cujzyuz6jzyzonadca3i66pqjq"
53+
oci_config = oci.config.from_file("~/.oci/config", CONFIG_PROFILE)
54+
COHERE_API_KEY = oci_config['security_token_file']
55+
DEBUG = True
56+
57+
58+
#
59+
# def load_oci_config()
60+
#
61+
def load_oci_config():
62+
# read OCI config to connect to OCI with API key
63+
oci_config = oci.config.from_file("~/.oci/config", CONFIG_PROFILE)
64+
65+
# check the config to access to api keys
66+
if DEBUG:
67+
print(oci_config)
68+
69+
return oci_config
70+
71+
72+
#
73+
# do some post processing on text
74+
#
75+
def post_process(splits):
76+
for split in splits:
77+
split.page_content = split.page_content.replace("\n", " ")
78+
split.page_content = re.sub("[^a-zA-Z0-9 \n\.]", " ", split.page_content)
79+
# remove duplicate blank
80+
split.page_content = " ".join(split.page_content.split())
81+
82+
return splits
83+
84+
85+
#
86+
# def: Initialize_rag_chain
87+
#
88+
def initialize_rag_chain():
89+
# Initialize RAG
90+
91+
# Loading a list of pdf documents
92+
all_pages = []
93+
94+
# modified to load a list of pdf
95+
for book in BOOK_LIST:
96+
print(f"Loading book: {book}...")
97+
loader = PyPDFLoader(book)
98+
99+
# loader split in pages
100+
pages = loader.load()
101+
print(f"Loaded {len(pages)} pages...")
102+
103+
all_pages.extend(pages)
104+
105+
print("PDF document loaded!")
106+
107+
# This split in chunks
108+
# try with smaller chuncks
109+
text_splitter = RecursiveCharacterTextSplitter(
110+
chunk_size=CHUNK_SIZE, chunk_overlap=CHUNK_OVERLAP
111+
)
112+
113+
splits = text_splitter.split_documents(all_pages)
114+
115+
print(f"We have splitted the pdf in {len(splits)} splits...")
116+
117+
# some post processing
118+
splits = post_process(splits)
119+
120+
print("Initializing vector store...")
121+
122+
if EMBED_TYPE == "COHERE":
123+
print("Loading Cohere Embeddings Model...")
124+
embed_model = CohereEmbeddings(cohere_api_key=COHERE_API_KEY)
125+
if EMBED_TYPE == "LOCAL":
126+
print(f"Loading HF Embeddings Model: {EMBED_HF_MODEL_NAME}")
127+
128+
model_kwargs = {"device": "cpu"}
129+
# changed to True for BAAI, to use cosine similarity
130+
encode_kwargs = {"normalize_embeddings": True}
131+
132+
embed_model = HuggingFaceEmbeddings(
133+
model_name=EMBED_HF_MODEL_NAME,
134+
model_kwargs=model_kwargs,
135+
encode_kwargs=encode_kwargs,
136+
)
137+
138+
# using Chroma as Vector store
139+
print(f"Indexing: using {VECTOR_STORE_NAME} as Vector Store...")
140+
141+
if VECTOR_STORE_NAME == "CHROME":
142+
vectorstore = Chroma.from_documents(documents=splits, embedding=embed_model)
143+
if VECTOR_STORE_NAME == "FAISS":
144+
vectorstore = FAISS.from_documents(documents=splits, embedding=embed_model)
145+
146+
# increased num. of docs to 5 (default to 4)
147+
retriever = vectorstore.as_retriever(search_kwargs={"k": MAX_DOCS_RETRIEVED})
148+
149+
# Build the class for OCI GenAI
150+
151+
# Only needed for OCI LLM
152+
print(f"Using {LLM_TYPE} llm...")
153+
154+
if LLM_TYPE == "OCI":
155+
156+
llm = OCIGenAI(
157+
service_endpoint="https://inference.generativeai.us-chicago-1.oci.oraclecloud.com",
158+
compartment_id="ocid1.compartment.oc1..aaaaaaaajdyhd7dqnix2avhlckbhhkkcl3cujzyuz6jzyzonadca3i66pqjq",
159+
model_kwargs={"max_tokens": 1000},
160+
auth_type='SECURITY_TOKEN',
161+
)
162+
if LLM_TYPE == "COHERE":
163+
llm = cohere.Client(COHERE_API_KEY)
164+
response = llm.generate(
165+
prompt="Please explain to me how LLMs work",
166+
)
167+
print(response)
168+
return llm
169+
170+
# for now hard coded...
171+
rag_prompt = hub.pull("rlm/rag-prompt")
172+
173+
print("Building rag_chain...")
174+
rag_chain = (
175+
{"context": retriever, "question": RunnablePassthrough()} | rag_prompt | llm
176+
)
177+
178+
print("Init RAG complete...")
179+
return rag_chain
180+
181+
182+
#
183+
# def: get_answer from LLM
184+
#
185+
def get_answer(rag_chain, question):
186+
response = rag_chain.invoke(question)
187+
188+
print(f"Question: {question}")
189+
print("The response:")
190+
print(response)
191+
print()
192+
193+
return response

0 commit comments

Comments
 (0)