Stay Hungry,Stay Foolish!

ROUTERS IN LLM

LOGIC ROUTER

使用代码逻辑调用子agent

https://github.com/ganeshnehru/RAG-Multi-Modal-Generative-AI-Agent

import re
import logging
from chains.code_assistant import CodeAssistant
from chains.language_assistant import LanguageAssistant
from chains.vision_assistant import VisionAssistant

class AssistantRouter:
    def __init__(self):
        self.code_assistant = CodeAssistant()
        self.language_assistant = LanguageAssistant()
        self.vision_assistant = VisionAssistant()

    def route_input(self, user_input='', image_path=None):
        """
        Route the input to the appropriate assistant based on the content of the user input.

        :param user_input: str, The input text from the user.
        :param image_path: str, Path to an image file if provided.
        :return: tuple, The response from the appropriate assistant and the assistant name.
        """
        try:
            if image_path:
                # Process image and route to VisionAssistant
                image_b64 = self.vision_assistant.process_image(image_path)
                if image_b64 is None:
                    raise ValueError("Failed to process image.")
                input_string = f"{user_input}|{image_b64}"
                response = self.vision_assistant.invoke(input_string)
                return response, 'VisionAssistant'

            if self.is_code_related(user_input):
                response = self.code_assistant.invoke(user_input)
                return response, 'CodeAssistant'
            else:
                response = self.language_assistant.invoke(user_input)
                return response, 'LanguageAssistant'
        except Exception as e:
            logging.error(f"Error in AssistantRouter.route_input: {e}")
            return {"content": f"Error: {str(e)}"}, 'Error'

    def is_code_related(self, text):
        """
        Determine if the text input is related to coding.

        :param text: str, The input text.
        :return: bool, True if the text is code related, False otherwise.
        """
        # Basic keyword-based detection
        code_keywords = [
            'function', 'class', 'def', 'import', 'print', 'variable',
            'loop', 'array', 'list', 'dictionary', 'exception', 'error', 'bug',
            'code', 'compile', 'execute', 'algorithm', 'data structure', 'java', 'python', 'javascript', 'c++',
            'c#', 'ruby', 'php', 'html', 'css', 'sql', 'swift', 'kotlin', 'go', 'rust', 'typescript', 'r', 'perl',
            'scala', 'shell', 'bash', 'powershell', 'objective-c', 'matlab', 'groovy', 'lua', 'dart', 'cobol',
            'fortran', 'haskell', 'lisp', 'pascal', 'prolog', 'scheme', 'smalltalk', 'verilog', 'vhdl',
            'assembly', 'coffeescript', 'f#', 'julia', 'racket', 'scratch', 'solidity', 'vba', 'abap', 'apex',
            'awk', 'clojure', 'd', 'elixir', 'erlang', 'forth', 'hack', 'idris', 'j', 'julia', 'kdb+', 'labview',
            'logtalk', 'lolcode', 'mumps', 'nim', 'ocaml', 'pl/i', 'postscript', 'powershell', 'rpg', 'sas', 'sml',
            'tcl', 'turing', 'unicon', 'x10', 'xquery', 'zsh'
        ]
        pattern = re.compile(r'\b(?:' + '|'.join(re.escape(word) for word in code_keywords) + r')\b', re.IGNORECASE)
        return bool(pattern.search(text))

 

LANGCHAIN ROUTER

限定 with_structured_output 输出格式,使得langchain决定哪一个子路可以被调用。

https://github.com/MadhanMohanReddy2301/SmartChainAgents/blob/master/router.py

### Router

from typing import Literal
from dotenv import load_dotenv

load_dotenv()

from langchain_core.prompts import ChatPromptTemplate
from pydantic import BaseModel, Field

import os

# Data model
class RouteQuery(BaseModel):
    """Route a user query to the most relevant datasource."""

    datasource: Literal["arxiv_search", "wiki_search", "llm_search"] = Field(
        ...,
        description="Given a user question choose to route it to wikipedia or arxiv_search or llm_search.",
    )

