From 42dff15d63e58e1e673295475ca8cf83af125e00 Mon Sep 17 00:00:00 2001 From: andre-scheinwald <130578303+andre-scheinwald@users.noreply.github.com> Date: Tue, 18 Feb 2025 15:55:30 -0700 Subject: [PATCH 1/2] prompt_engineering_dump .csv file is one of the iterations of the prompt engineering code I Was attempting. Will probably have to double check this one. Some of it looked good. Don't remember if there was an issue or I wanted to add more. .py file is the file that contains the prompt engineering code. Line 242 and below is what I was working on more recently. --- ...il_landfill_name_and_coords_extraction.csv | 49 +++ brazil_landfill_name_and_coords_extraction.py | 381 ++++++++++++++++++ 2 files changed, 430 insertions(+) create mode 100644 brazil_landfill_name_and_coords_extraction.csv create mode 100644 brazil_landfill_name_and_coords_extraction.py diff --git a/brazil_landfill_name_and_coords_extraction.csv b/brazil_landfill_name_and_coords_extraction.csv new file mode 100644 index 0000000..7a025b0 --- /dev/null +++ b/brazil_landfill_name_and_coords_extraction.csv @@ -0,0 +1,49 @@ +landfill_name,gas_capture,gas_flare,gas_to_energy_project,project_title,filename,location.region,location.city,location.country,coordinates.latitude,coordinates.longitude +Dois Arcos Landfill,True,True,True,Dois Arcos Landfill Gas Project Activity,10257_PDD.pdf,Rio de Janeiro State,São Pedro da Aldeia,Brazil,-22.82601389,-42.05100556 +Oeste de Caucaia Landfill,True,True,True,Oeste de Caucaia Landfill Project Activity,10261_PDD.pdf,Ceará,Caucaia,Brazil,-3.78847222,-38.67357222 +CGR Piaçaguera,True,True,False,Terrestre Ambiental Landfill Gás Project,1133_PDD.pdf,São Paulo,Santos,Brazil,-23.885835,-46.312335 +ESTRE Pedreira Landfill,True,True,True,1134 ESTRE Pedreira Landfill Gás Project (EPLGP),1134_PDD.pdf,São Paulo,Iracemápolis,Brazil,-23.114376,-47.551041 +Bragança landfill,True,True,True,Embralixo/Araúna – Bragança Landfill Gas Project,1179_PDD.pdf,São Paulo,Bragança Paulista,Brazil,-23.2475,-45.8675 +URBAM landfill,True,True,False,URBAM/ARAUNA – Landfill Gas Project (UALGP),1247_PDD.pdf,São Paulo,São José dos Campos,Brazil,-23.2475,-45.8675 +MARCA Landfill,True,True,True,Brazil MARCA Landfill Gas to Energy Project,137_PDD.pdf,Espirito Santo State,Cariacica,Brazil,-20.3161,-40.2933 +Alto-Tietê landfill,True,True,True,Alto-Tietê landfill gas capture project,1636_PDD.pdf,São Paulo State,Itaquaquecetuba,Brazil,-23.433333,-46.291667 +Caieiras Landfill,True,True,False,Caieiras landfill gas emission reduction,171_PDD.pdf,São Paulo State,Caieiras,Brazil,-23.4319509,-46.5422455 +SANTEC Resíduos landfill,True,True,False,SANTEC Resíduos landfill gas emission reduction Project Activity,1908_PDD.pdf,Santa Catarina,Içara,Brazil,-28.78983333,-49.32866667 +Anaconda Ambiental Sanitary Landfill,True,True,False,Anaconda Landfill Gas Project,226_PDD.pdf,São Paulo,Santa Isabel,Brazil,-23.193809,-47.058886 +Onyx Landfill Gas Recovery Project,True,True,False,"Onyx Landfill Gas Recovery Project – Trémembé, Brazil",27_PDD.pdf,São Paulo,Tremembé,Brazil,-22.82601389,-45.56333333 +CTR Candeias Landfill Gas Project,True,True,True,CTR Candeias Landfill Gas Project,3958_PDD.pdf,Pernambuco,Jaboatão dos Guararapes,Brazil,-8.164258,-34.985286 +Itaoca Landfill,True,True,False,Itaoca Landfill Gas Project,4657_PDD.pdf,Rio de Janeiro,São Gonçalo,Brazil,-22.775,-43.373 +CTL Landfill,True,True,True,CTL Landfill Gas Project,5947_PDD.pdf,São Paulo State,São Paulo,Brazil,-23.5505,-46.6333 +CGR Guatapará landfill,True,True,True,CGR Guatapara Landfill Project,6553_PDD.pdf,São Paulo State,Guatapará,Brazil,-21.395833,-47.955 +Uberlândia landfill I and II,True,True,True,Uberlândia Landfills I and II Gas to Energy Project,7110_PDD.pdf,State of Minas Gerais,Uberlândia,Brazil,-18.878361,-48.318583 +Ventura Landfill,True,True,True,Projeto de Gás de Aterro TECIPAR – PROGAT,7799_PDD.pdf,São Paulo,Santana de Parnaíba,Brazil,-23.416711,-46.959638 +UTGR – Jambeiro,True,True,False,ENGEP & BEGREEN CDM Project at UTGR – Jambeiro Landfill,8011_PDD.pdf,São Paulo State,Jambeiro,Brazil,-23.273889,-45.752222 +CGR Catanduva Landfill Gas Project,True,True,True,CGR Catanduva Landfill Gas Project,8205_PDD.pdf,São Paulo,Catanduva,Brazil,-21.123247,-48.928236 +CGR Piratininga,True,True,True,ESTRE Piratininga Landfill Gas Project,8213_PDD.pdf,São Paulo,Piratininga,Brazil,-22.371667,-49.170278 +Onda Verde Landfill,True,True,True,Constroeste Landfill Gas to Energy Project,8603_PDD.pdf,São Paulo,Onda Verde,Brazil,-20.617240503129633,-49.33414936065674 +Aurá Landfill,True,True,False,Aurá Landfill Gas Project,888_PDD.pdf,State of Pará,Belém,Brazil,-1.45556,-48.49 +Canabrava Landfill,True,True,False,Canabrava Landfill Gas Project,893_PDD.pdf,Bahia,Salvador,Brazil,-12.9711,-38.5108 +Gramacho Landfill,True,True,True,Gramacho Landfill Gas Project,9087_PDD.pdf,Rio de Janeiro,Duque de Caxias,Brazil,-22.746111,-43.260278 +Estre Itapevi Landfill,True,True,True,0911: ESTRE Itapevi Landfill Gas Project (EILGP),911_PDD.pdf,São Paulo State,Itapevi,Brazil,-23.401961,-47.025269 +Quitaúna Landfill,True,True,False,Quitaúna Landfill Gas Project (QLGP),912_PDD.pdf,São Paulo,Guarulhos,Brazil,-23.41289167,-46.55770833 +Lara Landfill,True,True,True,"Landfill Gas to Energy Project at Lara Landfill, Mauá, Brazil",91_PDD.pdf,São Paulo,Mauá,Brazil,-23.705014,-46.474225 +ITVR São Leopoldo,True,True,False,ITVR Sao Leopoldo landfill gas project,9290_PDD.pdf,Rio Grande do Sul State,São Leopoldo,Brazil,-29.7461,-51.1966 +CTDR Bob Ambiental,True,True,False,CTDR Bob Ambiental landfill gas project,9295_PDD.pdf,Rio de Janeiro State,Belford Roxo,Brazil,-22.7011805,-43.3888194 +Rio Grande landfill,True,True,False,Rio Grande landfill gas project,9300_PDD.pdf,Rio Grande do Sul,Rio Grande,Brazil,-32.0288888,-52.2911111 +CTR da Caturrita landfill,True,True,False,CTR da Caturrita landfill gas project,9302_PDD.pdf,Rio Grande do Sul State,Santa Maria,Brazil,-29.6558,-53.8661 +Canhanduba Landfill,True,True,True,Canhanduba Landfill Project,9943_PDD.pdf,Santa Catarina,Joinville,Brazil,-26.301271,-48.799136 +João Pessoa Landfill,True,True,True,1165 PROBIOGAS-JP – João Pessoa Landfill Gas Project,1165_PDD.pdf,Paraíba,João Pessoa,Brazil,-7.115125,-34.8631 +Aterro Vila Velha,True,True,False,CTRVV Landfill emission reduction project,1491_PDD.pdf,Espírito Santo,Vila Velha,Brazil,-20.4567,-40.3911 +Feira de Santana Landfill,True,True,True,Feira de Santana Landfill Gas Project,1626_PDD.pdf,Bahia State,Feira de Santana,Brazil,-12.246944,-38.9975 +Bandeirantes Landfill,True,True,True,Bandeirantes Landfill Gas to Energy Project (BLFGE),164_PDD.pdf,Southeastern region,São Paulo,Brazil,-23.4161289,-46.7622611 +CGR Paulínia Landfill,True,True,True,ESTRE’s Paulínia Landfill Gas Project (EPLGP),165_PDD.pdf,São Paulo State,Paulínia,Brazil,-22.773506,-47.196161 +CTRS / BR.040 Landfill,True,True,True,Exploitation of the biogas from Controlled Landfill in Solid Waste Management Central – CTRS / BR.040,3464_PDD.pdf,Minas Gerais,Belo Horizonte,Brazil,-19.93258333,-44.01808333 +São João Landfill,True,True,True,0373 São João Landfill Gas to Energy Project (SJ),373_PDD.pdf,São Paulo,São João da Boa Vista,Brazil,-21.971982,-46.728277 +Aterro Metropolitano Central,True,True,True,Salvador da Bahia Landfill Gas Management Project,52_PDD.pdf,Bahia State,Lauro de Freitas,Brazil,-12.8625,-38.3636 +Central de Resíduos do Recreio Landfill,True,True,True,Central de Resíduos do Recreio Landfill Gas Project (CRRLGP),648_PDD.pdf,Recreio dos Bandeirantes,Rio de Janeiro,Brazil,-22.922006,-43.53351 +Natal Landfill,True,True,True,Natal Landfill Gas to Energy Project,7637_PDD.pdf,Rio Grande do Norte,Ceará-Mirim,Brazil,-5.711788,-35.382797 +CTR Rosario Landfill,True,True,True,8242 CTR Rosario Landfill Gas Project,8242_PDD.pdf,Córdoba Province,Córdoba,Argentina,-31.4201,-64.1888 +Proactiva CGA Iperó Landfill,True,True,True,Proactiva CGA Iperó Landfill Gas to Energy Project,8751_PDD.pdf,São Paulo,Iperó,Brazil,-23.117569,-47.540556 +CTR Macaúbas,True,True,True,Macaúbas Landfill Gas Project,9063_PDD.pdf,Minas Gerais,Sabará,Brazil,-19.856389,-43.844444 +CTR Maceio,True,True,True,CTR Maceio Landfill Gas Project,9228_PDD.pdf,Alagoas,Maceió,Brazil,-9.561214,-35.697483 +CPTR Marituba landfill,True,True,False,CPTR Marituba landfill gas project,9298_PDD.pdf,Pará State,Marituba,Brazil,-1.396279,-48.3377 diff --git a/brazil_landfill_name_and_coords_extraction.py b/brazil_landfill_name_and_coords_extraction.py new file mode 100644 index 0000000..2565f67 --- /dev/null +++ b/brazil_landfill_name_and_coords_extraction.py @@ -0,0 +1,381 @@ +# works for a single file, yay! +import pandas as pd +from dotenv import load_dotenv +import os +from openai import OpenAI +import json + +_ = load_dotenv(r'C:\Users\andre.scheinwald\OneDrive - RMI\Documents\env files\openapi.env') + +#client = OpenAI(api_key=os.getenv('work_account_key')) +client = OpenAI(api_key=os.getenv('key')) + +assistant = client.beta.assistants.create( + name="Document Reader Assistant", + instructions="""Read the uploaded documents and answer questions about them. Do not use any outside knowledge to answer questions. + Cite what page the relevant information is on.""", + model="gpt-4o-mini", + tools=[{"type": "file_search"}], +) + +# Create a vector store called "Financial Statements" +vector_store = client.beta.vector_stores.create(name="CDM docs") + +# Ready the files for upload to OpenAI +#file_paths = [r'C:\Users\andre.scheinwald\Downloads\brazil_test.pdf'] +file_paths = [r'C:\Users\andre.scheinwald\Downloads\cdm_files\10257_PDD.pdf'] +file_streams = [open(path, "rb") for path in file_paths] + +file_paths = [] +for dirpath, dirnames, filenames in os.walk(r'C:\Users\andre.scheinwald\Downloads\cdm_files'): + for filename in filenames: + full_path = os.path.join(dirpath, filename) + file_paths.append(full_path) + +# Use the upload and poll SDK helper to upload the files, add them to the vector store, +# and poll the status of the file batch for completion. +file_batch = client.beta.vector_stores.file_batches.upload_and_poll( + vector_store_id=vector_store.id, files=file_streams +) + +# You can print the status and the file counts of the batch to see the result of this operation. +print(file_batch.status) +print(file_batch.file_counts) + +assistant = client.beta.assistants.update( + assistant_id=assistant.id, + tool_resources={"file_search": {"vector_store_ids": [vector_store.id]}}, +) + + + +# Upload the user provided file to OpenAI +for files in file_paths: + message_file = client.files.create( + file=open(files, "rb"), purpose="assistants" + ) + + # Create a thread and attach the file to the message + thread = client.beta.threads.create( + messages=[ + { + "role": "user", + "content": """Please review the attached file and answer the following questions: What is the landfill name, location (region, city, and country), coordinates, and filename of the uploaded file referenced? + Coordinates should be in decimal format with positive or negative values for cardinal direction. Return a response in JSON format. + Do not add formatting such as \n or tabs.""", + # Attach the new file to the message. + "attachments": [ + { "file_id": message_file.id, "tools": [{"type": "file_search"}] } + ], + } + ] + ) + + # The thread now has a vector store with that file in its tool resources. + print(thread.tool_resources.file_search) + + # Use the create and poll SDK helper to create a run and poll the status of + # the run until it's in a terminal state. + + run = client.beta.threads.runs.create_and_poll( + thread_id=thread.id, assistant_id=assistant.id + ) + + messages = list(client.beta.threads.messages.list(thread_id=thread.id, run_id=run.id)) + + message_content = messages[0].content[0].text + annotations = message_content.annotations + #citations = [] + for index, annotation in enumerate(annotations): + message_content.value = message_content.value.replace(annotation.text, f"[{index}]") + if file_citation := getattr(annotation, "file_citation", None): + cited_file = client.files.retrieve(file_citation.file_id) + #citations.append(f"[{index}] {cited_file.filename}") + + print(message_content.value) + #print("\n".join(citations)) + cleaned_response_str = message_content.value.replace('\n', '').replace(' ', '') + data = json.loads(cleaned_response_str) + test = [] + test.append(data) + +df = pd.json_normalize(data) + + +vector_stores = client.beta.vector_stores.list() + +for store in vector_stores.data: + vector_store_id = store.id + print(f"Deleting vector store: {store.name} (ID: {store.id})") + client.beta.vector_stores.delete(vector_store_id=vector_store_id) + + + +# this WAS working for multiple files. But once again just spits out the same results for 1 file, twice. +import pandas as pd +from dotenv import load_dotenv +import os +from openai import OpenAI +import json + +_ = load_dotenv(r'C:\Users\andre.scheinwald\OneDrive - RMI\Documents\env files\openapi.env') + +# Initialize OpenAI client +client = OpenAI(api_key=os.getenv('key')) + +assistant = client.beta.assistants.create( + name="Document Reader Assistant", + instructions="""Read the uploaded documents and answer questions about them. Do not use any outside knowledge to answer questions. + Cite what page the relevant information is on.""", + model="gpt-4o-mini", + tools=[{"type": "file_search"}], +) + +# Create a vector store called "Financial Statements" +vector_store = client.beta.vector_stores.create(name="CDM docs") + +# Specify the folder to search for files +folder_path = r'C:\Users\andre.scheinwald\Downloads\cdm_files' + +# Get the full filenames including directory info +file_paths = [] +for dirpath, dirnames, filenames in os.walk(folder_path): + for filename in filenames: + full_path = os.path.join(dirpath, filename) + file_paths.append(full_path) + +# Print the full filenames +for file_path in file_paths: + print(file_path) + +# Process files in batches +batch_size = 10 # Adjust the batch size as needed +for i in range(0, len(file_paths), batch_size): + batch_file_paths = file_paths[i:i + batch_size] + file_streams = [open(path, "rb") for path in batch_file_paths] + + # Use the upload and poll SDK helper to upload the files, add them to the vector store, + # and poll the status of the file batch for completion. + file_batch = client.beta.vector_stores.file_batches.upload_and_poll( + vector_store_id=vector_store.id, files=file_streams + ) + + # You can print the status and the file counts of the batch to see the result of this operation. + print(file_batch.status) + print(file_batch.file_counts) + + # Close the file streams after use + for stream in file_streams: + stream.close() + +assistant = client.beta.assistants.update( + assistant_id=assistant.id, + tool_resources={"file_search": {"vector_store_ids": [vector_store.id]}}, +) + +test = [] +# Upload the user provided file to OpenAI +for file_path in file_paths: + message_file = client.files.create( + file=open(file_path, "rb"), purpose="assistants" + ) + + print(f'file_path: {file_path}') + print(f'message_file_id: {message_file.id}') + + + # Create a thread and attach the file to the message + thread = client.beta.threads.create( + messages=[ + { + "role": "user", + "content": """Please review the attached file and answer the following questions: What is the landfill name, location (region, city, and country), coordinates, and filename of the uploaded file referenced? + Coordinates should be in decimal format with positive or negative values for cardinal direction. Return a response in JSON format. + Do not add formatting such as \n or tabs.""", + # Attach the new file to the message. + "attachments": [ + { "file_id": message_file.id, "tools": [{"type": "file_search"}] } + ], + } + ] + ) + + # The thread now has a vector store with that file in its tool resources. + print(thread.tool_resources.file_search) + + # Use the create and poll SDK helper to create a run and poll the status of + # the run until it's in a terminal state. + + run = client.beta.threads.runs.create_and_poll( + thread_id=thread.id, assistant_id=assistant.id + ) + + messages = list(client.beta.threads.messages.list(thread_id=thread.id, run_id=run.id)) + + message_content = messages[0].content[0].text + annotations = message_content.annotations + + for index, annotation in enumerate(annotations): + message_content.value = message_content.value.replace(annotation.text, f"[{index}]") + if file_citation := getattr(annotation, "file_citation", None): + cited_file = client.files.retrieve(file_citation.file_id) + + print(message_content.value) + + cleaned_response_str = message_content.value.replace('\n', '').replace(' ', '') + data = json.loads(cleaned_response_str) + test.append(data) + +df = pd.json_normalize(test) + +# List and delete all vector stores +vector_stores = client.beta.vector_stores.list() + +for store in vector_stores.data: + vector_store_id = store.id + print(f"Deleting vector store: {store.name} (ID: {store.id})") + client.beta.vector_stores.delete(vector_store_id=vector_store_id) + + + + +# this WAS working for multiple files. But once again just spits out the same results for 1 file, twice. +import pandas as pd +from dotenv import load_dotenv +import os +from openai import OpenAI +import json + +_ = load_dotenv(r'C:\Users\andre.scheinwald\OneDrive - RMI\Documents\env files\openapi.env') + +# Initialize OpenAI client +client = OpenAI(api_key=os.getenv('key')) + +assistant = client.beta.assistants.create( + name="Document Reader Assistant", + instructions="""Read the uploaded documents and answer questions about them. Do not use any outside knowledge to answer questions. + Cite what page the relevant information is on.""", + model="gpt-4o-mini", + tools=[{"type": "file_search"}], +) + +# Create a vector store called "Financial Statements" +#vector_store = client.beta.vector_stores.create(name="CDM docs") + +# Specify the folder to search for files +#folder_path = r'C:\Users\andre.scheinwald\Downloads\cdm_files' +folder_path = r'C:\Users\andre.scheinwald\OneDrive - RMI\Documents\Python Scripts\cdm_scraping\downloads' + +# Get the full filenames including directory info +file_paths = [] +for dirpath, dirnames, filenames in os.walk(folder_path): + for filename in filenames: + full_path = os.path.join(dirpath, filename) + file_paths.append(full_path) + +# Print the full filenames +for file_path in file_paths: + print(file_path) + +test = [] +errors = [] +# Upload the user provided file to OpenAI +for file_path in file_paths: + message_file = client.files.create( + file=open(file_path, "rb"), purpose="assistants" + ) + + print(f'file_path: {file_path}') + print(f'message_file_id: {message_file.id}') + + + # Create a thread and attach the file to the message + thread = client.beta.threads.create( + messages=[ + { + "role": "user", + "content": """Please review all files and answer the following questions for every single file: What is the landfill name, location (region, city, and country), + gas_capture (True or False), gas_flare (True or False), gas_to_energy_project (True or False, coordinates, project title, and filename of the uploaded file referenced? + Coordinates should be in decimal format with positive or negative values for cardinal direction. Return a response in JSON format. + Do not add formatting such as \n or tabs. Name each json response 'landfills'. Do not use any other name. + Do not include any text outside the json response. This includes coding markup. + The format should look like this: {'landfills': [{'landfill_name': 'Dois Arcos Landfill', + 'location': {'region': 'Rio de Janeiro State', + 'city': 'São Pedro da Aldeia', + 'country': 'Brazil'}, + 'gas_capture': True, + 'gas_flare': True, + 'gas_to_energy_project': True, + 'coordinates': {'latitude': -22.82601389, 'longitude': -42.05100556}, + 'project_title': 'Dois Arcos Landfill Gas Project Activity', + 'filename': '10257_PDD.pdf'}]}""", + # Attach the new file to the message. + "attachments": [ + { "file_id": message_file.id, "tools": [{"type": "file_search"}] } + ], + } + ] + ) + + # The thread now has a vector store with that file in its tool resources. + print(thread.tool_resources.file_search) + + # Use the create and poll SDK helper to create a run and poll the status of + # the run until it's in a terminal state. + + run = client.beta.threads.runs.create_and_poll( + thread_id=thread.id, assistant_id=assistant.id + ) + + messages = list(client.beta.threads.messages.list(thread_id=thread.id, run_id=run.id)) + + message_content = messages[0].content[0].text + annotations = message_content.annotations + + for index, annotation in enumerate(annotations): + message_content.value = message_content.value.replace(annotation.text, f"[{index}]") + if file_citation := getattr(annotation, "file_citation", None): + cited_file = client.files.retrieve(file_citation.file_id) + + print(message_content.value) + + cleaned_response_str = message_content.value.replace('\n', '').replace(' ', '').replace('json', '').replace("```", "") + + try: + data = json.loads(cleaned_response_str) + test.append(data) + except json.JSONDecodeError as e: + print(f"JSONDecodeError: {e}") + print(f"Problematic JSON string: {cleaned_response_str}") + errors.append(cleaned_response_str) + +# Ensure 'landfills' is always a list in the 'test' list +for entry in test: + if 'landfills' in entry and isinstance(entry['landfills'], dict): + entry['landfills'] = [entry['landfills']] + + +df = pd.json_normalize(test, record_path = 'landfills') + +fixed_errors = [] +for entry in errors: + # Replace single quotes with double quotes and fix boolean values + entry = entry.replace("'", '"').replace('True', 'true').replace('False', 'false') + fixed_entries = json.loads(entry) + fixed_errors.append(fixed_entries) + +df2 = pd.json_normalize(fixed_errors, record_path='landfills') + +df3 = pd.concat([df, df2], ignore_index=True) + +df3.to_csv(r'C:\Users\andre.scheinwald\OneDrive - RMI\Documents\Python Scripts\cdm_scraping\brazil_landfill_name_and_coords_extraction.csv', index=False) + +# List and delete all vector stores +vector_stores = client.beta.vector_stores.list() + +while vector_stores.has_more: + for store in vector_stores.data: + vector_store_id = store.id + print(f"Deleting vector store: {store.name} (ID: {store.id})") + client.beta.vector_stores.delete(vector_store_id=vector_store_id) + vector_stores = client.beta.vector_stores.list() \ No newline at end of file From c4c8109f313be7bdda7943253c751258dc5154f6 Mon Sep 17 00:00:00 2001 From: andre-scheinwald <130578303+andre-scheinwald@users.noreply.github.com> Date: Fri, 21 Feb 2025 15:49:17 -0700 Subject: [PATCH 2/2] extraction check Manually went through the pdf documents and compared the results of the prompt engineering to the information in the extraction.csv. Created a new file called extraction.xlsx which records correct and incorrect data, as well as highlights unverified data. Corrections are stored as notes in this file. Added an additional column to flag files that can't be verified. Then generated accents.csv. Which is the final file to use for lining up existing facilities in the db to what we have here. It has the corrections and properly uses ansi format to preserve accent marks. --- ...l_landfill_name_and_coords_extraction.xlsx | Bin 0 -> 20909 bytes ...ame_and_coords_extraction_with_accents.csv | 53 ++++++++++++++++++ 2 files changed, 53 insertions(+) create mode 100644 brazil_landfill_name_and_coords_extraction.xlsx create mode 100644 brazil_landfill_name_and_coords_extraction_with_accents.csv diff --git a/brazil_landfill_name_and_coords_extraction.xlsx b/brazil_landfill_name_and_coords_extraction.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..c7854f94bf84d4bd45775a66aaabed5decd68cd6 GIT binary patch literal 20909 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 cNZO$_QGhoq@MILwAyoVfAAvb?nJ