File size: 6,292 Bytes
7f10572 2584174 7f10572 2584174 7f10572 6bf4f51 8476b87 6bf4f51 8476b87 6bf4f51 8476b87 6bf4f51 8476b87 6bf4f51 8476b87 6bf4f51 8476b87 6bf4f51 8476b87 6bf4f51 128f98f |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 |
---
license: mit
language:
- en
base_model:
- meta-llama/Meta-Llama-3-8B-Instruct
pipeline_tag: text-generation
tags:
- Food
- nutrient prediction
- healthy diet
- Food NEL
- Food NER
---
# FoodyLLM: A FAIR-aligned specialized large language model for food and nutrition analysis #
## The model is based on Meta-Llama-3-8B-Instruct, which was fine-tuned (using LoRA) for food and nutrition analysis.
More specifically, it can conduct the following tasks:
- Assessing recipe nutritional profiles
- Classifying recipes by traffic light nutrition labels (see https://www.food.gov.uk/safety-hygiene/check-the-label for details on the labeling)
- Extract food named entities from text (Food NER)
- Link the food entities to three distinct ontologies, Hansard taxonomy, FoodOn and SNOMED-CT (Food NEL)
## How to use it: ##
### Load the model: ###
```python
from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig
import torch
base_model = "meta-llama/Meta-Llama-3-8B-Instruct"
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
bnb_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_quant_type="nf4",
bnb_4bit_compute_dtype=torch.float16,
bnb_4bit_use_double_quant=True,
)
model = AutoModelForCausalLM.from_pretrained(
base_model,
quantization_config=bnb_config,
device_map={"": 0},
attn_implementation="eager"
)
tokenizer = AutoTokenizer.from_pretrained(base_model, trust_remote_code=True)
tokenizer.pad_token = '<|pad|>'
tokenizer.pad_token_id = 128255
#Load LORA weights
model.load_adapter("Matej/FoodyLLM")
model.config.use_cache = True
model.eval()
```
### Return the nutrient values for an example recipe: ###
```python
system_prompt = ""
user_prompt = "Compute the nutrient values per 100 grams in a recipe with the following ingredients: 250 g cream, whipped, cream topping, pressurized, 250 g yogurt, greek, plain, nonfat, 50 g sugars, powdered"
messages = [
{
"role": "user",
"content": f"{system_prompt} {user_prompt}".strip()
}
]
prompt = tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
#Here we have a batch of one
tokenizer_input = [prompt]
inputs = tokenizer(tokenizer_input, return_tensors="pt", padding=True, truncation=True, max_length=1024).to(device)
generated_ids = model.generate(**inputs, max_new_tokens=1024, do_sample=True)
answers = tokenizer.batch_decode(generated_ids[:, inputs['input_ids'].shape[1]:])
answers = [x.split('<|eot_id|>')[0].strip() for x in answers]
print(answers[0])
```
### Expected answer: Nutrient values per 100 g highlighted: energy - 134.24, fat - 5.78, protein - 7.51, salt - 0.06, saturates - 3.58, sugars - 13.00 ###
### Classifying recipes by traffic light nutrition labels: ###
```python
user_prompt = "Review the fsa traffic lights per 100 grams in a recipe using the following ingredients: 1/2 cup soup, swanson chicken broth 99% fat free, 1 pinch salt, table"
messages = [
{
"role": "user",
"content": f"{system_prompt} {user_prompt}".strip()
}
]
prompt = tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
# Here we have a batch of one
tokenizer_input = [prompt]
inputs = tokenizer(tokenizer_input, return_tensors="pt", padding=True, truncation=True, max_length=1024).to(device)
generated_ids = model.generate(**inputs, max_new_tokens=1024, do_sample=True)
answers = tokenizer.batch_decode(generated_ids[:, inputs['input_ids'].shape[1]:])
answers = [x.split('<|eot_id|>')[0].strip() for x in answers]
print(answers[0])
```
### Expected answer: Food Standards Agency lights in each 100 g: fat - green, salt - red, saturates - green, sugars - green ###
### Extract food named entities: ###
```python
user_prompt = "Retrieve all food entities referenced in the text: Line a large colander with a cheesecloth. Stir salt into the yogurt, and pour the yogurt into the cheesecloth. Set the colander in the sink or bowl to catch the liquid that drains off. Leave to drain for 24 hours. After draining for the 24 hours, transfer the resulting cheese to a bowl. Stir in the olive oil. Store in a covered container in the refrigerator."
messages = [
{
"role": "user",
"content": f"{system_prompt} {user_prompt}".strip()
}
]
prompt = tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
# Here we have a batch of one
tokenizer_input = [prompt]
inputs = tokenizer(tokenizer_input, return_tensors="pt", padding=True, truncation=True, max_length=1024).to(device)
generated_ids = model.generate(**inputs, max_new_tokens=1024, do_sample=True)
answers = tokenizer.batch_decode(generated_ids[:, inputs['input_ids'].shape[1]:])
answers = [x.split('<|eot_id|>')[0].strip() for x in answers]
print(answers[0])
```
### Expected answer: Indeed, the entities concerning food are outlined below: salt, yogurt, liquid, cheese, olive oil. ###
### Link named entities to the SNOMEDCT ontology: ###
```python
user_prompt = "Link the following food entities to a SNOMEDCT ontology: cream cheese, meat"
messages = [
{
"role": "user",
"content": f"{system_prompt} {user_prompt}".strip()
}
]
prompt = tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
# Here we have a batch of one
tokenizer_input = [prompt]
inputs = tokenizer(tokenizer_input, return_tensors="pt", padding=True, truncation=True, max_length=1024).to(device)
generated_ids = model.generate(**inputs, max_new_tokens=1024, do_sample=True)
answers = tokenizer.batch_decode(generated_ids[:, inputs['input_ids'].shape[1]:])
answers = [x.split('<|eot_id|>')[0].strip() for x in answers]
print(answers[0])
```
### Expected answer: Indeed, the entities are connected in this fashion: cream cheese - [http://purl.bioontology.org/ontology/SNOMEDCT/226849005](http://purl.bioontology.org/ontology/SNOMEDCT/226849005); [http://purl.bioontology.org/ontology/SNOMEDCT/255621006](http://purl.bioontology.org/ontology/SNOMEDCT/255621006); [http://purl.bioontology.org/ontology/SNOMEDCT/102264005](http://purl.bioontology.org/ontology/SNOMEDCT/102264005), meat - [http://purl.bioontology.org/ontology/SNOMEDCT/28647000](http://purl.bioontology.org/ontology/SNOMEDCT/28647000). ###
|