Skip to content

Commit e65b810

Browse files
committed
add ai tutor updated code and resources, such as txt files
1 parent 855af78 commit e65b810

File tree

5 files changed

+71
-131
lines changed

5 files changed

+71
-131
lines changed

9_pinecone.py

+59-50
Original file line numberDiff line numberDiff line change
@@ -1,54 +1,48 @@
11
import os
2+
from pathlib import Path
23
import requests
34
from dotenv import load_dotenv
45
from bs4 import BeautifulSoup
6+
7+
import pinecone
58
from llama_index import (
69
SimpleDirectoryReader,
710
LLMPredictor,
811
ServiceContext,
912
GPTVectorStoreIndex,
1013
QuestionAnswerPrompt,
14+
download_loader
1115
)
12-
import pinecone
1316
from llama_index.vector_stores import PineconeVectorStore
1417
from llama_index.storage.storage_context import StorageContext
1518
from langchain.chat_models import ChatOpenAI
1619

1720
load_dotenv()
21+
# PineconeReader = download_loader("PineconeReader")
22+
# reader = PineconeReader(
23+
# api_key=os.getenv("PINECONE_API_KEY"),
24+
# environment="us-west4-gcp"
25+
# )
26+
# docs_from_pinecone = reader.load_data(index_name="nietzsche")
1827

1928
urls = [
2029
"https://www.projekt-gutenberg.org/nietzsch/wanderer/wanderer.html",
2130
"https://www.projekt-gutenberg.org/nietzsch/wanderer/wande002.html",
2231
"https://www.projekt-gutenberg.org/nietzsch/wanderer/wande003.html",
23-
"https://www.projekt-gutenberg.org/nietzsch/wanderer/wande004.html"
32+
"https://www.projekt-gutenberg.org/nietzsch/wanderer/wande004.html",
2433
]
2534

26-
def create_pages(urls):
27-
28-
pages = []
29-
for url in urls:
30-
pagename = url.split("/")[-1]
31-
pages.append(pagename)
32-
33-
return pages
34-
35-
3635
def scrape_book(urls):
37-
from pathlib import Path
38-
result = []
39-
40-
for url in urls:
4136

37+
for url in urls:
38+
result = []
4239
req = requests.get(url)
43-
soup = BeautifulSoup(
44-
req.text,
45-
"html.parser",
46-
)
40+
soup = BeautifulSoup(req.text, "html.parser")
4741

48-
# keep only the heading tags and <p> tags
42+
# keep only the heading tags up to h3, and p tags
4943
text = soup.find_all(["h1", "h2", "h3", "p"])
5044

51-
# remove the tags and keep only the text
45+
# remove the tags and keep the inner text
5246
text = [t.text for t in text]
5347

5448
for i in text:
@@ -65,9 +59,15 @@ def scrape_book(urls):
6559

6660
with open(book_path / f"{pagename}.txt", "w") as f:
6761
f.write("\n".join(result))
68-
69-
return result
7062

63+
def create_pages(urls):
64+
65+
pages = []
66+
for url in urls:
67+
pagename = url.split("/")[-1]
68+
pages.append(pagename)
69+
70+
return pages
7171

7272
def build_docs(pages):
7373
docs = {}
@@ -85,55 +85,64 @@ def build_context(model_name):
8585

8686
def build_index(pages, docs):
8787

88+
page_indices = {}
8889
pinecone.init(
8990
api_key=os.getenv("PINECONE_API_KEY"),
9091
environment="us-west4-gcp"
9192
)
92-
pinecone.create_index("nietzsche", dimension=1536, metric="cosine")
93+
94+
# create a Pinecone index if you don't have one
95+
# https://openai.com/blog/new-and-improved-embedding-model (12288 -> 1536 dimensions)
96+
# pinecone.create_index("nietzsche", dimension=1536, metric="cosine")
97+
9398
pinecone_index = pinecone.Index("nietzsche")
9499

100+
# pinecone_index.upsert("nietzsche_wandere", [1,2,3])
101+
# pinecone_index.describe_index_stats()
102+
# pinecone_index.delete_index()
103+
95104
service_context = build_context("gpt-3.5-turbo")
96105

