Machine Learning

How to build a Jenali and Lamaindex journal

How to share how Ai and Lamaindex journal will create a journal. We will cover one important job of this Journal AI: asking for advice. We will start with very basic startup and work there. We can see a major development in this work when installing design patterns as Agentic Rag and the agent's transaction.

You can get a Source code for this AI in Gituthub Repo here. And who am I.

Ai Journal View

I want to build my principles by following Ray Dalio's habit. AI journal will help me in showing yourself, followed by my improvement, and I even give advice. The full job of Ai Journal looks like this:

Ai Journal Overview. Photo by author.

Today, we will only cover the initiation of Team-Alreds, which are represented by many purple cycles in the above drawing.

The easiest form: llm has a great idea

In the most direct use, we can pass all the appropriate content in the bottom and paste the question we want to ask. We can do what Elmaindex have a few lines of the code.

import pymupdf
from llama_index.llms.openai import OpenAI

path_to_pdf_book = './path/to/pdf/book.pdf'
def load_book_content():
    text = ""
    with pymupdf.open(path_to_pdf_book) as pdf:
        for page in pdf:
            text += str(page.get_text().encode("utf8", errors='ignore'))
    return text

system_prompt_template = """You are an AI assistant that provides thoughtful, practical, and *deeply personalized* suggestions by combining:
- The user's personal profile and principles
- Insights retrieved from *Principles* by Ray Dalio
Book Content: 
```
{book_content}
```
User profile:
```
{user_profile}
```
User's question:
```
{user_question}
```
"""

def get_system_prompt(book_content: str, user_profile: str, user_question: str):
    system_prompt = system_prompt_template.format(
        book_content=book_content,
        user_profile=user_profile,
        user_question=user_question
    )
    return system_prompt

def chat():
    llm = get_openai_llm()
    user_profile = input(">>Tell me about yourself: ")
    user_question = input(">>What do you want to ask: ")
    user_profile = user_profile.strip()
    book_content = load_book_summary()
    response = llm.complete(prompt=get_system_prompt(book_content, user_profile, user_question))
    return response

This method has a downsides:

  • Lower clarification: Loading all the context of the book may move the llm to lose focus on the user's question.
  • High Cost: Submitting limited content to all llm calls means higher and poor cost.

In this way, if you pass all the content of the Ray Dalio book, answers to such questions as “How can you cope with stress?” Be very overall. Such answers without negotiating with my query has made me feel that AI was not listening to me. Or includes many important ideas such as Realization, 5 step process to get what you wantbesides Having a very open mind. I like advice I have to be addressed to the question I suggested. Let's see how we can improve the RAG.

Advanced Form: Agentic Rag

So, what Agentic Rag? Agentic Rag includes making powerful decisions and data restoration. In our AI book, the Flow of Agentic Rag looks like this:

Agentic Rag categories. Photo by the writer
  • Questions test: The scattered questions lead to bad question consequences. The agent will examine the user's question and specify the questions if the agent believes it is necessary.
  • Rewrastly write the question: Recycle the user investigation to process the content pointed to the Semantic area. I have found these important steps in improving accuracy during restoration. Suppose your information information is Q / A pair and points to the part of the section to search for answers. Re-rewrite a user question statement on the correct question will help you find the best content.
  • Quector Vector Index: Many parameters may be organized when building such indication, including chunk size, overlapping, or form of a different index. For simplicity, we use vectorstorsToreindex here, with the default strategy of chunkling.
  • Filter & Synthetic: Instead of a complex process of resetting, I clearly teach the llm to filter and receive appropriate content when it is fast. I see the llm taking the most appropriate content, or sometimes has lower score than others.

With this Agentic Dance, you can bring back the most appropriate content on user questions, producing more intensified advice.

Let's examine the implementation. With LMLAANDEX SDK, creating and insisting the indicator in your location directory.

from llama_index.core import Document, VectorStoreIndex, StorageContext, load_index_from_storage

Settings.embed_model = OpenAIEmbedding(api_key="ak-xxxx")
PERSISTED_INDEX_PATH = "/path/to/the/directory/persist/index/locally"

def create_index(content: str):
    documents = [Document(text=content)]
    vector_index = VectorStoreIndex.from_documents(documents)
    vector_index.storage_context.persist(persist_dir=PERSISTED_INDEX_PATH)

def load_index():
    storage_context = StorageContext.from_defaults(persist_dir=PERSISTED_INDEX_PATH)
    index = load_index_from_storage(storage_context)
    return index

