Merge pull request #70 from ssciwr/cleaning_code
rename misinformation to ammico
4
.github/workflows/ci.yml
поставляемый
@ -31,12 +31,12 @@ jobs:
|
||||
python -m textblob.download_corpora
|
||||
- name: Run pytest
|
||||
run: |
|
||||
cd misinformation
|
||||
cd ammico
|
||||
python -m pytest -m "not gcv and not long" -svv --cov=. --cov-report=xml
|
||||
- name: Upload coverage
|
||||
if: matrix.os == 'ubuntu-22.04' && matrix.python-version == '3.9'
|
||||
uses: codecov/codecov-action@v3
|
||||
with:
|
||||
fail_ci_if_error: true
|
||||
files: misinformation/coverage.xml
|
||||
files: ammico/coverage.xml
|
||||
verbose: true
|
||||
|
||||
2
.github/workflows/docs.yml
поставляемый
@ -15,7 +15,7 @@ jobs:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0 # otherwise, you will failed to push refs to dest repo
|
||||
- name: install misinformation
|
||||
- name: install ammico
|
||||
run: |
|
||||
pip install -e .
|
||||
python -m pip install -r requirements-dev.txt
|
||||
|
||||
10
Dockerfile
@ -6,24 +6,24 @@ RUN apt update && apt install -y build-essential libgl1 libglib2.0-0 libsm6 libx
|
||||
USER $NB_USER
|
||||
|
||||
# Copy the repository into the container
|
||||
COPY --chown=${NB_UID} . /opt/misinformation
|
||||
COPY --chown=${NB_UID} . /opt/ammico
|
||||
|
||||
# Install the Python package
|
||||
RUN python -m pip install /opt/misinformation
|
||||
RUN python -m pip install /opt/ammico
|
||||
|
||||
# Make JupyterLab the default for this application
|
||||
ENV JUPYTER_ENABLE_LAB=yes
|
||||
|
||||
# Export where the data is located
|
||||
ENV XDG_DATA_HOME=/opt/misinformation/data
|
||||
ENV XDG_DATA_HOME=/opt/ammico/data
|
||||
|
||||
# Copy notebooks into the home directory
|
||||
RUN rm -rf $HOME/work
|
||||
RUN cp /opt/misinformation/notebooks/*.ipynb $HOME
|
||||
RUN cp /opt/ammico/notebooks/*.ipynb $HOME
|
||||
|
||||
ARG GOOGLE_CREDS
|
||||
ENV GOOGLE_APPLICATION_CREDENTIALS=credentials.json
|
||||
RUN echo ${GOOGLE_CREDS} > $GOOGLE_APPLICATION_CREDENTIALS
|
||||
# Bundle the pre-built models (that are downloaded on demand) into the
|
||||
# Docker image.
|
||||
RUN misinformation_prefetch_models
|
||||
RUN ammico_prefetch_models
|
||||
|
||||
24
README.md
@ -1,10 +1,10 @@
|
||||
# AMMICO - AI Media and Misinformation Content Analysis Tool
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
This package extracts data from images such as social media images, and the accompanying text/text that is included in the image. The analysis can extract a very large number of features, depending on the user input.
|
||||
|
||||
@ -34,7 +34,7 @@ Use pre-processed image files such as social media posts with comments and proce
|
||||
|
||||
## Installation
|
||||
|
||||
The `AMMICO` package can be installed using pip: Navigate into your package folder `misinformation/` and execute
|
||||
The `AMMICO` package can be installed using pip: Navigate into your package folder `ammico/` and execute
|
||||
```
|
||||
pip install .
|
||||
```
|
||||
@ -43,19 +43,19 @@ This will install the package and its dependencies locally.
|
||||
|
||||
## Usage
|
||||
|
||||
There are sample notebooks in the `misinformation/notebooks` folder for you to explore the package:
|
||||
There are sample notebooks in the `notebooks` folder for you to explore the package:
|
||||
1. Text extraction: Use the notebook `get-text-from-image.ipynb` to extract any text from the images. The text is directly translated into English. If the text should be further analysed, set the keyword `analyse_text` to `True` as demonstrated in the notebook.\
|
||||
**You can run this notebook on google colab: [Here](https://colab.research.google.com/github/ssciwr/misinformation/blob/main/notebooks/get-text-from-image.ipynb)**
|
||||
**You can run this notebook on google colab: [Here](https://colab.research.google.com/github/ssciwr/ammico/blob/main/notebooks/get-text-from-image.ipynb)**
|
||||
Place the data files and google cloud vision API key in your google drive to access the data.
|
||||
1. Emotion recognition: Use the notebook `facial_expressions.ipynb` to identify if there are faces on the image, if they are wearing masks, and if they are not wearing masks also the race, gender and dominant emotion.
|
||||
**You can run this notebook on google colab: [Here](https://colab.research.google.com/github/ssciwr/misinformation/blob/main/notebooks/facial_expressions.ipynb)**
|
||||
**You can run this notebook on google colab: [Here](https://colab.research.google.com/github/ssciwr/ammico/blob/main/notebooks/facial_expressions.ipynb)**
|
||||
Place the data files in your google drive to access the data.
|
||||
1. Content extraction: Use the notebook `image_summary.ipynb` to create captions for the images and ask questions about the image content.
|
||||
**You can run this notebook on google colab: [Here](https://colab.research.google.com/github/ssciwr/misinformation/blob/main/notebooks/image_summary.ipynb)**
|
||||
**You can run this notebook on google colab: [Here](https://colab.research.google.com/github/ssciwr/ammico/blob/main/notebooks/image_summary.ipynb)**
|
||||
1. Multimodal content: Use the notebook `multimodal_search.ipynb` to find the best fitting images to an image or text query.
|
||||
**You can run this notebook on google colab: [Here](https://colab.research.google.com/github/ssciwr/misinformation/blob/main/notebooks/multimodal_search.ipynb)**
|
||||
**You can run this notebook on google colab: [Here](https://colab.research.google.com/github/ssciwr/ammico/blob/main/notebooks/multimodal_search.ipynb)**
|
||||
1. Object analysis: Use the notebook `ojects_expression.ipynb` to identify certain objects in the image. Currently, the following objects are being identified: person, bicycle, car, motorcycle, airplane, bus, train, truck, boat, traffic light, cell phone.
|
||||
**You can run this notebook on google colab: [Here](https://colab.research.google.com/github/ssciwr/misinformation/blob/main/notebooks/objects_expression.ipynb)**
|
||||
**You can run this notebook on google colab: [Here](https://colab.research.google.com/github/ssciwr/ammico/blob/main/notebooks/objects_expression.ipynb)**
|
||||
|
||||
There are further notebooks that are currently of exploratory nature (`colors_expression.ipynb` to identify certain colors on the image). To crop social media posts use the `cropposts.ipynb` notebook.
|
||||
|
||||
|
||||
@ -146,7 +146,9 @@ def crop_posts_image(
|
||||
):
|
||||
"""
|
||||
get file lists from dir and sub dirs
|
||||
ref_view:ref_view for crop the posts images
|
||||
|
||||
|
||||
ref_view: ref_view for crop the posts images
|
||||
view: posts image that need cropping
|
||||
rte: None - not cropped, or (crop_view, number of matches)
|
||||
"""
|
||||
@ -185,7 +187,7 @@ def crop_posts_image(
|
||||
def get_file_list(dir, filelist, ext=None, convert_unix=True):
|
||||
"""
|
||||
get file lists from dir and sub dirs
|
||||
dir:root dir for file lists
|
||||
dir: root dir for file lists
|
||||
ext: file extension
|
||||
rte: File list
|
||||
"""
|
||||
@ -252,11 +254,9 @@ def crop_posts_from_files(
|
||||
|
||||
def test_crop_from_file():
|
||||
# Load images
|
||||
# view1 = np.array(Image.open("data/ref/ref-00.png")) / 255
|
||||
# view2 = np.array(Image.open("data/napsa/100539_ben.png")) / 255
|
||||
view1 = np.array(Image.open("data/ref/ref-06.png"))
|
||||
view2 = np.array(Image.open("data/napsa/102956_eng.png"))
|
||||
crop_view, match_num = crop_posts_image(view1, view2, plt_match=True, plt_crop=True)
|
||||
crop_view, _ = crop_posts_image(view1, view2, plt_match=True, plt_crop=True)
|
||||
cv2.imwrite("data/crop_100489_ind.png", crop_view)
|
||||
|
||||
|
||||
@ -267,10 +267,3 @@ def test_crop_from_folder():
|
||||
crop_posts_from_files(
|
||||
ref_dir, crop_dir, save_crop_dir, plt_match=False, plt_crop=False
|
||||
)
|
||||
|
||||
|
||||
# do tests:
|
||||
|
||||
# test_crop_from_file()
|
||||
|
||||
# test_crop_from_folder()
|
||||
@ -1,11 +1,11 @@
|
||||
import ipywidgets
|
||||
from IPython.display import display
|
||||
|
||||
import misinformation.faces as faces
|
||||
import misinformation.text as text
|
||||
import misinformation.objects as objects
|
||||
import ammico.faces as faces
|
||||
import ammico.text as text
|
||||
import ammico.objects as objects
|
||||
|
||||
import misinformation.summary as summary
|
||||
import ammico.summary as summary
|
||||
|
||||
|
||||
class JSONContainer:
|
||||
@ -11,8 +11,8 @@ from tensorflow.keras.preprocessing.image import img_to_array
|
||||
from deepface import DeepFace
|
||||
from retinaface import RetinaFace
|
||||
|
||||
from misinformation.utils import DownloadResource
|
||||
import misinformation.utils as utils
|
||||
from ammico.utils import DownloadResource
|
||||
import ammico.utils as utils
|
||||
|
||||
DEEPFACE_PATH = ".deepface"
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
from misinformation.utils import AnalysisMethod
|
||||
from ammico.utils import AnalysisMethod
|
||||
import torch
|
||||
import torch.nn.functional as Func
|
||||
import requests
|
||||
@ -17,7 +17,6 @@ from lavis.processors import load_processor
|
||||
class MultimodalSearch(AnalysisMethod):
|
||||
def __init__(self, subdict: dict) -> None:
|
||||
super().__init__(subdict)
|
||||
# self.subdict.update(self.set_keys())
|
||||
|
||||
multimodal_device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
|
||||
|
||||
@ -319,11 +318,7 @@ class MultimodalSearch(AnalysisMethod):
|
||||
)
|
||||
|
||||
similarity = features_image_stacked @ multi_features_stacked.t()
|
||||
# similarity_soft_max = torch.nn.Softmax(dim=0)(similarity / 0.01)
|
||||
sorted_lists = [
|
||||
sorted(range(len(similarity)), key=lambda k: similarity[k, i], reverse=True)
|
||||
for i in range(len(similarity[0]))
|
||||
]
|
||||
sorted_lists = torch.argsort(similarity, dim=0, descending=True).T.tolist()
|
||||
places = [[item.index(i) for i in range(len(item))] for item in sorted_lists]
|
||||
|
||||
for q in range(len(search_query)):
|
||||
@ -350,7 +345,7 @@ class MultimodalSearch(AnalysisMethod):
|
||||
|
||||
def itm_text_precessing(self, search_query):
|
||||
for query in search_query:
|
||||
if not (len(query) == 1) and (query in ("image", "text_input")):
|
||||
if (len(query) != 1) and (query in ("image", "text_input")):
|
||||
raise SyntaxError(
|
||||
'Each querry must contain either an "image" or a "text_input"'
|
||||
)
|
||||
@ -1,6 +1,6 @@
|
||||
from misinformation.utils import AnalysisMethod
|
||||
from misinformation.objects_cvlib import ObjectCVLib
|
||||
from misinformation.objects_cvlib import init_default_objects
|
||||
from ammico.utils import AnalysisMethod
|
||||
from ammico.objects_cvlib import ObjectCVLib
|
||||
from ammico.objects_cvlib import init_default_objects
|
||||
|
||||
|
||||
class ObjectDetectorClient(AnalysisMethod):
|
||||
@ -1,7 +1,5 @@
|
||||
import cv2
|
||||
import cvlib as cv
|
||||
import numpy as np
|
||||
from PIL import Image
|
||||
|
||||
|
||||
def objects_from_cvlib(objects_list: list) -> dict:
|
||||
@ -52,12 +50,8 @@ class ObjectCVLib(ObjectsMethod):
|
||||
image_path: The path to the local file.
|
||||
"""
|
||||
img = cv2.imread(image_path)
|
||||
# preimg = Image.open(image_path).convert("RGB")
|
||||
# preimg2 = np.asarray(preimg)
|
||||
# img = cv2.cvtColor(preimg2, cv2.COLOR_BGR2RGB)
|
||||
|
||||
_, label, _ = cv.detect_common_objects(img)
|
||||
# output_image = draw_bbox(im, bbox, label, conf)
|
||||
objects = objects_from_cvlib(label)
|
||||
return objects
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
from misinformation.utils import AnalysisMethod
|
||||
from ammico.utils import AnalysisMethod
|
||||
from torch import device, cuda, no_grad
|
||||
from PIL import Image
|
||||
from lavis.models import load_model_and_preprocess
|
||||
@ -28,7 +28,6 @@ class SummaryDetector(AnalysisMethod):
|
||||
return summary_model, summary_vis_processors
|
||||
|
||||
def load_model(self, model_type):
|
||||
# self.summary_device = device("cuda" if cuda.is_available() else "cpu")
|
||||
select_model = {
|
||||
"base": SummaryDetector.load_model_base,
|
||||
"large": SummaryDetector.load_model_large,
|
||||
@ -58,9 +57,9 @@ class SummaryDetector(AnalysisMethod):
|
||||
|
||||
def analyse_questions(self, list_of_questions):
|
||||
(
|
||||
summary_VQA_model,
|
||||
summary_VQA_vis_processors,
|
||||
summary_VQA_txt_processors,
|
||||
summary_vqa_model,
|
||||
summary_vqa_vis_processors,
|
||||
summary_vqa_txt_processors,
|
||||
) = load_model_and_preprocess(
|
||||
name="blip_vqa",
|
||||
model_type="vqav2",
|
||||
@ -71,18 +70,18 @@ class SummaryDetector(AnalysisMethod):
|
||||
path = self.subdict["filename"]
|
||||
raw_image = Image.open(path).convert("RGB")
|
||||
image = (
|
||||
summary_VQA_vis_processors["eval"](raw_image)
|
||||
summary_vqa_vis_processors["eval"](raw_image)
|
||||
.unsqueeze(0)
|
||||
.to(self.summary_device)
|
||||
)
|
||||
question_batch = []
|
||||
for quest in list_of_questions:
|
||||
question_batch.append(summary_VQA_txt_processors["eval"](quest))
|
||||
question_batch.append(summary_vqa_txt_processors["eval"](quest))
|
||||
batch_size = len(list_of_questions)
|
||||
image_batch = image.repeat(batch_size, 1, 1, 1)
|
||||
|
||||
with no_grad():
|
||||
answers_batch = summary_VQA_model.predict_answers(
|
||||
answers_batch = summary_vqa_model.predict_answers(
|
||||
samples={"image": image_batch, "text_input": question_batch},
|
||||
inference_method="generate",
|
||||
)
|
||||
|
До Ширина: | Высота: | Размер: 1005 KiB После Ширина: | Высота: | Размер: 1005 KiB |
|
До Ширина: | Высота: | Размер: 1.2 MiB После Ширина: | Высота: | Размер: 1.2 MiB |
|
До Ширина: | Высота: | Размер: 58 KiB После Ширина: | Высота: | Размер: 58 KiB |
|
До Ширина: | Высота: | Размер: 37 KiB После Ширина: | Высота: | Размер: 37 KiB |
|
До Ширина: | Высота: | Размер: 42 KiB После Ширина: | Высота: | Размер: 42 KiB |
|
До Ширина: | Высота: | Размер: 307 KiB После Ширина: | Высота: | Размер: 307 KiB |
|
До Ширина: | Высота: | Размер: 1.3 MiB После Ширина: | Высота: | Размер: 1.3 MiB |
|
До Ширина: | Высота: | Размер: 671 KiB После Ширина: | Высота: | Размер: 671 KiB |
|
До Ширина: | Высота: | Размер: 272 KiB После Ширина: | Высота: | Размер: 272 KiB |
@ -1,4 +1,4 @@
|
||||
import misinformation.cropposts as crpo
|
||||
import ammico.cropposts as crpo
|
||||
import numpy as np
|
||||
from PIL import Image
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
import json
|
||||
import misinformation.display as misinf_display
|
||||
import ammico.display as ammico_display
|
||||
|
||||
|
||||
def test_explore_analysis_faces(get_path):
|
||||
mydict = {"IMG_2746": {"filename": get_path + "IMG_2746.png"}}
|
||||
temp = misinf_display.explore_analysis(mydict, identify="faces") # noqa
|
||||
temp = ammico_display.explore_analysis(mydict, identify="faces") # noqa
|
||||
temp = None # noqa
|
||||
with open(get_path + "example_faces.json", "r") as file:
|
||||
outs = json.load(file)
|
||||
@ -17,7 +17,7 @@ def test_explore_analysis_faces(get_path):
|
||||
|
||||
def test_explore_analysis_objects(get_path):
|
||||
mydict = {"IMG_2809": {"filename": get_path + "IMG_2809.png"}}
|
||||
temp = misinf_display.explore_analysis(mydict, identify="objects") # noqa
|
||||
temp = ammico_display.explore_analysis(mydict, identify="objects") # noqa
|
||||
temp = None # noqa
|
||||
with open(get_path + "example_analysis_objects.json", "r") as file:
|
||||
outs = json.load(file)
|
||||
@ -1,6 +1,5 @@
|
||||
import misinformation.faces as fc
|
||||
import ammico.faces as fc
|
||||
import json
|
||||
import pytest
|
||||
|
||||
|
||||
def test_analyse_faces(get_path):
|
||||
@ -3,7 +3,7 @@ import math
|
||||
from PIL import Image
|
||||
import numpy
|
||||
from torch import device, cuda
|
||||
import misinformation.multimodal_search as ms
|
||||
import ammico.multimodal_search as ms
|
||||
|
||||
related_error = 1e-2
|
||||
gpu_is_not_available = not cuda.is_available()
|
||||
@ -1,7 +1,7 @@
|
||||
import json
|
||||
import pytest
|
||||
import misinformation.objects as ob
|
||||
import misinformation.objects_cvlib as ob_cvlib
|
||||
import ammico.objects as ob
|
||||
import ammico.objects_cvlib as ob_cvlib
|
||||
|
||||
OBJECT_1 = "cell phone"
|
||||
OBJECT_2 = "motorcycle"
|
||||
@ -2,7 +2,7 @@ import os
|
||||
import pytest
|
||||
from torch import device, cuda
|
||||
from lavis.models import load_model_and_preprocess
|
||||
import misinformation.summary as sm
|
||||
import ammico.summary as sm
|
||||
|
||||
|
||||
IMAGES = ["d755771b-225e-432f-802e-fb8dc850fff7.png", "IMG_2746.png"]
|
||||
@ -1,7 +1,7 @@
|
||||
import os
|
||||
import pytest
|
||||
import spacy
|
||||
import misinformation.text as tt
|
||||
import ammico.text as tt
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
@ -1,6 +1,6 @@
|
||||
import json
|
||||
import pandas as pd
|
||||
import misinformation.utils as ut
|
||||
import ammico.utils as ut
|
||||
|
||||
|
||||
def test_find_files(get_path):
|
||||
@ -5,7 +5,7 @@ from spacytextblob.spacytextblob import SpacyTextBlob
|
||||
from textblob import TextBlob
|
||||
from textblob import download_corpora
|
||||
import io
|
||||
from misinformation import utils
|
||||
from ammico import utils
|
||||
import grpc
|
||||
import pandas as pd
|
||||
from bertopic import BERTopic
|
||||
@ -113,7 +113,6 @@ class TextDetector(utils.AnalysisMethod):
|
||||
self.subdict["text_english_correct"] = str(self.textblob.correct())
|
||||
|
||||
def sentiment_analysis(self):
|
||||
# self.subdict["sentiment"] = self.doc._.blob.sentiment_assessments.assessments
|
||||
# polarity is between [-1.0, 1.0]
|
||||
self.subdict["polarity"] = self.doc._.blob.polarity
|
||||
# subjectivity is a float within the range [0.0, 1.0]
|
||||
@ -9,7 +9,7 @@ class DownloadResource:
|
||||
|
||||
We use this as a wrapper to the pooch library. The wrapper registers
|
||||
each data file and allows prefetching through the CLI entry point
|
||||
misinformation_prefetch_models.
|
||||
ammico_prefetch_models.
|
||||
"""
|
||||
|
||||
# We store a list of defined resouces in a class variable, allowing
|
||||
@ -24,7 +24,7 @@ class DownloadResource:
|
||||
return pooch.retrieve(**self.kwargs)
|
||||
|
||||
|
||||
def misinformation_prefetch_models():
|
||||
def ammico_prefetch_models():
|
||||
"""Prefetch all the download resources"""
|
||||
for res in DownloadResource.resources:
|
||||
res.get()
|
||||
@ -95,14 +95,3 @@ def append_data_to_dict(mydict: dict) -> dict:
|
||||
def dump_df(mydict: dict) -> DataFrame:
|
||||
"""Utility to dump the dictionary into a dataframe."""
|
||||
return DataFrame.from_dict(mydict)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
files = find_files(
|
||||
path="/home/inga/projects/misinformation-project/misinformation/data/test_no_text/"
|
||||
)
|
||||
mydict = initialize_dict(files)
|
||||
outdict = {}
|
||||
outdict = append_data_to_dict(mydict)
|
||||
df = dump_df(outdict)
|
||||
print(df.head(10))
|
||||
@ -6,7 +6,7 @@
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.insert(0, os.path.abspath("../../misinformation/"))
|
||||
sys.path.insert(0, os.path.abspath("../../ammico/"))
|
||||
|
||||
|
||||
# -- Project information -----------------------------------------------------
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
.. misinformation documentation master file, created by
|
||||
.. ammico documentation master file, created by
|
||||
sphinx-quickstart on Mon Dec 19 13:39:22 2022.
|
||||
You can adapt this file completely to your liking, but it should at least
|
||||
contain the root `toctree` directive.
|
||||
|
||||
@ -9,11 +9,12 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"id": "51f8888b-d1a3-4b85-a596-95c0993fa192",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"This notebooks shows some preliminary work on detecting facial expressions with DeepFace. It is mainly meant to explore its capabilities and to decide on future research directions. We package our code into a `misinformation` package that is imported here:"
|
||||
"This notebooks shows some preliminary work on detecting facial expressions with DeepFace. It is mainly meant to explore its capabilities and to decide on future research directions. We package our code into a `ammico` package that is imported here:"
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -25,9 +26,9 @@
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import misinformation\n",
|
||||
"from misinformation import utils as mutils\n",
|
||||
"from misinformation import display as mdisplay"
|
||||
"import ammico\n",
|
||||
"from ammico import utils as mutils\n",
|
||||
"from ammico import display as mdisplay"
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -130,7 +131,7 @@
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"for key in mydict.keys():\n",
|
||||
" mydict[key] = misinformation.faces.EmotionDetector(mydict[key]).analyse_image()"
|
||||
" mydict[key] = ammico.faces.EmotionDetector(mydict[key]).analyse_image()"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@ -9,11 +9,12 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"id": "9eeeb302-296e-48dc-86c7-254aa02f2b3a",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"This notebooks shows some preliminary work on Image Multimodal Search with lavis library. It is mainly meant to explore its capabilities and to decide on future research directions. We package our code into a `misinformation` package that is imported here:"
|
||||
"This notebooks shows some preliminary work on Image Multimodal Search with lavis library. It is mainly meant to explore its capabilities and to decide on future research directions. We package our code into a `ammico` package that is imported here:"
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -25,8 +26,8 @@
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import misinformation\n",
|
||||
"import misinformation.multimodal_search as ms"
|
||||
"import ammico\n",
|
||||
"import ammico.multimodal_search as ms"
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -46,7 +47,7 @@
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"images = misinformation.utils.find_files(\n",
|
||||
"images = ammico.utils.find_files(\n",
|
||||
" path=\"data/\",\n",
|
||||
" limit=10,\n",
|
||||
")"
|
||||
@ -61,7 +62,7 @@
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"mydict = misinformation.utils.initialize_dict(images)"
|
||||
"mydict = ammico.utils.initialize_dict(images)"
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -276,8 +277,8 @@
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"outdict = misinformation.utils.append_data_to_dict(mydict)\n",
|
||||
"df = misinformation.utils.dump_df(outdict)"
|
||||
"outdict = ammico.utils.append_data_to_dict(mydict)\n",
|
||||
"df = ammico.utils.dump_df(outdict)"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@ -8,10 +8,11 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"This notebooks shows some preliminary work on detecting objects expressions with cvlib. It is mainly meant to explore its capabilities and to decide on future research directions. We package our code into a `misinformation` package that is imported here:"
|
||||
"This notebooks shows some preliminary work on detecting objects expressions with cvlib. It is mainly meant to explore its capabilities and to decide on future research directions. We package our code into a `ammico` package that is imported here:"
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -22,10 +23,10 @@
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import misinformation\n",
|
||||
"from misinformation import utils as mutils\n",
|
||||
"from misinformation import display as mdisplay\n",
|
||||
"import misinformation.objects as ob"
|
||||
"import ammico\n",
|
||||
"from ammico import utils as mutils\n",
|
||||
"from ammico import display as mdisplay\n",
|
||||
"import ammico.objects as ob"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@ -8,10 +8,11 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"This notebooks shows some preliminary work on Image Captioning and Visual question answering with lavis. It is mainly meant to explore its capabilities and to decide on future research directions. We package our code into a `misinformation` package that is imported here:"
|
||||
"This notebooks shows some preliminary work on Image Captioning and Visual question answering with lavis. It is mainly meant to explore its capabilities and to decide on future research directions. We package our code into a `ammico` package that is imported here:"
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -22,9 +23,9 @@
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from misinformation import utils as mutils\n",
|
||||
"from misinformation import display as mdisplay\n",
|
||||
"import misinformation.summary as sm"
|
||||
"from ammico import utils as mutils\n",
|
||||
"from ammico import display as mdisplay\n",
|
||||
"import ammico.summary as sm"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@ -26,8 +26,8 @@
|
||||
" # update python version\n",
|
||||
" # install setuptools\n",
|
||||
" !pip install setuptools==61 -qqq\n",
|
||||
" # install misinformation\n",
|
||||
" !pip install git+https://github.com/ssciwr/misinformation.git -qqq\n",
|
||||
" # install ammico\n",
|
||||
" !pip install git+https://github.com/ssciwr/ammico.git -qqq\n",
|
||||
" # mount google drive for data and API key\n",
|
||||
" from google.colab import drive\n",
|
||||
"\n",
|
||||
@ -43,9 +43,9 @@
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import misinformation\n",
|
||||
"from misinformation import utils as mutils\n",
|
||||
"from misinformation import display as mdisplay"
|
||||
"import ammico\n",
|
||||
"from ammico import utils as mutils\n",
|
||||
"from ammico import display as mdisplay"
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -133,7 +133,7 @@
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"for key in mydict:\n",
|
||||
" mydict[key] = misinformation.text.TextDetector(\n",
|
||||
" mydict[key] = ammico.text.TextDetector(\n",
|
||||
" mydict[key], analyse_text=True\n",
|
||||
" ).analyse_image()"
|
||||
]
|
||||
|
||||
@ -1,127 +0,0 @@
|
||||
{
|
||||
"v9_4": {
|
||||
"order": 169,
|
||||
"variable_label": "4=PICTURE_SPECIFIC_VisualONLY",
|
||||
"variable_explanation": "Person visible",
|
||||
"variable_coding": "Bool",
|
||||
"variable_comment": "Yes if there's someone shown",
|
||||
"variable_mydict": "face",
|
||||
"value_mydict": "Yes"
|
||||
},
|
||||
"v9_5a": {
|
||||
"order": 170,
|
||||
"variable_label": "5a=PICTURE_SPECIFIC_VisualONLY",
|
||||
"variable_explanation": "More than one person shown",
|
||||
"variable_coding": "Bool",
|
||||
"variable_comment": "Yes if there are several individuals who appear in the post (do not count profile pictures)",
|
||||
"variable_mydict": "multiple_faces",
|
||||
"value_mydict": "Yes"
|
||||
},
|
||||
"v9_5b": {
|
||||
"order": 171,
|
||||
"variable_label": "5b=PICTURE_SPECIFIC_VisualONLY",
|
||||
"variable_explanation": "How many people shown?",
|
||||
"variable_coding": "Int",
|
||||
"variable_comment": "If more than 15, put 99",
|
||||
"variable_mydict": "no_faces",
|
||||
"value_mydict": "0"
|
||||
},
|
||||
"v9_6": {
|
||||
"order": 172,
|
||||
"variable_label": "6=PICTURE_SPECIFIC_VisualONLY",
|
||||
"variable_explanation": "Face fully visible",
|
||||
"variable_coding": "Bool",
|
||||
"variable_comment": "Yes if you can see all their face (no mask on)",
|
||||
"variable_mydict": "wears_mask",
|
||||
"value_mydict": "No"
|
||||
},
|
||||
"v9_7": {
|
||||
"order": 173,
|
||||
"variable_label": "7=PICTURE_SPECIFIC_VisualONLY",
|
||||
"variable_explanation": "Face ONLY partially visible",
|
||||
"variable_coding": "Bool",
|
||||
"variable_comment": "Yes if you can only see part of their face, including when they are wearing a mask",
|
||||
"variable_mydict": "wears_mask",
|
||||
"value_mydict": "Yes"
|
||||
},
|
||||
"v9_8": {
|
||||
"order": 174,
|
||||
"variable_label": "8=PICTURE_SPECIFIC_VisualONLY",
|
||||
"variable_explanation": "Facial positive expression",
|
||||
"variable_coding": "Bool",
|
||||
"variable_comment": "Yes if they display some kind of positive facial expression (smiling, happy, relieved, hopeful etc.)",
|
||||
"variable_mydict": "emotion (category)",
|
||||
"value_mydict": "Positive"
|
||||
},
|
||||
"v9_8a": {
|
||||
"order": 175,
|
||||
"variable_label": "8a=PICTURE_SPECIFIC_VisualONLY",
|
||||
"variable_explanation": "Positive expression: happiness",
|
||||
"variable_coding": "Bool",
|
||||
"variable_comment": "Yes if they display happiness",
|
||||
"variable_mydict": "emotion",
|
||||
"value_mydict": "happy"
|
||||
},
|
||||
"v9_9": {
|
||||
"order": 176,
|
||||
"variable_label": "9=PICTURE_SPECIFIC_VisualONLY",
|
||||
"variable_explanation": "Facial negative expression",
|
||||
"variable_coding": "Bool",
|
||||
"variable_comment": "Yes if they display some kind of negative facial expression (crying, showing ager, fear, disgust etc.)",
|
||||
"variable_mydict": "emotion (category)",
|
||||
"value_mydict": "Negative"
|
||||
},
|
||||
"v9_10": {
|
||||
"order": 177,
|
||||
"variable_label": "10=PICTURE_SPECIFIC_VisualONLY",
|
||||
"variable_explanation": "Negative expression: anxiety",
|
||||
"variable_coding": "Bool",
|
||||
"variable_comment": "Yes if they show fear or anxiety. If you can't tell, choose No=0",
|
||||
"variable_mydict": "emotion",
|
||||
"value_mydict": "fear"
|
||||
},
|
||||
"v9_11": {
|
||||
"order": 178,
|
||||
"variable_label": "11=PICTURE_SPECIFIC_VisualONLY",
|
||||
"variable_explanation": "Negative expression: anger",
|
||||
"variable_coding": "Bool",
|
||||
"variable_comment": "Yes if they show anger or outrage. If you can't tell, choose No=0",
|
||||
"variable_mydict": "emotion",
|
||||
"value_mydict": "angry"
|
||||
},
|
||||
"v9_12": {
|
||||
"order": 179,
|
||||
"variable_label": "12=PICTURE_SPECIFIC_VisualONLY",
|
||||
"variable_explanation": "Negative expression: disgust",
|
||||
"variable_coding": "Bool",
|
||||
"variable_comment": "Yes if they show disgust. If you can't tell, choose No=0",
|
||||
"variable_mydict": "emotion",
|
||||
"value_mydict": "disgust"
|
||||
},
|
||||
"v9_13": {
|
||||
"order": 180,
|
||||
"variable_label": "13=PICTURE_SPECIFIC_VisualONLY",
|
||||
"variable_explanation": "Negative expression: other, specify",
|
||||
"variable_coding": "Bool",
|
||||
"variable_comment": "Yes if they show any other negative emotion, please specify. If you can't tell, choose No=0",
|
||||
"variable_mydict": "emotion",
|
||||
"value_mydict": "sad"
|
||||
},
|
||||
"v9_13_text": {
|
||||
"order": 181,
|
||||
"variable_label": "13=PICTURE_SPECIFIC_VisualONLY",
|
||||
"variable_explanation": "Negative expression: other, specify",
|
||||
"variable_coding": "Str",
|
||||
"variable_mydict": "emotion",
|
||||
"value_mydict": ""
|
||||
},
|
||||
"v11_3": {
|
||||
"order": 189,
|
||||
"variable_label": "111_3=PICTURE_SPECIFIC_VisualONLY",
|
||||
"variable_explanation": "Respect of the rules",
|
||||
"variable_coding": "Bool",
|
||||
"variable_comment": "Yes if the post shows mask wearing, vaccine taking, social distancing, any proof of respecting the rules",
|
||||
"variable_mydict": "wears_mask",
|
||||
"value_mydict": "Yes"
|
||||
}
|
||||
}
|
||||
Двоичные данные
misinformation/test/data/IMG_1730.png
|
До Ширина: | Высота: | Размер: 10 MiB |
Двоичные данные
misinformation/test/data/IMG_2750.png
|
До Ширина: | Высота: | Размер: 801 KiB |
Двоичные данные
misinformation/test/data/IMG_2805.png
|
До Ширина: | Высота: | Размер: 758 KiB |
Двоичные данные
misinformation/test/data/IMG_2806.png
|
До Ширина: | Высота: | Размер: 788 KiB |
Двоичные данные
misinformation/test/data/IMG_2807.png
|
До Ширина: | Высота: | Размер: 1.4 MiB |
Двоичные данные
misinformation/test/data/IMG_2808.png
|
До Ширина: | Высота: | Размер: 1.3 MiB |
2
notebooks/cropposts.ipynb
сгенерированный
@ -24,7 +24,7 @@
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import misinformation.cropposts as crpo\n",
|
||||
"import ammico.cropposts as crpo\n",
|
||||
"import numpy as np\n",
|
||||
"import matplotlib.pyplot as plt\n",
|
||||
"from PIL import Image\n",
|
||||
|
||||
15
notebooks/facial_expressions.ipynb
сгенерированный
@ -9,11 +9,12 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"id": "51f8888b-d1a3-4b85-a596-95c0993fa192",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"This notebooks shows some preliminary work on detecting facial expressions with DeepFace. It is mainly meant to explore its capabilities and to decide on future research directions. We package our code into a `misinformation` package that is imported here:"
|
||||
"This notebooks shows some preliminary work on detecting facial expressions with DeepFace. It is mainly meant to explore its capabilities and to decide on future research directions. We package our code into a `ammico` package that is imported here:"
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -31,8 +32,8 @@
|
||||
" # update python version\n",
|
||||
" # install setuptools\n",
|
||||
" !pip install setuptools==61 -qqq\n",
|
||||
" # install misinformation\n",
|
||||
" !pip install git+https://github.com/ssciwr/misinformation.git -qqq\n",
|
||||
" # install ammico\n",
|
||||
" !pip install git+https://github.com/ssciwr/ammico.git -qqq\n",
|
||||
" # mount google drive for data and API key\n",
|
||||
" from google.colab import drive\n",
|
||||
"\n",
|
||||
@ -46,9 +47,9 @@
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import misinformation\n",
|
||||
"from misinformation import utils as mutils\n",
|
||||
"from misinformation import display as mdisplay"
|
||||
"import ammico\n",
|
||||
"from ammico import utils as mutils\n",
|
||||
"from ammico import display as mdisplay"
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -145,7 +146,7 @@
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"for key in mydict.keys():\n",
|
||||
" mydict[key] = misinformation.faces.EmotionDetector(mydict[key]).analyse_image()"
|
||||
" mydict[key] = ammico.faces.EmotionDetector(mydict[key]).analyse_image()"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
16
notebooks/get-text-from-image.ipynb
сгенерированный
@ -24,8 +24,8 @@
|
||||
" # update python version\n",
|
||||
" # install setuptools\n",
|
||||
" !pip install setuptools==61 -qqq\n",
|
||||
" # install misinformation\n",
|
||||
" !pip install git+https://github.com/ssciwr/misinformation.git -qqq\n",
|
||||
" # install ammico\n",
|
||||
" !pip install git+https://github.com/ssciwr/ammico.git -qqq\n",
|
||||
" # mount google drive for data and API key\n",
|
||||
" from google.colab import drive\n",
|
||||
"\n",
|
||||
@ -40,9 +40,9 @@
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import os\n",
|
||||
"import misinformation\n",
|
||||
"from misinformation import utils as mutils\n",
|
||||
"from misinformation import display as mdisplay"
|
||||
"import ammico\n",
|
||||
"from ammico import utils as mutils\n",
|
||||
"from ammico import display as mdisplay"
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -126,7 +126,7 @@
|
||||
"source": [
|
||||
"for key in mydict:\n",
|
||||
" print(key)\n",
|
||||
" mydict[key] = misinformation.text.TextDetector(\n",
|
||||
" mydict[key] = ammico.text.TextDetector(\n",
|
||||
" mydict[key], analyse_text=True\n",
|
||||
" ).analyse_image()"
|
||||
]
|
||||
@ -198,7 +198,7 @@
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# make a list of all the text_english entries per analysed image from the mydict variable as above\n",
|
||||
"topic_model, topic_df, most_frequent_topics = misinformation.text.PostprocessText(\n",
|
||||
"topic_model, topic_df, most_frequent_topics = ammico.text.PostprocessText(\n",
|
||||
" mydict=mydict\n",
|
||||
").analyse_topic()"
|
||||
]
|
||||
@ -220,7 +220,7 @@
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"input_file_path = \"data_out.csv\"\n",
|
||||
"topic_model, topic_df, most_frequent_topics = misinformation.text.PostprocessText(\n",
|
||||
"topic_model, topic_df, most_frequent_topics = ammico.text.PostprocessText(\n",
|
||||
" use_csv=True, csv_path=input_file_path\n",
|
||||
").analyse_topic(return_topics=10)"
|
||||
]
|
||||
|
||||
15
notebooks/image_summary.ipynb
сгенерированный
@ -8,10 +8,11 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"This notebooks shows some preliminary work on Image Captioning and Visual question answering with lavis. It is mainly meant to explore its capabilities and to decide on future research directions. We package our code into a `misinformation` package that is imported here:"
|
||||
"This notebooks shows some preliminary work on Image Captioning and Visual question answering with lavis. It is mainly meant to explore its capabilities and to decide on future research directions. We package our code into a `ammico` package that is imported here:"
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -28,8 +29,8 @@
|
||||
" # update python version\n",
|
||||
" # install setuptools\n",
|
||||
" !pip install setuptools==61 -qqq\n",
|
||||
" # install misinformation\n",
|
||||
" !pip install git+https://github.com/ssciwr/misinformation.git -qqq\n",
|
||||
" # install ammico\n",
|
||||
" !pip install git+https://github.com/ssciwr/ammico.git -qqq\n",
|
||||
" # mount google drive for data and API key\n",
|
||||
" from google.colab import drive\n",
|
||||
"\n",
|
||||
@ -44,10 +45,10 @@
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import misinformation\n",
|
||||
"from misinformation import utils as mutils\n",
|
||||
"from misinformation import display as mdisplay\n",
|
||||
"import misinformation.summary as sm"
|
||||
"import ammico\n",
|
||||
"from ammico import utils as mutils\n",
|
||||
"from ammico import display as mdisplay\n",
|
||||
"import ammico.summary as sm"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
15
notebooks/multimodal_search.ipynb
сгенерированный
@ -9,11 +9,12 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"id": "9eeeb302-296e-48dc-86c7-254aa02f2b3a",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"This notebooks shows some preliminary work on Image Multimodal Search with lavis library. It is mainly meant to explore its capabilities and to decide on future research directions. We package our code into a `misinformation` package that is imported here:"
|
||||
"This notebooks shows some preliminary work on Image Multimodal Search with lavis library. It is mainly meant to explore its capabilities and to decide on future research directions. We package our code into a `ammico` package that is imported here:"
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -31,8 +32,8 @@
|
||||
" # update python version\n",
|
||||
" # install setuptools\n",
|
||||
" !pip install setuptools==61 -qqq\n",
|
||||
" # install misinformation\n",
|
||||
" !pip install git+https://github.com/ssciwr/misinformation.git -qqq\n",
|
||||
" # install ammico\n",
|
||||
" !pip install git+https://github.com/ssciwr/ammico.git -qqq\n",
|
||||
" # mount google drive for data and API key\n",
|
||||
" from google.colab import drive\n",
|
||||
"\n",
|
||||
@ -48,8 +49,8 @@
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import misinformation.utils as mutils\n",
|
||||
"import misinformation.multimodal_search as ms"
|
||||
"import ammico.utils as mutils\n",
|
||||
"import ammico.multimodal_search as ms"
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -373,8 +374,8 @@
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"outdict = misinformation.utils.append_data_to_dict(mydict)\n",
|
||||
"df = misinformation.utils.dump_df(outdict)"
|
||||
"outdict = ammico.utils.append_data_to_dict(mydict)\n",
|
||||
"df = ammico.utils.dump_df(outdict)"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
15
notebooks/objects_expression.ipynb
сгенерированный
@ -8,10 +8,11 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"This notebooks shows some preliminary work on detecting objects expressions with cvlib. It is mainly meant to explore its capabilities and to decide on future research directions. We package our code into a `misinformation` package that is imported here:"
|
||||
"This notebooks shows some preliminary work on detecting objects expressions with cvlib. It is mainly meant to explore its capabilities and to decide on future research directions. We package our code into a `ammico` package that is imported here:"
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -28,8 +29,8 @@
|
||||
" # update python version\n",
|
||||
" # install setuptools\n",
|
||||
" !pip install setuptools==61 -qqq\n",
|
||||
" # install misinformation\n",
|
||||
" !pip install git+https://github.com/ssciwr/misinformation.git -qqq\n",
|
||||
" # install ammico\n",
|
||||
" !pip install git+https://github.com/ssciwr/ammico.git -qqq\n",
|
||||
" # mount google drive for data and API key\n",
|
||||
" from google.colab import drive\n",
|
||||
"\n",
|
||||
@ -42,10 +43,10 @@
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import misinformation\n",
|
||||
"from misinformation import utils as mutils\n",
|
||||
"from misinformation import display as mdisplay\n",
|
||||
"import misinformation.objects as ob"
|
||||
"import ammico\n",
|
||||
"from ammico import utils as mutils\n",
|
||||
"from ammico import display as mdisplay\n",
|
||||
"import ammico.objects as ob"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@ -5,9 +5,9 @@ requires = [
|
||||
build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
name = "misinformation"
|
||||
name = "ammico"
|
||||
version = "0.0.1"
|
||||
description = "Misinformation campaign analysis"
|
||||
description = "AI Media and Misinformation Content Analysis Tool"
|
||||
readme = "README.md"
|
||||
maintainers = [
|
||||
{ name = "Inga Ulusoy", email = "ssc@iwr.uni-heidelberg.de" },
|
||||
@ -55,7 +55,7 @@ dependencies = [
|
||||
]
|
||||
|
||||
[project.scripts]
|
||||
misinformation_prefetch_models = "misinformation.utils:misinformation_prefetch_models"
|
||||
ammico_prefetch_models = "ammico.utils:ammico_prefetch_models"
|
||||
|
||||
[tool.setuptools]
|
||||
packages = ["misinformation"]
|
||||
packages = ["ammico"]
|
||||
|
||||