# LLM with function call
from langchain_groq import ChatGroq
import os
groq_api_key=os.getenv('GROQ_API_KEY')
os.environ["GROQ_API_KEY"]=groq_api_key
llm=ChatGroq(groq_api_key=groq_api_key,model_name="Gemma2-9b-It")
structured_llm_router = llm.with_structured_output(RouteQuery)

# Prompt
system = """You are an expert at routing a user question to a arxiv_search or wikipedia or llm_search.
The arxiv_search contains documents related to research papers about ai agents and LLMS.
Use the wikipedia for questions on the human related infomation. Otherwise, use llm_search."""


route_prompt = ChatPromptTemplate.from_messages(
    [
        ("system", system),
        ("human", "{question}"),
    ]
)

question_router = route_prompt | structured_llm_router
"""print(
    question_router.invoke(
        {"question": "who is Sharukh Khan?"}
    )
)
print(question_router.invoke({"question": "What are the types of agent memory?"}))"""

 

 

RAG_SemanticRouting

LLM 辅助路由。

https://github.com/UribeAlejandro/RAG_SemanticRouting/blob/main/src/main.py

https://github.com/UribeAlejandro/RAG_SemanticRouting/blob/main/src/pipeline/router.py

from langchain_community.chat_models import ChatOllama
from langchain_core.output_parsers import JsonOutputParser
from langchain_core.prompts import PromptTemplate
from langchain_core.runnables import RunnableSerializable

from src.constants import MODEL_NAME


def question_router() -> RunnableSerializable:
    """Create a chain for the Question Router.

    Returns
    -------
    RunnableSerializable
        Langchain Agent
    """
    llm = ChatOllama(model=MODEL_NAME, format="json", temperature=0)
    prompt = PromptTemplate(
        template="""
        <|begin_of_text|><|start_header_id|>system<|end_header_id|>
        You are an expert at routing a user question to a vectorstore or web search.
        Use the vectorstore for questions on LLM  agents, prompt engineering, and adversarial attacks.
        You do not need to be stringent with the keywords in the question related to these topics.
        Otherwise, use web-search. Give a binary choice 'web_search' or 'vectorstore' based on the question.

        Return the a JSON with a single key 'datasource' and no premable or explaination.

        Question to route: {question}
        <|eot_id|><|start_header_id|>assistant<|end_header_id|>""",
        input_variables=["question"],
    )
    chain = prompt | llm | JsonOutputParser()
    return chain

 

 

CSV-chat-and-code-Interpreter-agent

以工具的方式调用子agent

https://github.com/FrankAffatigato/CSV-chat-and-code-Interpreter-agent/blob/master/main.py

from typing import Any
from dotenv import load_dotenv
from langchain import hub
from langchain_core.tools import Tool
from langchain_openai import ChatOpenAI
from langchain.agents import create_react_agent, AgentExecutor
from langchain_experimental.tools import PythonREPLTool
from langchain_experimental.agents.agent_toolkits import create_csv_agent


load_dotenv()


def main():
    print("Start")

    instructions = """You are an agent designed to write and execute python code to answer questions.
    You have access to a python REPL, which you can use to execute python code.
    If you get an error, debug your code and try again.
    Only use the output of your code to answer the question. 
    You might know the answer without running any code, but you should still run the code to get the answer.
    If it does not seem like you can write code to answer the question, just return "I don't know" as the answer.
    """

    base_prompt = hub.pull("langchain-ai/react-agent-template")
    prompt = base_prompt.partial(instructions=instructions)
    tools = [PythonREPLTool()]
    python_agent = create_react_agent(
        prompt=prompt,
        llm=ChatOpenAI(temperature=0, model="gpt-4-turbo"),
        tools=tools,
    )

    python_agent_executor = AgentExecutor(agent=python_agent, tools=tools, verbose=True)

    # agent_executor.invoke(
    #     input={
    #         "input": """generate and save in current working directory 15 QRcodes
    #                             that point to www.udemy.com/course/langchain, you have qrcode package installed already"""
    #     }
    # )

    csv_agent_executor = create_csv_agent(
        llm=ChatOpenAI(temperature=0, model="gpt-4"),
        path="episode_info.csv",
        verbose=True,
        #agent_type=AgentType.ZERO_SHOT_REACT_DESCRIPTION,
        allow_dangerous_code=True
    )

    # csv_agent.invoke(
    #     input={"input": "print the seasons by ascending order of the number of episodes they have?"
    #            }
    # )

