Ez a cikk bemutatja a Llama 3.1, az NVIDIA NIM és a LangChain használatát tudásgráf-alapú ügynök létrehozására a lekérdezéssel kiegészített generáláshoz (RAG), kihasználva a strukturált adatokat és a dinamikus lekérdezések generálását az információ-visszakeresés és a válaszadás pontosságának javítása érdekében.
Míg a legtöbb ember a strukturálatlan szövegek, például a vállalati dokumentumok vagy dokumentációk helyett a visszakereséssel bővített generálásra (RAG) összpontosít, én eléggé hűvös vagyok a visszakereső rendszerekkel szemben a strukturált információkkal, különösen szemben. Nagy izgalom volt a GraphRAG, különösen a Microsoft implementációja kapcsán. Megvalósításukban azonban a bemeneti adat strukturálatlan szöveg, dokumentum formájában, amelyet egy nagy nyelvi modell (LLM) segítségével tudásgráfrá alakítanak át.
Ebben a blogbejegyzésben bemutatjuk, hogyan lehet retrievert megvalósítani egy tudásgrafikonon, amely strukturált információit tartalmazza, és amely információkat nyújt a kábítószer-mellékhatásokról. Ha valaha is foglalkozott a tudásgráfokkal és a visszakereséssel, az első gondolata az lehet, hogy egy LLM segítségével adatbázislekérdezéseket generál, hogy egy adott kérdés megválaszolásához releváns információkat kérjen le egy tudásgráfról. Az adatbázis-lekérdezések létrehozása LLM-ekkel azonban még mindig fejlődik, és még nem biztos, hogy a legkonzisztensebb vagy legrobusztusabb megoldást kínálja. Tehát mik az életképes alternatívák jelenleg?
Véleményem szerint a jelenlegi legjobb megoldás a dinamikus lekérdezésgenerálás. Ahelyett, hogy teljes egészében egy LLM-re támaszkodna a teljes lekérdezés generálására, ez a módszer egy logikai réteget alkalmaz, amely determinisztikusan generál egy adatbázis-lekérdezést előre meghatározott bemeneti paraméterekből. Ez a megoldás egy függvényhívás támogatással rendelkező LLM segítségével valósítható meg. A függvényhívási szolgáltatás használatának előnye abban rejlik, hogy egy LLM-nek meg lehet határozni, hogyan készítse elő a függvény strukturált bemenetét. Ez a megközelítés biztosítja, hogy a lekérdezésgenerálási folyamat ellenőrizhető és konzisztens legyen, miközben lehetővé teszi a felhasználói beviteli rugalmasságot.
A kép azt a folyamatot szemlélteti, amely során megértik a felhasználó kérdését, hogy konkrét információkat nyerjenek ki. Az áramlás három fő lépésből áll:
Egy felhasználó kérdést tesz fel a Lyrica gyógyszer gyakori mellékhatásairól 35 év alattiaknál.
Az LLM dönti el, hogy melyik függvényt hívja meg, és a szükséges paramétereket. Ebben a példában a mellékhatások nevű függvényt választotta olyan paraméterekkel, mint a Lyrica gyógyszer és a maximális életkor 35 év.
Az azonosított függvény és paraméterek egy adatbázis-lekérdezés (Cypher) utasítás determinisztikus és dinamikus generálására szolgálnak a releváns információk lekéréséhez.
A funkcióhívás-támogatás létfontosságú a fejlett LLM-használati esetekben, például lehetővé teszi az LLM-ek számára, hogy több visszakeresőt használjanak a felhasználói szándék alapján, vagy több ügynököt tartalmazó folyamatokat építsenek ki. Írtam néhány cikket kereskedelmi LLM-ek használatával, natív funkcióhívási támogatással. Azonban a nemrég kiadott Llama-3.1-et fogjuk használni, amely egy kiváló nyílt forráskódú LLM natív függvényhívási támogatással.
A kód elérhető .
A Tudásgráf beállítása
A Neo4j-t, amely egy natív gráf adatbázis, fogjuk használni a nemkívánatos események információinak tárolására. beállíthat egy ingyenes felhő Sandbox projektet, amely előre feltöltött FAERS-szel érkezik.
A példányosított adatbázispéldánynak van egy gráfja a következő sémával.
A séma középpontjában a Case csomópont áll, amely összekapcsolja a gyógyszerbiztonsági jelentés különböző aspektusait, beleértve az érintett gyógyszereket, a tapasztalt reakciókat, az eredményeket és az előírt terápiákat. Mindegyik gyógyszert az jellemzi, hogy elsődleges, másodlagos, kísérő vagy kölcsönhatásban lévő gyógyszer. Az esetek a gyártóra, a beteg korcsoportjára és a jelentés forrására vonatkozó információkhoz is kapcsolódnak. Ez a séma lehetővé teszi a kábítószerek közötti kapcsolatok, reakcióik és kimenetelek strukturált nyomon követését és elemzését.
Kezdjük azzal, hogy kapcsolatot hozunk létre az adatbázissal egy Neo4jGraph objektum példányosításával:
Számos lehetőség kínálkozik a nyílt forráskódú LLM-ek, például a Llama-3.1 fogadására. Az fogjuk használni, amely biztosít, és támogatja a Llama 3.1 modellek függvényhívását. Amikor létrehozol egy fiókot, 1000 tokent kapsz, ami több mint elég a követéshez. Létre kell hoznia egy API-kulcsot, és át kell másolnia a jegyzetfüzetbe:
A láma-3.1–70b-t fogjuk használni, mert a 8b verziónak van némi akadozása az opcionális paraméterekkel a függvénydefiníciókban.
Az NVIDIA NIM mikroszolgáltatásokban az a szép, hogy ha biztonsági vagy egyéb aggályai vannak, könnyedén , így könnyen cserélhető, és csak egy URL-paramétert kell hozzáadnia az LLM-konfigurációhoz:
# connect to an local NIM running at localhost:8000, # specifying a specific model llm = ChatNVIDIA( base_url="//localhost:8000/v1", model="meta/llama-3.1-70b-instruct" )
Eszköz meghatározása
Egyetlen eszközt konfigurálunk négy választható paraméterrel. Ezeken a paramétereken alapuló megfelelő Cypher utasítást készítünk, hogy lekérjük a tudásgráfból a releváns információkat. Eszközünk képes lesz azonosítani a leggyakoribb mellékhatásokat a bevitt gyógyszer, az életkor és a gyógyszergyártó alapján.
@tool def get_side_effects( drug: Optional[str] = Field( description="disease mentioned in the question. Return None if no mentioned." ), min_age: Optional[int] = Field( description="Minimum age of the patient. Return None if no mentioned." ), max_age: Optional[int] = Field( description="Maximum age of the patient. Return None if no mentioned." ), manufacturer: Optional[str] = Field( description="manufacturer of the drug. Return None if no mentioned." ), ): """Useful for when you need to find common side effects.""" params = {} filters = [] side_effects_base_query = """ MATCH (c:Case)-[:HAS_REACTION]->(r:Reaction), (c)-[:IS_PRIMARY_SUSPECT]->(d:Drug) """ if drug and isinstance(drug, str): candidate_drugs = [el["candidate"] for el in get_candidates(drug, "drug")] if not candidate_drugs: return "The mentioned drug was not found" filters.append("d.name IN $drugs") params["drugs"] = candidate_drugs if min_age and isinstance(min_age, int): filters.append("c.age > $min_age ") params["min_age"] = min_age if max_age and isinstance(max_age, int): filters.append("c.age < $max_age ") params["max_age"] = max_age if manufacturer and isinstance(manufacturer, str): candidate_manufacturers = [ el["candidate"] for el in get_candidates(manufacturer, "manufacturer") ] if not candidate_manufacturers: return "The mentioned manufacturer was not found" filters.append( "EXISTS {(c)<-[:REGISTERED]-(:Manufacturer {manufacturerName: $manufacturer})}" ) params["manufacturer"] = candidate_manufacturers[0] if filters: side_effects_base_query += " WHERE " side_effects_base_query += " AND ".join(filters) side_effects_base_query += """ RETURN d.name AS drug, r.description AS side_effect, count(*) AS count ORDER BY count DESC LIMIT 10 """ print(f"Using parameters: {params}") data = graph.query(side_effects_base_query, params=params) return data
A get_side_effectsfüggvény arra szolgál, hogy meghatározott keresési feltételek segítségével lekérje a gyógyszerek gyakori mellékhatásait egy tudásgráfról. Elfogadja a gyógyszernév, a beteg korosztálya és a gyógyszergyártó opcionális paramétereit a keresés testreszabásához. Minden paraméterhez tartozik egy leírás, amelyet az LLM-nek továbbítanak a függvényleírással együtt, lehetővé téve az LLM számára, hogy megértse a használatukat. A függvény ezután létrehoz egy dinamikus Cypher-lekérdezést a megadott bemenetek alapján, végrehajtja ezt a lekérdezést a tudásgráfon, és visszaadja az eredményül kapott mellékhatásadatokat.
Eszközünk először leképezte a kérdésben említett Lyrica gyógyszert a „['LYRICA', 'LYRICA CR']” értékekre a tudásgráfban, majd végrehajtott egy megfelelő Cypher utasítást, hogy megtalálja a leggyakoribb mellékhatásokat.
Grafikon alapú LLM-ügynök
Már csak egy LLM-ügynök konfigurálása maradt hátra, amely a meghatározott eszköz segítségével válaszolhat a gyógyszer mellékhatásaira vonatkozó kérdésekre.
A kép egy felhasználót ábrázol, aki interakcióba lép egy Llama 3.1 ügynökkel, hogy érdeklődjön a gyógyszer mellékhatásairól. Az ügynök hozzáfér egy mellékhatás-eszközhöz, amely információkat kér le egy tudásgráfról, hogy a felhasználó rendelkezésére álljon a releváns adatoknak.
Kezdjük a prompt sablon meghatározásával:
prompt = ChatPromptTemplate.from_messages( [ ( "system", "You are a helpful assistant that finds information about common side effects. " "If tools require follow up questions, " "make sure to ask the user for clarification. Make sure to include any " "available options that need to be clarified in the follow up questions " "Do only the things the user specifically requested. ", ), MessagesPlaceholder(variable_name="chat_history"), ("user", "{input}"), MessagesPlaceholder(variable_name="agent_scratchpad"), ] )
A prompt sablon tartalmazza a rendszerüzenetet, az opcionális csevegési előzményeket és a felhasználói bevitelt. Az agent_scratchpad az LLM számára van fenntartva, mivel néha több lépésre van szüksége a kérdés megválaszolásához, például végrehajtani és lekérni az információkat az eszközökből.
A LangChain könyvtár egyszerűvé teszi az eszközök hozzáadását az LLM-hez a bind_tools metódussal:
Az ügynök átalakításokon és kezelőkön keresztül dolgozza fel a bemenetet, amelyek formázzák a csevegési előzményeket, alkalmazzák az LLM-et a kötött eszközökkel, és elemzik a kimenetet. Végül az ügynök egy végrehajtóval van beállítva, amely kezeli a végrehajtási folyamatot, meghatározza a bemeneti és kimeneti típusokat, és tartalmazza a részletes naplózási beállításokat a végrehajtás során.
Teszteljük az ügynököt:
agent_executor.invoke( { "input": "What are the most common side effects when using lyrica for people below 35 years old?" } )
Eredmények:
Az LLM megállapította, hogy a get_side_effects függvényt kell használnia megfelelő argumentumokkal. A függvény ezután dinamikusan generál egy Cypher utasítást, lekéri a vonatkozó információkat, és visszaküldi az LLM-nek a végső válasz generálásához.
Összegzés
A függvényhívási képességek hatékonyan kiegészítik az olyan nyílt forráskódú modelleket, mint a Llama 3.1, lehetővé téve a külső adatforrásokkal és eszközökkel való strukturáltabb és szabályozottabb interakciókat. A strukturálatlan dokumentumok lekérdezésén túl a gráfalapú ügynökök izgalmas lehetőségeket kínálnak a tudásgráfokkal és strukturált adatokkal való interakcióhoz. Az ilyen modellek egyszerű üzemeltetése olyan platformokon, mint egyre könnyebben hozzáférhetővé teszi őket.
Mint mindig, a kód elérhető .
Ha többet szeretne megtudni erről a témáról, csatlakozzon hozzánk november 7-én a NODES 2024-en, amely az intelligens alkalmazásokról, tudásgrafikonokról és mesterséges intelligenciáról szóló ingyenes virtuális fejlesztői konferenciánk.