97-
pages_indexes = {}
98106
for page in pages:
99-
metadata_filters = {"page": page}
107+
100108
vector_store = PineconeVectorStore(
101109
pinecone_index=pinecone_index,
102-
metadata_filters=metadata_filters
110+
metadata_filters={"page": page}
103111
)
104112
storage_context = StorageContext.from_defaults(vector_store=vector_store)
105-
pages_indexes[page] = GPTVectorStoreIndex.from_documents(
113+
page_indices[page] = GPTVectorStoreIndex.from_documents(
106114
docs[page], storage_context=storage_context, service_context=service_context
107115
)
108-
pages_indexes[page].index_struct.index_id = page
116+
page_indices[page].index_struct.index_id = page
109117

110118
print("Indexing complete.")
111-
return pages_indexes
112-
113-
def create_query_engine(chapter="wande002.html"):
114-
115-
PROMPT_TEMPLATE = (
116-
"Here are the context information:"
117-
" \n----------------------------------\n"
118-
"{context_str}"
119-
" \n----------------------------------\n"
120-
"Answer the following question in the original german text, then provide an english translation and explanation in as instructive and educational way as possible: {query_str}\n"
121-
)
122-
QA_PROMPT = QuestionAnswerPrompt(PROMPT_TEMPLATE)
123-
124-
query_engine = indices[chapter].as_query_engine(
125-
text_qa_template=QA_PROMPT
126-
)
127-
return query_engine
119+
return page_indices
128120

129121
if __name__ == "__main__":
122+
# uncomment this to download books from project guternberg
130123
# scrape_book(urls)
124+
# assuming books have already been downloaded into your local directory
131125
pages = create_pages(urls)
132-
docs = build_docs(pages) # print(docs.keys())
126+
docs = build_docs(pages)
127+
# print(docs.keys())
133128
indices = build_index(pages, docs)
134129

135-
query_engine = create_query_engine(chapter="wande002.html")
136-
response = query_engine.query("what are important things according to Nietzsche?")
130+
# response = indices["wande002.html"].as_query_engine().query(
131+
# "What are Nietzsche's view on religion? Answer in the original German text, and provide an English translation for the answer"
132+
# )
133+
134+
PROMPT_TEMPLATE = (
135+
"Here are the context information:"
136+
"\n-----------------------------\n"
137+
"{context_str}"
138+
"\n-----------------------------\n"
139+
"Answer the following question in the original German text, and provide an english translation and explanation in as instructive and educational way as possible: {query_str} \n"
140+
)
141+
142+
QA_PROMPT = QuestionAnswerPrompt(PROMPT_TEMPLATE)
143+
query_engine = indices["wande002.html"].as_query_engine(text_qa_template=QA_PROMPT)
144+
response = query_engine.query("What are important things according to Nietzsche?")
137145

138146
print(str(response))
139147
print(response.get_formatted_sources())
148+

README.md

+11-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# llm-python
2-
A set of instructional materials, code samples and Python scripts featuring LLMs (GPT etc) through interfaces like llamaindex, langchain, Chroma, Alpaca etc. Mainly used to store reference code for my LangChain tutorials on YouTube.
2+
A set of instructional materials, code samples and Python scripts featuring LLMs (GPT etc) through interfaces like llamaindex, langchain, Chroma (Chromadb), Pinecone etc. Mainly used to store reference code for my LangChain tutorials on YouTube.
33

44
<!-- <img src="assets/youtube.png" width="50%" alt="LangChain youtube tutorials" /> -->
55
![LangChain youtube tutorials](assets/llmseries.png)
@@ -12,14 +12,22 @@ Learn LangChain from my YouTube channel:
1212
- Part 5: [Query any website with LLamaIndex + GPT3 (ft. Chromadb, Trafilatura)](https://youtu.be/6K1lyyzpxtk)
1313
- Part 6: [Locally-hosted, offline LLM w/LlamaIndex + OPT (open source, instruction-tuning LLM)](https://youtu.be/qAvHs6UNb2k)
1414

15+
### Side Lessons (good supplements to the main series above)
16+
- [OpenAI tutorial and video walkthrough](https://youtu.be/skw-togjY7Q)
17+
1518
### Quick Start
1619
1. Clone this repo
1720
2. Install requirements: `pip install -r requirements.txt`
1821
3. Some sample data are provided to you in the `news` foldeer, but you can use your own data by replacing the content (or adding to it) with your own text files.
19-
4. Create a `.env` file which contains your OpenAI API key. You can get one from [here](https://beta.openai.com/). The `.env` file should look like this:
22+
4. Create a `.env` file which contains your OpenAI API key. You can get one from [here](https://beta.openai.com/). `HUGGINGFACEHUB_API_TOKEN` and `PINECONE_API_KEY` are optional, but they are used in some of the lessons.
23+
24+
The `.env` file should look like this:
2025
```
2126
OPENAI_API_KEY=your_api_key_here
27+
28+
# optionals (not required for most of the series)
2229
HUGGINGFACEHUB_API_TOKEN=your_api_token_here
30+
PINECONE_API_KEY=your_api_key_here
2331
```
24-
HuggingFace is optional but is recommended if you want to use the Inference API and explore those models outside of the OpenAI ecosystem. This is demonstrated in Part 3 of the tutorial series.
32+
HuggingFace and Pinecone are optional but is recommended if you want to use the Inference API and explore those models outside of the OpenAI ecosystem. This is demonstrated in Part 3 of the tutorial series.
2533
5. Run the examples in any order you want. For example, `python 6_team.py` will run the website Q&A example, which uses GPT-3 to answer questions about a company and the team of people working at Supertype.ai. Watch the corresponding video to follow along each of the examples.

book/wande002.html.txt

+1-22
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,5 @@
1-
Friedrich Wilhelm Nietzsche
2-
Der Wanderer und sein Schatten
3-
Der Schatten: Da ich dich so lange nicht reden hörte, so möchte ich dir eine Gelegenheit geben.
4-
Der Wanderer: Es redet: – wo? und wer? Fast ist es mir, als hörte ich mich selber reden, nur mit noch schwächerer Stimme als die meine ist.
5-
Der Schatten (nach einer Weile): Freut es dich nicht, Gelegenheit zum Reden zu haben?
6-
Der Wanderer: Bei Gott und allen Dingen, an die ich nicht glaube, mein Schatten redet; ich höre es, aber glaube es nicht.
7-
Der Schatten: Nehmen wir es hin und denken wir nicht weiter darüber nach, in einer Stunde ist alles vorbei.
8-
Der Wanderer: Ganz so dachte ich, als ich in einem Walde bei Pisa erst zwei und dann fünf Kamele sah.
9-
Der Schatten: Es ist gut, daß wir beide auf gleiche Weise nachsichtig gegen uns sind, wenn einmal unsere Vernunft stille steht: so werden wir uns auch im Gespräche nicht ärgerlich werden und nicht gleich dem andern Daumenschrauben anlegen, falls sein Wort uns einmal unverständlich klingt. Weiß man gerade nicht zu antworten, so genügt es schon, etwas zu sagen: das ist die billige Bedingung, unter der ich mich mit jemandem unterrede. Bei einem längeren Gespräche wird auch der Weiseste einmal zum Narren Und dreimal zum Tropf.
10-
Der Wanderer: Deine Genügsamkeit ist nicht schmeichelhaft für den, welchem du sie eingestehst.
11-
Der Schatten: Soll ich denn schmeicheln?
12-
Der Wanderer: Ich dachte, der menschliche Schatten sei seine Eitelkeit; diese aber würde nie fragen: "soll ich denn schmeicheln?"
13-
Der Schatten: Die menschliche Eitelkeit, soweit ich sie kenne, fragt auch nicht an, wie ich schon zweimal tat, ob sie reden dürfe: sie redet immer.
14-
Der Wanderer: Ich merke erst, wie unartig ich gegen dich bin, mein geliebter Schatten: ich habe noch mit keinem Worte gesagt, wie sehr ich mich freue, dich zu hören und nicht bloß zu sehen. Du wirst es wissen, ich liebe den Schatten, wie ich das Licht liebe. Damit es Schönheit des Gesichts, Deutlichkeit der Rede, Güte und Festigkeit des Charakters gebe, ist der Schatten so nötig wie das Licht. Es sind nicht Gegner: sie halten sich vielmehr liebevoll an den Händen, und wenn das Licht verschwindet, schlüpft ihm der Schatten nach.
15-
Der Schatten: Und ich hasse dasselbe, was du hassest, die Nacht; ich liebe die Menschen, weil sie Lichtjünger sind und freue mich des Leuchtens, das in ihrem Auge ist, wenn sie erkennen und entdecken, die unermüdlichen Erkenner und Entdecker. Jener Schatten, welchen alle Dinge zeigen, wenn der Sonnenschein der Erkenntnis auf sie fällt, – jener Schatten bin ich auch.
16-
Der Wanderer: Ich glaube dich zu verstehen, ob du dich gleich etwas schattenhaft ausgedrückt hast. Aber du hattest recht: gute Freunde geben einander hier und da ein dunkles Wort als Zeichen des Einverständnisses, welches für jeden dritten ein Rätsel sein soll. Und wir sind gute Freunde. Deshalb genug des Vorredens! Ein paar hundert Fragen drücken auf meine Seele, und die Zeit, da du auf sie antworten kannst, ist vielleicht nur kurz. Sehen wir zu, worüber wir in aller Eile und Friedfertigkeit miteinander zusammenkommen.
17-
Der Schatten: Aber die Schatten sind schüchterner als die Menschen: du wirst niemandem mitteilen, wie wir zusammen gesprochen haben!
18-
Der Wanderer: Wie wir zusammen gesprochen haben? Der Himmel behüte mich vor langgesponnenen, schriftlichen Gesprächen! Wenn Plato weniger Lust am Spinnen gehabt hätte, würden seine Leser mehr Lust an Plato haben. Ein Gespräch, das in der Wirklichkeit ergötzt, ist, in Schrift verwandelt und gelesen, ein Gemälde mit lauter falschen Perspektiven: Alles ist zu lang oder zu kurz. – Doch werde ich vielleicht mitteilen dürfen, worüber wir übereingekommen sind?
19-
Der Schatten: Damit bin ich zufrieden; denn alle werden darin nur deine Ansichten wiedererkennen: des Schattens wird niemand gedenken.
20-
Der Wanderer: Vielleicht irrst du, Freund! Bis jetzt hat man in meinen Ansichten mehr den Schatten wahrgenommen als mich.
21-
Der Schatten: Mehr den Schatten als das Licht? Ist es möglich?
22-
Der Wanderer: Sei ernsthaft, lieber Narr! Gleich meine erste Frage verlangt Ernst. –
231
Vom Baum der Erkenntnis. – Wahrscheinlichkeit, aber keine Wahrheit: Freischeinlichkeit, aber keine Freiheit, – diese beiden Früchte sind es, derentwegen der Baum der Erkenntnis nicht mit dem Baum des Lebens verwechselt werden kann.
242
Die Vernunft der Welt. – Daß die Welt nicht der Inbegriff einer ewigen Vernünftigkeit ist, läßt sich endgültig dadurch beweisen, daß jenes Stück Welt, welches wir kennen – ich meine unsre menschliche Vernunft –, nicht allzu vernünftig ist. Und wenn sie nicht allezeit und vollständig weise und rationell ist, so wird es die übrige Welt auch nicht sein; hier gilt der Schluß a minori ad majus, a parte ad totum, und zwar mit entscheidender Kraft.
253
"Am Anfang war." – Die Entstehung verherrlichen – das ist der metaphysische Nachtrieb, welcher bei der Betrachtung der Historie wieder ausschlägt und durchaus meinen macht, am Anfang aller Dinge stehe das Wertvollste und Wesentlichste.
264
Maß für den Wert der Wahrheit. – Für die Höhe der Berge ist die Mühsal ihrer Besteigung durchaus kein Maßstab. Und in der Wissenschaft soll es anders sein! – sagen uns einige, die für eingeweiht gelten wollen –, die Mühsal um die Wahrheit soll gerade über den Wert der Wahrheit entscheiden! Diese tolle Moral geht von dem Gedanken aus, daß die "Wahrheiten" eigentlich nichts weiter seien, als Turngerätschaften, an denen wir uns wacker müde zu arbeiten hätten, – eine Moral für Athleten und Festturner des Geistes.
5+
Sprachgebrauch und Wirklichkeit. – Es gibt eine erheuchelte Mißachtung aller der Dinge, welche tatsächlich die Menschen am wichtigsten nehmen, aller nächsten Dinge. Man sagt zum Beispiel "man ißt nur, um zu leben," – eine verfluchte Lüge, wie jene, welche von der Kindererzeugung als der eigentlichen Absicht aller Wollust redet. Umgekehrt ist die Hochschätzung der "wichtigsten Dinge" fast niemals ganz echt: die Priester und Metaphysiker haben uns zwar auf diesen Gebieten durchaus an einen heuchlerisch übertreibenden Sprachgebrauch gewöhnt, aber das Gefühl doch nicht umgestimmt, welches diese wichtigsten Dinge nicht so wichtig nimmt wie jene verachteten nächsten Dinge. – Eine leidige Folge dieser doppelten Heuchelei aber ist immerhin, daß man die nächsten Dinge, zum Beispiel Essen, Wohnen, Sich-Kleiden, Verkehren, nicht zum Objekt des stetigen unbefangenen und allgemeinen Nachdenkens und Umbildens macht, sondern, weil dies für herabwürdigend gilt, seinen intellektuellen und künstlerischen Ernst davon abwendet; so daß hier die Gewohnheit und die Frivolität über die Unbedachtsamen, namentlich über die unerfahrene Jugend, leichten Sieg haben: während andererseits unsere fortwährenden Verstöße gegen die einfachsten Gesetze des Körpers und Geistes uns alle, Jüngere und Ältere, in eine beschämende Abhängigkeit und Unfreiheit bringen, – ich meine in jene im Grunde überflüssige Abhängigkeit von Ärzten, Lehrern und Seelsorgern, deren Druck jetzt immer noch auf der ganzen Gesellschaft liegt.

0 commit comments

Comments
 (0)