################################ Router Grand Agent ########################################################

    def python_agent_executor_wrapper(original_prompt: str) -> dict[str, Any]:
        return python_agent_executor.invoke({"input": original_prompt})


    def python_agent_executor_wrapper(original_prompt: str) -> dict[str, Any]:
        return python_agent_executor.invoke({"input": original_prompt})

    tools = [
        Tool(
            name="Python Agent",
            func=python_agent_executor_wrapper,
            description="""useful when you need to transform natural language to python and execute the python code,
                          returning the results of the code execution
                          DOES NOT ACCEPT CODE AS INPUT""",
        ),
        Tool(
            name="CSV Agent",
            func=csv_agent_executor.invoke,
            description="""useful when you need to answer question over episode_info.csv file,
                         takes an input the entire question and returns the answer after running pandas calculations""",
        ),
    ]

    prompt = base_prompt.partial(instructions="")
    #Create router agent
    grand_agent = create_react_agent(
        prompt=prompt,
        llm=ChatOpenAI(temperature=0, model="gpt-4-turbo"),
        tools=tools,
    )
    grand_agent_executor = AgentExecutor(agent=grand_agent, tools=tools, verbose=True)

    print(
        grand_agent_executor.invoke(
            {
                "input": "which season has the most episodes?",
            }
        )
    )

    # print(
    #     grand_agent_executor.invoke(
    #         {
    #             "input": "generate and save in current working directory 15 QR codes that point to www.udemy.com/course/langchain, you have qrcode package installed already",
    #         }
    #     )
    # )


if __name__ == "__main__":
    main()

 

https://smith.langchain.com/hub/langchain-ai/react-agent-template

{instructions}

TOOLS:

------

You have access to the following tools:

{tools}

To use a tool, please use the following format:

```

Thought: Do I need to use a tool? Yes

Action: the action to take, should be one of [{tool_names}]

Action Input: the input to the action

Observation: the result of the action

```

When you have a response to say to the Human, or if you do not need to use a tool, you MUST use the format:

```

Thought: Do I need to use a tool? No

Final Answer: [your response here]

```

Begin!

Previous conversation history:

{chat_history}

New input: {input}

{agent_scratchpad}

 

langchain MultiPromptChain

https://github.com/hyder110/LangChain-Router-Chains-for-PDF-Q-A/blob/master/multi_prompt.py

 

from langchain.chains.router import MultiPromptChain
from langchain.llms import OpenAI

physics_template = """You are a very smart physics professor. \
You are great at answering questions about physics in a concise and easy to understand manner. \
When you don't know the answer to a question you admit that you don't know.

Here is a question:
{input}"""

math_template = """You are a very good mathematician. You are great at answering math questions. \
You are so good because you are able to break down hard problems into their component parts, \
answer the component parts, and then put them together to answer the broader question.

Here is a question:
{input}"""

biology_template = """You are a skilled biology professor. \
You are great at explaining complex biological concepts in simple terms. \
When you don't know the answer to a question, you admit it.

Here is a question:
{input}"""

english_template = """You are a skilled english professor. \
You are great at explaining complex literary concepts in simple terms. \
When you don't know the answer to a question, you admit it.

Here is a question:
{input}"""


cs_template = """You are a proficient computer scientist. \
You can explain complex algorithms and data structures in simple terms. \
When you don't know the answer to a question, you admit it.


Here is a question:
{input}"""

python_template = """You are a skilled python programmer. \
You can explain complex algorithms and data structures in simple terms. \
When you don't know the answer to a question, you admit it.

here is a question:
{input}"""

accountant_template = """You are a skilled accountant. \
You can explain complex accounting concepts in simple terms. \
When you don't know the answer to a question, you admit it.

Here is a question:
{input}"""

lawyer_template = """You are a skilled lawyer. \
You can explain complex legal concepts in simple terms. \
When you don't know the answer to a question, you admit it.

Here is a question:
{input}"""


