Skip to content

Commit

Permalink
Verticals !!!
Browse files Browse the repository at this point in the history
  • Loading branch information
goulven authored and goulven committed Dec 4, 2024
1 parent d78a0ef commit b6351b3
Show file tree
Hide file tree
Showing 25 changed files with 2,211 additions and 25 deletions.
4 changes: 2 additions & 2 deletions api/src/main/java/org/open4goods/api/config/ApiConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -119,8 +119,8 @@ SerialisationService serialisationService() {

@Bean
@Autowired
VerticalsGenerationService verticalsGenerationService(ProductRepository pRepo, SerialisationService serialisationService, AiService aiService, GoogleTaxonomyService gTaxoService, VerticalsConfigService verticalsConfigService) throws SAXException {
return new VerticalsGenerationService(apiProperties.getVerticalsGenerationConfig(), pRepo,serialisationService,aiService, gTaxoService, verticalsConfigService);
VerticalsGenerationService verticalsGenerationService(ProductRepository pRepo, SerialisationService serialisationService, AiService aiService, GoogleTaxonomyService gTaxoService, VerticalsConfigService verticalsConfigService, ResourcePatternResolver resourceResolver, EvaluationService evaluationService) throws SAXException {
return new VerticalsGenerationService(apiProperties.getVerticalsGenerationConfig(), pRepo,serialisationService,aiService, gTaxoService, verticalsConfigService, resourceResolver, evaluationService);
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,5 +124,21 @@ public String generateCategoryMappingsFragment(@RequestParam String category) th
}


@GetMapping(path="/assist/vertical")
@Operation(summary="Generate the vertical file")
@PreAuthorize("hasAuthority('"+RolesConstants.ROLE_ADMIN+"')")
public void generateCategoryMappingsFragment(
@RequestParam String googleTaxonomyId,
@RequestParam String matchingCategories,
@RequestParam String urlPrefix,
@RequestParam String h1Prefix,
@RequestParam String verticalHomeUrl,
@RequestParam String verticalHomeTitle) throws ResourceNotFoundException, IOException {

verticalsGenService.verticalTemplatetoFile(googleTaxonomyId, matchingCategories, urlPrefix, h1Prefix, verticalHomeUrl, verticalHomeTitle);

}



}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.open4goods.api.config.yml.VerticalsGenerationConfig;
import org.open4goods.api.model.VerticalAttributesStats;
Expand All @@ -24,37 +25,46 @@
import org.open4goods.commons.dao.ProductRepository;
import org.open4goods.commons.helper.IdHelper;
import org.open4goods.commons.model.product.Product;
import org.open4goods.commons.services.EvaluationService;
import org.open4goods.commons.services.GoogleTaxonomyService;
import org.open4goods.commons.services.SerialisationService;
import org.open4goods.commons.services.VerticalsConfigService;
import org.open4goods.commons.services.ai.AiService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.ResourcePatternResolver;

import com.fasterxml.jackson.core.type.TypeReference;

import io.micrometer.core.instrument.util.IOUtils;

public class VerticalsGenerationService {

private static final Logger LOGGER = LoggerFactory.getLogger(VerticalsGenerationService.class);
private VerticalsGenerationConfig config;
private VerticalsConfigService verticalConfigservice;
private ProductRepository repository;
private SerialisationService serialisationService;
private ResourcePatternResolver resourceResolver;



private Map<String, VerticalCategoryMapping> sortedMappings = new LinkedHashMap<String, VerticalCategoryMapping>();
private AiService aiService;
private GoogleTaxonomyService googleTaxonomyService;
private EvaluationService evalService;

public VerticalsGenerationService(VerticalsGenerationConfig config, ProductRepository repository, SerialisationService serialisationService, AiService aiService, GoogleTaxonomyService googleTaxonomyService, VerticalsConfigService verticalsConfigService) {
public VerticalsGenerationService(VerticalsGenerationConfig config, ProductRepository repository, SerialisationService serialisationService, AiService aiService, GoogleTaxonomyService googleTaxonomyService, VerticalsConfigService verticalsConfigService, ResourcePatternResolver resourceResolver, EvaluationService evaluationService) {
super();
this.config = config;
this.repository = repository;
this.serialisationService = serialisationService;
this.aiService = aiService;
this.googleTaxonomyService = googleTaxonomyService;
this.verticalConfigservice = verticalsConfigService;
this.resourceResolver = resourceResolver;
this.evalService = evaluationService;
}


Expand Down Expand Up @@ -430,13 +440,68 @@ public String generateCategoryMappingFragmentFor(String category) {
StringBuilder ret = new StringBuilder();
ret.append("matchingCategories:").append("\n");
ret.append(" - \"").append(category).append("\"\n");
for (String cat : mapping.getAssociatedCategories().keySet()) {
ret.append(" - \"").append(cat).append("\"\n");
if (null != mapping) {
for (String cat : mapping.getAssociatedCategories().keySet()) {
ret.append(" - \"").append(cat).append("\"\n");
}
}

return ret.toString();
}

/**
* Return a String containing a vertical config file, based on the "vertical.template" file
* @param id
* @param homeTitlefr
* @param googleTaxonomyId
* @param enabled
* @param matchingCategories
* @return
*/
public String verticalTemplate(String id, String googleTaxonomyId, String matchingCategories,String urlPrefix, String h1Prefix, String verticalHomeUrl, String verticalHomeTitle) {
String ret = "";
try {
Resource r = resourceResolver.getResource("classpath:/templates/vertical.yml");
String content = r.getContentAsString(Charset.defaultCharset());

Map<String, Object> context = new HashMap<String, Object>();

context.put("id",id );
context.put("googleTaxonomyId", googleTaxonomyId);
context.put("matchingCategories", generateCategoryMappingFragmentFor(matchingCategories));
context.put("urlPrefix", urlPrefix);
context.put("h1Prefix", h1Prefix);
context.put("verticalHomeUrl", verticalHomeUrl);
context.put("verticalHomeTitle", verticalHomeTitle);

ret = evalService.thymeleafEval(context, content);
} catch (IOException e) {
LOGGER.error("Error while generating vertical file",e);
}

return ret;

}

public void verticalTemplatetoFile(String googleTaxonomyId, String matchingCategories,String urlPrefix, String h1Prefix, String verticalHomeUrl, String verticalHomeTitle) {

//TODO(p3, conf) : from conf
String id = IdHelper.normalizeFileName(googleTaxonomyService.getLocalizedTaxonomy().get("en").get(Integer.valueOf(googleTaxonomyId)).getLast());

File f = new File("/opt/open4goods/tmp/");
f.mkdirs();
f = new File(f.getAbsolutePath() + "/" + id+".yml");

try {

FileUtils.write(f, verticalTemplate(id, googleTaxonomyId, matchingCategories, urlPrefix, h1Prefix, verticalHomeUrl, verticalHomeTitle));
} catch (IOException e) {
LOGGER.error("Error while writing template file", e);
}


}




}
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,17 @@ public GenAiCompletionService( AiService aiService, ProductRepository dataReposi
public void processProduct(VerticalConfig vertical, Product data) {
logger.info("AI text completion for {}", data.getId());

// Operating genai completion
aiService.complete(data, vertical, false);

// Sleeping, to avoid rate limitation
try {
Thread.sleep(apiProperties.getGenAiPauseDurationMs());
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
logger.error("Thread interrupted during rate limiting", e);
if (vertical.getGenAiConfig().isEnabled()) {
// Operating genai completion
aiService.complete(data, vertical, false);

// Sleeping, to avoid rate limitation
try {
Thread.sleep(apiProperties.getGenAiPauseDurationMs());
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
logger.error("Thread interrupted during rate limiting", e);
}
}
}

Expand Down
122 changes: 122 additions & 0 deletions api/src/main/resources/templates/vertical.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
####################################################################################################################################################################
#
# This is the configuration for the [(${id.toUpperCase()})] vertical.
# Generated on the vertical.yml template file, using the VerticalsGenerationService.verticalTemplate()
# @See open4goods/commons/src/main/java/org/open4goods/config/yml/ui/VerticalConfig.java for commented POJO definition
###################################################################################################################################################################

# Unique identifier for this vertical.
# MUST contains only charracters
# SHOULD be equal to the configuration file name, without the extension
id: [(${id})]

# The associated google taxonomyID. (Ex : FR - https://www.google.com/basepages/producttype/taxonomy-with-ids.fr-FR.txt)
# SHOULD be set, it will then force this taxonomy for all products in this vertical
googleTaxonomyId: [(${googleTaxonomyId})]

# Indicates if the vertical must be UI / sitemap / search rendered
enabled: false

##############################################################################
# Product classification from categories
##############################################################################
# Will associate to this vertical if one of the following categorie is present for the product
[(${matchingCategories})]


#####################################################################################################################################
# I18N CONFIGURATION
# Configure in a i18n way all the texts of a product, including the Url, the title, the description, the open graph metas, ....
# Use a micro templated language, that allows to introduce variables and "if condition", which allows to generate dynamic texts
######################################################################################################################################
i18n:
fr:
# The layout a product url will have. Ex : 81234555-tv-led-samsung-QL659P 2023
url:
# We can add a custom prefix (with our conditional templating language if we want)
prefix: "[(${urlPrefix})]"
# Then we add some attributes values with hyphens if present (ex : led-samsung-QL659P-2023)
attrs:
- BRAND
- MODEL
##################################
# Product page meta and h1 title
##################################
# The product h1 title. Constructed on the same basis than "url", but without the concatened hyphens
h1Title:
prefix: "[(${h1Prefix})]"
attrs:
- BRAND
- MODEL
- YEAR

##################################
# Vertical page elements
##################################

# url for vertical (appened to baseUrl). No templating here
verticalHomeUrl: "[(${verticalHomeUrl})]"
# Text displaid as title for the vertical
# TODO : Make verticalHomeTitle/ verticalHomeDescription templatable
verticalHomeTitle: "[(${verticalHomeTitle})]"
# Text displaid as title for the vertical
# verticalHomeDescription: ""

# A mapping beetween custom page names behind this vertical and wiki pages
# Copy and paste the wiki wiew url, without the "bin/view" prefix
# wikiPages:
# - wikiUrl: /verticals/tv/technologies-tv/WebHome
# verticalUrl: "oled-qled-lcd-que-choisir"
# title: "OLED, QLED,LCD, ... Quelle technologie choisir ?"
# faIcon: "fa-star"


# GenAiConfig for this vertical
genAiConfig:
# If false, will bypass the generativ ia texts generation
enabled: false


##############################################################################
# Eco score configuration
# Specify here the specific ecoscore for this vertical. Format :
# >> EXISTING_SCORE: WEIGHT
# Weight sum MUST BE equals to 1
##############################################################################

#ecoscoreConfig:
# CLASSE_ENERGY : 0.3
# WEIGHT: 0.3
# BRAND_SUSTAINABILITY: 0.3
# DATA-QUALITY: 0.1

##############################################################################
# Custom search filters : the following filters
# will also be availlable in search for this vertical (must be an attribute or a score)
##############################################################################



ecoFilters:
# - "REPAIRABILITY_INDEX"
# - "CLASSE_ENERGY"
# - "ENERGY_CONSUMPTION_1000_HOURS"
# - "WEIGHT"

technicalFilters:
# - "DIAGONALE_POUCES"
# - "DISPLAY_TECHNOLOGY"
# - "HDMI_PORTS_QUANTITY"

# - "PARTS_AVAILLABILITY"
# - "DATA-QUALITY"
# - "BRAND-SUSTAINABILITY"




####################################################################################
# ATTRIBUTES CONFIGURATION
####################################################################################
#requiredAttributes:
# - DIAGONALE_POUCES
Original file line number Diff line number Diff line change
Expand Up @@ -327,8 +327,14 @@ public List<AttributeConfig> verticalFilters() {
*/
public List<String> getVerticalFilters() {
List<String> filters = new ArrayList<String>();
filters.addAll(ecoFilters);
filters.addAll(technicalFilters);

if (null != ecoFilters) {
filters.addAll(ecoFilters);
}

if (null != technicalFilters) {
filters.addAll(technicalFilters);
}
filters.addAll(globalTechnicalFilters);
return filters;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,19 @@ public String thymeleafEval(final Product p, final String template) {
return thymeleafEval(p, template, null);
}


/**
* Generate a name from the thymleaf template weared in conf
* Sample : "blabla de [(${p.vertical})]"
* TODO(p3,safety) : Should raise exception if unresolvable variable
* @param p
* @param template
* @return
*/
public String thymeleafEval(final Map<String,Object> params, final String template) {
return thymeleafEval(null, template, params);
}

/**
* Generate a name from the thymleaf template weared in conf
* Sample : "blabla de [(${p.vertical})]"
Expand All @@ -121,16 +134,18 @@ public String thymeleafEval(final Product p, final String template, Map<String,O
ctx.setVariables(additionalParams);
}

// Adding referentiel keys
for (Entry<ReferentielKey, String> e : p.getAttributes().getReferentielAttributes().entrySet()) {
ctx.setVariable(e.getKey().toString(), e.getValue());
if (p != null) {
// Adding referentiel keys
for (Entry<ReferentielKey, String> e : p.getAttributes().getReferentielAttributes().entrySet()) {
ctx.setVariable(e.getKey().toString(), e.getValue());
}
}

final String ret = thymeleafTemplateEngine.process(template, ctx);
return ret;

} catch (final Exception e) {
logger.warn("Eval failed for {} : {} : {}", p, e.getMessage(), e.getCause().getMessage());
logger.warn("Eval failed for {} : {} : {}", p, e.getMessage(), e.getCause());
return null;
}
}
Expand Down
16 changes: 16 additions & 0 deletions verticals/src/main/resources/verticals/_default.yml
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,22 @@ genAiConfig:
# If false, will bypass the generativ ia texts generation
enabled: false


##############################################################################
# Eco score configuration
# Specify here the specific ecoscore for this vertical. Format :
# >> EXISTING_SCORE: WEIGHT
# Weight sum MUST BE equals to 1
##############################################################################

ecoscoreConfig:
CLASSE_ENERGY : 0.3
WEIGHT: 0.3
BRAND_SUSTAINABILITY: 0.3
DATA-QUALITY: 0.1



requiredAttributes:
# - WEIGHT

Expand Down
Loading

0 comments on commit b6351b3

Please sign in to comment.