借助LlamaIndex实现简单Agent

借助LlamaIndex实现简单Agent

1 简介

智能体的构建发展是一个趋势,借助LlamaIndex简单实现Agent。本文主要借助LlamaIndex中的FunctionTool和Workflow。Workflow是使用事件流的方法实现。

2 构建公共类

由于LlamaIndex中的OpenAI无法直接连接国内大模型,因此需要使用OpenAI构建CustomLikeOpenAI。

from typing import Any

from llama_index.core.base.llms.types import CompletionResponseGen, LLMMetadata, CompletionResponse
from llama_index.core.llms import CustomLLM
from openai import OpenAI
from pydantic import Field


class CustomLikeOpenAI(CustomLLM):
    model: str = Field(description="自定义模型名称")
    api_key: str = Field(description="自定义API Key")
    api_base: str = Field(description="自定义API地址")
    context_window: int = Field(default=32768, description="上下文窗口大小")
    temperature: float = Field(ge=0, le=1, default=0.3, description="设置温度,值域须为 [0, 1]")
    num_output: int = Field(default=8192, description="设置max_tokens")

    def __init__(self, **data):
        # 必须调用父类初始化
        super().__init__(**data)

        # 创建对象
        self._client = OpenAI(
            api_key=self.api_key,
            base_url=self.api_base
        )

    @property
    def metadata(self) -> LLMMetadata:
        """Get LLM metadata."""
        return LLMMetadata(
            context_window=self.context_window,
            num_output=self.num_output,
            model_name=self.model
        )

    def complete(self, prompt: str, **kwargs: Any) -> CompletionResponse:
        """
        生成文本

        :param prompt: 添加提示词
        :param kwargs: 其他相关参数
        :return: CompletionResponse
        """
        # 构建生成
        completion = self._client.chat.completions.create(
            model=self.model,
            messages=[
                {"role": "user", "content": prompt}
            ],
            temperature=self.temperature,
            max_tokens=self.num_output
        )
        # 返回值
        return CompletionResponse(text=completion.choices[0].message.content)

    def stream_complete(self, prompt: str, **kwargs: Any) -> CompletionResponseGen:
        """
        生成流式文本

        :param prompt: 提示词
        :param kwargs: 其他参数
        :return: CompletionResponseGen迭代器
        """

        # 根据需要可以不实现,如果不想实现使用下面代码即可
        # raise NotImplementedError("Streaming not supported")

        # 构建数据流
        stream = self._client.chat.completions.create(
            model=self.model,
            messages=[
                {"role": "user", "content": prompt}
            ],
            temperature=self.temperature,
            max_tokens=self.num_output,
            stream=True
        )
        # 遍历数据流
        for chunk in stream:
            # 获取新文本
            delta = chunk.choices[0].delta

            # 判断数据是否存在
            if delta.content:
                yield CompletionResponse(text=delta.content, delta=delta.content)

3 函数调用实现Agent

源代码

# 使用LlamaIndex中的ReActAgent和函数调用的方法,实现Agent
# ReActAgent集成AgentRunner/AgentWorker 此方法LlamaIndex未来会被舍弃,推荐使用AgentWorkflow 和 Workflows.
# 需要安装的组件
"""
pip install llama-index
pip install llama-index-llms-openai-like
"""

import asyncio

from llama_index.core.agent import ReActAgent
from llama_index.core.tools import FunctionTool

from my_custom_rag.custom_like_openai import CustomLikeOpenAI


def add(x: int, y: int) -> int:
    """Useful function to add two numbers."""
    return x + y


def multiply(x: int, y: int) -> int:
    """Useful function to multiply two numbers."""
    return x * y


async def main():
    # 函数回调
    tools = [
        FunctionTool.from_defaults(fn=add, description="实现加法"),
        FunctionTool.from_defaults(fn=multiply, description="实现乘法")
    ]

    # Llama index中的OpenAILike调用千问和Kimi不能使用,一直报参数错误,所以只能自定义了
    llm = CustomLikeOpenAI(
        model="XXXX",
        api_base="XXXX",
        api_key="XXXX"
    )

    # 构建Agent
    agent = ReActAgent.from_tools(
        llm=llm,
        verbose=True,
        tools=tools
    )
    ret = agent.chat(message="1乘以10等于几")
    print(ret)


if __name__ == "__main__":
    asyncio.run(main())

截图

4 WorkFlow实现Agent

运行流程

flowchart TD
	subgraph 说明
    A1[(1)找到启动的方法,含有StartEvent参数的方法 ] --> B1
    B1[(2)执行第一个任务流,根据含有StartEvent参数的方法的输出找到的方法 ] --> C1
    C1[(3)执行任务流,根据上一个方法的输出找到下一个方法] --> D1
    D1[(4)执行结束,直到执行方法的返回值是StopEvent]
    end
    
    subgraph 函数
    A2[(1)call_tool] --> B2
    B2[(2)generate_joke] --> C2
    C2[(3)……] --> D2
    D2[(4)critique_joke]
    end    

代码

# 需要安装的组件
"""
pip install llama-index
pip install llama-index-llms-openai-like
"""


import asyncio

from llama_index.core.workflow import (
    Event,
    StartEvent,
    StopEvent,
    Workflow,
    step
)

from my_custom_rag.custom_like_openai import CustomLikeOpenAI


class ToolCallEvent(Event):
    """
    用于回调返回数据
    """
    data: str


class JokeEvent(Event):
    """
    笑话实体类
    """
    joke: str


class JokeFlow(Workflow):
    # Llama index中的OpenAILike调用千问和Kimi不能使用,一直报参数错误,所以只能自定义了
    llm = CustomLikeOpenAI(
        model="XXXX",
        api_base="XXXX",
        api_key="XXXX"
    )

    @step
    async def call_tool(self, ev: StartEvent) -> ToolCallEvent:
        """
        生成笑话
        :param ev: 开始事件
        :return: 返回笑话事件
        """
        topic = ev.topic

        prompt = f"根据主题 {topic} 拓展相关主题."
        response = await self.llm.acomplete(prompt)
        print("生成的相关主题:", response)
        return ToolCallEvent(data=str(response))

    @step
    async def generate_joke(self, ev: ToolCallEvent) -> JokeEvent:
        """
        评价笑话事件

        :param ev: 笑话事件
        :return: 停止事件
        """
        prompt = f"写一个关于{ev.data}主题的笑话."
        response = await self.llm.acomplete(prompt)
        print("生成的笑话:", response)

        return JokeEvent(joke=str(response))

    @step
    async def critique_joke(self, ev: JokeEvent) -> StopEvent:
        """
        评价笑话事件

        :param ev: 笑话事件
        :return: 停止事件
        """
        joke = ev.joke

        prompt = f"请分析和评价笑话: {joke}"
        response = await self.llm.acomplete(prompt)
        return StopEvent(result=str(response))


async def main():
    w = JokeFlow(timeout=60, verbose=True)
    result = await w.run(topic="水果")
    print(str(result))


if __name__ == "__main__":
    asyncio.run(main())
    

截图

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值