When we have a clue, we can build an engine for a question more than that. Question engine is a powerful discharge that allows you to modify parameters during question (eg in my start, writing on top of the_mondo NO_TEXT Because the agent will consider the content of the letter to be restored by the performance call and includes the final result. Having a question engine to combine the outcome before passing on to the agent will be allowed.

from llama_index.core.indices.vector_store import VectorIndexRetriever
from llama_index.core.query_engine import RetrieverQueryEngine
from llama_index.core.response_synthesizers import ResponseMode
from llama_index.core import  VectorStoreIndex, get_response_synthesizer

def _create_query_engine_from_index(index: VectorStoreIndex):
    # configure retriever
    retriever = VectorIndexRetriever(
        index=index,
        similarity_top_k=TOP_K,
    )
    # return the original content without using LLM to synthesizer. For later evaluation.
    response_synthesizer = get_response_synthesizer(response_mode=ResponseMode.NO_TEXT)
    # assemble query engine
    query_engine = RetrieverQueryEngine(
        retriever=retriever,
        response_synthesizer=response_synthesizer
    )
    return query_engine

Updates look like the following:

You are an assistant that helps reframe user questions into clear, concept-driven statements that match 
the style and topics of Principles by Ray Dalio, and perform look up principle book for relevant content. 

Background:
Principles teaches structured thinking about life and work decisions.
The key ideas are:
* Radical truth and radical transparency
* Decision-making frameworks
* Embracing mistakes as learning

Task:
- Task 1: Clarify the user's question if needed. Ask follow-up questions to ensure you understand the user's intent.
- Task 2: Rewrite a user’s question into a statement that would match how Ray Dalio frames ideas in Principles. Use formal, logical, neutral tone.
- Task 3: Look up principle book with given re-wrote statements. You should provide at least {REWRITE_FACTOR} rewrote versions.
- Task 4: Find the most relevant from the book content as your fina answers.

Finally, we can create an agent and those activities described.

def get_principle_rag_agent():
    index = load_persisted_index()
    query_engine = _create_query_engine_from_index(index)

    def look_up_principle_book(original_question: str, rewrote_statement: List[str]) -> List[str]:
        result = []
        for q in rewrote_statement:
            response = query_engine.query(q)
            content = [n.get_content() for n in response.source_nodes]
            result.extend(content)
        return result

    def clarify_question(original_question: str, your_questions_to_user: List[str]) -> str:
        """
        Clarify the user's question if needed. Ask follow-up questions to ensure you understand the user's intent.
        """
        response = ""
        for q in your_questions_to_user:
            print(f"Question: {q}")
            r = input("Response:")
            response += f"Question: {q}nResponse: {r}n"
        return response

    tools = [
        FunctionTool.from_defaults(
            fn=look_up_principle_book,
            name="look_up_principle_book",
            description="Look up principle book with re-wrote queries. Getting the suggestions from the Principle book by Ray Dalio"),
        FunctionTool.from_defaults(
            fn=clarify_question,
            name="clarify_question",
            description="Clarify the user's question if needed. Ask follow-up questions to ensure you understand the user's intent.",
        )
    ]

    agent = FunctionAgent(
        name="principle_reference_loader",
        description="You are a helpful agent will based on user's question and look up the most relevant content in principle book.n",
        system_prompt=QUESTION_REWRITE_PROMPT,
        tools=tools,
    )
    return agent

rag_agent = get_principle_rag_agent()
response = await agent.run(chat_history=chat_history)

There is a few beings that I had during launch:

  • One dear truth I have received provides unused parameter, original_question In the workout agreement helps. I found that if I didn't have such a parameter, the llm sometimes does not follow the rewrite instructions and transmits the first question to rewrote_statement parameter. Too original_question Puritutes somewhat emphasize MLM reset.
  • Different llms treats different differently. I found DEEPSEEK V3 very much to cause job calls than some model providers. This does not mean that they are not useful. If the effective call must be started 90% of the time, it should be part of a job dissolution instead of the registration as a performance call. Also, compared to Openai's models, I found Gemin well when I found a source of a book when it included the results.
  • Further content downloads in the context window, strengthening the power of more models of model. The smaller model of a stronger is likely to lose the main context provided.

However, to complete the advice work, you will need more work agents instead of one agent. Let us consider how you can cause your agents together in the work travel.

Last form: Agent's Work

Before we start, I recommend this article with anthropic, building active agents. One liner summary of the article is what Should always prioritize to build a job flow instead of a moving agent where possible. In LMLAINTEX, you can do it both. It allows you to create an automated Auto's work with an automated auto or customization of performance in clear control of a clear conversion of steps. I will provide the example of both of them.

Work flow means. Photo by author.

Let's see how you can build the moving work. Here is an example of the code.

interviewer = FunctionAgent(
        name="interviewer",
        description="Useful agent to clarify user's questions",
        system_prompt=_intervierw_prompt,
        can_handoff_to = ["retriver"]
        tools=tools
)
interviewer = FunctionAgent(
        name="retriever",
        description="Useful agent to retrive principle book's content.",
        system_prompt=_retriver_prompt,
        can_handoff_to = ["advisor"]
        tools=tools
)
advisor = FunctionAgent(
        name="advisor",
        description="Useful agent to advise user.",
        system_prompt=_advisor_prompt,
        can_handoff_to = []
        tools=tools
)
workflow = AgentWorkflow(
        agents=[interviewer, advisor, retriever],
        root_agent="interviewer",
    )
handler = await workflow.run(user_msg="How to handle stress?")

It stimulates that the agent version is based on the calling of the LLM model. Underling, Lamaaitex Workflow provides the meanings of agent as llM models. When the llm model causes that “Agent Function call”, the Llamindex will go to your next compatible operating agent. Your previous provider's release added to the internal maternity of work, and your next agent will take the state as part of the context in the cost of the LLM model. And is patient state including memory The elements of management of the internal status or external data of the load (index document here).

However, as I up, you can clearly control the steps in your work travel to get more control. With LMLAINTEX, it can be done by expanding the flow item. For example:

class ReferenceRetrivalEvent(Event):
    question: str

class Advice(Event):
    principles: List[str]
    profile: dict
    question: str
    book_content: str

class AdviceWorkFlow(Workflow):
    def __init__(self, verbose: bool = False, session_id: str = None):
        state = get_workflow_state(session_id)
        self.principles = state.load_principle_from_cases()
        self.profile = state.load_profile()
        self.verbose = verbose
        super().__init__(timeout=None, verbose=verbose)

    @step
    async def interview(self, ctx: Context,
                        ev: StartEvent) -> ReferenceRetrivalEvent:
        # Step 1: Interviewer agent asks questions to the user
        interviewer = get_interviewer_agent()
        question = await _run_agent(interviewer, question=ev.user_msg, verbose=self.verbose)

        return ReferenceRetrivalEvent(question=question)

    @step
    async def retrieve(self, ctx: Context, ev: ReferenceRetrivalEvent) -> Advice:
        # Step 2: RAG agent retrieves relevant content from the book
        rag_agent = get_principle_rag_agent()
        book_content = await _run_agent(rag_agent, question=ev.question, verbose=self.verbose)
        return Advice(principles=self.principles, profile=self.profile,
                      question=ev.question, book_content=book_content)

    @step
    async def advice(self, ctx: Context, ev: Advice) -> StopEvent:
        # Step 3: Adviser agent provides advice based on the user's profile, principles, and book content
        advisor = get_adviser_agent(ev.profile, ev.principles, ev.book_content)
        advise = await _run_agent(advisor, question=ev.question, verbose=self.verbose)
        return StopEvent(result=advise)

Recovery of some event events control the conversion of Workflow Step Transition. For example, retrieve step Returns the Advice The event to create the performance of advice Step. Don't achieve Advice event of exceeding information required You need.

During the implementation, if you are upset that you start with work to reduce other central measures, context It is important when you want to fail to be made of work travel. You can save your status in a listed format and recover your work travel unintentionally not inaccurate. Your work movement will continue the murder based on the original position.

workflow = AgentWorkflow(
    agents=[interviewer, advisor, retriever],
    root_agent="interviewer",
)
try:
    handler = w.run()
    result = await handler
except Exception as e:
    print(f"Error during initial run: {e}")
    await fail_over()
    # Optional, serialised and save the contexct for debugging 
    ctx_dict = ctx.to_dict(serializer=JsonSerializer())
    json_dump_and_save(ctx_dict)
    # Resume from the same context
    ctx_dict = load_failed_dict()
    restored_ctx = Context.from_dict(workflow, ctx_dict,serializer=JsonSerializer())
    handler = w.run(ctx=handler.ctx)
    result = await handler

Summary

In this regard, we discussed that using LMLAINDEX to use AI Journal's Core journal. The main reading includes:

  • Using Agentic Rag for the power of the llm to rewrite the first question and the effect of synthesis.
  • Use customized transaction to get clear clear control of the action change. Create dynamic agents where necessary.

SourThe CE code of this Journal AI is in my Gitub Repo here. I hope you enjoy this article and this little app I've built. Cheers!

Source link

Related Articles

Leave a Reply

Your email address will not be published. Required fields are marked *

Back to top button