O modalitate mai inteligentă și mai rapidă de a căuta în biblioteca Steam Tu cunoşti sentimentul. Căutați un joc care este strategic, co-op, poate cu o temă de science-fiction. Veți obține un perete de titluri care se potrivesc. Ceea ce ați vrut a fost o listă scurtă care captează cu adevărat vibrația din spatele cuvintelor dvs. În acest ghid, vă arătăm cum să construiți exact asta prin împerecherea Superlinked cu LlamaIndex. Rezultatul este un retriever de jocuri personalizate Steam care înțelege genul plus descrierea plus etichetele și oferă răspunsuri în milisecunde. * în Doriți să vedeți acest lucru pe datele dvs. cu interogări reale și numere de latență? . Get in touch Fii la atingere Fii la atingere Târgu Mureș; dr Retriever-urile personalizate vă oferă controlul asupra contextului domeniului, metadatelor și logicii de clasare. Acestea depășesc căutarea generică a asemănării atunci când interogările sunt tulburi sau jargon greu. Superlinked combină mai multe câmpuri de text într-un singur spațiu semantic și rulează interogări în memorie pentru rezultate rapide. LlamaIndex oferă interfața cu retriever-ul curat și conectează direct la motoarele de interogare și la sinteza răspunsurilor. Există o integrare oficială Superlinked Retriever pentru LlamaIndex pe care o puteți importa și utiliza. Superlinked Retriever pentru LlamaIndex Superlinked se integrează cu LlamaIndex prin intermediul oficial listate pe LlamaHub, astfel încât să puteți adăuga Superlinked la stack-ul LlamaIndex existent cu o instalare simplă și Apoi îl introduceţi în Aflați mai multe despre Parametrii clasei și constructorului sunt documentați în referința API LlamaIndex. SuperlinkedRetriever from llama_index.retrievers.superlinked import SuperlinkedRetriever RetrieverQueryEngine . Pagina oficială de integrare . Pagina oficială de integrare Pagina oficială de integrare 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") Preferați să o construiți manual sau să personalizați logica în continuare? Why Superlinked + LlamaIndex? De ce Superlinked + LlamaIndex? Obiectivul este simplu: luați punctele forte ale Superlinked pentru recuperarea multi-field și împachetați-le astfel încât dezvoltatorii să poată adopta și extinde în sisteme RAG reale. Superlinked vă ajută să definiți spații vectoriale expresive și interogări care amestecă câmpuri cum ar fi numele, descrierea și genul într-o singură vizualizare semantică. LlamaIndex aduce abstracția de recuperare, motoarele de interogare și sinteza de răspuns care se încadrează în aplicații și agenți cu o lipire minimă. De asemenea, puteți urmări în folosind aceleași blocuri de construcție din notebook-urile Superlinked. Google Colab Google Colab Colab De ce contează Custom Retrievers Ajustat pentru domeniul dvs. – Retriever-urile generice sunt bune pentru utilizare generală, dar tind să rateze lucrurile subtile. Gândiți-vă la jargon, scurtături sau fraze specifice domeniului, acestea nu sunt de obicei luate, cu excepția cazului în care retrieverul dvs. știe ce să caute. Funcționează dincolo de text – Cele mai multe date din lumea reală nu sunt doar text simplu. Veți avea adesea și metadate și etichete. De exemplu, într-un sistem de recomandare a jocurilor, nu ne pasă doar de descrierea jocului. Vrem, de asemenea, să luăm în considerare genurile, etichetele, evaluările utilizatorilor și multe altele. Gândiți-vă la această logică: cineva care caută un „joc de strategie cooperativă cu elemente de science-fiction” nu va ajunge departe cu potrivirea numai cu textul. Logica personalizată de filtrare și clasificare – Uneori doriți să aplicați propriile reguli la modul în care lucrurile sunt marcate sau filtrate. Poate doriți să acordați prioritate conținutului mai nou sau să penalizați rezultatele care nu îndeplinesc anumite praguri de calitate. Câștiguri de performanță – Să fim reali: soluțiile cu scop general sunt construite pentru a funcționa „bine” pentru toată lumea, nu foarte bine pentru dvs. Dacă știți datele și modelele dvs. de acces, puteți ajusta retrieverul pentru a rula mai repede, pentru a clasifica mai bine și pentru a reduce zgomotul inutil în rezultate. Dezintegrarea implementării Partea 1: Dependențe de bază și importuri 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 Structura de import dezvăluie abordarea noastră hibridă: LlamaIndex Core: oferă stratul de abstracție de recuperare Superlinked Framework: se ocupă de calculul vectorilor și de căutarea semantică Pandas: Gestionarea prelucrării și manipulării datelor Partea 2: Înțelegerea LlamaIndex Custom Retrievers Înainte de a vă scufunda în implementarea noastră Superlinked, este esențial să înțelegeți cum funcționează arhitectura de retriever personalizată a LlamaIndex și de ce este atât de puternică pentru a construi aplicații RAG specifice domeniului. Abstracţie de bază LlamaIndex oferă un abstract Frumusețea acestui design constă în simplitatea sa – orice retriever personalizat trebuie să implementeze doar o metodă de bază: 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 Furtuna aici este prezența Protocolului de recuperare de la LlamaIndex. Deoarece acest "protocol de recuperare" face ușor să conectați diferite backend-uri sau strategii fără a fi nevoie să atingeți restul sistemului. 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. De ce contează asta? Această abstracţiune este curată şi Asta înseamnă că poți: Puternică Combinați mai multe strategii - utilizați căutarea densă vectorială și filtrarea cuvintelor cheie împreună, dacă este necesar. Rulați cu ușurință testele A / B - Comparați diferite retriever-uri pentru a vedea ce oferă rezultate mai bune pentru utilizatorii dvs. Conectați-vă la orice agent sau instrument - Fie că construiți un chatbot, o interfață de căutare sau un sistem complet de agenți, această interfață de retriever este ușor de utilizat. Gândiți-vă la protocolul de recuperare ca la contractul API între "creierul de recuperare" și orice altceva. odată ce îl urmați, sunteți liber să inovați oricum doriți în spatele scenei. Plugging Superlinked în LlamaIndex Bine, așa că clasa este, în esență, instrumentul nostru pentru a oferi recomandări de joc inteligente, semantice. Vom începe cu o privire rapidă la modul în care este pus împreună, și apoi mai târziu să se scufunde mai adânc în fiecare parte pentru a vedea cu adevărat ce face acest lucru tick. SuperlinkedSteamGamesRetriever În primul rând, este , gândiți-vă la ea ca la fundație. Este ceea ce păstrează totul organizat și fiabil. De asemenea, vom prezenta detalii cheie precum , , şi Acest lucru păstrează toate informațiile jocului curate și consecvente și se conectează direct la conducta Superlinked, astfel încât totul să curgă fără probleme. 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() Următorul este cel Aici se întâmplă magia căutării semantice. model pentru a transforma o grămadă de informații despre joc (cum ar fi numele, descrierea, genul etc.) în reprezentări vectoriale dense. În esență, se netezește tot textul împreună în ceva ce modelul poate înțelege. Deci, dacă cineva caută ceva de genul "aventură în lumea deschisă", poate găsi jocuri care se potrivesc cu adevărat cu acea vibe, nu doar cele cu acele cuvinte exacte. text similarity space sentence-transformers/all-mpnet-base-v2 înseamnă self.text_space = sl.TextSimilaritySpace( text=self.game.combined_text, model="sentence-transformers/all-mpnet-base-v2" ) pe este locul în care lucrurile încep cu adevărat să facă clic. ia diferite bucăți de informații (cum ar fi numele jocului, descrierea, genul și mai mult) și le zdrobește într-o bucată mare de text. Acest lucru oferă modelului o imagine mai completă a fiecărui joc atunci când îl transformă în vectori. 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) ) Şi în sfârşit, este ceea ce face totul super snappy. mulțumită Superlinked , retrieverul poate gestiona interogările în timp real, fără întârzieri, doar rezultate instantanee. ceea ce înseamnă că, indiferent dacă cineva este în căutarea pentru un anumit gen sau doar căutarea pentru ceva nou pentru a juca, ei obține recomandări rapide și exacte, fără a aștepta. 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]) Puneți toate aceste bucăți împreună și aveți — o setare solidă pentru a oferi recomandări de jocuri care au de fapt sens pentru utilizator. Este rapid, inteligent și personal. Iată cum arată întregul lucru în acțiune... 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 Partea 3: Definirea și setarea schemei superlinkate Începând cu proiectarea schemei, acum în Superlinked, schema nu este doar despre definirea tipurilor de date, este mai mult ca o definiție formală între datele noastre și motorul de calcul vectorial de bază. În noi Schema este definită astfel: 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() Să aruncăm o privire asupra a ceea ce unele dintre aceste elemente de fapt : face (→ ) 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" ) Deoarece utilizatorii nu caută doar după gen sau nume, ei descriu ceea ce sunt Prin încorporarea tuturor semnalelor importante în , putem potrivi mai bine interogările de limbaj natural cu cele mai relevante jocuri. În căutarea combined_text Partea 4: Configurarea spațiului vectorial # 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]) Pentru a stimula căutarea semantică a setului nostru de date de jocuri Steam, am făcut două alegeri intenționate de design care echilibrează performanța, simplitatea și flexibilitatea. În primul rând, pentru modelul de încorporare, am selectat from the Sentence Transformers library. This model produces 768-dimensional embeddings that strike a solid middle ground: they're expressive enough to capture rich semantic meaning, yet lightweight enough to be fast in production. I mean it’s a reliable general-purpose model, known to perform well across diverse text types — which matters a lot when your data ranges from short genre tags to long-form game descriptions. In our case, I needed a model that wouldn’t choke on either end of that spectrum, and Luați-o în mod curat all-mpnet-base-v2 all-mpnet-base-v2 Apoi, deși Superlinked acceptă indexarea în mai multe spații - unde puteți combina mai multe câmpuri sau chiar modalități (cum ar fi textul + imaginile). Aș fi inclus în De asemenea, aici, dar nu am informații despre data de lansare a jocurilor.Dar doar pentru a pune acest lucru aici, dacă avem informații despre data de lansare, aș putea conecta RecencySpace aici, și chiar pot sorta jocurile cu La fel ca în cazul jocurilor de noroc. cool. TextSimilaritySpace RecencySpace TextSimilaritySpace Partea 5: Pipe de date și setarea executorului # 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") În centrul sistemului nostru de recuperare este o conductă raționalizată construită atât pentru claritate, cât și pentru viteză. , care servește ca stratul nostru ETL. Se asigură că fiecare câmp din setul de date este tipărit corect și cartografiat în mod consecvent la schema noastră; în esență acționând ca contract între datele noastre CSV brute și stratul de indexare Superlinked. DataFrameParser Odată ce datele sunt structurate, le alimentez într-o , care este ideal pentru seturile de date care se potrivesc confortabil în memorie. Această abordare menține totul fulger-rapid, fără a introduce supraîncărcare de stocare sau latență de rețea. Acest lucru face ca Superlinked să fie potrivit pentru aplicații în timp real, cum ar fi sistemele interactive de recomandare, unde viteza are un impact direct asupra experienței utilizatorului. InMemorySource InMemoryExecutor Partea a 6-a: Motorul de recuperare 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) Unul dintre lucrurile care face ca Superlinked să fie cu adevărat plăcut de lucrat este constructorul său de interogări în stil fluent. Dacă ați folosit biblioteci precum SQLAlchemy sau Django ORM, modelul se va simți familiar. Fiecare metodă din lanț adaugă claritate în loc de confuzie. În cazul nostru, interogarea începe prin selectarea indexului relevant și definirea căutării similitudinii folosind metoda, care calculează asemănarea cosine în spațiul de încorporare. Aceasta este ceea ce ne permite să recuperăm jocuri semantic apropiate pe baza interogării în limba naturală a utilizatorului. .similar() O altă decizie de design pe care am luat-o a fost Mă interesează rezultatul set, mai degrabă decât să facă ceva de genul Acest lucru poate părea minor, dar păstrează datele slabe, reduce prelucrarea în exces și asigură că nu pierdem sarcina inutilă în timpul post-procesării.Gândiți-vă la asta ca la precizie în vrac, mai ales când mutați date între componente într-un conductor sensibil la latență. explicitly select the fields SELECT * Partea 7: Prelucrarea rezultatelor și crearea nodurilor # 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 Acum, odată ce primim rezultatele de la Superlinked, le-am transformat într-un format care se joacă bine cu LlamaIndex. Acest lucru devine conținutul fiecărui nod, făcând mai ușor pentru modelul de limbă să raționeze.Este o mică atingere, dar îmbunătățește într-adevăr cât de relevante și ușor de înțeles sunt datele recuperate atunci când sunt transmise la LLM. human-readable text Apoi, mă asigur că din setul de date, inclusiv lucruri precum genul, prețurile și detaliile jocului - sunt păstrate în metadate. Acest lucru este crucial, deoarece procesele din aval ar putea dori să filtreze, să afișeze sau să clasifice rezultatele pe baza acestor informații. all original fields În cele din urmă, aplic o greutate ușoară Strategia. În loc să ne bazăm pe scorurile de asemănare brute, atribuim scoruri pe baza poziției rezultatului din lista clasată. Acest lucru păstrează lucrurile simple și consecvente. Rezultatul de top are întotdeauna cel mai mare scor, iar restul urmează în ordine descrescătoare. Nu este fantezist, dar ne oferă un sistem de scoruri stabil și interpretabil care funcționează bine pe diferite interogări. score normalisation Timp de afișare: Executarea conductei Acum că toate componentele sunt în funcțiune, este timpul să aducem la viață sistemul nostru 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) Această setare combină retrieverul semantic personalizat cu un generator de răspuns alimentat de LLM. Întrebările se mișcă fără probleme prin conductă și, în loc să scuipe doar date brute, returnează o sugestie atentă cu privire la ce fel de joc utilizatorul ar putea dori să joace în funcție de ceea ce au cerut. Takeaways 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 Dacă doriți o conversație rapidă cu privire la locul în care se potrivește un amestec de codificatoare sau de recuperare multi-field în conductă, ! Discutati cu unul dintre inginerii nostri Discutati cu unul dintre inginerii nostri Discutati cu unul dintre inginerii nostri Referințe de integrare: pachet de retriever superlinked pe documente PyPI și LlamaIndex pentru retrieverele personalizate. Contribuabilii Vipul Maheshwari, autor Filip Makraduli, redactor