0% found this document useful (0 votes)
10 views

Case Study

Uploaded by

ASR PANDEY
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
10 views

Case Study

Uploaded by

ASR PANDEY
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 25

1.

Using Multiple LLMs (Chains)


Deep Explanation:
Using multiple Large Language Models (LLMs) in a chained fashion allows for complex
processing of inputs. Each LLM can handle different tasks—such as generating text, summarizing,
or providing contextual responses—leading to improved output quality. By linking these models,
you can create sophisticated workflows where the output of one model serves as the input for
another. This approach is useful in applications like conversational agents, where maintaining
context and quality is crucial.
Programs:
Program 1: Basic LLM Chain
python

from transformers import pipeline

# Load two different LLMs (Language Models) for text generation using the GPT-2 model
llm1 = pipeline("text-generation", model="gpt2") # First model for initial text generation
llm2 = pipeline("text-generation", model="gpt2") # Second model for further text generation

# Define the initial input text which serves as a prompt


input_text = "Hello, how are you?"

# Generate a response from the first LLM


output1 = llm1(input_text, max_length=50, truncation=True) # Generate text with a maximum
length of 50 tokens

# Extract the generated text from the first output


generated_text_1 = output1[0]['generated_text'] # Access the generated text from the output

# Print the output from the first model to see the generated response
print("Output from LLM1:", generated_text_1)

# Ensure the generated text is not empty or just whitespace


if generated_text_1.strip(): # Check if there's meaningful content in the generated text
# Pass the output of the first LLM to the second LLM for further generation
output2 = llm2(generated_text_1, max_length=50, max_new_tokens=50, truncation=True)
# Generate additional text based on the output from LLM1
# Print the final output from the second LLM
print("Output from LLM2:", output2[0]['generated_text']) # Display the result from the second
model
else:
# If the first output is empty, notify the user
print("No meaningful output from LLM1 to pass to LLM2.")

Program 2: Sequential LLM Responses


from transformers import pipeline

llm1 = pipeline("text-generation", model="gpt2")


llm2 = pipeline("text-generation", model="gpt2")

def chain_llms(input_text):
# Generate a response using the first LLM
response1 = llm1(input_text, max_new_tokens=50)[0]['generated_text']
print("Response from llm1:", response1) # Debugging print

# Use the output of the first LLM as input for the second LLM
response2 = llm2(response1, max_new_tokens=50)[0]['generated_text']
print("Response from llm2:", response2) # Debugging print

return response2

# Test the chaining function with a sample input


print(chain_llms("What is AI?"))

Program 3: Conditional Chains


from transformers import pipeline

llm1=pipeline("text-generation",model="gpt2")
llm2=pipeline("text-generation",model="gpt2")
def conditional_chain(input_text):
# Check if the input is a question
if "?" in input_text:
# Generate a response using the first LLM
return llm1(input_text, max_length=50)[0]['generated_text']
# If not a question, use the second LLM
return llm2(input_text, max_length=50)[0]['generated_text']

# Test the conditional chain with different inputs


print(conditional_chain("What is LLM?"))
print(conditional_chain("Explain LLM."))

Program 4: Contextual Input for Multiple LLMs


from transformers import pipeline

llm1=pipeline("text-generation", model="gpt2")
llm2=pipeline("text-generation", model="gpt2")
# Define initial context for the conversation
context = "AI is a field of study."

def context_chain(input_text):
# Combine context with user input for more informed responses
full_input = f"{context} {input_text}"
# Generate a response using the first LLM
return llm1(full_input, max_length=50)[0]['generated_text']

# Test the context-aware function


print(context_chain("What are its applications?"))

Program 5: Feedback Loop


from transformers import pipeline

# Load two different LLMs (Language Models) for text generation using the GPT-2 model
llm1 = pipeline("text-generation", model="gpt2") # First model for initial text generation
llm2 = pipeline("text-generation", model="gpt2") # Second model for further text generation

def feedback_loop(input_text, iterations=3):


"""
This function generates responses in a feedback loop using two LLMs.
Parameters:
input_text (str): The initial input text to start the conversation.
iterations (int): The number of iterations to loop through for generating responses.
Returns:
str: The final output after iterating through the LLMs.
"""
# Loop through a specified number of iterations
for _ in range(iterations):
# Generate a response from the first LLM
response1 = llm1(input_text, max_length=50, truncation=True) # Enable truncation
# Ensure the generated output is valid and not empty
if response1 and isinstance(response1, list) and len(response1) > 0:
generated_text_1 = response1[0]['generated_text'] # Access the generated text from the output
print("LLM1 Response:", generated_text_1) # Print the response from LLM1
# Use the output from the first LLM as input for the second LLM
response2 = llm2(generated_text_1, max_length=50, truncation=True) # Enable truncation
# Ensure the generated output from LLM2 is valid
if response2 and isinstance(response2, list) and len(response2) > 0:
input_text = response2[0]['generated_text'] # Access the generated text from LLM2
print("LLM2 Response:", input_text) # Print the response from LLM2
else:
print("Final Output:", feedback_loop("Tell me about quantum computing."))

