AI Agent Service Toolkit:一站式大模型智能体开发套件

413 阅读4分钟

项目简介

该工具包基于LangGraph、FastAPI和Streamlit构建,提供了构建和运行大模型Agent的最小原子能力,包含LangGraph代理、FastAPI服务、用于与服务交互的客户端以及一个使用客户端提供聊天界面的Streamlit应用。用户可以利用该工具包提供的模板快速搭建基于LangGraph框架的智能体应用,简化部署和调试过程,快速验证效果。 在这里插入图片描述

功能特点

○ LangGraph代理:基于LangGraph框架的智能体工作流,可自由设置节点和中断处理。 ○ FastAPI服务:提供API服务,包含流式和非流式。 ○ 内容审核:实现LlamaGuard进行内容审核。 ○ UI界面:基于Streamlit的聊天界面,简化交互流程。 ○ 多代理支持:在服务中运行多个代理,并通过URL路径调用,支持在UI界面随时切换。 ○ 异步设计:利用async/await高效处理并发请求。 ○ Docker支持:包含Dockerfile和docker compose文件,方便开发和部署。

文件结构解析

○ src/agents/:定义具有不同功能的几个代理。 ○ src/core/:包括LLM定义和其他设置。 ○ src/service/service.py:基于FastAPI的流式和非流式服务。 ○ src/client/client.py:封装的客户端,用于与代理服务API进行交互。 ○ src/streamlit_app.py:基于Streamlit的聊天界面。

快速启动

1. 配置文件

在项目根目录下创建一个.env文件,并填入模型服务商的API KEY。

# 最少需要填入一个模型服务商的API—KEY
# API keys for different providers
OPENAI_API_KEY=
DEEPSEEK_API_KEY=
ANTHROPIC_API_KEY=
GOOGLE_API_KEY=
GROQ_API_KEY=
USE_AWS_BEDROCK=false

# Use a fake model for testing
USE_FAKE_MODEL=false

# Set a default model
DEFAULT_MODEL=

# Web server configuration
HOST=0.0.0.0
PORT=8080

# Authentication secret, HTTP bearer token header is required if set
AUTH_SECRET=

# Langsmith configuration
LANGCHAIN_TRACING_V2=false
LANGCHAIN_PROJECT=default
LANGCHAIN_ENDPOINT=https://api.smith.langchain.com
LANGCHAIN_API_KEY=

# Application mode. If the value is "dev", it will enable uvicorn reload
MODE=

# OpenWeatherMap API key
OPENWEATHERMAP_API_KEY=

# Add for running ollama
# OLLAMA_MODEL=llama3.2
# Note: set OLLAMA_BASE_URL if running service in docker and ollama on bare metal
# OLLAMA_BASE_URL=http://host.docker.internal:11434

# Agent URL: used in Streamlit app - if not set, defaults to http://{HOST}:{PORT}
# AGENT_URL=http://0.0.0.0:8080

2. 创建并启动虚拟环境

pip install uv
uv sync --frozen
source .venv/bin/activate

3. 启动agent服务

python src/run_service.py

4. 启动UI界面

source .venv/bin/activate
streamlit run src/streamlit_app.py

自定义agent

按照该项目的介绍,自定义agent需要如下两步:

  1. 在src/agents下新增自定义的agent模块。
  2. 将新增的agent导入src/agents/agents.py。

该项目默认提供了4种agent,其中的chatbot只能做简单的对话,因此笔者打算将其改造为智能问答阅读助手,可以用于解读上传的文件。

只需修改src/streamlit_app.py

# ... existing code ...

# Config options
with st.sidebar:
    st.header(f"{APP_ICON} {APP_TITLE}")
    ""
    "Full toolkit for running an AI agent service built with LangGraph, FastAPI and Streamlit"
    
    # 在session state中存储文件数据
    if "file_data" not in st.session_state:
        st.session_state.file_data = None
        st.session_state.file_type = None

    # 添加文件上传功能
    with st.expander("📤 Upload File"):
        uploaded_file = st.file_uploader("Choose a file")
        if uploaded_file is not None:
            try:

                # 尝试不同的编码方式读取文件
                def try_read_file(file, encodings=['utf-8', 'gbk', 'gb2312', 'gb18030', 'latin1']):
                    for encoding in encodings:
                        try:
                            content = file.getvalue().decode(encoding)
                            print(content)
                            return content, encoding
                        except UnicodeDecodeError:
                            file.seek(0)  # 重置文件指针
                            continue
                    raise UnicodeDecodeError("Failed to decode file with any known encoding")

                # 处理不同类型的文件
                if uploaded_file.name.endswith('.csv'):
                    content, encoding = try_read_file(uploaded_file)
                    st.session_state.file_data = pd.read_csv(StringIO(content))
                    st.session_state.file_type = 'csv'
                    st.success(f"File {uploaded_file.name} uploaded successfully! (Encoding: {encoding})")
                    
                elif uploaded_file.name.endswith('.json'):
                    content, encoding = try_read_file(uploaded_file)
                    st.session_state.file_data = pd.read_json(StringIO(content))
                    st.session_state.file_type = 'json'
                    st.success(f"File {uploaded_file.name} uploaded successfully! (Encoding: {encoding})")
                    
                else:  # 文本文件
                    content, encoding = try_read_file(uploaded_file)
                    st.session_state.file_data = content
                    st.session_state.file_type = 'txt'
                    st.success(f"File {uploaded_file.name} uploaded successfully! (Encoding: {encoding})")

            except Exception as e:
                st.error(f"Error processing file: {e}")

    with st.popover(":material/settings: Settings", use_container_width=True):
        model_idx = agent_client.info.models.index(agent_client.info.default_model)
        model = st.selectbox("LLM to use", options=agent_client.info.models, index=model_idx)
        agent_list = [a.key for a in agent_client.info.agents]
        agent_idx = agent_list.index(agent_client.info.default_agent)
        agent_client.agent = st.selectbox(
            "Agent to use",
            options=agent_list,
            index=agent_idx,
        )
        use_streaming = st.toggle("Stream results", value=True)

# ... rest of the code ...

在上述改动的代码中,只需要在UI界面的侧边栏增加一个文件上传区域,同时把文件内容解析到状态变量st.session_state.file_data。这样只要设置好系统提示词,同时将状态变量的值拼接到用户输入的问题中就可以实现基于文档内容的问答了。

在这里插入图片描述

其他说明

FastAPI提供了一个类似Postman的在线调试路径,方便用户快速debug,浏览器输入:http://127.0.0.1:8080/docs#/ 即可打开。 在这里插入图片描述

同时,如果不使用默认的Streamlit UI界面,或者功能无法满足需求,可以自行替换UI界面,agent的服务接口不受影响。

总结

LangGraph是一个流行的Agent工作流开发框架,基于该工具包可以方便构建大模型智能体服务,简化部署和调试过程,无需重复开发无关紧要的模块,方便开发者快速验证效果。