Ένας πιο έξυπνος, ταχύτερος τρόπος αναζήτησης στη βιβλιοθήκη σας στο Steam Ξέρεις το συναίσθημα. Ψάχνετε για ένα παιχνίδι που είναι στρατηγικό, συνεργατικό, ίσως με ένα θέμα επιστημονικής φαντασίας. Μπορείτε να πάρετε έναν τοίχο τίτλων που ταιριάζουν με αυτό το είδος. Αυτό που θέλατε ήταν μια σύντομη λίστα που πραγματικά συλλαμβάνει την ατμόσφαιρα πίσω από τα λόγια σας. Σε αυτόν τον οδηγό, δείχνουμε πώς να οικοδομήσουμε ακριβώς αυτό συνδυάζοντας το Superlinked με το LlamaIndex. Το αποτέλεσμα είναι ένα προσαρμοσμένο πρόγραμμα αναζήτησης παιχνιδιών Steam που κατανοεί το είδος συν την περιγραφή συν τις ετικέτες και εξυπηρετεί απαντήσεις σε χιλιοστά δευτερόλεπτα. *Να Θέλετε να δείτε αυτό στα δεδομένα σας με πραγματικά ερωτήματα και αριθμούς καθυστέρησης; Επικοινωνήστε μαζί μας. . Get in touch Πάρτε το άγγιγμα Πάρτε το άγγιγμα Δρ ; Δρ Τα προσαρμοσμένα προγράμματα αναζήτησης σας δίνουν τον έλεγχο του πλαισίου τομέα, των μεταδεδομένων και της λογικής κατάταξης. Το Superlinked συνδυάζει πολλαπλά πεδία κειμένου σε έναν σημασιολογικό χώρο και εκτελεί ερωτήματα στη μνήμη για γρήγορα αποτελέσματα. Το LlamaIndex παρέχει την καθαρή διεπαφή λήψης και συνδέει απευθείας σε μηχανές ερωτήσεων και σύνθεση απαντήσεων. Υπάρχει μια επίσημη ενσωμάτωση Superlinked Retriever για το LlamaIndex που μπορείτε να εισαγάγετε και να χρησιμοποιήσετε. Επίσημο Superlinked Retriever για το LlamaIndex Το Superlinked ενσωματώνει με το LlamaIndex μέσω του επίσημου που αναφέρονται στο LlamaHub, ώστε να μπορείτε να προσθέσετε το Superlinked στο υπάρχον LlamaIndex Stack με μια απλή εγκατάσταση και Στη συνέχεια, τοποθετήστε το σε ένα Μάθετε περισσότερα για το Οι παράμετροι της κλάσης και του κατασκευαστή τεκμηριώνονται στην αναφορά API του LlamaIndex. SuperlinkedRetriever from llama_index.retrievers.superlinked import SuperlinkedRetriever RetrieverQueryEngine . Επίσημη σελίδα ενσωμάτωσης . Επίσημη σελίδα ενσωμάτωσης Επίσημη σελίδα ενσωμάτωσης pip install llama-index-retrievers-superlinked from llama_index.retrievers.superlinked import SuperlinkedRetriever # sl_app: a running Superlinked App # query_descriptor: a Superlinked QueryDescriptor that describes your query plan retriever = SuperlinkedRetriever( sl_client=sl_app, sl_query=query_descriptor, page_content_field="text", query_text_param="query_text", metadata_fields=None, top_k=10, ) nodes = retriever.retrieve("strategic co-op sci fi game") Προτιμάτε να το χτίσετε με το χέρι ή να προσαρμόσετε περαιτέρω τη λογική; Διαβάστε περισσότερα Why Superlinked + LlamaIndex? Γιατί Superlinked + LlamaIndex; Ο στόχος είναι απλός: πάρτε τα πλεονεκτήματα της Superlinked για ανακάλυψη πολλαπλών πεδίων και συσκευάστε τα έτσι ώστε οι προγραμματιστές να μπορούν να υιοθετήσουν και να επεκτείνουν σε πραγματικά συστήματα RAG. Το Superlinked σας βοηθά να ορίσετε εκφραστικούς φορητούς χώρους και ερωτήματα που συνδυάζουν πεδία όπως όνομα, περιγραφή και είδος σε μια ενιαία σημασιολογική προβολή. Μπορείτε επίσης να ακολουθήσετε σε χρησιμοποιώντας τα ίδια δομικά στοιχεία από τα σημειωματάρια Superlinked. Google Κολάμπ google Κολάμπ Κολάμπ Γιατί τα Custom Retrievers μετράνε Προσαρμοσμένα για το Domain σας – Τα γενικά Retrievers είναι ωραία για γενική χρήση, αλλά τείνουν να χάσουν τα λεπτά πράγματα. Σκεφτείτε τη φράση τζάργκον, συντομογραφία ή συγκεκριμένη φράση τομέα, αυτά συνήθως δεν λαμβάνονται εκτός αν το Retriever σας ξέρει τι να αναζητήσει. Λειτουργεί πέρα από το κείμενο – Τα περισσότερα δεδομένα του πραγματικού κόσμου δεν είναι μόνο απλό κείμενο. Συχνά θα έχετε μεταδεδομένα και ετικέτες επίσης. Για παράδειγμα, σε ένα σύστημα συστάσεων παιχνιδιών, δεν νοιαζόμαστε μόνο για την περιγραφή του παιχνιδιού. Θέλουμε επίσης να συντελέσουμε σε είδη, ετικέτες, αξιολογήσεις χρηστών και πολλά άλλα. Σκεφτείτε αυτή τη λογική: κάποιος που αναζητά ένα «σχέδιο συνεργασίας με στοιχεία επιστημονικής φαντασίας» δεν θα φτάσει μακριά με την αντιστοίχιση μόνο κειμένου. Προσαρμοσμένη λογική φιλτραρίσματος και κατάταξης – Μερικές φορές θέλετε να εφαρμόσετε τους δικούς σας κανόνες για το πώς τα πράγματα βαθμολογούνται ή φιλτράρονται. Ίσως θέλετε να δώσετε προτεραιότητα σε νεότερο περιεχόμενο ή να τιμωρήσετε τα αποτελέσματα που δεν πληρούν ορισμένα όρια ποιότητας. Οφέλη απόδοσης – Ας είμαστε αληθινοί: οι λύσεις γενικού σκοπού είναι κατασκευασμένες για να λειτουργούν «εντάξει» για όλους, όχι για εσάς.Αν γνωρίζετε τα δεδομένα σας και τα πρότυπα πρόσβασης, μπορείτε να ρυθμίσετε το λήπτη σας για να τρέχει γρηγορότερα, να κατατάσσεται καλύτερα και να μειώνει τον περιττό θόρυβο στα αποτελέσματα. Κατακερματισμός εφαρμογής Μέρος 1: Βασικές εξαρτήσεις και εισαγωγές import time import logging import pandas as pd from typing import List from llama_index.core.retrievers import BaseRetriever from llama_index.core.schema import NodeWithScore, QueryBundle, TextNode from llama_index.core.query_engine import RetrieverQueryEngine from llama_index.core.response_synthesizers import get_response_synthesizer from llama_index.core import Settings from llama_index.llms.openai import OpenAI import superlinked.framework as sl Η δομή των εισαγωγών αποκαλύπτει την υβριδική μας προσέγγιση: LlamaIndex Core: Παρέχει το στρώμα αφαίρεσης ανάκτησης Superlinked Framework: Διαχειρίζεται τον υπολογισμό των φορέων και τη σημασιολογική αναζήτηση Pandas: Διαχειρίζεται την προεπεξεργασία δεδομένων και τη χειραγώγηση Μέρος 2: Κατανόηση LlamaIndex Custom Retrievers Πριν βουτήξουμε στην εφαρμογή Superlinked, είναι σημαντικό να κατανοήσουμε πώς λειτουργεί η αρχιτεκτονική προσαρμοσμένων ανακτητών του LlamaIndex και γιατί είναι τόσο ισχυρή για την κατασκευή ειδικών εφαρμογών RAG. Βάση αφαίρεσης Το LlamaIndex παρέχει μια αφηρημένη Η ομορφιά αυτού του σχεδιασμού έγκειται στην απλότητά του – κάθε προσαρμοσμένο πρόγραμμα ανάκτησης χρειάζεται να εφαρμόσει μόνο μία βασική μέθοδο: BaseRetriever from abc import abstractmethod from llama_index.core.retrievers import BaseRetriever from llama_index.core.schema import NodeWithScore, QueryBundle class BaseRetriever: @abstractmethod def _retrieve(self, query_bundle: QueryBundle) -> List[NodeWithScore]: """Retrieve nodes given query.""" pass Το κατώφλι εδώ είναι η παρουσία του Πρωτοκόλλου ανάκτησης από το LlamaIndex. Δεδομένου ότι αυτό το "πρόγραμμα ανάκτησης" καθιστά εύκολο να συνδέσετε διαφορετικά backend ή στρατηγικές χωρίς να χρειάζεται να αγγίξετε το υπόλοιπο του συστήματός σας. Input: QueryBundle This is the query object passed into your retriever. At minimum, it contains the user's raw query string (e.g., "sci-fi strategy games"). But it can also include extra metadata like filters, embeddings, or user preferences. Basically, anything that might help shape a more relevant response. Output: List[NodeWithScore] The retriever returns a list of nodes—these are your chunks of content, documents, or data entries—each paired with a relevance score. The higher the score, the more relevant the node is to the query. This list is what gets passed downstream to the LLM or other post-processing steps. As in our case, we are plugging on the Processing: Backend-Agnostic Here’s the cool part: how you get from query to result is totally up to you. You can use a vector database, a traditional search engine, a REST API, or even something handcrafted for your specific use case. This decouples logic and gives you full control over the retrieval stack. Γιατί αυτό έχει σημασία; Αυτή η αφαίρεση είναι καθαρή και Αυτό σημαίνει ότι μπορείτε: Ισχυρή Συνδυάστε πολλαπλές στρατηγικές – Χρησιμοποιήστε πυκνή αναζήτηση και φιλτράρισμα λέξεων-κλειδιών μαζί, εάν είναι απαραίτητο. Εκτελέστε εύκολα δοκιμές A / B - Συγκρίνετε διαφορετικά προγράμματα ανάκτησης για να δείτε τι δίνει καλύτερα αποτελέσματα για τους χρήστες σας. Συνδέστε σε οποιονδήποτε πράκτορα ή εργαλείο - Είτε δημιουργείτε ένα chatbot, ένα interface αναζήτησης ή ένα πλήρες σύστημα πράκτορα, αυτό το retriever διασυνδέει εύκολα. Σκεφτείτε το πρωτόκολλο ανάκτησης ως το συμβόλαιο API μεταξύ του "εγκέφαλου ανάκτησης" σας και όλων των άλλων.Μόλις το ακολουθήσετε, είστε ελεύθεροι να καινοτομήσετε ό, τι θέλετε πίσω από τις σκηνές. Σύνδεση Superlinked στο LlamaIndex Εντάξει, έτσι το Η κατηγορία είναι βασικά το go-to εργαλείο μας για την παροχή έξυπνων, σημασιολογικών συστάσεων παιχνιδιών.Θα ξεκινήσουμε με μια γρήγορη ματιά στο πώς τοποθετείται και στη συνέχεια θα βουτήξουμε βαθύτερα σε κάθε μέρος για να δούμε πραγματικά τι κάνει αυτό το πράγμα να τσιμπήσει. SuperlinkedSteamGamesRetriever Πρώτα από όλα είναι η , σκεφτείτε το ως το θεμέλιο. Είναι αυτό που κρατά τα πάντα οργανωμένα και αξιόπιστα. Σας παρουσιάζουμε βασικές λεπτομέρειες όπως , , και Αυτό διατηρεί όλες τις πληροφορίες του παιχνιδιού καθαρή και συνεπή, και συνδέεται κατευθείαν στον αγωγό του Superlinked έτσι ώστε όλα να ρέουν ομαλά. schema definition GameSchema game_number name desc_snippet genre class GameSchema(sl.Schema): game_number: sl.IdField name: sl.String desc_snippet: sl.String game_details: sl.String languages: sl.String genre: sl.String game_description: sl.String original_price: sl.Float discount_price: sl.Float combined_text: sl.String # New field for combined text self.game = GameSchema() Επόμενο είναι το Αυτό είναι που συμβαίνει η μαγεία της σημασιολογικής αναζήτησης. μοντέλο για να μετατρέψει μια δέσμη πληροφοριών παιχνιδιού (όπως το όνομα, περιγραφή, είδος κ.λπ.) σε πυκνές αντιπροσωπείες φορέα. Βασικά, εξομαλύνει όλο αυτό το κείμενο μαζί σε κάτι που το μοντέλο μπορεί να καταλάβει. Έτσι, αν κάποιος ψάχνει για κάτι σαν «ανοιχτό κόσμο περιπέτειας», μπορεί να βρει παιχνίδια που ταιριάζουν πραγματικά σε αυτή τη διάθεση, όχι μόνο εκείνα με αυτές τις ακριβείς λέξεις. text similarity space sentence-transformers/all-mpnet-base-v2 Σημαίνει self.text_space = sl.TextSimilaritySpace( text=self.game.combined_text, model="sentence-transformers/all-mpnet-base-v2" ) Η είναι όπου τα πράγματα αρχίζουν πραγματικά να κάνετε κλικ. παίρνει διαφορετικά κομμάτια των πληροφοριών (όπως το όνομα του παιχνιδιού, περιγραφή, είδος, και περισσότερο) και τα συνθλίβει σε ένα μεγάλο κομμάτι κειμένου. Αυτό δίνει στο μοντέλο μια πληρέστερη εικόνα του κάθε παιχνιδιού όταν το μετατρέπουμε σε φορείς. combined text field self.df['combined_text'] = ( self.df['name'].astype(str) + " " + self.df['desc_snippet'].astype(str) + " " + self.df['genre'].astype(str) + " " + self.df['game_details'].astype(str) + " " + self.df['game_description'].astype(str) ) Και τέλος, είναι αυτό που κάνει τα πάντα super snappy. χάρη στο Superlinked , το Retriever μπορεί να χειριστεί ερωτήματα σε πραγματικό χρόνο, χωρίς καθυστερήσεις, μόνο άμεσα αποτελέσματα. αυτό σημαίνει ότι είτε κάποιος κυνηγά για ένα συγκεκριμένο είδος ή απλά ψάχνει για κάτι νέο για να παίξει, παίρνουν γρήγορες και ακριβείς συστάσεις χωρίς να περιμένουν. in-memory execution InMemoryExecutor # Set up in-memory source and executor source = sl.InMemorySource(self.game, parser=parser) self.executor = sl.InMemoryExecutor(sources=[source], indices=[self.index]) self.app = self.executor.run() # Load data source.put([self.df]) Βάλτε όλα αυτά τα κομμάτια μαζί, και έχετε το — μια σταθερή ρύθμιση για την παροχή συστάσεων παιχνιδιών που έχουν πραγματικά νόημα για τον χρήστη. Είναι γρήγορη, έξυπνη και προσωπική. SuperlinkedSteamGamesRetriever class SuperlinkedSteamGamesRetriever(BaseRetriever): """A custom LlamaIndex retriever using Superlinked for Steam games data.""" def __init__(self, csv_file: str, top_k: int = 10): """ Initialize the retriever with a CSV file path and top_k parameter. Args: csv_file (str): Path to games_data.csv top_k (int): Number of results to return (default: 10) """ self.top_k = top_k # Load the dataset and ensure all required columns are present self.df = pd.read_csv(csv_file) print(f"Loaded dataset with {len(self.df)} games") print("DataFrame Columns:", list(self.df.columns)) required_columns = [ 'game_number', 'name', 'desc_snippet', 'game_details', 'languages', 'genre', 'game_description', 'original_price', 'discount_price' ] for col in required_columns: if col not in self.df.columns: raise ValueError(f"Missing required column: {col}") # Combine relevant columns into a single field for text similarity self.df['combined_text'] = ( self.df['name'].astype(str) + " " + self.df['desc_snippet'].astype(str) + " " + self.df['genre'].astype(str) + " " + self.df['game_details'].astype(str) + " " + self.df['game_description'].astype(str) ) self._setup_superlinked() def _setup_superlinked(self): """Set up Superlinked schema, space, index, and executor.""" # Define schema class GameSchema(sl.Schema): game_number: sl.IdField name: sl.String desc_snippet: sl.String game_details: sl.String languages: sl.String genre: sl.String game_description: sl.String original_price: sl.Float discount_price: sl.Float combined_text: sl.String # New field for combined text self.game = GameSchema() # Create text similarity space using the combined_text field self.text_space = sl.TextSimilaritySpace( text=self.game.combined_text, model="sentence-transformers/all-mpnet-base-v2" ) # Create index self.index = sl.Index([self.text_space]) # Map DataFrame columns to schema parser = sl.DataFrameParser( self.game, mapping={ self.game.game_number: "game_number", self.game.name: "name", self.game.desc_snippet: "desc_snippet", self.game.game_details: "game_details", self.game.languages: "languages", self.game.genre: "genre", self.game.game_description: "game_description", self.game.original_price: "original_price", self.game.discount_price: "discount_price", self.game.combined_text: "combined_text" } ) # Set up in-memory source and executor source = sl.InMemorySource(self.game, parser=parser) self.executor = sl.InMemoryExecutor(sources=[source], indices=[self.index]) self.app = self.executor.run() # Load data source.put([self.df]) print(f"Initialized Superlinked retriever with {len(self.df)} games") def _retrieve(self, query_bundle: QueryBundle) -> List[NodeWithScore]: """ Retrieve top-k games based on the query string. Args: query_bundle (QueryBundle): Contains the query string Returns: List[NodeWithScore]: List of retrieved games with scores """ query_text = query_bundle.query_str # Define Superlinked query with explicit field selection query = ( sl.Query(self.index) .find(self.game) .similar(self.text_space, query_text) .select([ self.game.game_number, self.game.name, self.game.desc_snippet, self.game.game_details, self.game.languages, self.game.genre, self.game.game_description, self.game.original_price, self.game.discount_price ]) .limit(self.top_k) ) # Execute query result = self.app.query(query) df_result = sl.PandasConverter.to_pandas(result) # Convert results to NodeWithScore objects nodes_with_scores = [] for i, row in df_result.iterrows(): text = f"{row['name']}: {row['desc_snippet']}" metadata = { "game_number": row["id"], "name": row["name"], "desc_snippet": row["desc_snippet"], "game_details": row["game_details"], "languages": row["languages"], "genre": row["genre"], "game_description": row["game_description"], "original_price": row["original_price"], "discount_price": row["discount_price"] } score = 1.0 - (i / self.top_k) node = TextNode(text=text, metadata=metadata) nodes_with_scores.append(NodeWithScore(node=node, score=score)) return nodes_with_scores print("✅ SuperlinkedSteamGamesRetriever class defined successfully!") Integration Architecture Deep Dive Μέρος 3: Ορισμός και ρύθμιση του υπερσυνδεδεμένου σχήματος Ξεκινώντας με το σχεδιασμό σχήματος, τώρα στο Superlinked, το σχήμα δεν είναι μόνο για τον καθορισμό των τύπων δεδομένων, είναι περισσότερο σαν ένας τυπικός ορισμός μεταξύ των δεδομένων μας και της υποκείμενης μηχανής υπολογισμού vector. Στην δική μας Το σχέδιο ορίζεται ως εξής: SuperlinkedSteamGamesRetriever class GameSchema(sl.Schema): game_number: sl.IdField name: sl.String desc_snippet: sl.String game_details: sl.String languages: sl.String genre: sl.String game_description: sl.String original_price: sl.Float discount_price: sl.Float combined_text: sl.String # New field for combined text self.game = GameSchema() Ας ξεχωρίσουμε τι πραγματικά είναι μερικά από αυτά τα στοιχεία : Κάνει (→ ) Think of this as our primary key. It gives each game a unique identity and allows Superlinked to index and retrieve items efficiently, I mean basically it’s about how we are telling the Superlinked to segregate the unique identify of the games, and btw it’s especially important when you're dealing with thousands of records. sl.IdField game_number and Now these aren't just type hints—they enable Superlinked to optimize operations differently depending on the field. For instance, fields can be embedded and compared semantically, while fields can support numeric filtering or sorting. sl.String sl.Float sl.String sl.Float This is the of our retriever. It’s a synthetic field where we concatenate the game name, description, genre, and other relevant attributes into a single block of text. This lets us build a single using sentence-transformer embeddings: combined_text semantic anchor text similarity space self.text_space = sl.TextSimilaritySpace( text=self.game.combined_text, model="sentence-transformers/all-mpnet-base-v2" ) Γιατί να το κάνετε αυτό; Επειδή οι χρήστες δεν ψάχνουν μόνο για το είδος ή το όνομα, περιγράφουν τι είναι Με την ενσωμάτωση όλων των σημαντικών σημάτων σε , μπορούμε να ταιριάξουμε καλύτερα ασαφή, ερωτήματα φυσικής γλώσσας με τα πιο σχετικά παιχνίδια. Ψάχνοντας για combined_text Μέρος 4: Διαμόρφωση του διαστήματος vector # Create text similarity space using the combined_text field self.text_space = sl.TextSimilaritySpace( text=self.game.combined_text, model="sentence-transformers/all-mpnet-base-v2" ) # Create index self.index = sl.Index([self.text_space]) Για να ενεργοποιήσω τη σημασιολογική αναζήτηση πάνω από το σύνολο δεδομένων παιχνιδιών Steam, έκανα δύο σκόπιμες επιλογές σχεδιασμού που εξισορροπούν την απόδοση, την απλότητα και την ευελιξία. Πρώτον, για το μοντέλο ενσωμάτωσης, επέλεξα Αυτό το μοντέλο παράγει ενσωματώσεις 768 διαστάσεων που χτυπούν ένα σταθερό μεσαίο έδαφος: είναι αρκετά εκφραστικές για να συλλάβουν πλούσιο σημασιολογικό νόημα, αλλά αρκετά ελαφρές για να είναι γρήγορες στην παραγωγή. εννοώ ότι είναι ένα αξιόπιστο μοντέλο γενικού σκοπού, γνωστό ότι εκτελεί καλά σε διάφορους τύπους κειμένου - το οποίο έχει μεγάλη σημασία όταν τα δεδομένα σας κυμαίνονται από σύντομες ετικέτες είδους έως περιγραφές παιχνιδιών μακράς μορφής. Το χειρίζεσαι καθαρά. all-mpnet-base-v2 all-mpnet-base-v2 Στη συνέχεια, αν και το Superlinked υποστηρίζει την ευρετηρίαση πολλαπλών χώρων - όπου μπορείτε να συνδυάσετε πολλαπλά πεδία ή ακόμα και μεθόδους (όπως κείμενο + εικόνες). Θα είχα συμπεριλάβει το Εδώ επίσης, αλλά δεν έχω τις πληροφορίες σχετικά με την ημερομηνία κυκλοφορίας για τα παιχνίδια. αλλά μόνο για να το βάλω εδώ, αν έχουμε τις πληροφορίες για την ημερομηνία κυκλοφορίας, θα μπορούσα να συνδέσω το RecencySpace εδώ, και μπορώ ακόμη και να ταξινομήσω τα παιχνίδια με το Όπως και τα τελευταία παιχνίδια του.Περισσότερα TextSimilaritySpace RecencySpace TextSimilaritySpace Μέρος 5: Ο αγωγός δεδομένων και η ρύθμιση του εκτελεστή # Map DataFrame columns to schema - Critical for data integrity parser = sl.DataFrameParser( self.game, mapping={ self.game.game_number: "game_number", self.game.name: "name", self.game.desc_snippet: "desc_snippet", self.game.game_details: "game_details", self.game.languages: "languages", self.game.genre: "genre", self.game.game_description: "game_description", self.game.original_price: "original_price", self.game.discount_price: "discount_price", self.game.combined_text: "combined_text" } ) # Set up in-memory source and executor source = sl.InMemorySource(self.game, parser=parser) self.executor = sl.InMemoryExecutor(sources=[source], indices=[self.index]) self.app = self.executor.run() # Load data source.put([self.df]) print(f"Initialized Superlinked retriever with {len(self.df)} games") Στην καρδιά του συστήματος ανάκτησής μας βρίσκεται ένας εξορθολογισμένος αγωγός που χτίστηκε τόσο για τη σαφήνεια όσο και για την ταχύτητα. Διασφαλίζει ότι κάθε πεδίο στο σύνολο δεδομένων πληκτρολογείται σωστά και χαρτογραφείται με συνέπεια στο σχήμα μας. ουσιαστικά ενεργώντας ως σύμβαση μεταξύ των ακατέργαστων δεδομένων CSV μας και του στρώματος ευρετηρίασης Superlinked. DataFrameParser Μόλις τα δεδομένα είναι δομημένα, τα τροφοδοτώ σε ένα , το οποίο είναι ιδανικό για σύνολα δεδομένων που ταιριάζουν άνετα στη μνήμη. Αυτή η προσέγγιση διατηρεί τα πάντα αστραπιαία χωρίς να εισάγει υπερφόρτωση αποθήκευσης ή καθυστέρηση δικτύου. Αυτό είναι που κάνει το Superlinked κατάλληλο για εφαρμογές σε πραγματικό χρόνο όπως τα διαδραστικά συστήματα συστάσεων, όπου η ταχύτητα επηρεάζει άμεσα την εμπειρία του χρήστη. InMemorySource InMemoryExecutor Μέρος 6: Η μηχανή ανάκτησης def _retrieve(self, query_bundle: QueryBundle) -> List[NodeWithScore]: """ Retrieve top-k games based on the query string. Args: query_bundle (QueryBundle): Contains the query string Returns: List[NodeWithScore]: List of retrieved games with scores """ query_text = query_bundle.query_str # Define Superlinked query with explicit field selection query = ( sl.Query(self.index) .find(self.game) .similar(self.text_space, query_text) .select([ self.game.game_number, self.game.name, self.game.desc_snippet, self.game.game_details, self.game.languages, self.game.genre, self.game.game_description, self.game.original_price, self.game.discount_price ]) .limit(self.top_k) ) # Execute query result = self.app.query(query) df_result = sl.PandasConverter.to_pandas(result) Ένα από τα πράγματα που κάνει το Superlinked πραγματικά ευχάριστο να συνεργαστεί με είναι ο προγραμματιστής ερωτήσεων με ευέλικτο στυλ. Εάν έχετε χρησιμοποιήσει βιβλιοθήκες όπως το SQLAlchemy ή το Django ORM, το μοτίβο θα αισθάνεται εξοικειωμένο. Κάθε μέθοδος στην αλυσίδα προσθέτει σαφήνεια αντί για σύγχυση. Στην περίπτωσή μας, το ερώτημα ξεκινά με την επιλογή του σχετικού ευρετηρίου και τον ορισμό της αναζήτησης ομοιότητας χρησιμοποιώντας το μέθοδος, η οποία υπολογίζει την ομοιότητα cosine στον χώρο ενσωμάτωσης.Αυτό μας επιτρέπει να ανακτήσουμε σημασιολογικά κοντινά παιχνίδια με βάση το ερώτημα της φυσικής γλώσσας του χρήστη. .similar() Μια άλλη πολύ προσεκτική απόφαση που πήρα ήταν να Με ενδιαφέρει το αποτέλεσμα, αντί να κάνω κάτι σαν Αυτό μπορεί να ακούγεται ασήμαντο, αλλά διατηρεί τα δεδομένα αδύναμα, μειώνει την υπερβολική επεξεργασία και εξασφαλίζει ότι δεν περνάμε περιττό φορτίο χρήσης κατά τη διάρκεια της μετα-επεξεργασίας. explicitly select the fields SELECT * Μέρος 7: Επεξεργασία αποτελεσμάτων και δημιουργία κόμβων # Convert to LlamaIndex NodeWithScore format nodes_with_scores = [] for i, row in df_result.iterrows(): text = f"{row['name']}: {row['desc_snippet']}" metadata = { "game_number": row["id"], "name": row["name"], "desc_snippet": row["desc_snippet"], "game_details": row["game_details"], "languages": row["languages"], "genre": row["genre"], "game_description": row["game_description"], "original_price": row["original_price"], "discount_price": row["discount_price"] } # Simple ranking score based on result position score = 1.0 - (i / self.top_k) node = TextNode(text=text, metadata=metadata) nodes_with_scores.append(NodeWithScore(node=node, score=score)) return nodes_with_scores Τώρα, μόλις λάβουμε τα αποτελέσματα από το Superlinked, τα μεταμόρφωσα σε μια μορφή που παίζει καλά με το LlamaIndex. Συνδυάζοντας το όνομα του παιχνιδιού με τη σύντομη περιγραφή του. Αυτό γίνεται το περιεχόμενο κάθε κόμβου, καθιστώντας ευκολότερο για το μοντέλο γλώσσας να σκεφτεί. Είναι ένα μικρό άγγιγμα, αλλά βελτιώνει πραγματικά πόσο σχετικό και κατανοητό είναι τα δεδομένα που ανακτώνται όταν μεταφέρονται στο LLM. human-readable text Στη συνέχεια, θα διασφαλίσω ότι από το σύνολο δεδομένων, συμπεριλαμβανομένων των πραγμάτων όπως το είδος, η τιμολόγηση και οι λεπτομέρειες του παιχνιδιού - διατηρούνται στα μεταδεδομένα. Αυτό είναι ζωτικής σημασίας επειδή οι μεταγενέστερες διαδικασίες μπορεί να θέλουν να φιλτράρουν, να εμφανίζουν ή να κατατάσσουν τα αποτελέσματα με βάση αυτές τις πληροφορίες. all original fields Τέλος, εφαρμόζουμε ένα ελαφρύ Στρατηγική. Αντί να βασιζόμαστε σε βαθμολογίες ακατέργαστης ομοιότητας, αποδίδουμε βαθμολογίες με βάση τη θέση του αποτελέσματος στη λίστα κατάταξης. Αυτό κρατά τα πράγματα απλά και συνεπή. Το κορυφαίο αποτέλεσμα έχει πάντα την υψηλότερη βαθμολογία και τα υπόλοιπα ακολουθούν με μειωμένη σειρά. Δεν είναι φανταστικό, αλλά μας δίνει ένα σταθερό και ερμηνεύσιμο σύστημα βαθμολόγησης που λειτουργεί καλά σε διαφορετικά ερωτήματα. score normalisation Show Time: Εκτέλεση του αγωγού Τώρα που όλα τα εξαρτήματα είναι στη θέση τους, ήρθε η ώρα να φέρουμε το σύστημα Retrieval-Augmented Generation (RAG) στη ζωή. # Initialize the RAG pipeline print("Setting up complete Retrieval pipeline...") # Create response synthesizer and query engine response_synthesizer = get_response_synthesizer() query_engine = RetrieverQueryEngine( retriever=retriever, response_synthesizer=response_synthesizer ) print("✅ RAG pipeline configured successfully!") print("\n" + "="*60) print("FULL RAG PIPELINE DEMONSTRATION") print("="*60) # Test queries with full RAG responses test_queries = [ "I want to find a magic game with spells and wizards", "Recommend a fun party game for friends", "I'm looking for a strategic sci-fi game", "What's a good cooperative game for teamwork?" ] for i, query in enumerate(test_queries, 1): print(f"\nQuery {i}: '{query}'") print("-" * 50) response = query_engine.query(query) print(f"Response: {response}") print("\n" + "="*50) Αυτή η ρύθμιση συνδυάζει το προσαρμοσμένο μας σημασιολογικό λήπτη με μια γεννήτρια ανταπόκρισης που τροφοδοτείται από το LLM. Τα ερωτήματα κινούνται ομαλά μέσα από τον αγωγό και αντί να ψεκάζουν απλά τα ακατέργαστα δεδομένα, επιστρέφει μια στοχαστική πρόταση για το είδος του παιχνιδιού που ο χρήστης μπορεί πραγματικά να θέλει να παίξει με βάση αυτό που ζήτησαν. Takeaways Τσιτσιπάς Custom retrievers let you bake domain rules and jargon into the system. Combining multiple text fields into one index improves query understanding. In LlamaIndex you only need to implement _retrieve for a custom backend. Superlinked InMemoryExecutor gives real time latency on moderate datasets. Schema choice matters for clean parsing and mapping. Simple position based scoring is a stable default when you want predictable ranks.\ If you want a quick chat about where mixture of encoders or multi-field retrieval fits in your pipeline, ! talk to one of our engineers Αν θέλετε μια γρήγορη συνομιλία για το πού το μείγμα κωδικοποιητών ή η ανάκτηση πολλαπλών πεδίων ταιριάζει στον αγωγό σας, ! Μιλήστε με έναν από τους μηχανικούς μας Μιλήστε με έναν από τους μηχανικούς μας Μιλήστε με έναν από τους μηχανικούς μας Αναφορές ενσωμάτωσης: Πακέτο Superlinked Retriever σε έγγραφα PyPI και LlamaIndex για προσαρμοσμένα Retriever. Συνεισφέροντες Vipul Maheshwari, συγγραφέας Filip Makraduli, εκδότης