QA RAG dengan Evaluasi Diri II

Untuk variasi ini, kami melakukan perubahan pada prosedur evaluasi. Selain pasangan tanya-jawab, kami juga meneruskan konteks yang diambil ke evaluator LLM.

Untuk mencapai hal ini, kami menambahkan fungsi itemgetter tambahan di RunnableParallel kedua untuk mengumpulkan string konteks dan meneruskannya ke templat prompt qa_eval_prompt_with_context yang baru.

rag_chain = ( 
RunnableParallel(context = retriever | format_docs, question = RunnablePassthrough() ) |
RunnableParallel(answer= qa_prompt | llm | retrieve_answer, question = itemgetter("question"), context = itemgetter("context") ) |
qa_eval_prompt_with_context |
llm_selfeval |
json_parser
)

Diagram Alir Implementasi :

Salah satu kendala umum dalam penggunaan implementasi rantai seperti LCEL adalah kesulitan dalam mengakses variabel perantara, yang penting untuk melakukan debug pada pipeline. Kami melihat beberapa opsi di mana kami masih dapat mengakses variabel perantara apa pun yang kami minati menggunakan manipulasi LCEL

Menggunakan RunnableParallel untuk meneruskan keluaran perantara

Seperti yang kita lihat sebelumnya, RunnableParallel memungkinkan kita meneruskan banyak argumen ke langkah berikutnya dalam rantai. Jadi kami menggunakan kemampuan RunnableParallel ini untuk meneruskan nilai perantara yang diperlukan hingga akhir.

Dalam contoh di bawah ini, kami memodifikasi rantai RAG evaluasi mandiri asli untuk menghasilkan teks konteks yang diambil bersama dengan keluaran evaluasi mandiri akhir. Perubahan utamanya adalah kita menambahkan objek RunnableParallel ke setiap langkah proses untuk meneruskan variabel konteks.

Selain itu, kami juga menggunakan fungsi itemgetter untuk menentukan dengan jelas masukan untuk langkah selanjutnya. Misalnya, untuk dua objek RunnableParallel terakhir, kami menggunakan pengambil item(‘masukan’) untuk memastikan bahwa hanya argumen masukan dari langkah sebelumnya yang diteruskan ke objek parser LLM/Json.

rag_chain = ( 
RunnableParallel(context = retriever | format_docs, question = RunnablePassthrough() ) |
RunnableParallel(answer= qa_prompt | llm | retrieve_answer, question = itemgetter("question"), context = itemgetter("context") ) |
RunnableParallel(input = qa_eval_prompt, context = itemgetter("context")) |
RunnableParallel(input = itemgetter("input") | llm_selfeval , context = itemgetter("context") ) |
RunnableParallel(input = itemgetter("input") | json_parser, context = itemgetter("context") )
)

Output dari rantai ini terlihat seperti berikut:

Variasi yang lebih ringkas:

rag_chain = ( 
RunnableParallel(context = retriever | format_docs, question = RunnablePassthrough() ) |
RunnableParallel(answer= qa_prompt | llm | retrieve_answer, question = itemgetter("question"), context = itemgetter("context") ) |
RunnableParallel(input = qa_eval_prompt | llm_selfeval | json_parser, context = itemgetter("context"))
)

Menggunakan variabel Global untuk menyimpan langkah perantara

Metode ini pada dasarnya menggunakan prinsip logger. Kami memperkenalkan fungsi baru yang menyimpan masukannya ke variabel global, sehingga memungkinkan kami mengakses variabel perantara melalui variabel global

global context

def save_context(x):
global context
context = x
return x

rag_chain = (
RunnableParallel(context = retriever | format_docs | save_context, question = RunnablePassthrough() ) |
RunnableParallel(answer= qa_prompt | llm | retrieve_answer, question = itemgetter("question") ) |
qa_eval_prompt |
llm_selfeval |
json_parser
)

Di sini kita mendefinisikan variabel global yang disebut konteks dan sebuah fungsi dipanggil simpan_konteks yang menyimpan nilai inputnya ke global konteks variabel sebelum mengembalikan input yang sama. Dalam rantai, kami menambahkan simpan_konteks berfungsi sebagai langkah terakhir dari langkah pengambilan konteks.

Opsi ini memungkinkan Anda mengakses langkah perantara apa pun tanpa membuat perubahan besar pada rantai.

Mengakses variabel perantara menggunakan variabel global

Menggunakan panggilan balik

Melampirkan callback ke rantai Anda adalah metode umum lainnya yang digunakan untuk mencatat nilai variabel perantara. Ada banyak hal yang perlu dibahas tentang topik callback di LangChain, jadi saya akan membahasnya secara mendetail di postingan lain.

Fuente