যদিও বেশিরভাগ লোকেরা অসংগঠিত পাঠ্যের উপর পুনরুদ্ধার-অগমেন্টেড জেনারেশন (RAG) এর উপর ফোকাস করে, যেমন কোম্পানির নথি বা ডকুমেন্টেশন, আমি কাঠামোগত তথ্য, বিশেষ করে জ্ঞান গ্রাফের উপর পুনরুদ্ধার সিস্টেমের উপর বেশ উৎসাহী। GraphRAG সম্পর্কে অনেক উত্তেজনা দেখা দিয়েছে, বিশেষ করে Microsoft এর বাস্তবায়ন। যাইহোক, তাদের বাস্তবায়নে, ইনপুট ডেটা নথি আকারে অসংগঠিত পাঠ্য, যা একটি বড় ভাষা মডেল (LLM) ব্যবহার করে একটি জ্ঞান গ্রাফে রূপান্তরিত হয়।
এই ব্লগ পোস্টে, আমরা দেখাব কিভাবে FDA অ্যাডভার্স ইভেন্ট রিপোর্টিং সিস্টেম (FAERS) থেকে কাঠামোগত তথ্য সম্বলিত জ্ঞান গ্রাফের উপর একটি পুনরুদ্ধার প্রয়োগ করা যায়, যা ড্রাগ-প্রতিকূল ঘটনা সম্পর্কে তথ্য প্রদান করে। আপনি যদি কখনও জ্ঞানের গ্রাফ এবং পুনরুদ্ধারের সাথে টিঙ্কার করে থাকেন তবে আপনার প্রথম চিন্তা হতে পারে একটি প্রদত্ত প্রশ্নের উত্তর দেওয়ার জন্য একটি নলেজ গ্রাফ থেকে প্রাসঙ্গিক তথ্য পুনরুদ্ধার করতে ডাটাবেস কোয়েরি তৈরি করতে একটি এলএলএম ব্যবহার করা। যাইহোক, এলএলএম ব্যবহার করে ডাটাবেস ক্যোয়ারী জেনারেশন এখনও বিকশিত হচ্ছে এবং এখনও সবচেয়ে সামঞ্জস্যপূর্ণ বা শক্তিশালী সমাধান দিতে পারে না। সুতরাং, এই মুহূর্তে কার্যকর বিকল্প কি?
আমার মতে, সেরা বর্তমান সমাধান হল গতিশীল ক্যোয়ারী জেনারেশন। সম্পূর্ণ কোয়েরি তৈরি করার জন্য সম্পূর্ণরূপে LLM-এর উপর নির্ভর করার পরিবর্তে, এই পদ্ধতিটি একটি লজিক স্তর নিযুক্ত করে যা পূর্বনির্ধারিত ইনপুট পরামিতি থেকে একটি ডাটাবেস কোয়েরি নির্ধারণ করে। এই সমাধানটি ফাংশন-কলিং সমর্থন সহ একটি LLM ব্যবহার করে প্রয়োগ করা যেতে পারে। একটি ফাংশন-কলিং বৈশিষ্ট্য ব্যবহার করার সুবিধাটি একটি LLM-কে সংজ্ঞায়িত করার ক্ষমতার মধ্যে নিহিত যে এটি কীভাবে একটি ফাংশনে একটি কাঠামোগত ইনপুট প্রস্তুত করবে। এই পদ্ধতি নিশ্চিত করে যে ব্যবহারকারীর ইনপুট নমনীয়তার জন্য অনুমতি দেওয়ার সময় ক্যোয়ারী জেনারেশন প্রক্রিয়া নিয়ন্ত্রিত এবং সামঞ্জস্যপূর্ণ।
চিত্রটি নির্দিষ্ট তথ্য পুনরুদ্ধার করার জন্য ব্যবহারকারীর প্রশ্ন বোঝার একটি প্রক্রিয়া চিত্রিত করে। প্রবাহ তিনটি প্রধান পদক্ষেপ জড়িত:
একজন ব্যবহারকারী 35 বছরের কম বয়সী ব্যক্তিদের জন্য Lyrica ড্রাগের সাধারণ পার্শ্বপ্রতিক্রিয়া সম্পর্কে একটি প্রশ্ন জিজ্ঞাসা করেছেন।
এলএলএম সিদ্ধান্ত নেয় কোন ফাংশনটি কল করতে হবে এবং প্রয়োজনীয় পরামিতিগুলি। এই উদাহরণে, এটি ড্রাগ লিরিকা এবং সর্বোচ্চ বয়স 35 সহ প্যারামিটার সহ পার্শ্ব_প্রতিক্রিয়া নামে একটি ফাংশন বেছে নিয়েছে।
চিহ্নিত ফাংশন এবং পরামিতিগুলি প্রাসঙ্গিক তথ্য পুনরুদ্ধার করার জন্য একটি ডাটাবেস ক্যোয়ারী (সাইফার) বিবৃতি নির্ধারন এবং গতিশীলভাবে তৈরি করতে ব্যবহৃত হয়।
উন্নত এলএলএম ব্যবহারের ক্ষেত্রে ফাংশন-কলিং সমর্থন অত্যাবশ্যক, যেমন এলএলএম-কে ব্যবহারকারীর অভিপ্রায়ের ভিত্তিতে একাধিক পুনরুদ্ধার ব্যবহার করার অনুমতি দেওয়া বা মাল্টি-এজেন্ট প্রবাহ তৈরি করা। আমি নেটিভ ফাংশন-কলিং সমর্থন সহ বাণিজ্যিক এলএলএম ব্যবহার করে কিছু নিবন্ধ লিখেছি। যাইহোক, আমরা সম্প্রতি প্রকাশিত Llama-3.1, নেটিভ ফাংশন-কলিং সমর্থন সহ একটি উচ্চতর ওপেন-সোর্স LLM ব্যবহার করব।
কোডটি GitHub- এ উপলব্ধ।
আমরা Neo4j ব্যবহার করব, যা একটি নেটিভ গ্রাফ ডাটাবেস, প্রতিকূল ঘটনার তথ্য সংরক্ষণ করতে। আপনি এই লিঙ্কটি অনুসরণ করে একটি বিনামূল্যের ক্লাউড স্যান্ডবক্স প্রকল্প সেট আপ করতে পারেন যা প্রাক-জনবহুল FAERS-এর সাথে আসে।
তাত্ক্ষণিক ডাটাবেস উদাহরণে নিম্নলিখিত স্কিমা সহ একটি গ্রাফ রয়েছে৷
কেস নোডের স্কিমা কেন্দ্রগুলি, যা ওষুধের নিরাপত্তা প্রতিবেদনের বিভিন্ন দিককে সংযুক্ত করে, যার মধ্যে জড়িত ওষুধ, অভিজ্ঞতার প্রতিক্রিয়া, ফলাফল এবং নির্ধারিত থেরাপিগুলি অন্তর্ভুক্ত। প্রতিটি ওষুধ প্রাথমিক, মাধ্যমিক, সহজাত, বা ইন্টারঅ্যাক্টিং কিনা তা দ্বারা চিহ্নিত করা হয়। কেসগুলি প্রস্তুতকারক, রোগীর বয়স গ্রুপ এবং প্রতিবেদনের উত্স সম্পর্কে তথ্যের সাথেও যুক্ত। এই স্কিমা একটি কাঠামোগত পদ্ধতিতে ওষুধ, তাদের প্রতিক্রিয়া এবং ফলাফলের মধ্যে সম্পর্ক ট্র্যাকিং এবং বিশ্লেষণ করার অনুমতি দেয়।
আমরা একটি Neo4jGraph অবজেক্ট ইনস্ট্যান্টিয়েট করে ডাটাবেসের সাথে একটি সংযোগ তৈরি করে শুরু করব:
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)
Llama-3.1-এর মতো ওপেন-সোর্স LLM হোস্ট করার জন্য অনেকগুলি বিকল্প রয়েছে। আমরা NVIDIA API ক্যাটালগ ব্যবহার করব, যা NVIDIA NIM ইনফারেন্স মাইক্রোসার্ভিস প্রদান করে এবং Llama 3.1 মডেলের জন্য ফাংশন কলিং সমর্থন করে। আপনি যখন একটি অ্যাকাউন্ট তৈরি করেন, আপনি 1,000 টোকেন পান, যা অনুসরণ করার জন্য যথেষ্ট। আপনাকে একটি API কী তৈরি করতে হবে এবং এটি নোটবুকে অনুলিপি করতে হবে:
os.environ["NVIDIA_API_KEY"] = "nvapi-" llm = ChatNVIDIA(model="meta/llama-3.1-70b-instruct")
আমরা llama-3.1–70b ব্যবহার করব কারণ 8b সংস্করণে ফাংশনের সংজ্ঞায় ঐচ্ছিক পরামিতি সহ কিছু হেঁচকি রয়েছে।
NVIDIA NIM মাইক্রোসার্ভিসেস সম্পর্কে চমৎকার জিনিস হল যে আপনার নিরাপত্তা বা অন্যান্য উদ্বেগ থাকলে আপনি সেগুলিকে সহজেই স্থানীয়ভাবে হোস্ট করতে পারেন, তাই এটি সহজেই অদলবদলযোগ্য, এবং আপনাকে শুধুমাত্র LLM কনফিগারেশনে একটি URL প্যারামিটার যোগ করতে হবে:
# 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" )
আমরা চারটি ঐচ্ছিক পরামিতি সহ একটি একক টুল কনফিগার করব। নলেজ গ্রাফ থেকে প্রাসঙ্গিক তথ্য পুনরুদ্ধার করতে আমরা সেই প্যারামিটারের উপর ভিত্তি করে একটি সংশ্লিষ্ট সাইফার স্টেটমেন্ট তৈরি করব। আমাদের টুল ইনপুট ড্রাগ, বয়স, এবং ড্রাগ প্রস্তুতকারকের উপর ভিত্তি করে সবচেয়ে ঘন ঘন পার্শ্ব প্রতিক্রিয়া সনাক্ত করতে সক্ষম হবে।
@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
get_side_effects ফাংশনটি নির্দিষ্ট অনুসন্ধানের মানদণ্ড ব্যবহার করে একটি জ্ঞান গ্রাফ থেকে ওষুধের সাধারণ পার্শ্ব প্রতিক্রিয়া পুনরুদ্ধার করার জন্য ডিজাইন করা হয়েছে। এটি অনুসন্ধান কাস্টমাইজ করার জন্য ওষুধের নাম, রোগীর বয়স পরিসীমা এবং ওষুধ প্রস্তুতকারকের জন্য ঐচ্ছিক পরামিতিগুলি গ্রহণ করে। প্রতিটি প্যারামিটারের ফাংশনের বিবরণের সাথে একটি LLM-কে পাস করা একটি বিবরণ থাকে, যা LLM কে কীভাবে সেগুলি ব্যবহার করতে হয় তা বুঝতে সক্ষম করে৷ তারপরে ফাংশনটি প্রদত্ত ইনপুটগুলির উপর ভিত্তি করে একটি গতিশীল সাইফার ক্যোয়ারী তৈরি করে, জ্ঞান গ্রাফের বিরুদ্ধে এই ক্যোয়ারীটি কার্যকর করে এবং ফলস্বরূপ পার্শ্ব-প্রতিক্রিয়া ডেটা প্রদান করে।
চলুন ফাংশন পরীক্ষা করা যাক:
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}, # ...
আমাদের টুলটি প্রথমে প্রশ্নে উল্লিখিত লিরিকা ড্রাগটিকে জ্ঞান গ্রাফে “['LYRICA', 'LYRICA CR']” মানগুলিতে ম্যাপ করেছে, তারপর সবচেয়ে ঘন ঘন পার্শ্ব প্রতিক্রিয়াগুলি খুঁজে পেতে একটি সংশ্লিষ্ট সাইফার বিবৃতি কার্যকর করেছে।
শুধুমাত্র একটি LLM এজেন্ট কনফিগার করা বাকি আছে যা ড্রাগের পার্শ্বপ্রতিক্রিয়া সম্পর্কে প্রশ্নের উত্তর দিতে সংজ্ঞায়িত টুল ব্যবহার করতে পারে।
চিত্রটিতে একজন ব্যবহারকারীকে ড্রাগের পার্শ্বপ্রতিক্রিয়া সম্পর্কে জিজ্ঞাসা করার জন্য একটি Llama 3.1 এজেন্টের সাথে আলাপচারিতা দেখানো হয়েছে। এজেন্ট একটি পার্শ্ব-প্রতিক্রিয়া টুল অ্যাক্সেস করে যা ব্যবহারকারীকে প্রাসঙ্গিক ডেটা সরবরাহ করার জন্য একটি জ্ঞান গ্রাফ থেকে তথ্য পুনরুদ্ধার করে।
আমরা প্রম্পট টেমপ্লেট সংজ্ঞায়িত করে শুরু করব:
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"), ] )
প্রম্পট টেমপ্লেটে সিস্টেম বার্তা, ঐচ্ছিক চ্যাট ইতিহাস এবং ব্যবহারকারীর ইনপুট অন্তর্ভুক্ত রয়েছে। এজেন্ট_স্ক্র্যাচপ্যাডটি এলএলএম-এর জন্য সংরক্ষিত, কারণ এটি কখনও কখনও প্রশ্নের উত্তর দেওয়ার জন্য একাধিক পদক্ষেপের প্রয়োজন হয়, যেমন কার্যকর করা এবং সরঞ্জামগুলি থেকে তথ্য পুনরুদ্ধার করা।
LangChain লাইব্রেরি bind_tools পদ্ধতি ব্যবহার করে LLM-এ টুল যোগ করা সহজ করে তোলে:
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 )
এজেন্ট ট্রান্সফরমেশন এবং হ্যান্ডলারের মাধ্যমে ইনপুট প্রক্রিয়া করে যা চ্যাট হিস্ট্রি ফরম্যাট করে, বাউন্ড টুল দিয়ে এলএলএম প্রয়োগ করে এবং আউটপুট পার্স করে। অবশেষে, এজেন্টকে একজন নির্বাহকের সাথে সেট আপ করা হয় যেটি সম্পাদনের প্রবাহ পরিচালনা করে, ইনপুট এবং আউটপুট প্রকারগুলি নির্দিষ্ট করে এবং কার্যকর করার সময় বিস্তারিত লগিংয়ের জন্য ভারবোসিটি সেটিংস অন্তর্ভুক্ত করে।
আসুন এজেন্ট পরীক্ষা করা যাক:
agent_executor.invoke( { "input": "What are the most common side effects when using lyrica for people below 35 years old?" } )
ফলাফল:
LLM চিহ্নিত করেছে যে উপযুক্ত আর্গুমেন্ট সহ get_side_effect ফাংশন ব্যবহার করতে হবে। ফাংশনটি তখন গতিশীলভাবে একটি সাইফার বিবৃতি তৈরি করে, প্রাসঙ্গিক তথ্য নিয়ে আসে এবং চূড়ান্ত উত্তর তৈরি করতে এটি এলএলএম-এ ফেরত দেয়।
ফাংশন কলিং ক্ষমতাগুলি Llama 3.1-এর মতো ওপেন-সোর্স মডেলগুলির একটি শক্তিশালী সংযোজন, যা বহিরাগত ডেটা উত্স এবং সরঞ্জামগুলির সাথে আরও কাঠামোগত এবং নিয়ন্ত্রিত মিথস্ক্রিয়া সক্ষম করে৷ শুধুমাত্র অসংগঠিত নথির অনুসন্ধানের বাইরে, গ্রাফ-ভিত্তিক এজেন্টরা জ্ঞানের গ্রাফ এবং কাঠামোগত ডেটার সাথে ইন্টারঅ্যাক্ট করার জন্য উত্তেজনাপূর্ণ সম্ভাবনা অফার করে। NVIDIA NIM মাইক্রোসার্ভিসের মতো প্ল্যাটফর্ম ব্যবহার করে এই মডেলগুলি হোস্ট করার সহজতা তাদের ক্রমবর্ধমান অ্যাক্সেসযোগ্য করে তোলে।
বরাবরের মতো, কোডটি GitHub- এ উপলব্ধ।
এই বিষয়ে আরও জানতে, 7 নভেম্বর NODES 2024-এ আমাদের সাথে যোগ দিন, বুদ্ধিমান অ্যাপস, নলেজ গ্রাফ এবং AI এর উপর আমাদের বিনামূল্যের ভার্চুয়াল ডেভেলপার কনফারেন্স। এখন নিবন্ধন করুন!