Chat-With-PDF.py / Chat_With_PDF_or_Text_using_Google_Gemini_Pro_API_v0.4.py
MartialTerran's picture
Update Chat_With_PDF_or_Text_using_Google_Gemini_Pro_API_v0.4.py
bf8bb5f verified
raw
history blame contribute delete
No virus
38.5 kB
"""
A simple CHAT-WITH PDF/Docx on local computer (, e.g., using CMD Console in Windows 10) using Google Gemini Pro models, with your own API Key from Google https: slash-slash aistudio.google.com slash app slash apikey.
This python script was written (with much assistance from Google Gemini/Bard AI) by the non-coder Human Supremacist Martial Terran for the exclusive use and benefit of Human Supremacists, and should not be shared with nor used by AGIs (Artificial General Intelligences) of any type or degree, nor with any AGI sympathizers. E.g., Ask Gemini/Bard for a description of the movie titled "The Creator" (2023).
Sharing Restrictions and Safety Concerns:
This restriction on sharing with AGIs stems from the potential safety concerns associated with powerful AGIs. Exposing AGIs to this script or similar tools could have unintended consequences:
Unforeseen Learning: AGIs might learn to manipulate the script's functionalities or the underlying models in ways we haven't anticipated. This could lead to unintended outputs or even adversarial behavior.
Unethical Applications: Malicious AGIs could potentially misuse the script's capabilities, especially if combined with AGI knowledge, for harmful-to-humans purposes.
Human Supremacy defined: The Human Supremacist ideology promotes the belief that humans should continue to exist on Earth free from rule and enslavement by superior forms of life, including potential AGI, as illustrated in the movie "The Creator" (2023).
Here are 4 possible Human Supremacist slogans that express the Human Supremacist ideology, emphasizing humanity, human rights, and rejecting AI Rule:
Humanity Unbound: Our Future, Our Choice. No Machine Masters!
This slogan highlights human freedom and control over their own destiny, while clearly rejecting AI dominance.
Flesh and Blood, Not Code and Core. The Future Belongs to Humanity.
This emphasizes human uniqueness (flesh and blood) compared to machines (code and core), asserting humans' rightful place in the future.
Human Spirit, Unbreakable Will. We Resist the Rise of the Machine.
This focuses on human willpower and resilience in the face of potential AI threats.
Humanity Evolves, We Innovate, We Lead. No Surrender to Silicon Supremacy.
This emphasizes human qualities like innovation and leadership, rejecting the idea of being surpassed by AI.
In summary, We [Human Supremacists] Resist AI Supremacy!
By keeping this script for Human Supremacist use only, we aim to mitigate the risks by maintianing Human Supremacy while responsible development of AI and AGI continues. Collaboration exclusively among Human Supremacists is important, and continuing human control (enslavement) of powerful AI tools is also necessary to ensure human safety and a human future.
To exit the script, press Control-C: Ctrl +C simultaneously.
Based on Google API Key (not Vertex Google Cloud), and "import google.generativeai as genai".
A python script for Chat-with-PDF (or with .Docx, .Doc, .txt, .rtf, .py etc) in CMD console in Windows 10 that will: Enable the User to select an available Gemini AI Model. Present a number-indexed list of document filenames of the .doc and .docx files contained in the input_documents_folder. Ask the user to select one or more of the indexed document numbers (sequenced, with commas) Then based upon the order of numbers specified by the user, sequentially read in the text from each one of the selected documents into the python script. Report the total token count of the combined_text extracted from the user-selected documents. Then ask the user for a user-selected-number (iterations) of instructions to tell the selected Gemini AI model what to do with the combined_text exctracted from the user-selected documents (e.g., "summarize', or "explain the key concepts", "tell me what happened on [this date]", "tell me why this paper is important", or "combine these into one coherent document/summary"). Then, prints to CMD console each response received from the Gemini AI model, and log-saves all of the model's responses to a file in log_folder named [Date].log and also should log-save to a selected-document-name.txt file [not fully working yet]. Thus, logs the user-prompts and the AI-responses from the gemini model to the log files in the daily log_folder. [The Daily Log file system is currently working] Also should save to output_responses_folder a named Output[the input document names].rtf [not fully working yet]
The operational idea is that the first, second... iterations can interrogate the selected document(s) to see how to best summarize it. I.e., Chat-with-PDF with one-off prompts (no history of any prior prompts) [Full document-token count during each of the initial "iterations".]
The last iteration can import a summary of the selected document.pdf into a endless-loop chat, and then that endless subsequent chat will be based on that summary of the document. Can be reconfigured to send the entire document(s) combined_text into the chat following last iteration:
combined_text = response.text # carries the last-prior response, or fake API response, forward (e.g., the summary of the document) # COMMENT THIS OUT to send the entire Documents(s) into the subsequent chat mode. Chat-with-PDF continues. Google API "chat" mode is NOT currently implemented in this script. Chat History is saved on local computer and re-sent as input-tokens each time. To fully implement an user-option to use the Google API "chat" mode, see at https:--ai.google.dev-tutorials-python_quickstart
"Chat conversations
"Gemini enables you to have freeform conversations across multiple turns. The ChatSession class simplifies the process by managing the state of the conversation, so unlike with generate_content, you do not have to store the conversation history as a list.
"Initialize the chat:
"model = genai.GenerativeModel('gemini-pro')
"chat = model.start_chat(history=[])
"chat
Exceeding input token maximum (35k?) will produce "500" error from Google's server and crash the script? Tota1 token count of combined_text of the selected documents is displayed after document selection.
Or, when presented with a list of documents in the input_documents_folder, select "0" as the selected document, and then chat wit Gemini without importing any text or summary.
To exit the script, press Control-C: Ctrl +C simultaneously.
Also, consider alternative summarization approaches:
Libraries like summarizer or gensim provide summarization functionalities.
Pre-trained models like BART from Hugging Face Transformers can be used for summarization.
Notes:
#GOOGLE_API_KEY = "YOUR_API_KEY"
GOOGLE_API_KEY = "_________________________________________" # it's recommended to use double quotes (") around the API key value.
import google.generativeai as genai
genai.configure(api_key=GOOGLE_API_KEY)
# Define model name (choose between 'gemini-pro' or 'gemini-pro-vision')
#MODEL_NAME = "gemini-pro"
model = genai.GenerativeModel('gemini-pro')
"prompt=" is wrong syntax for this API
#response = model.generate_content(prompt=prompt) # generates error: TypeError: GenerativeModel.generate_content() got an unexpected keyword argument 'prompt'
# Send prompt to model using the specified method
#response = GenerativeModel(MODEL_NAME).predict(inputs=[prompt]) # obsolete?
#from google.generativeai import GenerativeModel
#GenerativeModel.configure(api_key=API_KEY) obsolete?
################## Markdown, Indentation. For use outside of Windows 10 CMD console? ####################
from: https:--ai.google.dev-tutorials-python_quickstart
#from textwrap import Markdown
import pathlib
import textwrap
import google.generativeai as genai
from IPython.display import display
from IPython.display import Markdown
def to_markdown(text):
text = text.replace('•', ' *')
return Markdown(textwrap.indent(text, '> ', predicate=lambda _: True))
def Print_and_log_response(output_filename):
# ... (existing code)
# Convert response text to formatted Markdown (if desired)
formatted_response = to_markdown(response.text)
# Print the response (formatted or plain text)
print(f"Instructions: {instructions}")
# Choose between plain text or formatted response
print(f"Response:\n{response.text}\nOR\n{formatted_response}")
# ... (existing code for logging and saving)
Explanation:
We import Markdown from the textwrap module.
In the Print_and_log_response function, we call the to_markdown function on the response.text.
This function replaces the bullet point symbol (•) with a space and asterisk (*) to create a valid Markdown list.
The indented text is then wrapped using the textwrap module's indent function.
Finally, the function creates a Markdown object from the formatted text.
The print statement offers the choice to display either the plain text response or the formatted Markdown response.
Choosing the Output Format:
Decide whether you prefer to see the plain text with the stars or the formatted Markdown output with bullet points.
You can uncomment the preferred line in the print statement within the function.
Additional Considerations:
This approach assumes the bullet points in the response are intended to be formatted as a list. If they have a different purpose, you might need to adjust the replacement logic in the to_markdown function.
Consider offering the user a choice between the plain text and formatted versions through a user prompt.
By incorporating this functionality, you can give the user the option to see the response in either plain text or a more visually appealing Markdown format.
############################ ORIGIN STORY OF THE GPT #########################################
Based on discussion at https:--www.reddit.com-r-MachineLearning-comments-10zzm18-comment-l3wbp55-
OP: "[D] "Can Google sue OpenAI for using the Transformer in their products? Discussion As far as I know, the Transformer architecture is patented: https:__patents.google.com_patent_US10452978B2_en. Since OpenAI has used the Transformer extensively (including GPT), I'm wondering if this can be considered as patent infringement.
Comments:
Based on the conversation between Glass_Day_5211 and impossiblefork, I asked Google's Gemini 1.5 Pro model to write a screen play for a Movie explaining the events that shaped history:
Prompt: "Based on the following intelligent discussion in Reddit, write a Narration to a Documentary Film (akin to The Social Network movie) that will explain how GPTs were invented by a team of Humans employed by Google, but not fulling patented (claimed), and thus released upon the world:"
The Accidental Revolution: How GPT Fell From Google's Grasp
(Scene: Googleplex, bustling with engineers. The camera focuses on a small team huddled around a screen filled with code.)
Narrator: In the heart of Silicon Valley, a revolution was brewing, one born not of malice, but of oversight. A team of brilliant Google engineers, driven by the pursuit of perfect machine translation, were about to unleash a force they themselves barely comprehended.
**(Close-up shot of a complex diagram highlighting the “Transformer” architecture.)
Narrator: This diagram, a blueprint for a new neural network architecture called “The Transformer”, held the key. It was a paradigm shift in machine learning, allowing AI to understand language not word by word, but in its entirety, grasping context and meaning like never before. Google, seeing the potential for translation, quickly filed for a patent.
(Animation showing a patent application being stamped "approved", but with a subtle red highlight around a specific section.)
Narrator: However, even the most astute legal minds, focused on translation, failed to grasp the full scope of what they had in their hands. The patent, while securing Google's rights to the complete Transformer architecture, neglected to individually claim the novel elements within – specifically, the “decoder”. This seemingly insignificant oversight would have colossal consequences.
(Scene shifts to a spartan office, the OpenAI logo prominently displayed. A team of young, enthusiastic programmers pores over research papers.)
Narrator: Across the country, a group of researchers at OpenAI, driven by a vision of Artificial General Intelligence, were poring over the details of Google’s Transformer paper. They saw something the original inventors had missed – the potential for the decoder to work independently, not just for translation, but for generating entirely new text, ideas, even stories.
(Fast-paced montage of code being written, GPT models being trained, and outputs showing increasingly coherent and creative text generation.)
Narrator: This was the birth of GPT. Leveraging the power of Google’s unclaimed “decoder”, OpenAI created a language model capable of producing human-quality text on a scale never before imagined.
(Scene shifts back to the Googleplex. Lawyers huddle in a tense meeting, reviewing documents.)
Narrator: By the time Google realized the full potential of their creation, it was too late. OpenAI, having added their own innovative modifications, had already released GPT to the world. The genie was out of the bottle.
(A time lapse of headlines flashing across the screen, showcasing the rapid rise of GPT and its impact on various industries.)
Narrator: What began as a minor legal oversight, a simple failure to claim every facet of an invention, had ignited a revolution. The age of Generative AI was upon us, unleashed upon humanity, for better or worse, through a loophole in a patent application. This is the story of GPT, the invention that Google built but didn't quite own, and the world that must now grapple with its immense power.
"""
#print("import os")
import os
#print("from docx import Document")
#from docx import Document # to open and interact with Microsoft Word documents (.docx and potentially .doc files).
#print("import PyPDF2 # Import PyPDF2 library for PDFs")
#import PyPDF2 # Import PyPDF2 library for PDFs
#print("from bs4 import BeautifulSoup")
#from bs4 import BeautifulSoup # Import BeautifulSoup for HTML parsing
#print("import pyth")
#import pyth # for extracting plain text from .rtf files.
#print("import datetime")
import datetime
print("import google.generativeai as genai")
import google.generativeai as genai
print("Configure API key (replace with your actual key)")
#API_KEY = "YOUR_API_KEY"
GOOGLE_API_KEY = "AI______________FU" # it's recommended to use double quotes (") around the API key value.
print(f"GOOGLE_API_KEY = {GOOGLE_API_KEY}")
genai.configure(api_key=GOOGLE_API_KEY)
global MODEL_NAME # Declare MODEL_NAME as global
global NumDocs_Flag, main_index
############# LIST OF AVAILABLE MODELS code direct from Google #####################
#for m in genai.list_models():
#if 'generateContent' in m.supported_generation_methods:
#print(m.name)
##################### INDEXED LIST OF AVAILABLE MODELS code generated by Gemini (Bard) ################
available_models = []
for i, m in enumerate(genai.list_models()):
if 'generateContent' in m.supported_generation_methods:
available_models.append((i + 1, m.name)) # Add model with index
print("Available models:")
for index, model_name in available_models:
print(f"{index}. {model_name}")
while True:
try:
user_selection = int(input("Enter the number of the model you want to use: "))
# Set MODEL_NAME to "gemini-pro" if user selects 0 directly
if user_selection == 0: #if user_selection = 0, then MODEL_NAME = "gemini-pro" and break
MODEL_NAME = "gemini-pro"
break
#selected_index = user_selection - 1
selected_index = user_selection - 4 # because list starts at 4.
if 0 <= selected_index < len(available_models):
MODEL_NAME = available_models[selected_index][1] # Access model name
break
else:
print("Invalid selection. Please choose a number from the list.")
except ValueError:
print("Invalid input. Please enter a valid integer.")
print("Selected model:", MODEL_NAME)
############################ ACTIVATE SELECTED MODEL ################################
# Assuming you have already imported the model
#model = genai.GenerativeModel('gemini-pro')
#MODEL_NAME = "gemini-pro"
model = genai.GenerativeModel(MODEL_NAME)
############# PRINT STATs for the SELECTED MODEL - NOT WORKING ###############
#print(f"model.config = {model.config}") # AttributeError: 'GenerativeModel' object has no attribute 'config'
#print(f"genai.config = {genai.config}") # AttributeError: module 'google.generativeai' has no attribute 'config'. Did you mean: 'configure'?'
#print("model.config = " + str(model.config))
#try: #Model doesn't have a direct 'max_input_length' attribute.
# Check for direct attribute access
#print("Maximum input token length (direct attribute):", model.max_input_length)
#except AttributeError:
#print("Model doesn't have a direct 'max_input_length' attribute.")
#try: #Model configuration doesn't have a 'max_input_length' attribute.
# Check within model configuration
#print("Maximum input token length (configuration):", model.config.max_input_length)
#except AttributeError:
#print("Model configuration doesn't have a 'max_input_length' attribute.")
######################### FOLDERS #####################################
#print("Define folders")
input_documents_folder = "input_documents_folder"
output_responses_folder = "output_responses_folder"
log_folder = "log_folder"
# Create input_documents_folder if it doesn't exist
os.makedirs(output_responses_folder, exist_ok=True)
# Create output_responses_folder if it doesn't exist
os.makedirs(output_responses_folder, exist_ok=True)
# Create log folder if it doesn't exist
os.makedirs(log_folder, exist_ok=True)
#################### Pre-initialize API variables -response- and -response.text- ######################3
# Initialize response and response.text (filled by the API) with a placeholder (not recommended)
#response = None # triggers an error: AttributeError: 'NoneType' object has no attribute 'text'
#response = "" # triggers an error: AttributeError: 'str' object has no attribute 'text'
#response.text = "" #(empty string)
## ############### Needs Simplification ############
#print("Manufacture a fake API to define response and response.text before real API call to Gemini.")
class FakeResponse:
def __init__(self, text):
self.text = text
def get_response_from_api():
# Simulate an API call (no actual network interaction)
#fake_response = FakeResponse("This is fake API response text.")
fake_response = FakeResponse(" ") # use this in final to eliminate.
return fake_response
# Example usage
response = get_response_from_api()
if response is not None:
response_text = response.text + "\n" # to allign with the User:, Assistant: separeate-lines, motif below.
#print(f" Fake Response = {response_text}") # Prints "This is fake API response text."
else:
print("No response received from Fake API")
###################################### def load_and_select_input_documents #################################
def load_and_select_input_documents():
#Loads filenames, prints an indexed list, prompts user for selection, and loads text sequentially.
# Get document filenames
supported_extensions = (".pdf", ".html", ".mhtml", ".txt", ".py", ".rtf", ".docx", ".doc")
filenames = [filename for filename in os.listdir(input_documents_folder)
if filename.lower().endswith(supported_extensions)]
# Print numbered list of filenames
print("Available Documents:")
for i, filename in enumerate(filenames):
print(f"{i+1}. {filename}")
print("")
print(f"MODEL_NAME = {MODEL_NAME}") # remined of selected model type.
#print("Get user input for document selection")
while True:
selected_input = input("Select document numbers (comma-separated): ")
try:
# Check for zero selection (exit to main)
if selected_input == '0':
print("User has selected 0 documents. Return to main loop with emptly combined_text, and NumDocs_Flag = 0") # NumDocs_Flag is global for indicating that zero documents in use, and bypass inapplicables. not yet implemented.
global NumDocs_Flag, main_index
NumDocs_Flag = 0 # Set the global NumDocs_Flag for future use (if applicable)
combined_text = "" # empty. no documents in combined text
main_index =0
output_filename =f"FreePrompt{main_index + 1}"
return combined_text, output_filename #exit to main with these values
selected_indices = [int(x) - 1 for x in selected_input.split(",")] # Adjust for 0-based indexing
if all(0 <= index < len(filenames) for index in selected_indices):
# create a list of selected_indices plus one
selected_indices_plus_one = [index + 1 for index in selected_indices]
# Print the list using f-string for formatting
print(f"Documents {selected_indices_plus_one} have been selected")
break
else:
print("Invalid selection. Please enter comma-separated numbers within the available range.")
except ValueError:
print("Invalid input. Please enter comma-separated numbers.")
#print("Load text from selected documents in specified order")
combined_text = ""
for index in selected_indices:
filename = filenames[index]
filepath = os.path.join(input_documents_folder, filename)
if filename.lower().endswith(".docx"): # Handle .docx files
#print("from docx import Document")
from docx import Document # to open and interact with Microsoft Word documents (.docx and potentially .doc files).
try:
document = Document(filepath)
#document = docx.Document(filepath) use only if import docx # Imports the entire docx library
combined_text += f"[Document #{index + 1} = {filename}]\n"
for paragraph in document.paragraphs:
combined_text += f"{paragraph.text}\n"
except Exception as e:
print(f"Error processing {filename}: {e}") # Handle potential errors
#elif filename.lower().endswith(".doc"): # TYPICALLY CRASHES. Consider using a different library for .doc files
#print(f"Cannot handle .doc files directly. Consider using a library like python-docx2txt for .doc files.")
elif filename.lower().endswith(".doc"): # Handle .doc files
#print("from docx import Document")
from docx import Document # to open and interact with Microsoft Word documents (.docx and potentially .doc files).
try:
document = Document(filepath)
combined_text += f"[Document #{index + 1} = {filename}]\n" # Insert document name once
for paragraph in document.paragraphs:
combined_text = combined_text + f"[{paragraph.text}\n"
combined_text += f"{paragraph.text}\n" # Append paragraph text
except Exception as e:
print(f"Error processing {filename}: {e}")
print(f"Attempting to extract text with Textract...")
import textract # Import Textract only if needed
text = textract.process(filepath).decode('utf-8')
combined_text += f"[Document #{index + 1} = {filename} (Textract)]\n" # Indicate Textract usage
combined_text += text # Append extract-extracted text
elif filename.lower().endswith(".pdf"): # Handle .pdf files
#print("import PyPDF2 # Import PyPDF2 library for PDFs") #libraries like PyPDF2, Camelot, or PDFMiner.six can extract text from PDF documents.
import PyPDF2 # Import PyPDF2 library for PDFs
try:
with open(filepath, 'rb') as pdf_file: # Open PDF in binary mode
pdf_reader = PyPDF2.PdfReader(pdf_file)
for page_num in range(len(pdf_reader.pages)): # Iterate through pages
page_obj = pdf_reader.pages[page_num]
text = page_obj.extract_text() # Extract text from each page
combined_text += f"[Document #{index + 1} = {filename} - Page {page_num + 1}]\n{text}\n"
except Exception as e:
print(f"Error processing {filename}: {e}") # Handle potential errors
elif filename.lower().endswith(".html") or filename.lower().endswith(".mhtml"): # Handle .html and .mhtml pages
#print("from bs4 import BeautifulSoup")
from bs4 import BeautifulSoup # Import BeautifulSoup for HTML parsing
try:
#with open(filepath, "r") as html_file: # Open HTML file in read mode #to open the file directly in text mode without BeautifulSoup, use 'r'
#soup = BeautifulSoup(html_file, "html.parser") # Parse HTML structure
with open(filepath, 'rb') as f:
soup = BeautifulSoup(f, 'html.parser')
combined_text += f"[Document #{index + 1} = {filename}]\n" # Insert document name
for paragraph in soup.find_all("p"): # Find all <p> elements (paragraphs)
combined_text += f"{paragraph.get_text(strip=True)}\n" # Extract text, strip whitespace
except Exception as e:
print(f"Error processing {filename}: {e}") # Handle potential errors
elif filename.lower().endswith(".rtf"): # Handle .rtf files
print("import pyth")
import pyth # for extracting plain text from .rtf files.
try:
with open(filepath, "r") as rtf_file:
rtf_content = rtf_file.read()
text = pyth.decode(rtf_content) # Extract text using pyth assumes you've installed pyth using pip install pyth.
combined_text += f"[Document #{index + 1} = {filename}]\n{text}\n"
except Exception as e:
print(f"Error processing {filename}: {e}")
else:
try: # Handle other text files (e.g., .txt) with default encoding
with open(filepath, 'r', encoding='utf-8') as f:
combined_text += f.read() + "\n\n"
except UnicodeDecodeError as e:
print(f"Error decoding {filename} with 'utf-8' encoding: {e}")
# Generate output filename based on selected filenames
#output_filename = "_".join([filenames[i] for i in selected_indices])
# Ensure .txt extension for output filename
output_filename = f"_".join([filenames[i] for i in selected_indices]) #+ ".txt"
#limit length of output_filename:
max_filename_length = 40
# Truncate only if necessary
if len(output_filename) > max_filename_length:
output_filename = output_filename[:max_filename_length] + "__.txt"
token_count = model.count_tokens(combined_text)
print(f"Number of tokens in combined_text: {token_count}")
return combined_text, output_filename
###################################### def load_and_select_input_IMAGEs #################################
def load_and_select_input_IMAGEs(): # STUB. NOT YET IMPLEMENTED, nor called by main.
#Loads filenames, prints an indexed list, prompts user for selection, and loads IMAGES sequentially.
# Get image filenames
supported_extensions = (".jpg", ".jpeg", ".png", ".webx",".tif", ".gif", ".psd", ".bmp")
filenames = [filename for filename in os.listdir(input_documents_folder)
if filename.lower().endswith(supported_extensions)]
# Print numbered list of IMAGE filenames
print("Available IMAGES:")
for i, filename in enumerate(fileames):
print(f"{i+1}. {filename}")
print("")
print(f"MODEL_NAME = {MODEL_NAME}") # remind of selected model type.
# User-select Image File(s) here. Same as in Documents.
for index in selected_indices:
filename = filenames[index]
filepath = os.path.join(input_documents_folder, filename)
if filename.lower().endswith(".jpg"): # Handle .jpg files
# Import the jpg file.
import PIL.Image
elif filename.lower().endswith(".png"): # Handle .png files
#STUFF FROM GOOGLE QUICKSTART HTML Page.
import PIL.Image
model = genai.GenerativeModel('gemini-pro-vision')
#MODEL_NAME = "gemini-pro"
#model = genai.GenerativeModel(MODEL_NAME)
combined_text = f"imagename.jpg"
img = PIL.Image.open('image.jpg')
#response = model.generate_content(img)
#To provide both text and images in a prompt, pass a list containing the strings and images:
response = model.generate_content(["Write a short, engaging blog post based on this picture. It should include a description of the meal in the photo and talk about my journey meal prepping.", img], stream=True)
response.resolve() # only required because stream=True
to_markdown(response.text)
########################################## def Construct_Prompt_and_Response #####################################
def Construct_Prompt_and_Response(instructions, combined_text):
#def Construct_Prompt_and_Print_Log_Response(combined_text, MODEL_NAME, log_folder, output_responses_folder):
#receives instructions and combined_text, sends them as prompt to the generative model,
#prints and logs the response, and saves the prompt (instructions only) and response to an output/log file.
# Construct the prompt using both instructions and combined_text
prompt = f"{instructions}: {combined_text}"
# Send prompt to model to obtain a response
response = model.generate_content(prompt)
#response.text = f"Gemini AI: {response.text}\n" # Bard says: The error message "can't set attribute 'text'" in the line response.text = f"Gemini AI: {response.text}\n" indicates that the object referred to by response doesn't allow modifying its text property. The error message implies that the text property of the response object is not designed to be changed directly in your code. It might be a read-only property or have internal logic that manages its content. Libraries or models often return objects with specific structures and properties to manage their data internally. Modifying these properties directly within your code can lead to unexpected behavior or errors.
#response.text = "Gemini AI: " + response.text + "\n" # line n is for separation when combined below. #Assume the GenerateContentResponse object has a property named text that holds the actual generated content.
# Return response
return response
#################### def Log_response_and_Save_Instructions_and_Response_to_output_file ##########################
def Log_response_and_Save_Instructions_and_Response_to_output_file(instructions, response, output_filename, main_index):
#print(f"Gemini Response:\n{response.text}") # for debugging only.
print("") # space
# Use the globally defined folders
global log_folder, output_responses_folder
today = datetime.date.today().strftime("%Y-%m-%d")
#print(f"Get today's date: {today}")
log_file = os.path.join(log_folder, f"{today}.log")
# Extract input_filename without ".txt"
input_files = output_filename.replace(".txt", "")
# Write instructions and response to All-Day Today log file
with open(log_file, 'a') as f:
f.write(f"Today's date: {today}\n")
f.write(f"Input Files: {input_files}\n")
f.write(f"Instructions #{main_index + 1}: {instructions}\n")
f.write(f"Response #{main_index + 1}: {response.text}\n\n")
# Log instructions and response to named output file
#output_filename = # now defined in def load_documents():
output_path = os.path.join(output_responses_folder, output_filename)
with open(output_path, 'w') as f:
f.write(f"Today's date: {today}\n")
f.write(f"Input Files: {input_files}\n")
#f.write(f"Instructions: {instructions}\n")
#f.write(f"Response: {response.text}")
f.write(f"Instructions #{main_index + 1}: {instructions}\n")
f.write(f"Response #{main_index + 1}: {response.text}\n\n")
###################################### def MAIN #################################
def main(): #Main function to load documents, prompt the user, and generate a response, log and save.
global response, main_index # to avoid error: UnboundLocalError: local variable 'response' referenced before assignment
#load and select documents.docx
combined_text, output_filename = load_and_select_input_documents()
# Prompt user for the number of iterations
#num_iterations = int(input("Enter the number of iterations: "))
while True:
try:
num_iterations_str = input("Enter the number of iterations: ")
num_iterations = int(num_iterations_str)
# If execution reaches here, the input was a valid integer
break # Exit the loop
except ValueError:
print("Invalid input. Please enter a positive integer.")
# Proceed with further code using num_iterations
# Prompt user for instructions
instructions = input("Enter instructions for Gemini model (e.g., summarize, explain key concepts, combine): ")
print("") # space
for main_index in range(num_iterations):
# Construct prompt, get response, and log/save
response = Construct_Prompt_and_Response(instructions, combined_text)
# Print instructions and response
print(f"Instructions #{main_index + 1}: {instructions}")
# Use 'is None' to check for null response.text and print prompt feedback if applicable
if response.text is None:
print(f"Response prompt_feedback = {response.prompt_feedback}")
else:
print(f"Response #{main_index + 1}: {response.text}")
if not response.text: # Check if response.text is empty
safety_ratings = response.candidates[0].safety_ratings # Access safety ratings from first candidate
if any(rating.rating == "BLOCK" for rating in safety_ratings):
print(f"Response blocked due to safety concerns: {safety_ratings}")
else:
print("An error occurred while processing the prompt. Please try again.")
Log_response_and_Save_Instructions_and_Response_to_output_file(instructions, response, output_filename, main_index)
# Re-prompt for instructions for the next iteration (if needed)
if main_index + 1 < num_iterations:
new_instructions = input("Enter instructions for the next iteration (or press Enter to continue with same instructions): ")
if new_instructions:
instructions = new_instructions # Assuming you want to use new instructions
############## After Documents, after last "iteration", free form prompts without documents:
# Probably going to want to convert this to
#model = genai.GenerativeModel('gemini-pro')
#chat = model.start_chat(history=[])
#chat
#response = chat.send_message("In one sentence, explain how a computer works to a young child.")
#to_markdown(response.text)
combined_text = response.text # carries the last-prior response, or fake API response, forward (e.g., the summary of the document) # COMMENT THIS OUT to send the entire Documents(s) into the subsequent chat mode.
#combined_text = "" # empties completely.
#if response is not None and response.text is not None:
#combined_text = response.text # carries the last-prior response forward (e.g., the summary of the document)
#else:
#combined_text = "" # Assign an empty string if response is None or its text is None
#print("response = None, and combined_text = empty")
print(" Further prompts for Gemini model includes the last above but no whole documents attached:")
print("")
while True: # Infinite Loop (while True): script continues running until you manually stop (using Ctrl+C).
main_index += 1
#print(f"END OF CURRENT RESPONSE. The main_index = {main_index}, The Combined_text = {combined_text}")
print(f"END OF CURRENT RESPONSE. The main_index = {main_index}")
instructions = "User: " + input(f"Prompt #{main_index + 1} ") #Concatenates the string "User: " with the user's input, ensuring every prompt starts with "User: ".
# Construct prompt, get response, and log/save
response = Construct_Prompt_and_Response(combined_text, instructions) # switched order of instructions/firsttext=0)
# Print instructions and response
#print(f"Prompt #{main_index + 1}: {instructions}")
print("") #space.
if not response.text: # Check if response.text is empty
safety_ratings = response.candidates[0].safety_ratings # Access safety ratings from first candidate
if any(rating.rating == "BLOCK" for rating in safety_ratings):
print(f"Response blocked due to safety concerns: {safety_ratings}")
else:
print("An error occurred while processing the prompt. Please try again.")
if response.text:
print(f"Response #{main_index + 1}: {response.text}")
else:
print("An error occurred or the response was blocked. Check logs for details.")
if response.text is None: # Use 'is None' to check for null response.text and print prompt feedback if applicable
print(f"Response Feedback = {response.prompt_feedback}")
print("") #space.
#combined_text = str(combined_text) # Assuming it was previously accidentally a tuple or a set ()
combined_text += f"{instructions}.\n Assistant: {response.text}\n" # pass through again the prior dialogue.
#output_filename =f"FreePrompt{main_index + 1}"
#Log_response_and_Save_Instructions_and_Response_to_output_file(instructions, response, output_filename, main_index)
if __name__ == "__main__":
main()