2. Working with Data Loaders - Ingesting Documents


Deep Explanation:
Data loaders are essential for handling the ingestion of documents into your application. They help
automate the process of reading, parsing, and possibly preprocessing documents from various
formats or directories. Efficient data loading is crucial for tasks such as training models or
performing data analysis. You can extend data loaders to include metadata extraction, error
handling, and batch processing for scalability.
Programs:
Program 1: Simple Document Loader

# Load a single text document and print its content


with open('apikey', 'r') as file:
text = file.read()

# Print the content of the loaded document


print(text)

Program 2: Batch Document Loader


import os

def load_documents(directory):
# Initialize an empty list to store document contents
texts = []
# Iterate through all files in the specified directory
for filename in os.listdir(directory):
# Open and read each file, appending its content to the list
with open(os.path.join(directory, filename), 'r') as file:
texts.append(file.read())
return texts

# Load all documents from the specified directory


documents = load_documents('directory')
# Print the loaded documents
print(documents)

Program 3: Document Loader with Metadata


python

import os
def load_documents_with_metadata(directory):
# Initialize a list to hold documents with metadata
documents = []
# Loop through all files in the directory
for filename in os.listdir(directory):
with open(os.path.join(directory, filename), 'r') as file:
text = file.read()
# Append a dictionary with filename and content to the list
documents.append({'filename': filename, 'content': text})
return documents

# Load documents with metadata


docs_with_meta = load_documents_with_metadata('directory/')
# Print the documents along with their metadata
print(docs_with_meta)

Program 4: Load and Preprocess Documents


python

from nltk.corpus import stopwords


import nltk
import os

# Download the stopwords list


nltk.download('stopwords')

def preprocess(text):
# Remove stopwords from the text
stop_words = set(stopwords.words('english'))
return ' '.join([word for word in text.split() if word.lower() not in stop_words])

def load_and_preprocess(directory):
# Load and preprocess all documents in the specified directory
return [preprocess(open(os.path.join(directory, file)).read()) for file in os.listdir(directory)]

# Load and preprocess documents


processed_docs = load_and_preprocess('directory/')
# Print the preprocessed documents
print(processed_docs)

Program 5: Document Loader with Error Handling


import os

def load_documents_safe(directory):
# Initialize an empty list for documents
texts = []
# Loop through all files in the directory
for filename in os.listdir(directory):
try:
with open(os.path.join(directory, filename), 'r') as file:
# Attempt to read the file and add its content to the list
texts.append(file.read())
except Exception as e:
# Print an error message if file loading fails
print(f"Error loading {filename}: {e}")
return texts
# Load documents safely, handling potential errors
safe_docs = load_documents_safe('directory/')
# Print the safely loaded documents
print(safe_docs)

3. Working with Text Splitters - Chunking Data


Deep Explanation:
Text splitting or chunking is the process of dividing text into manageable pieces, which can be
particularly useful for natural language processing tasks. Chunking helps maintain context and
relevance while ensuring that models can handle the data efficiently. Techniques include splitting by
sentences, words, or even more complex criteria such as semantic meaning or sentiment. Proper
chunking can enhance the quality of information retrieval and processing.
Programs:
Program 1: Simple Text Splitter
python

import nltk
import nltk
from nltk import punkt
# Download the punkt tokenizer

nltk.download('punkt')
nltk.download('punkt_tab')

def split_text(text):
# Use nltk to split the text into sentences
return nltk.sent_tokenize(text)

# Sample text to split


text = "Hello world. This is a test."
# Get the chunks
chunks = split_text(text)
# Print the resulting sentence chunks
print(chunks)

Program 2: Split by Word Count

def chunk_by_word_count(text, word_count):


# Split the text into words
words = text.split()
# Create chunks based on the specified word count
return [' '.join(words[i:i + word_count]) for i in range(0, len(words), word_count)]

# Sample text to chunk


text = "This is a long text that needs to be chunked into smaller pieces."
# Chunk the text by word count
chunks = chunk_by_word_count(text, 5)
# Print the resulting word chunks
print(chunks)

Program 3: Split with Overlap

def chunk_with_overlap(text, chunk_size, overlap):


# Split the text into words
words = text.split()
chunks = []
# Create overlapping chunks
for i in range(0, len(words) - chunk_size + 1, chunk_size - overlap):
chunks.append(' '.join(words[i:i + chunk_size]))
return chunks

# Sample text for overlapping chunking


text = "This is an example of chunking with overlap."
# Chunk the text with specified size and overlap
chunks = chunk_with_overlap(text, 5, 2)
# Print the resulting overlapping chunks
print(chunks)

