diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 00000000..c5556040 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,6 @@ +# This CODEOWNERS file is auto-generated. See the script at for modification details. + +/.github/ @ai-cfia/devops +Dockerfile @ai-cfia/devops +docker-compose.yml @ai-cfia/devops +docker-compose.*.yml @ai-cfia/devops diff --git a/.github/workflows/python-api-test-workflows.yml b/.github/workflows/python-api-test-workflows.yml new file mode 100644 index 00000000..06cc08e2 --- /dev/null +++ b/.github/workflows/python-api-test-workflows.yml @@ -0,0 +1,21 @@ +name: Python api-test workflows + +on: + pull_request: + types: + - opened + - closed + - synchronize + +jobs: + markdown-check: + uses: ai-cfia/github-workflows/.github/workflows/workflow-markdown-check.yml@main + secrets: inherit + + repo-standard: + uses: ai-cfia/github-workflows/.github/workflows/workflow-repo-standards-validation.yml@main + secrets: inherit + + test-python: + uses: ai-cfia/github-workflows/.github/workflows/workflow-lint-test-python.yml@main + secrets: inherit diff --git a/.gitignore b/.gitignore index 15b65603..8c051a27 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,5 @@ keys.json questions.json keys_questions.txt questions_spreadsheet.csv -base_composition_questions.csv \ No newline at end of file +base_composition_questions.csv +*.pyc diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..aae83d15 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,10 @@ +{ + "python.testing.unittestArgs": [ + "-v", + "-s", + "./Tests", + "-p", + "test*.py" + ], + "python.testing.unittestEnabled": true +} diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..b44eef8c --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 AI @ Canadian Food Inspection Agency (CFIA) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md index 19d5f209..8eaed09d 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,3 @@ # harvester-prototype -This repository is for the frontend of the project react + +This repository is for the frontend of the project react diff --git a/TESTING.md b/TESTING.md new file mode 100644 index 00000000..e5273a89 --- /dev/null +++ b/TESTING.md @@ -0,0 +1,7 @@ +# Testing + +Run: + +```cmd +python -m unittest discover -s Tests +``` diff --git a/app.py b/app.py index 6797e07f..d16ff5d3 100644 --- a/app.py +++ b/app.py @@ -24,16 +24,16 @@ def getListImage(image_paths): return request def addText(request, number, baseQuestions=None): - if baseQuestions == None: + if baseQuestions is None: request.append(create_base_request(read_csv_file("base_composition_questions.csv"))) else: request.append(create_final_request(read_csv_file("questions_spreadsheet.csv"), baseQuestions)) return request -def generateRequest(directory, model:GenerativeModel, vertex:vertexai, baseQuestions=None, typeOfQuestion): +def generateRequest(directory, model:GenerativeModel, vertex:vertexai, baseQuestions=None): request = getListImage(collect_images(directory)) - if baseQuestions == None: + if baseQuestions is None: request = addText(request, 1) else: request = addText(request, 2, baseQuestions) @@ -55,10 +55,10 @@ def generateRequest(directory, model:GenerativeModel, vertex:vertexai, baseQuest stream=False, ) - if baseQuestions == None: + if baseQuestions is None: baseQuestions = toDict(responses.text) - else: - otherQuestion = toDict(responses, baseQuestions) + #else: + # otherQuestion = toDict(responses, baseQuestions) print(responses.text) @@ -66,7 +66,7 @@ def generateRequest(directory, model:GenerativeModel, vertex:vertexai, baseQuest def toDict(responses, baseQuestions=None): responseAsDict = {} - if baseQuestions == None: + if baseQuestions is None: for response in responses: texte = response indice = texte.find(":") @@ -85,10 +85,10 @@ def create_final_request(file, baseQuestions, typeOfQuestion): for index, line in file.iterrows(): if not line.isnull().all(): categorie = str(line['Categories']) - if line['Specification'] != None: + if line['Specification'] is not None: request_AsText += str(line['Specification']) + "\n" - if line['Categories'] != None: + if line['Categories'] is not None: if "not_asked" in categorie: break elif "all" in categorie: @@ -175,12 +175,12 @@ def create_base_request(file): model = GenerativeModel("gemini-1.0-pro-vision-001") projectinit=vertexai.init(project="test-application-2-416219", location="northamerica-northeast1") #Original question -baseQuestions = generateRequest('Company_Image_Folder\\Acti_Sol1', model, projectinit, None, "Original_question") -baseQuestions = generateRequest('Company_Image_Folder\\Acti_Sol1', model, projectinit, baseQuestions, "Original_question") +baseQuestions = generateRequest('company_image_folder\\Acti_Sol1', model, projectinit, None, "Original_question") +baseQuestions = generateRequest('company_image_folder\\Acti_Sol1', model, projectinit, baseQuestions, "Original_question") # Modified question -baseQuestions = generateRequest('Company_Image_Folder\\Acti_Sol1', model, projectinit, None, "Modified_question") -baseQuestions = generateRequest('Company_Image_Folder\\Acti_Sol1', model, projectinit, baseQuestions, "Modified_question") +baseQuestions = generateRequest('company_image_folder\\Acti_Sol1', model, projectinit, None, "Modified_question") +baseQuestions = generateRequest('company_image_folder\\Acti_Sol1', model, projectinit, baseQuestions, "Modified_question") #generateRequest('Company_Image_Folder\Bio_Fleur', model, projectinit) #generateRequest('Company_Image_Folder\Bio_Fleur', model, projectinit) -#generateRequest('Company_Image_Folder\Bio_Fleur', model, projectinit) \ No newline at end of file +#generateRequest('Company_Image_Folder\Bio_Fleur', model, projectinit) diff --git a/keys_questions.txt b/keys_questions.txt deleted file mode 100644 index f26418b8..00000000 --- a/keys_questions.txt +++ /dev/null @@ -1,53 +0,0 @@ -Make a break line for each question and in a form of json file -if response = yes write True -if response is null write None -if you have no responses for the question write None -Combine the multiple picture data together to response question -When question contains Give : give the text on the bag -name_of_the_registrant: Give the name of the manufacturer or registrant of the fertiliser or supplement -address_of_the_registrant: Give the full address of the manufacturer or registrant (address must include: street address or post office box number, city, province or state and postal code or ZIP code, as applicable) , and the country, if the product is manufactured outside of Canada -name_of_fertiliser: Give the name of fertiliser -name_of_fertiliser_contain_term : Did the fertiliser name contain term from the list of ingredients. -npk_grade_designation: Did the fertiliser contain a main nutrient principle if true did it contain NPK() -npk: What is the NPK -registration_number: Give the registration number -instructions: Did the fertiliser instruction are on the bag? -instructions_text: Give the instructions -instructions_contain_option1: Did the instructions contain comprehensive recommendations, including crop type targeted, application rate, frequency and timing of application. -instructions_contain_option2: Did the instructions contain if the product is only intended for use as a nutrient source in blended products, a statement such as “for use only as a nutrient source for the production of fertilisers and growing media” and include intended downstream uses ( for example, for use in mixtures intended for foliar application to ornamental and edible crops). -instructions_contain_option3: Did the instructions contain a statement indicating that the user should consult a regional agricultural advisor or agricultural specialist. -contain_trace_elements: Did the fertiliser contain trace elements. -include_tank_mixing: Did the fertiliser or supplement includes tank mixing with a pest control product as its proposed directions for use, the following statements must appear on the product label -tank_mixing_text_must_include1: Did the label contain this mention \This product can be tank mixed with parasiticides. (The text may be different, but the message must be the same). -tank_mixing_text_must_include2: Did the label contain this mention \In some cases, tank-mixed pest control products may result in reduced pesticide effectiveness or increased damage to the host crop. (The text may be different, but the message must be the same). -tank_mixing_text_must_include3: Did the label contain this mention \It is recommended to perform a flocculation test before mixing the product with other fertilisers or pesticides. (The text may be different, but the message must be the same). -net_weight: Give the weight. -dry_form_product: Did the product is in dry form -mesurement_dry_form: Did the unit on the label is presented in grams (g), kilograms (kg) or tonnes (t) -mesurement_liquid_form: if dry_form_product = false --> Did the unit on the label is presented in grams (g) or kilograms (kg), but their volume may appear, in addition to weight, in milliliters (ml) or liters (l). -guaranteed_analysis: Guaranteed analysis is on the product label. -0%_guarantees: No 0% guarantee is listed in the guaranteed analysis for contaminants (for example: heavy metals or pathogens) -active_ingredients_only: Guaranteed analysis contains only active ingredients -include_minimal_requirement: If the guaranteed analysis includes "minimum", then any asset guaranteed on an actual basis (such as trace minerals) must include "(real)" next to the guarantee. -not_include_minimal_requirement: If the Guaranteed analysis does not specify a minimum, all guarantees are assumed to be actual quantities. All assets guaranteed a minimum quantity under such a heading must specify “(minimum)” (such as major plant nutrients). -minimum_n: Give the minimum amount of total nitrogen (N) expressed as a percentage. -minimum_p2o5: Give the minimum quantity of assimilable phosphoric acid (P2O5) expressed as a percentage. -contain_Phosphate: Is the fertiliser contain phosphore or phosphorous -minimum_total_phosphoric_acid: If contain_phosphate = true-->Give the total phosphoric acid in the guaranteed analysis as a percentage. -minimum_available_phosphoric_acid: contain_phosphate= true--> Give the available phosphoric acid in the guaranteed analysis as a percentage. -minimum_k2o: Give the minimum quantity of soluble potash (K2O) expressed as a percentage. -secondary_nutrient :Give the minimum amount of each secondary nutrient in a list -trace_elements: Give the trace elements as percentage. -contain_microorganism: Did the fertiliser contain microorganism. -information_microorganism1: Did the microorganism information contain --> the minimum number of viable cells per gram -information_microorganism2: Did the microorganism information contain --> for each microorganism that is not a viable cell, another descriptor of the concentration of that microorganism per gram. -complex_microorganism_group: Did the fertilizer or supplement contains component that is a complex group of microorganisms whose composition remains unchanged without further manipulation originating from a single natural environment. -descriptor_concentration: If complex_microorganism_group =true --> Did the label contain a descriptor of the concentration of viable microorganisms per gram. -neutralize_acidity_component: Did the fertilizer or supplement contains an active component intended to neutralize acidity. -minimum_calcium: if neutralize_acidity_component = true --> Give the minimum quantity of calcium as percentage of pure element. -minimum_magnesium: if neutralize_acidity_component = true --> Give the minimum quantity of magnesium as percentage of pure element. -minimum_neutralizing_power: if neutralize_acidity_component = true --> Give the minimum neutralizing power as percentage, of the acid neutralizing capacity of the calcium carbonate. -particle_size: if neutralize_acidity_component = true --> Give the particle size. -contain_organic_matter:Did the fertilizer or supplement advertised as containing organic matter. -organic_matter_information: if contain_organic_matter = true --> Give the minimum quantity of organic_matter and the the maximum moisture content expressed as a percentage. -other_component: Give the minimum or actual quantity of any other active component expressed as a percentage. \ No newline at end of file diff --git a/Tests/testWithModifiedQuestion.py b/tests/__init__.py similarity index 100% rename from Tests/testWithModifiedQuestion.py rename to tests/__init__.py diff --git a/tests/__pycache__/testWithBaseQuestion.cpython-312.pyc b/tests/__pycache__/testWithBaseQuestion.cpython-312.pyc new file mode 100644 index 00000000..94e4c9a0 Binary files /dev/null and b/tests/__pycache__/testWithBaseQuestion.cpython-312.pyc differ diff --git a/tests/__pycache__/testsWithBaseQuestion.cpython-312.pyc b/tests/__pycache__/testsWithBaseQuestion.cpython-312.pyc new file mode 100644 index 00000000..8e1a8e71 Binary files /dev/null and b/tests/__pycache__/testsWithBaseQuestion.cpython-312.pyc differ diff --git a/Tests/testWithBaseQuestion.py b/tests/test_whit_base_question.py similarity index 91% rename from Tests/testWithBaseQuestion.py rename to tests/test_whit_base_question.py index 3006eeb2..0ef41550 100644 --- a/Tests/testWithBaseQuestion.py +++ b/tests/test_whit_base_question.py @@ -1,21 +1,21 @@ -import unittest - -class testWithBaseQuestion(unittest.TestCase): - def setUp(self): - # This method will be called before each test - pass - - def tearDown(self): - # This method will be called after each test - pass - - def test_case_1(self): - # Write your test case here - pass - - def test_case_2(self): - # Write your test case here - pass - -if __name__ == '__main__': - unittest.main() \ No newline at end of file +import unittest + +class testWithBaseQuestion(unittest.TestCase): + def setUp(self): + # This method will be called before each test + pass + + def tearDown(self): + # This method will be called after each test + pass + + def test_case_1(self): + # Write your test case here + pass + + def test_case_2(self): + # Write your test case here + pass + +if __name__ == '__main__': + unittest.main()