In hierdie blog sal ons 'nknowledge graphvir produkaanbevelings met behulp van taksonomie en komplementêre taksonomie.Die CocoIndexmaak dit maklik om kenniskaarte te bou en te onderhou met voortdurende bronupdates.
Product taxonomy is 'n manier om produkkatalogi in 'n logiese en hiërargiese struktuur te organiseer; 'n groot gedetailleerde verduideliking kan gevind wordhierIn die praktyk is dit 'n ingewikkelde probleem: 'n produk kan deel wees van verskeie kategorieë, en 'n kategorie kan verskeie ouers hê.
Ons sal ook die LLM gebruik om 'n lys van komplementêre taksonomieë vir elke produk te genereer - byvoorbeeld, wanneer iemand 'n notablad koop, kan hulle ook 'n pen as 'n komplementêre produk koop.
Die bron kode is beskikbaar byCocoIndex Voorbeelde - product_taxonomy.
Ons verbeter voortdurend, en meer funksies en voorbeelde kom binnekort.starringdieour GitHub repo.
GitHub repoVoorwaardes
- Installeer PostgreSQL. CocoIndex gebruik PostgreSQL intern vir incrementele verwerking.
- Installeer Neo4j, 'n grafiese databasis.
- Konfigureer jou OpenAI API sleutel. Alternatief, kan jy skakel na Ollama, wat LLM modelle plaaslik hardloop - gids.
Dokumenteer
Jy kan die amptelike CocoIndex Dokumentasie vir Property Graph Targets leeshier.
Data vloei om kennis grafiek te bou
Oorsig
Die kernstroom is oor~100 reëls van Python kode.
Ons sal 'n data vloei verklaar
- produkte ingestel (in JSON)
- for each product,
- parse JSON
- map & clean up data
- extract taxonomy from the mapped data
- versamel data
- Uitvoer data na neo4j
Voeg dokumente by as bron
@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))
hierflow_builder.add_source
Skep 'nKykDiefilename
Dit is die sleutel van die KTable.
Voeg data versamelaars
Voeg versamelaars by die wortelomvang by om die produk, taksonomie en komplementêre taksonomie te versamel.
product_node = data_scope.add_collector()
product_taxonomy = data_scope.add_collector()
product_complementary_taxonomy = data_scope.add_collector()
Verwerking van elke produk
Ons sal die JSON-lêer vir elke produk parseer en die data omskep na die formaat wat ons nodig het vir verdere verwerking.
Data kaartjie
@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),
)
Hier definieer ons 'n funksie vir data-mapping, byvoorbeeld,
- Maak die ID veld skoon
- Titel van die kaart -> Titel
- Maak die pryseveld skoon
- genereer 'n markdown string vir die produk besonderhede gebaseer op al die velde (vir LLM om taksonomie en komplementêre taksonomie te onttrek, vind ons dat markdown die beste werk as konteks vir LLM).
Die vloei
Binne die vloei sluit ons die data-mapping-transformasie in om elke produk JSON te verwerk.
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"])
- Die eerste transform() parseer die JSON-lêer.
- Die tweede transform() voer die gedefinieerde data-mapping uit.
- Ons versamel die velde wat ons nodig het vir die produknodus in Neo4j.
Ekstrakteer taksonomie en komplementêre taksonomie met behulp van LLM
Product Taxonomy Definisie
Aangesien ons die LLM gebruik om produktaksonomie te onttrek, moet ons 'n gedetailleerde instruksies op die klasvlak dokstring verskaf.
@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
Definieer produk Taxonomy Info
In wese wil ons al die moontlike taksonomies vir 'n produk onttrek, en dink oor watter ander produkte waarskynlik saam met die huidige produk gekoop sal word.
@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]
Vir elke produk wil ons 'n bietjie insig oor sy taksonomie en komplementêre taksonomie hê en ons kan dit gebruik as 'n brug om verwante produk te vind met behulp van kennisgraaf.
LLM Ekstraksie
Ten slotte sal ons gebruikcocoindex.functions.ExtractByLlm
om die taksonomie en komplementêre taksonomie uit die produkdetail te onttrek.
taxonomy = data["detail"].transform(cocoindex.functions.ExtractByLlm(
llm_spec=cocoindex.LlmSpec(
api_type=cocoindex.LlmApiType.OPENAI, model="gpt-4.1"),
output_type=ProductTaxonomyInfo))
Byvoorbeeld, die LLM neem die beskrywing van dieDie pen, en ekstrakteer taksonomie om te weesDie penDit beteken dat wanneer mense koopDie penHulle kan ook geïnteresseerd wees inNotasieDit is 'n komplimentêre taksonomie.
En dan sal ons die taksonomie en komplementêre taksonomie aan die versamelaar versamel.
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"])
Bepaal kennis grafiek
basiese konsepte
Alle nodes vir Neo4j benodig twee dinge:
- Label: Die tipe van die knoop. byvoorbeeld, produk, taksonomie.
- Primêre sleutelveld: Die veld wat die knoop uniek identifiseer. byvoorbeeld, id vir produkknodes.
CocoIndex gebruik die primêre sleutelveld om die nodes te ooreenkom en hulle te verdubbel. As jy verskeie nodes met dieselfde primêre sleutel het, hou CocoIndex slegs een van hulle.
Daar is twee maniere om nodes te kaarteer:
- Wanneer jy 'n versamelaar net vir die knoop het, kan jy dit direk na Neo4j uitvoer. byvoorbeeld produk.
- Wanneer u 'n versamelaar vir verhoudings het wat verbind word met die knoop, kan u nodes van geselekteerde velde in die verhoudingsversamelaar kaarteer.
Byvoorbeeld,
product_taxonomy.collect(id=cocoindex.GeneratedField.UUID, product_id=data["id"], taxonomy=t["name"])
Versamel 'n verhouding, en taksonomiese knoop word uit die verhouding geskep.
Om die Neo4j verbinding te stel:
conn_spec = cocoindex.add_auth_entry(
"Neo4jConnection",
cocoindex.storages.Neo4jConnection(
uri="bolt://localhost:7687",
user="neo4j",
password="cocoindex",
))
Uitvoerprodukte
Geskryf deur Neo4j
produkte
product_node.export(
"product_node",
cocoindex.storages.Neo4j(
connection=conn_spec,
mapping=cocoindex.storages.Nodes(label="Product")
),
primary_key_fields=["id"],
)
Dit vervoer Neo4j nodes met labelProduct
van dieproduct_node
die versamelaar.
- Dit verklaar die Neo4j-node label Product. Dit spesifiseer id as die primêre sleutelveld.
- Dit dra al die velde van product_node collector na Neo4j nodes met label Product.
UitvoerTaxonomieë
Geskryf deur Neo4j
Taxonomieë
Ons het nie 'n eksplisiete versamelaar virTaxonomy
node. hulle is deel van dieproduct_taxonomy
enproduct_complementary_taxonomy
versamelers en velde word versamel tydens die taksonomiese uitvinding.
Om hulle as Neo4j-nodes te eksporteer, moet ons eers verklaarTaxonomy
die nodes.
flow_builder.declare(
cocoindex.storages.Neo4jDeclaration(
connection=conn_spec,
nodes_label="Taxonomy",
primary_key_fields=["value"],
)
)
Volgende is die uitvoer van dieproduct_taxonomy
Soos die verhouding met 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"],
)
Ons kan ook dieproduct_complementary_taxonomy
Soos die verhouding met 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"],
)
diecocoindex.storages.Relationships
Verduidelik hoe om verhoudings in Neo4j te kaarteer.
In 'n verhouding is daar:
- 'n Bronnodus en 'n Doelnodus
- 'N verhouding wat die bron en doel verbind. Let daarop dat verskillende verhoudings dieselfde bron- en doelnodes kan deel.
NodeFromFields
Neem die velde van dieentity_relationship
versamel en skepTaxonomy
die nodes.
Die hooffunksie
Ten slotte, die hooffunksie vir die vloei inisialiseer die CocoIndex vloei en voer dit uit.
@cocoindex.main_fn()
def _run():
pass
if __name__ == "__main__":
load_dotenv(override=True)
_run()
Vra en toets jou indeks
Nou is jy almal gereed!
-
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.
Browse die kennis grafiek
Nadat die kennisgraaf gebou is, kan jy die kennisgraaf wat jy in Neo4j Browser gebou het, ondersoek.
Vir die ontwikkelaar omgewing, kan jy verbinding maak met die Neo4j leser met behulp van credentials:
- Gebruikersnaam: Neo4j
- wagwoord: cocoindex wat vooraf ingestel is in ons docker compose config.yaml.
Jy kan dit oopmaak byhttp://localhost:7474, en die volgende Cypher-vraag uit te voer om al die verhoudings te kry:
MATCH p=()-->() RETURN p
Ondersteun ons
Ons is voortdurend verbeter, en meer funksies en voorbeelde kom binnekort. as jy hierdie artikel hou, gee ons asseblief 'n ster ⭐ byGitHub repoom ons te help groei.
Dankie vir die lees!