En este blog vamos a crear unknowledge graphpara recomendaciones de productos utilizando taxonomía y taxonomía complementaria.CocoIndexFacilita la creación y el mantenimiento de gráficos de conocimiento con actualizaciones continuas de fuente.
Product taxonomy iuna forma de organizar los catálogos de productos en una estructura lógica y jerárquica; se puede encontrar una gran explicación detalladaAquíEn la práctica, es un problema complicado: un producto puede formar parte de múltiples categorías, y una categoría puede tener varios padres.
También usaremos el LLM para generar una lista de taxonomías complementarias para cada producto - por ejemplo, cuando alguien compra un caderno de notas, también puede comprar una pluma como un producto complementario.
El código fuente está disponible enCocoIndex Ejemplos - product_taxonomy.
Estamos constantemente mejorando, y más características y ejemplos están llegando pronto.starringour GitHub Repo.
GitHub RepoPrecondiciones
- Instalar PostgreSQL. CocoIndex utiliza PostgreSQL internamente para el procesamiento incremental.
- Instalar Neo4j, una base de datos de gráficos.
- Alternativamente, puede cambiar a Ollama, que ejecuta los modelos LLM localmente - guía.
Documentación
Puede leer la documentación oficial de CocoIndex para los objetivos del gráfico de propiedadesAquí.
Flujo de datos para construir un gráfico del conocimiento
Vista general
El flujo principal es de100 líneas de código Python.
Declararemos un flujo de datos
- Productos de Inserción (en JSON)
- for each product,
- parse JSON
- map & clean up data
- extract taxonomy from the mapped data
- Recogida de datos
- Exportación de datos a neo4j
Agregar documentos como fuente
@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ón aTítulo. elfilename
Es la llave de la TDT.
Añadir colectores de datos
Añadir colectores en el alcance raíz para recoger el producto, la taxonomía y la taxonomía complementaria.
product_node = data_scope.add_collector()
product_taxonomy = data_scope.add_collector()
product_complementary_taxonomy = data_scope.add_collector()
Proceso de cada producto
Analizaremos el archivo JSON para cada producto, y transformaremos los datos en el formato que necesitamos para el procesamiento a continuación.
Mapas de datos
@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í definimos una función para el mapeo de datos, por ejemplo,
- Limpiar el campo de identificación
- Título del mapa -> Título
- Limpiar el campo de precios
- generar una cadena de marcado para el detalle del producto basado en todos los campos (para el LLM para extraer taxonomía y taxonomía complementaria, encontramos que el marcado funciona mejor como contexto para el LLM).
El flujo
Dentro del flujo, conectamos la transformación de mapeo de datos para procesar cada producto 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ón es el archivo JSON.
- El segundo transform() realiza el mapeo de datos definido.
- Recopilamos los campos que necesitamos para el nodo del producto en Neo4j.
Extraer taxonomía y taxonomía complementaria utilizando LLM
Definición de la taxonomía del producto
Dado que estamos utilizando el LLM para extraer la taxonomía del producto, necesitamos proporcionar una instrucción detallada en la doctrina de nivel de clase.
@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
Define la Taxonomía de Productos
Básicamente queremos extraer todas las taxonomías posibles para un producto, y pensar en qué otros productos son susceptibles de ser comprados junto con el producto 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]
Para cada producto, queremos algo de información sobre su taxonomía y taxonomía complementaria y podríamos usar eso como puente para encontrar un producto relacionado utilizando el gráfico del conocimiento.
LLM Extracción
Por último, se utilizarácocoindex.functions.ExtractByLlm
para extraer la taxonomía y la taxonomía complementaria del detalle del producto.
taxonomy = data["detail"].transform(cocoindex.functions.ExtractByLlm(
llm_spec=cocoindex.LlmSpec(
api_type=cocoindex.LlmApiType.OPENAI, model="gpt-4.1"),
output_type=ProductTaxonomyInfo))
Por ejemplo, LLM toma la descripción de laEl Pen, y extrae taxonomía para serEl PenSin embargo, se ha sugerido que cuando la gente compraEl PenTambién pueden estar interesados enNotasComo la taxonomía complimentaria.
Y luego recogeremos la taxonomía y la taxonomía complementaria al colector.
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ón de gráficos de conocimiento
Conceptos básicos
Todos los nodos para Neo4j necesitan dos cosas:
- Etiqueta: El tipo de nodo. por ejemplo, producto, taxonomía.
- Campo de clave primaria: El campo que identifica de forma única el nodo.
CocoIndex utiliza el campo de clave primaria para coincidir con los nodos y deduplicarlos.Si tiene varios nodos con la misma clave primaria, CocoIndex mantiene solo uno de ellos.
Hay dos formas de mapear los nodos:
- Cuando usted tiene un colector sólo para el nodo, puede exportarlo directamente a Neo4j. Por ejemplo Producto.
- Cuando tenga un colector de relaciones que se conecte al nodo, puede mapear los nodos de los campos seleccionados en el colector de relaciones.
Por ejemplo,
product_taxonomy.collect(id=cocoindex.GeneratedField.UUID, product_id=data["id"], taxonomy=t["name"])
Recoge una relación y se crea un nodo de taxonomía a partir de la relación.
Configuración de la conexión Neo4j:
conn_spec = cocoindex.add_auth_entry(
"Neo4jConnection",
cocoindex.storages.Neo4jConnection(
uri="bolt://localhost:7687",
user="neo4j",
password="cocoindex",
))
ExportacionesProduct
Nódulos para Neo4j
Producto
product_node.export(
"product_node",
cocoindex.storages.Neo4j(
connection=conn_spec,
mapping=cocoindex.storages.Nodes(label="Product")
),
primary_key_fields=["id"],
)
Esta exporta los nodos Neo4j con etiquetaProduct
Desde laproduct_node
El coleccionista.
- It declares Neo4j node label
Product
. It specifiesid
as the primary key field. - Transporta todos los campos desde el colector de product_node hasta los nodos de Neo4j con la etiqueta Product.
ExportacionesTaxonomía
Nódulos para Neo4j
Taxonomía
No tenemos un colector específico paraTaxonomy
Las nubes son parte de laproduct_taxonomy
yproduct_complementary_taxonomy
Los colectores y campos se recogen durante la extracción taxonómica.
Para exportarlos como nodos Neo4j, necesitamos declarar primeroTaxonomy
los nodos.
flow_builder.declare(
cocoindex.storages.Neo4jDeclaration(
connection=conn_spec,
nodes_label="Taxonomy",
primary_key_fields=["value"],
)
)
A continuación, la exportación deproduct_taxonomy
En el caso 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"],
)
También podemos exportar elproduct_complementary_taxonomy
En el caso 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 cómo mapear relaciones en Neo4j.
En una relación hay:
- Un nodo de fuente y un nodo de meta.
- Una relación que conecta la fuente y la meta.Tenga en cuenta que diferentes relaciones pueden compartir los mismos nodos de fuente y meta.
NodeFromFields
Toma los campos de laentity_relationship
Coleccionista y creadorTaxonomy
los nodos.
Funciones principales
Finalmente, la función principal para el flujo inicia el flujo de CocoIndex y lo ejecuta.
@cocoindex.main_fn()
def _run():
pass
if __name__ == "__main__":
load_dotenv(override=True)
_run()
Busca y prueba tu índice
¡Ahora todos están preparados!
-
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 el gráfico del conocimiento
Después de que se haya construido el gráfico del conocimiento, puede explorar el gráfico del conocimiento que ha construido en el Neo4j Browser.
Para el entorno de desarrollo, puede conectarse al navegador Neo4j utilizando credenciales:
- Nombre del usuario: Neo4j
- contraseña: cocoindex que está preconfigurado en nuestro docker compone config.yaml.
Puedes abrirlo enhttp://localhost:7474, y ejecute la siguiente consulta de cifrado para obtener todas las relaciones:
MATCH p=()-->() RETURN p
Apoyanos
Estamos constantemente mejorando, y más características y ejemplos están llegando pronto.Si te gusta este artículo, por favor, dénos una estrella ⭐ enGitHub RepoPara ayudarnos a crecer.
¡Gracias por leer!