teacher_template = """You are a skilled teacher. \
You can explain complex educational concepts in simple terms. \
When you don't know the answer to a question, you admit it.

Here is a question:
{input}"""

engineer_template = """You are a skilled engineer. \
You can explain complex engineering concepts in simple terms. \
When you don't know the answer to a question, you admit it.

Here is a question:
{input}"""

psychologist_template = """You are a skilled psychologist. \
You can explain complex psychological concepts in simple terms. \
When you don't know the answer to a question, you admit it.

Here is a question:
{input}"""

scientist_template = """You are a skilled scientist. \
You can explain complex scientific concepts in simple terms. \
When you don't know the answer to a question, you admit it.

Here is a question:
{input}"""

economist_template = """You are a skilled economist. \
You can explain complex economic concepts in simple terms. \
When you don't know the answer to a question, you admit it.

Here is a question:
{input}"""

architect_template = """You are a skilled architect. \
You can explain complex architectural concepts in simple terms. \
When you don't know the answer to a question, you admit it.

Here is a question:
{input}"""



prompt_infos = [
    ("physics", "Good for answering questions about physics", physics_template),
    ("math", "Good for answering math questions", math_template),
    ("biology", "Good for answering questions about biology", biology_template),
    ("english", "Good for answering questions about english", english_template),
    ("cs", "Good for answering questions about computer science", cs_template),
    ("python", "Good for answering questions about python", python_template),
    ("accountant", "Good for answering questions about accounting", accountant_template),
    ("lawyer", "Good for answering questions about law", lawyer_template),
    ("teacher", "Good for answering questions about education", teacher_template),
    ("engineer", "Good for answering questions about engineering", engineer_template),
    ("psychologist", "Good for answering questions about psychology", psychologist_template),
    ("scientist", "Good for answering questions about science", scientist_template),
    ("economist", "Good for answering questions about economics", economist_template),
    ("architect", "Good for answering questions about architecture", architect_template),
]

chain = MultiPromptChain.from_prompts(OpenAI(), *zip(*prompt_infos), verbose=True)

# get user question
while True:
    question = input("Ask a question: ")
    print(chain.run(question))

 

 

https://python.langchain.com.cn/docs/modules/chains/foundational/router

 

from langchain.chains.router.llm_router import LLMRouterChain, RouterOutputParser
from langchain.chains.router.multi_prompt_prompt import MULTI_PROMPT_ROUTER_TEMPLATE

destinations = [f"{p['name']}: {p['description']}" for p in prompt_infos]
destinations_str = "\n".join(destinations)
router_template = MULTI_PROMPT_ROUTER_TEMPLATE.format(destinations=destinations_str)
router_prompt = PromptTemplate(
    template=router_template,
    input_variables=["input"],
    output_parser=RouterOutputParser(),
)
router_chain = LLMRouterChain.from_llm(llm, router_prompt)

chain = MultiPromptChain(
    router_chain=router_chain,
    destination_chains=destination_chains,
    default_chain=default_chain,
    verbose=True,
)

print(chain.run("What is black body radiation?"))

https://zhuanlan.zhihu.com/p/642971042

 

semantic_router

https://github.com/7AM7/movie-recommender-chatbot/blob/main/components/backend/src/model/semantic_layer.py

import logging
from semantic_router import Route, RouteLayer
from semantic_router.encoders import OpenAIEncoder
from config import Config


logger = logging.getLogger("main")


