Lai gan lielākā daļa cilvēku koncentrējas uz izguves paplašināto ģenerēšanu (RAG), nevis strukturētu tekstu, piemēram, uzņēmuma dokumentus vai dokumentāciju, es esmu diezgan vērīgs attiecībā uz izguves sistēmām, nevis strukturētu informāciju, jo īpaši zināšanu diagrammas . Par GraphRAG, īpaši Microsoft ieviešanu, ir bijis liels satraukums. Taču to realizācijā ievaddati ir nestrukturēts teksts dokumentu formā, kas tiek pārveidots zināšanu grafikā, izmantojot lielo valodas modeli (LLM).
Šajā emuāra ziņojumā mēs parādīsim, kā ieviest retrīveri, izmantojot zināšanu diagrammu, kurā ir strukturēta informācija no FDA nevēlamo notikumu ziņošanas sistēmas (FAERS) , kas piedāvā informāciju par narkotiku izraisītiem nevēlamiem notikumiem. Ja kādreiz esat nodarbojies ar zināšanu diagrammām un izguvi, jūsu pirmā doma varētu būt izmantot LLM, lai ģenerētu datu bāzes vaicājumus, lai izgūtu atbilstošu informāciju no zināšanu diagrammas, lai atbildētu uz doto jautājumu. Tomēr datu bāzes vaicājumu ģenerēšana, izmantojot LLM, joprojām attīstās un, iespējams, vēl nepiedāvā konsekventāko vai robustāko risinājumu. Tātad, kādas šobrīd ir dzīvotspējīgas alternatīvas?
Manuprāt, labākais pašreizējais risinājums ir dinamiskā vaicājumu ģenerēšana. Tā vietā, lai pilnībā paļautos uz LLM, lai ģenerētu pilnu vaicājumu, šī metode izmanto loģisko slāni, kas deterministiski ģenerē datu bāzes vaicājumu no iepriekš definētiem ievades parametriem. Šo risinājumu var ieviest, izmantojot LLM ar funkciju izsaukšanas atbalstu. Funkcijas izsaukšanas līdzekļa izmantošanas priekšrocība ir spēja definēt LLM, kā tam jāsagatavo strukturēta funkcijas ievade. Šī pieeja nodrošina, ka vaicājumu ģenerēšanas process tiek kontrolēts un konsekvents, vienlaikus nodrošinot lietotāja ievades elastību.
Attēls ilustrē lietotāja jautājuma izpratnes procesu, lai izgūtu konkrētu informāciju. Plūsma ietver trīs galvenos soļus:
Lietotājs uzdod jautājumu par zāļu Lyrica biežajām blakusparādībām cilvēkiem, kas jaunāki par 35 gadiem.
LLM izlemj, kuru funkciju izsaukt un nepieciešamos parametrus. Šajā piemērā tā izvēlējās funkciju ar nosaukumu side_effects ar tādiem parametriem kā zāles Lyrica un maksimālo vecumu 35 gadi.
Identificētā funkcija un parametri tiek izmantoti, lai deterministiski un dinamiski ģenerētu datu bāzes vaicājuma (Cypher) priekšrakstu, lai izgūtu attiecīgo informāciju.
Funkciju izsaukšanas atbalsts ir ļoti svarīgs progresīviem LLM lietošanas gadījumiem, piemēram, ļaujot LLM izmantot vairākus retrīverus, pamatojoties uz lietotāja nolūku vai veidojot vairāku aģentu plūsmas. Esmu uzrakstījis dažus rakstus, izmantojot komerciālus LLM ar vietējo funkciju izsaukšanas atbalstu. Tomēr mēs izmantosim nesen izlaisto Llama-3.1 — izcilu atvērtā koda LLM ar vietējo funkciju izsaukšanas atbalstu.
Kods ir pieejams vietnē GitHub .
Mēs izmantosim Neo4j, kas ir vietējā grafiku datu bāze, lai saglabātu informāciju par nevēlamiem notikumiem. Varat iestatīt bezmaksas mākoņa Sandbox projektu, kas tiek piegādāts ar iepriekš aizpildītiem FAERS, sekojot šai saitei .
Instantizētajai datu bāzes instancei ir diagramma ar šādu shēmu.
Shēmas centrā ir Case mezgls, kas saista dažādus zāļu drošības ziņojuma aspektus, tostarp iesaistītās zāles, piedzīvotās reakcijas, rezultātus un parakstītās terapijas. Katru narkotiku raksturo, vai tās ir primāras, sekundāras, vienlaicīgas vai mijiedarbīgas. Gadījumi ir saistīti arī ar informāciju par ražotāju, pacienta vecuma grupu un ziņojuma avotu. Šī shēma ļauj strukturētā veidā izsekot un analizēt attiecības starp narkotikām, to reakcijām un rezultātiem.
Sāksim, izveidojot savienojumu ar datu bāzi, izveidojot Neo4jGraph objektu:
os.environ["NEO4J_URI"] = "bolt://18.206.157.187:7687" os.environ["NEO4J_USERNAME"] = "neo4j" os.environ["NEO4J_PASSWORD"] = "elevation-reservist-thousands" graph = Neo4jGraph(refresh_schema=False)
Ir daudz iespēju mitināt atvērtā koda LLM, piemēram, Llama-3.1. Mēs izmantosim NVIDIA API katalogu , kas nodrošina NVIDIA NIM secinājumu mikropakalpojumus un atbalsta funkcijas, kas izsauc Llama 3.1 modeļus. Kad izveidojat kontu, jūs saņemat 1000 žetonus, kas ir vairāk nekā pietiekami, lai sekotu līdzi. Jums būs jāizveido API atslēga un jākopē tā piezīmju grāmatiņā:
os.environ["NVIDIA_API_KEY"] = "nvapi-" llm = ChatNVIDIA(model="meta/llama-3.1-70b-instruct")
Mēs izmantosim lama-3.1–70b , jo 8.b versijai ir dažas problēmas ar izvēles parametriem funkciju definīcijās.
NVIDIA NIM mikropakalpojumu jaukā īpašība ir tāda, ka varat tos viegli mitināt lokāli , ja jums ir drošības vai citas problēmas, tāpēc tos var viegli nomainīt, un LLM konfigurācijai ir jāpievieno tikai URL parametrs:
# connect to an local NIM running at localhost:8000, # specifying a specific model llm = ChatNVIDIA( base_url="http://localhost:8000/v1", model="meta/llama-3.1-70b-instruct" )
Mēs konfigurēsim vienu rīku ar četriem izvēles parametriem. Mēs izveidosim atbilstošu Cypher paziņojumu, pamatojoties uz šiem parametriem, lai izgūtu attiecīgo informāciju no zināšanu diagrammas. Mūsu rīks varēs noteikt biežākās blakusparādības, pamatojoties uz ievadītajām zālēm, vecumu un zāļu ražotāju.
@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
Funkcija get_side_effects ir paredzēta, lai izgūtu zāļu izplatītās blakusparādības no zināšanu diagrammas, izmantojot noteiktus meklēšanas kritērijus. Tas pieņem izvēles parametrus zāļu nosaukumam, pacienta vecuma diapazonam un zāļu ražotājam, lai pielāgotu meklēšanu. Katram parametram ir apraksts, kas tiek nodots LLM kopā ar funkcijas aprakstu, kas ļauj LLM saprast, kā tos izmantot. Pēc tam funkcija konstruē dinamisku šifra vaicājumu, pamatojoties uz sniegtajiem ievades datiem, izpilda šo vaicājumu attiecībā pret zināšanu grafiku un atgriež iegūtos blakusefektu datus.
Pārbaudīsim funkciju:
get_side_effects("lyrica") # Using parameters: {'drugs': ['LYRICA', 'LYRICA CR']} # [{'drug': 'LYRICA', 'side_effect': 'Pain', 'count': 32}, # {'drug': 'LYRICA', 'side_effect': 'Fall', 'count': 21}, # {'drug': 'LYRICA', 'side_effect': 'Intentional product use issue', 'count': 20}, # {'drug': 'LYRICA', 'side_effect': 'Insomnia', 'count': 19}, # ...
Mūsu rīks vispirms kartēja jautājumā minētās zāles Lyrica ar “['LYRICA', 'LYRICA CR'] vērtībām zināšanu diagrammā, pēc tam izpildīja atbilstošu Cypher paziņojumu, lai atrastu visbiežāk sastopamās blakusparādības.
Vienīgais, kas jādara, ir konfigurēt LLM aģentu, kas var izmantot definēto rīku, lai atbildētu uz jautājumiem par zāļu blakusparādībām.
Attēlā ir attēlots lietotājs, kurš mijiedarbojas ar Llama 3.1 aģentu, lai noskaidrotu, kādas ir zāļu blakusparādības. Aģents piekļūst blakusparādību rīkam, kas izgūst informāciju no zināšanu diagrammas, lai sniegtu lietotājam attiecīgos datus.
Sāksim, definējot uzvednes veidni:
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"), ] )
Uzvednes veidnē ir iekļauts sistēmas ziņojums, izvēles tērzēšanas vēsture un lietotāja ievade. Agent_scratchpad ir rezervēts LLM, jo dažkārt tai ir nepieciešamas vairākas darbības, lai atbildētu uz jautājumu, piemēram, izpilde un informācijas izgūšana no rīkiem.
LangChain bibliotēka ļauj vienkārši pievienot rīkus LLM, izmantojot metodi bind_tools:
tools = [get_side_effects] llm_with_tools = llm.bind_tools(tools=tools) agent = ( { "input": lambda x: x["input"], "chat_history": lambda x: _format_chat_history(x["chat_history"]) if x.get("chat_history") else [], "agent_scratchpad": lambda x: format_to_openai_function_messages( x["intermediate_steps"] ), } | prompt | llm_with_tools | OpenAIFunctionsAgentOutputParser() ) agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True).with_types( input_type=AgentInput, output_type=Output )
Aģents apstrādā ievadi, izmantojot transformācijas un apdarinātājus, kas formatē tērzēšanas vēsturi, lieto LLM ar saistītajiem rīkiem un parsē izvadi. Visbeidzot, aģents ir iestatīts ar izpildītāju, kas pārvalda izpildes plūsmu, norāda ievades un izvades veidus un ietver detalizētus reģistrēšanas iestatījumus izpildes laikā.
Pārbaudīsim aģentu:
agent_executor.invoke( { "input": "What are the most common side effects when using lyrica for people below 35 years old?" } )
Rezultāti:
LLM noteica, ka tai ir jāizmanto funkcija get_side_effects ar atbilstošiem argumentiem. Pēc tam funkcija dinamiski ģenerē Cypher paziņojumu, iegūst attiecīgo informāciju un atgriež to LLM, lai ģenerētu galīgo atbildi.
Funkciju izsaukšanas iespējas ir spēcīgs papildinājums tādiem atvērtā pirmkoda modeļiem kā Llama 3.1, nodrošinot strukturētāku un kontrolētāku mijiedarbību ar ārējiem datu avotiem un rīkiem. Uz grafiem balstīti aģenti piedāvā ne tikai nestrukturētu dokumentu vaicājumu, bet arī aizraujošas iespējas mijiedarboties ar zināšanu grafikiem un strukturētiem datiem. Vienkāršā šo modeļu mitināšana, izmantojot tādas platformas kā NVIDIA NIM mikropakalpojumi, padara tos arvien pieejamākus.
Kā vienmēr, kods ir pieejams vietnē GitHub .
Lai uzzinātu vairāk par šo tēmu, pievienojieties mums NODES 2024 7. novembrī — mūsu bezmaksas virtuālajā izstrādātāju konferencē par viedajām lietotnēm, zināšanu diagrammām un AI. Reģistrējies tagad!