Program 4: Chunking Based on Sentiment


import nltk
from textblob import TextBlob

def chunk_by_sentiment(text):
# Split the text into sentences
sentences = nltk.sent_tokenize(text)
chunks = []
current_chunk = []

# Iterate over sentences and create chunks based on sentiment


for sentence in sentences:
if TextBlob(sentence).sentiment.polarity > 0:
current_chunk.append(sentence)
else:
if current_chunk:
chunks.append(' '.join(current_chunk))
current_chunk = []
# Append any remaining positive sentences
if current_chunk:
chunks.append(' '.join(current_chunk))

return chunks
# Sample text for sentiment-based chunking
text = "I love programming. It's fun! I hate bugs."
# Create sentiment-based chunks
chunks = chunk_by_sentiment(text)
# Print the resulting sentiment chunks
print(chunks)

Program 5: Dynamic Chunking with LLM Evaluation


python

def mock_model(chunk):
# This is a simple mock model for demonstration
# It returns a score based on the length of the chunk
score = 1.0 if len(chunk.split()) >= 3 else 0.0 # Example logic
return {'score': score}

def dynamic_chunk(text, model):


words = text.split()
chunk_size = 5
chunks = []

# Dynamically adjust chunk size based on model evaluation


while words:
chunk = ' '.join(words[:chunk_size])
response = model(chunk)

# Adjust chunk size based on model response


if response['score'] < 0.5: # Example threshold
chunk_size -= 1 # Decrease chunk size
else:
chunks.append(chunk)
words = words[chunk_size:] # Move to the next part
chunk_size += 1 # Increase chunk size

return chunks

# Using the mock model


text = "This is some sample text for dynamic chunking."
chunks = dynamic_chunk(text, mock_model)
print(chunks)

4. Working with Chains (Conversational Retrieval)


Deep Explanation:
Conversational retrieval systems are designed to maintain context over multiple turns of dialogue.
They can use various strategies to retrieve relevant information, whether from a database or through
language generation models. By chaining responses based on user input and previous context, these
systems can provide more coherent and contextually aware interactions, making them suitable for
applications like chatbots and virtual assistants.
Programs:
Program 1: Basic Retrieval Chain
python

def retrieval_chain(user_input):
# Predefined responses for simple retrieval
responses = {
"hi": "Hello!",
"how are you?": "I'm fine, thank you!",
}
# Return response based on user input, or a default message
return responses.get(user_input.lower(), "I don't understand.")

# Test the retrieval chain with sample input


print(retrieval_chain("Hi"))

Program 2: Using Embeddings for Retrieval

from sentence_transformers import SentenceTransformer, util

# Load a pre-trained sentence transformer model


model = SentenceTransformer('all-MiniLM-L6-v2')

# Define a corpus of responses


corpus = ["Hello!", "How are you?", "What is AI?"]
# Encode the corpus into embeddings
corpus_embeddings = model.encode(corpus, convert_to_tensor=True)

def retrieve(user_input):
# Encode user input into an embedding
input_embedding = model.encode(user_input, convert_to_tensor=True)
# Calculate cosine similarity between input and corpus
cos_sim = util.pytorch_cos_sim(input_embedding, corpus_embeddings)
# Find the index of the best match
best_match = cos_sim.argmax()
return corpus[best_match]

# Test the retrieval function with a user input


print(retrieve("What is the status of your health"))
Program 5: Multi-turn Conversational Retrieval
python

# Placeholder for the retrieval_chain function


def retrieval_chain(user_input):
# Simple response logic; replace this with your actual implementation
return f"Response to: {user_input}"

# Initialize an empty history list to maintain conversation turns


history = []

def multi_turn_conversation(user_input):
# Add each user input to the history
history.append(user_input)
# Generate responses for all turns in the conversation history
responses = [retrieval_chain(u) for u in history]
return responses[-1] # Return the latest response

# Test the multi-turn conversation function


print(multi_turn_conversation("Hi"))
print(multi_turn_conversation("What is AI?"))
print(multi_turn_conversation("Tell me more about AI."))

5. Hugging Face Model Library


Deep Explanation:
Hugging Face provides a robust ecosystem for leveraging pre-trained language models for various
tasks, such as text generation, classification, and more. The Model Hub offers a wide range of
models that can be easily integrated into applications. Users can fine-tune these models on custom
datasets to improve performance on specific tasks. The library also facilitates model sharing,
making it easier for the community to collaborate and improve NLP capabilities.
Programs:
Program 1: Load a Pre-trained Model
python

from transformers import AutoModel, AutoTokenizer

# Specify the model name from Hugging Face Model Hub


model_name = "distilbert-base-uncased"

# Load the pre-trained model and tokenizer


model = AutoModel.from_pretrained(model_name)
tokenizer = AutoTokenizer.from_pretrained(model_name)