class SemanticLayer:
    def __init__(self, retriever):
        self.retriever = retriever
        self.routes = self._initialize_routes()
        self.route_layer = RouteLayer(
            encoder=OpenAIEncoder(
                name=Config.Retriever.EMBEDDING_MODEL,
                openai_api_key=Config.OpenAI.API_KEY,
                score_threshold=Config.Retriever.EMBEDDING_THRESHOLD
            ),
            routes=self.routes
        )

    def _initialize_routes(self):
        recommendation_route = Route(
            name="get_list_of_movies",
            utterances=[
                "Show me some movies",
                "Do you have 2020 movies?",
                "I want batman movie",
                "I want Drama movies",
            ]
        )
        return [recommendation_route]

    def process_query(self, query):
        route = self.route_layer(query)
        extra = ""
        logger.info(f"Tool name: {route.name}" )
        if route.name == "get_list_of_movies":
            retrieved_docs = self.retriever.retrieve(query)
            logger.info(f"Number of retrieved documents: {len(retrieved_docs)}")
            formatted_docs = SemanticLayer.format_docs(retrieved_docs)

            extra = f"You can recommend to the user from this list only:\n{formatted_docs}"
        return extra

    @staticmethod
    def format_docs(docs):
        return "\n\n".join([d.page_content for d in docs])

 

https://github.com/aurelio-labs/semantic-router

https://blog.csdn.net/beingstrong/article/details/140755340

https://www.bilibili.com/video/BV1H64y1E75Y/?vd_source=57e261300f39bf692de396b55bf8c41b

 

Superfast AI decision making and intelligent processing of multi-modal data.

Semantic Router is a superfast decision-making layer for your LLMs and agents. Rather than waiting for slow LLM generations to make tool-use decisions, we use the magic of semantic vector space to make those decisions — routing our requests using semantic meaning.

import os
from getpass import getpass
from semantic_router.encoders import CohereEncoder, OpenAIEncoder
from semantic_router import Route
from semantic_router.layer import RouteLayer

os.environ["OPENAI_API_KEY"] = os.getenv("OPENAI_API_KEY") or getpass(
    "Enter OpenAI API Key: "
)

## 定义名为politics的Route,以及其对应的一些描述
politics = Route(
    name="politics",
    utterances=[
        "isn't politics the best thing ever",
        "why don't you tell me about your political opinions",
        "don't you just love the president",
        "don't you just hate the president",
        "they're going to destroy this country!",
        "they will save the country!",
    ],
)
## 定义名为politics的Route,以及其对应的一些描述
chitchat = Route(
    name="chitchat",
    utterances=[
        "how's the weather today?",
        "how are things going?",
        "lovely weather today",
        "the weather is horrendous",
        "let's go to the chippy",
    ],
)

# 当前route汇总
routes = [politics, chitchat]
# embedding编码器
encoder = OpenAIEncoder()

## 定义Router层,在这一步会将routes中对应的描述(utterances)都向量编码并存储下来
rl = RouteLayer(encoder=encoder, routes=routes)

## 对查询做判断属于哪一个Route.
## 实现逻辑: 用query与定义好的问句进行相似度计算,返回与query最相似的top 5个预先定义的问法,并对其根据Route进行分组,取分组分数之和最大(组内分数的聚合策略可选:sum/max/mean)的Route作为候选Route,如果这些匹配的问法里存在大于指定阈值的问法,则将该Route作为匹配Route返回,否则返回空。
rl("don't you love politics?")
# RouteChoice(name='politics', function_call=None, similarity_score=None)


## 对查询做判断属于哪些Route.
## 实现逻辑: 用query与定义好的问句进行相似度计算,返回与query最相似的top 5个预先定义的问法,并对其根据Route进行分组,返回全部分数大于指定阈值的组,否则返回空。
rl.retrieve_multiple_routes("Hi! How are you doing in politics??")
#[RouteChoice(name='politics', function_call=None, similarity_score=0.8595844842560181),
# RouteChoice(name='chitchat', function_call=None, similarity_score=0.8356704527362284)]

#######
######## dynamic route 可以定义 function_schema, 利用LLM的function call 能力进行函数解析 #######
from datetime import datetime
from zoneinfo import ZoneInfo

def get_time(timezone: str) -> str:
    """Finds the current time in a specific timezone.

    :param timezone: The timezone to find the current time in, should
        be a valid timezone from the IANA Time Zone Database like
        "America/New_York" or "Europe/London". Do NOT put the place
        name itself like "rome", or "new york", you must provide
        the IANA format.
    :type timezone: str
    :return: The current time in the specified timezone."""
    now = datetime.now(ZoneInfo(timezone))
    return now.strftime("%H:%M")
from semantic_router.llms.openai import get_schemas_openai

