En aquest blog anirem construint unknowledge graphper a les recomanacions de productes utilitzant taxonomia i taxonomia complementària.CocoIndexFacilita la creació i el manteniment de gràfics de coneixement amb actualitzacions de font contínues.
Product taxonomy is una manera d'organitzar els catàlegs de productes en una estructura lògica i jeràrquica; es pot trobar una gran explicació detalladaAquíEn la pràctica, és un problema complicat: un producte pot formar part de múltiples categories, i una categoria pot tenir múltiples pares.
També utilitzarem LLM per generar una llista de taxonomies complementàries per a cada producte - per exemple, quan algú compra un quadern, també poden comprar una ploma com a producte complementari.
El codi font està disponible aCocoIndex Exemples - product_taxonomy.
Estem constantment millorant, i més característiques i exemples estan arribant aviat.starringour GitHub repo.
GitHub RepoPrerequisits
- CocoIndex utilitza PostgreSQL internament per al processament incremental.
- Instal·lar Neo4j, una base de dades de gràfics.
- Alternativament, podeu canviar a Ollama, que executa els models LLM localment - guia.
Documentació
Podeu llegir la documentació oficial de CocoIndex per als objectius del gràfic de la propietatAquí.
Flux de dades per construir el gràfic del coneixement
Visió general
El flux principal és de100 línies de codi Python.
Declararem un flux de dades
- Productes d’ingestió (en JSON)
- for each product,
- parse JSON
- map & clean up data
- extract taxonomy from the mapped data
- Recollida de dades
- Exportació de dades a neo4j
Afegir documents com a font
@cocoindex.flow_def(name="StoreProduct")
def store_product_flow(flow_builder: cocoindex.FlowBuilder, data_scope: cocoindex.DataScope):
data_scope["products"] = flow_builder.add_source(
cocoindex.sources.LocalFile(path="products",
included_patterns=["*.json"]),
refresh_interval=datetime.timedelta(seconds=5))
Aquíflow_builder.add_source
Creació aCàritas. elfilename
És la clau de l’esquerra.
Afegir col·lectors de dades
Afegir col·lectors a l'abast d'arrel per recollir el producte, la taxonomia i la taxonomia complementària.
product_node = data_scope.add_collector()
product_taxonomy = data_scope.add_collector()
product_complementary_taxonomy = data_scope.add_collector()
Processament de cada producte
We will parse the JSON file for each product, and transform the data to the format that we need for downstream processing.
Mapa de dades
@cocoindex.op.function(behavior_version=2)
def extract_product_info(product: cocoindex.typing.Json, filename: str) -> ProductInfo:
return ProductInfo(
id=f"{filename.removesuffix('.json')}",
url=product["source"],
title=product["title"],
price=float(product["price"].lstrip("$").replace(",", "")),
detail=Template(PRODUCT_TEMPLATE).render(**product),
)
Aquí definim una funció per a la cartografia de dades, per exemple,
- Neteja el camp d'ID
- Títol del mapa -> Títol
- clean up the
price
field - generar una cadena de marcatge per al detall del producte basat en tots els camps (per al LLM per extreure la taxonomia i la taxonomia complementària, trobem que el marcatge funciona millor com a context per al LLM).
El flux
Dins del flux, connectem la transformació de cartografia de dades per processar cada producte JSON.
with data_scope["products"].row() as product:
data = (product["content"]
.transform(cocoindex.functions.ParseJson(), language="json")
.transform(extract_product_info, filename=product["filename"]))
product_node.collect(id=data["id"], url=data["url"], title=data["title"], price=data["price"])
- La primera transformació() pars el fitxer JSON.
- El segon transform() realitza el mapping de dades definit.
- Recopilem els camps que necessitem per al node del producte en Neo4j.
Extracció de taxonomia i taxonomia complementària utilitzant LLM
Definició de taxonomia del producte
Atès que estem utilitzant LLM per extreure la taxonomia del producte, hem de proporcionar una instrucció detallada a la doctrina de nivell de classe.
@dataclasses.dataclass
class ProductTaxonomy:
"""
Taxonomy for the product.
A taxonomy is a concise noun (or short noun phrase), based on its core functionality, without specific details such as branding, style, etc.
Always use the most common words in US English.
Use lowercase without punctuation, unless it's a proper noun or acronym.
A product may have multiple taxonomies. Avoid large categories like "office supplies" or "electronics". Use specific ones, like "pen" or "printer".
"""
name: str
Informació taxonòmica del producte
Bàsicament volem extreure totes les taxonomies possibles per a un producte, i pensar en quins altres productes són susceptibles de ser comprats juntament amb el producte actual.
@dataclasses.dataclass
class ProductTaxonomyInfo:
"""
Taxonomy information for the product.
Fields:
- taxonomies: Taxonomies for the current product.
- complementary_taxonomies: Think about when customers buy this product, what else they might need as complementary products. Put labels for these complentary products.
"""
taxonomies: list[ProductTaxonomy]
complementary_taxonomies: list[ProductTaxonomy]
Per a cada producte, volem tenir una mica de coneixement sobre la seva taxonomia i taxonomia complementària i podríem utilitzar això com a pont per trobar el producte relacionat utilitzant el gràfic del coneixement.
LLM Extracció
Finalment, utilitzaremcocoindex.functions.ExtractByLlm
per extreure la taxonomia i la taxonomia complementària del detall del producte.
taxonomy = data["detail"].transform(cocoindex.functions.ExtractByLlm(
llm_spec=cocoindex.LlmSpec(
api_type=cocoindex.LlmApiType.OPENAI, model="gpt-4.1"),
output_type=ProductTaxonomyInfo))
Per exemple, LLM pren la descripció de laPenja de gel, i extreu la taxonomia a sergel penAixò vol dir que quan la gent compraPenja de gelTambé poden estar interessats enNotíciesCom a taxonomia complimentària.
I després recollirem la taxonomia i la taxonomia complementària al col·lector.
with taxonomy['taxonomies'].row() as t:
product_taxonomy.collect(id=cocoindex.GeneratedField.UUID, product_id=data["id"], taxonomy=t["name"])
with taxonomy['complementary_taxonomies'].row() as t:
product_complementary_taxonomy.collect(id=cocoindex.GeneratedField.UUID, product_id=data["id"], taxonomy=t["name"])
Construcció de grafs de coneixement
Conceptes bàsics
Tots els nodes per a Neo4j necessiten dues coses:
- Etiqueta: El tipus de node. per exemple, producte, taxonomia.
- Camp de clau primària: El camp que identifica de manera única el node. per exemple, id per a nodes de producte.
CocoIndex utilitza el camp de clau primària per coincidir amb els nodes i deduplicar-los. Si teniu múltiples nodes amb la mateixa clau primària, CocoIndex només en conserva un.
Hi ha dues maneres de mapejar els nodes:
- Quan disposeu d'un col·lector només per al node, podeu exportar-lo directament a Neo4j. Per exemple Producte.
- Quan disposeu d'un col·lector de relacions que es connecti amb el node, podeu mapejar els nodes dels camps seleccionats en el col·lector de relacions.
Per exemple,
product_taxonomy.collect(id=cocoindex.GeneratedField.UUID, product_id=data["id"], taxonomy=t["name"])
Recull una relació i es crea un node de taxonomia a partir de la relació.
Configuració de la connexió Neo4j:
conn_spec = cocoindex.add_auth_entry(
"Neo4jConnection",
cocoindex.storages.Neo4jConnection(
uri="bolt://localhost:7687",
user="neo4j",
password="cocoindex",
))
ExportacióEl producte
Enllaç a Neo4j
El producte
product_node.export(
"product_node",
cocoindex.storages.Neo4j(
connection=conn_spec,
mapping=cocoindex.storages.Nodes(label="Product")
),
primary_key_fields=["id"],
)
Això exporta nodes Neo4j amb etiquetaProduct
Des de laproduct_node
El col·leccionista
- Es declara Neo4j node etiqueta de producte. Especifica id com el camp clau primària.
- Transporta tots els camps des del col·lector de product_node fins als nodes Neo4j amb l'etiqueta Product.
ExportacióTaxonomia
Enllaç a Neo4j
Taxonomia
No hi ha col·leccionista explícit perTaxonomy
Els nadius són part de laproduct_taxonomy
iproduct_complementary_taxonomy
Col·lectors i camps es recullen durant l'extracció taxonòmica.
Per exportar-los com a nodes Neo4j, primer hem de declararTaxonomy
els nodes.
flow_builder.declare(
cocoindex.storages.Neo4jDeclaration(
connection=conn_spec,
nodes_label="Taxonomy",
primary_key_fields=["value"],
)
)
A continuació, l’exportacióproduct_taxonomy
És el cas de Neo4j.
product_taxonomy.export(
"product_taxonomy",
cocoindex.storages.Neo4j(
connection=conn_spec,
mapping=cocoindex.storages.Relationships(
rel_type="PRODUCT_TAXONOMY",
source=cocoindex.storages.NodeFromFields(
label="Product",
fields=[
cocoindex.storages.TargetFieldMapping(
source="product_id", target="id"),
]
),
target=cocoindex.storages.NodeFromFields(
label="Taxonomy",
fields=[
cocoindex.storages.TargetFieldMapping(
source="taxonomy", target="value"),
]
),
),
),
primary_key_fields=["id"],
)
Així mateix, es pot exportar elproduct_complementary_taxonomy
És el cas de Neo4j.
product_complementary_taxonomy.export(
"product_complementary_taxonomy",
cocoindex.storages.Neo4j(
connection=conn_spec,
mapping=cocoindex.storages.Relationships(
rel_type="PRODUCT_COMPLEMENTARY_TAXONOMY",
source=cocoindex.storages.NodeFromFields(
label="Product",
fields=[
cocoindex.storages.TargetFieldMapping(
source="product_id", target="id"),
]
),
target=cocoindex.storages.NodeFromFields(
label="Taxonomy",
fields=[
cocoindex.storages.TargetFieldMapping(
source="taxonomy", target="value"),
]
),
),
),
primary_key_fields=["id"],
)
Elcocoindex.storages.Relationships
Declara com mapejar relacions en Neo4j.
En una relació, hi ha:
- Un node font i un node objectiu.
- Una relació que connecta la font i la meta. Tingueu en compte que diferents relacions poden compartir els mateixos nodes de font i meta.
NodeFromFields
Pren els camps de laentity_relationship
Col·leccionista i creadorTaxonomy
els nodes.
Funció principal
Finalment, la funció principal per al flux inicia el flux CocoIndex i l'executa.
@cocoindex.main_fn()
def _run():
pass
if __name__ == "__main__":
load_dotenv(override=True)
_run()
Cerca i prova el teu índex
Ara tots estem preparats!
-
Install the dependencies:
pip install -e .
-
Run following commands to setup and update the index.
python main.py cocoindex setup python main.py cocoindex update
You'll see the index updates state in the terminal. For example, you'll see the following output:
documents: 9 added, 0 removed, 0 updated
-
(Optional) I used CocoInsight to troubleshoot the index generation and understand the data lineage of the pipeline. It is in free beta now, you can give it a try. Run following command to start CocoInsight:
python3 main.py cocoindex server -c https://cocoindex.io
-
And then open the url https://cocoindex.io/cocoinsight. It just connects to your local CocoIndex server, with Zero pipeline data retention.
Descobreix el gràfic del coneixement
Un cop construït el gràfic del coneixement, podeu explorar el gràfic del coneixement que heu construït en el navegador Neo4j.
Per a l'entorn de desenvolupador, podeu connectar-vos al navegador Neo4j utilitzant les credencials:
- Nom d'usuari: Neo4j
- contrasenya: cocoindex que està preconfigurat en el nostre docker compost config.yaml.
Es pot obrir ahttp://localhost:7474, i executeu la següent consulta Cypher per obtenir totes les relacions:
MATCH p=()-->() RETURN p
Support us
Estem constantment millorant, i més característiques i exemples estan arribant aviat. Si t'agrada aquest article, si us plau, dóna'ns una estrella ⭐ aGitHub repoPer ajudar-nos a créixer
Gràcies per llegir!