# Print confirmation of loading


print("Model and tokenizer loaded successfully.")
Program 2: Simple Text Classification
python

from transformers import pipeline

# Initialize a sentiment-analysis pipeline


classifier = pipeline("sentiment-analysis")

# Test the classifier with a sample text


result = classifier("I hate you")
# Print the sentiment analysis result
print(result)

Program 3: Fine-tuning a Model


python

from transformers import Trainer, TrainingArguments,


AutoModelForSequenceClassification

# Load a model for sequence classification


model = AutoModelForSequenceClassification.from_pretrained("distilbert-base-
uncased", num_labels=2)

# Define training arguments for fine-tuning


training_args = TrainingArguments(
output_dir='./results',
num_train_epochs=3, # Number of training epochs
per_device_train_batch_size=16, # Batch size for training
evaluation_strategy='epoch' # Evaluate after each epoch
)

# Initialize the Trainer with the model and training arguments


trainer = Trainer(model=model, args=training_args, train_dataset=train_dataset,
eval_dataset=eval_dataset)

# Start the training process


trainer.train()
print("Training complete.")

Program 4: Model Inference with Batch Processing


python

# Sample texts for classification


texts = ["I love programming!", "I hate bugs."]

# Run inference on multiple inputs at once using the classifier


results = classifier(texts)

# Print the results of the batch classification


print(results)

Program 5: Create a Custom Hugging Face Model


python

from transformers import DistilBertModel, DistilBertTokenizerFast


# Define a custom model class extending DistilBertModel
class MyCustomModel(DistilBertModel):
# You can add any additional layers or modify the forward method as needed

def forward(self, input_ids, attention_mask=None, **kwargs):


outputs = super().forward(input_ids, attention_mask=attention_mask, **kwargs)
# Add any custom processing here
return outputs

# Load a tokenizer for the model


tokenizer = DistilBertTokenizerFast.from_pretrained("distilbert-base-uncased")

# Instantiate the custom model


model = MyCustomModel.from_pretrained("distilbert-base-uncased")

# Save the model and tokenizer for future use


model.save_pretrained('./custom_model')
tokenizer.save_pretrained('./custom_model')
print("Custom model and tokenizer saved.")

Feel free to reach out if you need further modifications or additional information!

You said:
everthing is great now but you haven't provided the best explanation of the topic in the explanation
add their internal working their architectures and some real life examples
ChatGPT said:

Sure! Let's enhance the explanations with more details about the internal workings, architectures,
and real-life examples for each topic.

1. Using Multiple LLMs (Chains)


Deep Explanation:
Using multiple Large Language Models (LLMs) in a chained approach leverages the strengths of
different models to create a more robust system.
Internal Working and Architecture:
• Chaining Mechanism: The output of one LLM can be used as the input for another. This
can be achieved using frameworks that support pipelines or modular architectures.
• Model Types: Different types of models can be used in the chain. For example, one model
might be specialized in text generation (like GPT-3), while another might excel in
understanding context (like BERT).
Real-Life Examples:
• Chatbots: In customer support, a chatbot might use one model to understand user intent and
another to generate responses, allowing it to handle complex queries efficiently.
• Content Creation: A content generation system might use an LLM to draft text and another
to check grammar and style.
2. Working with Data Loaders - Ingesting Documents
Deep Explanation:
Data loaders are vital for managing the ingestion of documents into applications. They automate the
reading and preprocessing of various document formats, making them essential for data-driven
tasks.
Internal Working and Architecture:
• Batch Processing: Data loaders often read files in batches, which optimizes memory usage
and speeds up processing.
• File Handling: They may include functionalities for different file formats
(e.g., .txt, .csv, .pdf) and may implement error handling for corrupted files.
Real-Life Examples:
• Machine Learning Pipelines: In machine learning, data loaders are used to feed training
data into models. For instance, in a natural language processing (NLP) task, a data loader
might handle large datasets of text documents, providing them in a format suitable for model
training.
• Search Engines: Document ingestion processes for search engines use data loaders to
continuously update their indexes with new content.

3. Working with Text Splitters - Chunking Data


Deep Explanation:
Text chunking involves dividing text into smaller, manageable pieces. This is crucial in NLP for
maintaining context while ensuring models can process data effectively.
Internal Working and Architecture:
• Tokenization: Text is often tokenized into sentences or words, which helps in breaking
down the text while preserving semantic meaning.
• Overlap Handling: Techniques may be used to create overlapping chunks, ensuring that
context isn’t lost at the boundaries.
Real-Life Examples:
• Document Summarization: In summarization applications, chunking allows models to
process large documents piece by piece, leading to coherent summaries.
• Chatbots: For conversational systems, chunking user input ensures that context is preserved
across multiple turns of dialogue, allowing for more natural interactions.

4. Working with Chains (Conversational Retrieval)


Deep Explanation:
Conversational retrieval systems use models to maintain context over multiple interactions,
allowing them to provide coherent responses based on previous exchanges.
Internal Working and Architecture:
• Context Management: These systems often maintain a history of previous interactions,
which helps the model understand user intent and generate relevant responses.
• Re-ranking Mechanisms: Responses may be re-ranked based on their relevance to the
entire conversation, using techniques such as cosine similarity.
Real-Life Examples:
• Virtual Assistants: Applications like Siri or Google Assistant use conversational retrieval
systems to provide users with information based on their queries and context.
• Customer Support: Companies use chatbots that remember user queries across sessions,
providing a personalized experience.

5. Hugging Face Model Library


Deep Explanation:
Hugging Face offers a comprehensive library for leveraging pre-trained language models,
facilitating various NLP tasks with ease.
Internal Working and Architecture:
• Transformers Architecture: Most models in Hugging Face are based on the transformer
architecture, which uses self-attention mechanisms to process input data in parallel rather
than sequentially. This results in better context understanding and faster training times.
• Pre-trained Models: Models are pre-trained on large corpora and fine-tuned on specific
tasks, allowing for high performance with minimal data.
Real-Life Examples:
• Sentiment Analysis: Businesses use Hugging Face models for sentiment analysis on social
media data to gauge public opinion about products.
• Text Generation: Content creators use models like GPT-3 from Hugging Face to generate
creative writing, articles, or even poetry.
By understanding the internal workings, architectures, and real-life applications of these concepts,
you can better appreciate their significance and capabilities. If you need further details on any
specific aspect, feel free to ask!

You said:
now you have provided only explanation ,so first thing do the changes as i say in this add more
explanation in main topic heading then come to internal working and architecture and real life
examples with 5 programs whose difficulty level increases
ChatGPT said:

Sure! Let's enhance the structure with more detailed explanations under each main topic heading,
followed by internal workings, architectures, real-life examples, and the corresponding programs.

1. Using Multiple LLMs (Chains)


Deep Explanation:
Chaining multiple Large Language Models (LLMs) involves connecting different models to
perform a series of tasks sequentially. This approach enables the combination of various
capabilities, such as understanding context, generating coherent responses, and retrieving
information. By effectively utilizing the strengths of different LLMs, applications can handle
complex queries, maintain dialogue history, and provide high-quality responses tailored to user
needs.
Internal Working and Architecture:
• Pipelines: Chained models often use a pipeline architecture where the output of one model
serves as the input for the next. This can involve preprocessing steps, such as tokenization or
normalization.
• Modular Design: Each model in the chain can be fine-tuned for specific tasks, allowing for
flexibility and customization. For instance, one model might specialize in natural language
understanding while another excels at text generation.
Real-Life Examples:
• Customer Support Systems: Chatbots can utilize one model to interpret user queries and
another to generate appropriate responses, ensuring effective interaction.
• Content Generation Tools: Applications that help writers can use multiple models for idea
generation, grammar checking, and style suggestions.
Programs:
Program 1: Basic LLM Chain
python

from transformers import pipeline

# Load two different LLMs for generation


llm1 = pipeline("text-generation", model="gpt2")
llm2 = pipeline("text-generation", model="gpt2")

# Define the initial input text


input_text = "Hello, how are you?"

# Generate a response from the first LLM


output1 = llm1(input_text, max_length=50)

# Pass the output of the first LLM to the second LLM for further generation
output2 = llm2(output1[0]['generated_text'])

# Print the final output from the second LLM


print(output2)

Program 2: Sequential LLM Responses


python

def chain_llms(input_text):
# Generate a response using the first LLM
response1 = llm1(input_text, max_length=50)[0]['generated_text']

# Use the output of the first LLM as input for the second LLM
response2 = llm2(response1, max_length=50)[0]['generated_text']

return response2

# Test the chaining function with a sample input


print(chain_llms("What is AI?"))
Program 3: Conditional Chains
python

def conditional_chain(input_text):
# Check if the input is a question
if "?" in input_text:
# Generate a response using the first LLM
return llm1(input_text, max_length=50)[0]['generated_text']

# If not a question, use the second LLM


return llm2(input_text, max_length=50)[0]['generated_text']

# Test the conditional chain with different inputs


print(conditional_chain("What is LLM?"))
print(conditional_chain("Explain LLM."))

Program 4: Contextual Input for Multiple LLMs


python

# Define initial context for the conversation


context = "AI is a field of study."

def context_chain(input_text):
# Combine context with user input for more informed responses
full_input = f"{context} {input_text}"

# Generate a response using the first LLM


return llm1(full_input, max_length=50)[0]['generated_text']

# Test the context-aware function


print(context_chain("What are its applications?"))

Program 5: Feedback Loop


python

def feedback_loop(input_text, iterations=3):


# Loop through a specified number of iterations
for _ in range(iterations):
# Generate a response from the first LLM
input_text = llm1(input_text, max_length=50)[0]['generated_text']

# Use the output from the first LLM as input for the second LLM
input_text = llm2(input_text, max_length=50)[0]['generated_text']

return input_text

# Test the feedback loop with a sample query


print(feedback_loop("Tell me about quantum computing."))

2. Working with Data Loaders - Ingesting Documents


Deep Explanation:
Data loaders are crucial for efficiently ingesting and managing documents in various formats. They
automate the reading, parsing, and preprocessing of data, making them integral to data-driven tasks
in machine learning and NLP. A well-designed data loader can significantly improve workflow by
ensuring that data is correctly formatted and ready for analysis or model training.
Internal Working and Architecture:
• Batch Processing: Data loaders often read files in batches, which helps optimize memory
usage and speeds up data processing.
• Error Handling: Robust data loaders include error handling mechanisms to manage issues
like missing or corrupted files.
Real-Life Examples:
• Machine Learning Pipelines: In machine learning, data loaders are used to feed training
data into models, such as loading large datasets of text documents for NLP tasks.
• Web Crawlers: Document ingestion processes for search engines continuously update their
indexes with new content using data loaders.
Programs:
Program 1: Simple Document Loader
python

# Load a single text document and print its content


with open('document.txt', 'r') as file:
text = file.read()

# Print the content of the loaded document


print(text)

Program 2: Batch Document Loader


python

import os

def load_documents(directory):
# Initialize an empty list to store document contents
texts = []

# Iterate through all files in the specified directory


for filename in os.listdir(directory):
# Open and read each file, appending its content to the list
with open(os.path.join(directory, filename), 'r') as file:
texts.append(file.read())

return texts

# Load all documents from the specified directory


documents = load_documents('documents/')
# Print the loaded documents
print(documents)

Program 3: Document Loader with Metadata


python

def load_documents_with_metadata(directory):
# Initialize a list to hold documents with metadata
documents = []
# Loop through all files in the directory
for filename in os.listdir(directory):
with open(os.path.join(directory, filename), 'r') as file:
text = file.read()
# Append a dictionary with filename and content to the list
documents.append({'filename': filename, 'content': text})

return documents

# Load documents with metadata


docs_with_meta = load_documents_with_metadata('documents/')
# Print the documents along with their metadata
print(docs_with_meta)

Program 4: Load and Preprocess Documents


python

from nltk.corpus import stopwords


import nltk

# Download the stopwords list


nltk.download('stopwords')

def preprocess(text):
# Remove stopwords from the text
stop_words = set(stopwords.words('english'))
return ' '.join([word for word in text.split() if word.lower() not in
stop_words])

def load_and_preprocess(directory):
# Load and preprocess all documents in the specified directory
return [preprocess(open(os.path.join(directory, file)).read()) for file in
os.listdir(directory)]

# Load and preprocess documents


processed_docs = load_and_preprocess('documents/')
# Print the preprocessed documents
print(processed_docs)

Program 5: Document Loader with Error Handling


python

def load_documents_safe(directory):
# Initialize an empty list for documents
texts = []

# Loop through all files in the directory


for filename in os.listdir(directory):
try:
with open(os.path.join(directory, filename), 'r') as file:
# Attempt to read the file and add its content to the list
texts.append(file.read())
except Exception as e:
# Print an error message if file loading fails
print(f"Error loading {filename}: {e}")

return texts

# Load documents safely, handling potential errors


safe_docs = load_documents_safe('documents/')
# Print the safely loaded documents
print(safe_docs)

3. Working with Text Splitters - Chunking Data


Deep Explanation:
Text chunking is the process of dividing text into smaller, manageable pieces, which is essential for
effective processing in natural language applications. Chunking allows models to maintain context
while ensuring they can process data efficiently. By segmenting text into chunks, applications can
better handle large volumes of data and improve the quality of information retrieval and processing.
Internal Working and Architecture:
• Tokenization: Text is tokenized into sentences or words, preserving semantic meaning
while facilitating easier processing.
• Overlap Handling: Some chunking strategies involve creating overlapping segments,
ensuring context isn’t lost at the boundaries.
Real-Life Examples:
• Document Summarization: In summarization applications, chunking enables models to
process large documents piece by piece, leading to coherent summaries.
• Chatbots: For conversational systems, chunking user input helps preserve context across
multiple turns of dialogue, resulting in more natural interactions.
Programs:
Program 1: Simple Text Splitter
python

import nltk

# Download the punkt tokenizer


nltk.download('punkt')

def split_text(text):
# Use nltk to split the text into sentences
return nltk.sent_tokenize(text)

# Sample text to split


text = "Hello world. This is a test."
# Get the chunks
chunks = split_text(text)
# Print the chunks
print(chunks)

Program 2: Chunking by Sentence Length


python

def chunk_by_length(text, max_length=50):


sentences = text.split('. ')
chunks = []
current_chunk = []
for sentence in sentences:
# If adding the sentence exceeds the max length, store the current chunk
if len(' '.join(current_chunk)) + len(sentence) <= max_length:
current_chunk.append(sentence)
else:
chunks.append(' '.join(current_chunk))
current_chunk = [sentence] # Start a new chunk

# Append any remaining sentences as the last chunk


if current_chunk:
chunks.append(' '.join(current_chunk))

return chunks

# Sample text for chunking


text = "This is a long sentence. It will be split into smaller chunks based on
length."
# Create chunks
chunks = chunk_by_length(text, max_length=100)
# Print the resulting chunks
print(chunks)

Program 3: Overlapping Chunking


python

def overlapping_chunks(text, chunk_size=5, overlap=2):


words = text.split()
chunks = []

# Create overlapping chunks


for i in range(0, len(words), chunk_size - overlap):
chunk = words[i:i + chunk_size]
if chunk:
chunks.append(' '.join(chunk))

return chunks

# Sample text for overlapping chunking


text = "This is a sample text for testing overlapping chunking of text."
# Create overlapping chunks
chunks = overlapping_chunks(text, chunk_size=10, overlap=3)
# Print the resulting chunks
print(chunks)

Program 4: Chunking with Metadata


python

def chunk_with_metadata(text, max_length=50):


sentences = text.split('. ')
chunks = []
current_chunk = []

for i, sentence in enumerate(sentences):


if len(' '.join(current_chunk)) + len(sentence) <= max_length:
current_chunk.append(sentence)
else:
chunks.append({'chunk': ' '.join(current_chunk), 'index':
len(chunks)})
current_chunk = [sentence]

if current_chunk:
chunks.append({'chunk': ' '.join(current_chunk), 'index': len(chunks)})

return chunks

# Sample text for chunking with metadata


text = "This is the first sentence. Here is another one. And yet another."
# Create chunks with metadata
chunks = chunk_with_metadata(text)
# Print the resulting chunks with metadata
print(chunks)

Program 5: Sentiment-Based Chunking


python

from textblob import TextBlob

def chunk_by_sentiment(text):
sentences = text.split('. ')
chunks = []
current_chunk = []

for sentence in sentences:


# Analyze sentiment using TextBlob
if TextBlob(sentence).sentiment.polarity > 0:
current_chunk.append(sentence)
else:
if current_chunk:
chunks.append(' '.join(current_chunk))
current_chunk = []

if current_chunk:
chunks.append(' '.join(current_chunk))

return chunks

# Sample text for sentiment-based chunking


text = "I love programming. It's fun! I hate bugs."
# Create sentiment-based chunks
chunks = chunk_by_sentiment(text)
# Print the resulting sentiment chunks
print(chunks)

4. Working with Chains (Conversational Retrieval)


Deep Explanation:
Conversational retrieval systems maintain context over multiple interactions, allowing for coherent
and contextually relevant responses. These systems can dynamically adapt based on user inputs and
previous exchanges, enabling richer and more engaging dialogues. By employing a combination of
retrieval techniques and response generation, these systems enhance user experience in various
applications.
Internal Working and Architecture:
• Context Management: Systems maintain a history of user interactions, which helps in
understanding ongoing dialogue and generating relevant responses.
• Re-ranking Mechanisms: Responses may be evaluated and re-ranked based on their
relevance to the conversation, using techniques like cosine similarity.
Real-Life Examples:
• Virtual Assistants: Applications like Alexa and Google Assistant use conversational
retrieval systems to deliver responses based on user queries and context.
• Customer Support Chatbots: These bots remember previous queries, providing
personalized responses that improve user satisfaction.
Programs:
Program 1: Basic Retrieval Chain
python

def retrieval_chain(user_input):
# Predefined responses for simple retrieval
responses = {
"hi": "Hello!",
"how are you?": "I'm fine, thank you!",
}
# Return response based on user input, or a default message
return responses.get(user_input.lower(), "I don't understand.")

# Test the retrieval chain with sample input


print(retrieval_chain("Hi"))

Program 2: Using Embeddings for Retrieval


python

from sentence_transformers import SentenceTransformer, util

# Load a pre-trained sentence transformer model


model = SentenceTransformer('all-MiniLM-L6-v2')

# Define a corpus of responses


corpus = ["Hello!", "How are you?", "What is AI?"]
# Encode the corpus into embeddings
corpus_embeddings = model.encode(corpus, convert_to_tensor=True)

def retrieve(user_input):
# Encode user input into an embedding
input_embedding = model.encode(user_input, convert_to_tensor=True)
# Calculate cosine similarity between input and corpus
cos_sim = util.pytorch_cos_sim(input_embedding, corpus_embeddings)
# Find the index of the best match
best_match = cos_sim.argmax()
return corpus[best_match]

# Test the retrieval function with a user input


print(retrieve("What is artificial intelligence?"))

Program 3: Contextual Conversational Retrieval


python

# Initialize an empty list to maintain conversation history


context = []
def contextual_retrieve(user_input):
# Add user input to context history
context.append(user_input)
# Get response based on the latest input
response = retrieval_chain(user_input)
return response

# Test the contextual retrieval function


print(contextual_retrieve("Hi"))
print(contextual_retrieve("What is AI?"))

Program 4: Advanced Retrieval with Re-ranking


python

def rerank_responses(user_input):
# List of possible responses
responses = ["AI is the simulation of human intelligence.", "AI is cool.",
"AI stands for artificial intelligence."]
# Calculate similarity scores for each response
scores = [util.pytorch_cos_sim(model.encode(user_input),
model.encode(r)).item() for r in responses]
# Re-rank responses based on their similarity scores
ranked_responses = [x for _, x in sorted(zip(scores, responses),
reverse=True)]
return ranked_responses

# Test the re-ranking function


print(rerank_responses("What is AI?"))

Program 5: Multi-turn Conversational Retrieval


python

# Initialize an empty history list to maintain conversation turns


history = []

def multi_turn_conversation(user_input):
# Add each user input to the history
history.append(user_input)
# Generate responses for all turns in the conversation history
responses = [retrieval_chain(u) for u in history]
return responses[-1] # Return the latest response

# Test the multi-turn conversation function


print(multi_turn_conversation("Hi"))
print(multi_turn_conversation("What is AI?"))
print(multi_turn_conversation("Tell me more about AI."))

5. Hugging Face Model Library


Deep Explanation:
Hugging Face provides a powerful ecosystem for leveraging pre-trained language models for
various tasks in NLP, such as text generation, classification, and more. The Model Hub offers an
extensive range of models that can be seamlessly integrated into applications. Users can fine-tune
these models on specific datasets, allowing for enhanced performance tailored to unique tasks. The
library also fosters community collaboration by enabling users to share and access models easily.
Internal Working and Architecture:
• Transformers Architecture: Most models in Hugging Face are based on the transformer
architecture, which employs self-attention mechanisms to process input data in parallel. This
design results in improved understanding of context and faster training times.
• Pre-trained Models: Models are pre-trained on vast corpora and can be fine-tuned for
specific tasks, allowing high performance with minimal additional data.
Real-Life Examples:
• Sentiment Analysis: Businesses utilize Hugging Face models to perform sentiment analysis
on social media data, helping gauge public opinion about products.
• Text Generation: Content creators employ models like GPT-3 to generate creative writing,
articles, or poetry, significantly speeding up the writing process.
Programs:
Program 1: Load a Pre-trained Model
python

from transformers import AutoModel, AutoTokenizer

# Specify the model name from Hugging Face Model Hub


model_name = "distilbert-base-uncased"

# Load the pre-trained model and tokenizer


model = AutoModel.from_pretrained(model_name)
tokenizer = AutoTokenizer.from_pretrained(model_name)

# Print confirmation of loading


print("Model and tokenizer loaded successfully.")

Program 2: Simple Text Classification


python

from transformers import pipeline

# Initialize a sentiment-analysis pipeline


classifier = pipeline("sentiment-analysis")

# Test the classifier with a sample text


result = classifier("I love using Hugging Face models!")
# Print the sentiment analysis result
print(result)

Program 3: Fine-tuning a Model


python

from transformers import Trainer, TrainingArguments,


AutoModelForSequenceClassification

# Load a model for sequence classification


model = AutoModelForSequenceClassification.from_pretrained("distilbert-base-
uncased", num_labels=2)

# Define training arguments for fine-tuning


training_args = TrainingArguments(
output_dir='./results',
evaluation_strategy="epoch",
learning_rate=2e-5,
per_device_train_batch_size=16,
num_train_epochs=3,
)

# Initialize a Trainer with the model and training arguments


trainer = Trainer(
model=model,
args=training_args,
train_dataset=train_dataset, # Assume this dataset is defined elsewhere
eval_dataset=eval_dataset # Assume this dataset is defined elsewhere
)

# Start the fine-tuning process


trainer.train()

Program 4: Text Generation with a Pre-trained Model


python

# Load a text generation pipeline


text_generator = pipeline("text-generation", model="gpt2")

# Generate text based on a given prompt


generated_text = text_generator("Once upon a time", max_length=50)
# Print the generated text
print(generated_text)

Program 5: Custom Dataset with Hugging Face Datasets


python

from datasets import load_dataset

# Load a custom dataset from Hugging Face


dataset = load_dataset("ag_news")

# Print the dataset structure


print(dataset)

# Use the dataset for training or evaluation in a model


# This is a placeholder for where you would integrate the dataset with a model

Object 1

You might also like