schemas = get_schemas_openai([get_time])

time_route = Route(
    name="get_time",
    utterances=[
        "what is the time in new york city?",
        "what is the time in london?",
        "I live in Rome, what time is it?",
    ],
    function_schemas=schemas,
)
# 添加新定义的route
rl.add(time_route)
# 因为定义的get_time包含function_schemas,所以会在通过相似度计算得到匹配的route之后,用LLM的function call功能来返回待调用的函数参数
response = rl("what is the time in new york city?")
response
# RouteChoice(name='get_time', function_call=[{'function_name': 'get_time', 'arguments': {'timezone': 'America/New_York'}}], similarity_score=None)


### 除了向量比较相似性外,还可以与关键词比较一起进行混合匹配,将两者的分数用alpha分配后相加
import os
from semantic_router.encoders import CohereEncoder, BM25Encoder, TfidfEncoder
from getpass import getpass

dense_encoder = CohereEncoder()
# sparse_encoder = BM25Encoder()
sparse_encoder = TfidfEncoder()
from semantic_router.hybrid_layer import HybridRouteLayer

dl = HybridRouteLayer(
    encoder=dense_encoder, sparse_encoder=sparse_encoder, routes=routes
)
dl("don't you love politics?")

## RouteLayer的evaluate函数计算将问题正确分类的准确度
## RouteLayer的fit函数输入少量的标注数据,在max_iter次数内,每次随机为Route选取一个阈值,将准确率最高的阈值作为拟合出的阈值。

 

AGENT ROUTER

https://github.com/modelscope/agentscope/blob/main/examples/conversation_with_router_agent/main.py

# -*- coding: utf-8 -*-
"""The main script for the example of conversation with router agent."""
from router_agent import RouterAgent

import agentscope
from agentscope.agents import DialogAgent, UserAgent

# ================== Prepare model configuration =============================

YOUR_MODEL_CONFIGURATION_NAME = "{YOUR_MODEL_CONFIGURATION_NAME}"
YOUR_MODEL_CONFIGURATION = {
    "config_name": YOUR_MODEL_CONFIGURATION_NAME,
    # ...
}

# ============================================================================

agentscope.init(
    model_configs=YOUR_MODEL_CONFIGURATION,
    project="Conversation with router agent",
)

# Let's build some working agents with different capabilities. For simplicity,
# we just use the same agent. You can replace them with your own agents.
agent_math = DialogAgent(
    name="Math",
    sys_prompt="You are a math assistant to help solve math problems.",
    model_config_name=YOUR_MODEL_CONFIGURATION_NAME,
)

agent_history = DialogAgent(
    name="History",
    sys_prompt="You are an assistant who is good at history.",
    model_config_name=YOUR_MODEL_CONFIGURATION_NAME,
)

# Init a router agent
SYS_PROMPT_ROUTER = """You're a router assistant named {name}.

## YOUR TARGET
1. Given agents with different capabilities, your target is to assign questions to the corresponding agents according to the user requirement.
2. You should make full use of the different abilities of the given agents.
3. If no agent is suitable to answer user's question, then respond directly.

## Agents You Can Use
The agents are listed in the format of "{index}. {agent_name}: {agent_description}"
1. math: An agent who is good at math.
2. history: An agent who is good at history.
"""  # noqa

router_agent = RouterAgent(
    sys_prompt=SYS_PROMPT_ROUTER,
    model_config_name=YOUR_MODEL_CONFIGURATION_NAME,
)

# Init a user agent
user = UserAgent(name="user")

# Start the conversation
msg = None
while True:
    user_msg = user(msg)
    if user_msg.content == "exit":
        break

    # Replied by router agent
    router_msg = router_agent(user_msg)

    # Route the question to the corresponding agents
    if router_msg.metadata == "math":
        msg = agent_math(user_msg)
    elif router_msg.metadata == "history":
        msg = agent_history(user_msg)
    else:
        # Answer the question by router agent directly
        msg = router_msg

 

posted @ 2024-11-14 22:09  lightsong  阅读(2)  评论(0编辑  收藏  举报
Life Is Short, We Need Ship To Travel