@@ -881,3 +881,193 @@ if __name__ == '__main__':
881
881
</div >
882
882
883
883
** 至此,我们完成了本节课所有内容。** 希望大家通过今天的学习,能够更加系统地掌握Agent和Multi-Agents的核心思想和实现方法,并在实际开发中灵活运用。🎉🎉🎉
884
+
885
+ ## 4 Huggingface Spaces 部署
886
+
887
+ 本部分由社区[ 甘施羽] ( https://github.com/fresh-little-lemon/ ) 同学贡献🎉🎉
888
+
889
+ 小伙伴们可能在将 agent 的代码部署到 Huggingface Spaces 时遇到了一些困难,比如我不想让别人看到我的 api_key 但我又不知道环境变量怎么设?agent 的 demo 里引用了别的代码的内容,有没有比较方便的办法保留原本的文档结构,直接把天气和博客两个代码一锅端一块儿提交?接下来将手把手教大家解决上面两个痛点。
890
+
891
+ ### 4.1 Spaces本地设置环境变量
892
+
893
+ 首先创建一个新的Spaces,SDK 选择 Streamlit,你会发现在创建的页面中我们并没有关于环境变量或者密钥的选项,不急,先点击 Create Spaces
894
+ ![ ] ( https://raw.githubusercontent.com/fresh-little-lemon/image/main/InternML-Tutorial/5be353916f253e7f96ac8bbe89a20ac.png )
895
+
896
+ 然后就会跳转到如下页面,点击右上角 Settings
897
+ ![ ] ( https://raw.githubusercontent.com/fresh-little-lemon/image/main/InternML-Tutorial/Pasted%20image%2020241230222238.png )
898
+
899
+ 然后往下翻,找到 Variables and secrets,找到右上角创建 New secret
900
+ ![ ] ( https://raw.githubusercontent.com/fresh-little-lemon/image/main/InternML-Tutorial/Pasted%20image%2020241230222401.png )
901
+ 这里我们输入两个 api_key,一个是 ` token ` ——你的浦语/硅基流动 api,一个是 ` weather_token ` ——你的和风天气 api,要注意名称不要写错。
902
+ ![ ] ( https://raw.githubusercontent.com/fresh-little-lemon/image/main/InternML-Tutorial/Pasted%20image%2020241230222936.png )
903
+
904
+ 然后点击 Save 就保存好你的密钥了。
905
+ ![ ] ( https://raw.githubusercontent.com/fresh-little-lemon/image/main/InternML-Tutorial/Pasted%20image%2020241230223159.png )
906
+
907
+ 你可能会问为什么用 Secret 不用 Variable 呢,我们根据 huggingface 的官方文档 [ Spaces Overview] ( https://huggingface.co/docs/hub/spaces-overview#managing-secrets ) 的解释
908
+ ![ ] ( https://raw.githubusercontent.com/fresh-little-lemon/image/main/InternML-Tutorial/Pasted%20image%2020241230225352.png )
909
+ ![ ] ( https://raw.githubusercontent.com/fresh-little-lemon/image/main/InternML-Tutorial/Pasted%20image%2020241230225421.png )
910
+ ![ ] ( https://raw.githubusercontent.com/fresh-little-lemon/image/main/InternML-Tutorial/Pasted%20image%2020241230225444.png )
911
+ 虽然根据官方文档的描述,Secret 比 Variable 更保险, ` Spaces Secrets Scanner ` 会对 ` os.getenv() ` 方法报警,但从下面的小实验中可以看到,在 streamlit 页面中两者其实并无区别(当然官方文档也提到了:For Streamlit Spaces, secrets are exposed to your app through [ Streamlit Secrets Management] ( https://blog.streamlit.io/secrets-in-sharing-apps/ ) , and public variables are directly available as environment variables)
912
+
913
+ 首先我们创建一个 Variable 做对比
914
+ ![ ] ( https://raw.githubusercontent.com/fresh-little-lemon/image/main/InternML-Tutorial/Pasted%20image%2020241230223340.png )
915
+ 然后我们现在就有三个环境变量了
916
+ ![ ] ( https://raw.githubusercontent.com/fresh-little-lemon/image/main/InternML-Tutorial/Pasted%20image%2020241230223614.png )
917
+ 我们用下面这段代码测试,这三个环境变量是否可见,先测试 Variable
918
+ ```
919
+ import streamlit as st
920
+ import os
921
+
922
+ # 获取环境变量
923
+ visible_token = os.getenv('visible_token')
924
+
925
+ # 创建Streamlit页面
926
+ st.title('环境变量展示')
927
+
928
+ # 显示环境变量
929
+ st.write('visible_token:', visible_token)
930
+ ```
931
+
932
+ 可以看到,就这么水灵灵的就暴露出来了 ![ ] ( https://raw.githubusercontent.com/fresh-little-lemon/image/main/InternML-Tutorial/Pasted%20image%2020241230224142.png )
933
+ 那么 Secret 呢
934
+ ```
935
+ import streamlit as st
936
+ import os
937
+
938
+ token = os.getenv('token')
939
+ weather_token = os.getenv('weather_token')
940
+
941
+ st.title('环境变量展示')
942
+
943
+ st.write('token:', token)
944
+ st.write('weather_token:', weather_token)
945
+ ```
946
+
947
+ 很遗憾,仍然是可以暴露的
948
+ ![ ] ( https://raw.githubusercontent.com/fresh-little-lemon/image/main/InternML-Tutorial/Pasted%20image%2020241230225904.png )
949
+ 但可不可以用呢,答案是** 放心用,没问题的** ,因为只要你不傻傻地自己写代码暴露 api 别人是没办法获取你写在 Huggingface Spaces 环境变量中的 api_token 的,所以放心大胆的使用就好了。当然如果你对这种办法有些膈应,觉得可能有暴露的风险,或者单纯不想让别人用你的 api,我们下面将介绍另一种方法来解决这个问题。
950
+
951
+ ### 4.2 获取用户输入token与多页面导航
952
+
953
+ 首先因为 Huggingface Spaces在初始化时需要提供 python 环境的清单,因此我们修改 ` /root/agent_camp4/lagent/requirements.txt ` ,在其中添加如下 python 包
954
+ ```
955
+ torch==2.1.2
956
+ torchvision==0.16.2
957
+ torchaudio==2.1.2
958
+ termcolor==2.4.0
959
+ streamlit==1.39.0
960
+ class_registry==2.1.2
961
+ datasets==3.1.0
962
+ griffe==0.48.0
963
+ ```
964
+ ![ ] ( https://raw.githubusercontent.com/fresh-little-lemon/image/main/InternML-Tutorial/Pasted%20image%2020241219175535.png )
965
+
966
+ 不过实测发现 huggingfaces 上的 docker 找不到 ` requirements/optional.txt ` 和 ` requirements/runtime.txt `
967
+ ![ ] ( https://raw.githubusercontent.com/fresh-little-lemon/image/main/InternML-Tutorial/Pasted%20image%2020241223085959.png )
968
+
969
+ 我们将其手动添加至 ` requirements.txt ` 中,拷贝下面这段代码:
970
+ ```
971
+ torch==2.1.2
972
+ torchvision==0.16.2
973
+ torchaudio==2.1.2
974
+ termcolor==2.4.0
975
+ streamlit==1.39.0
976
+ class_registry==2.1.2
977
+ datasets==3.1.0
978
+ # -r requirements/optional.txt
979
+ google-search-results
980
+ lmdeploy>=0.2.5
981
+ pillow
982
+ python-pptx
983
+ timeout_decorator
984
+ torch
985
+ transformers>=4.34,<=4.40
986
+ vllm>=0.3.3
987
+ # -r requirements/runtime.txt
988
+ aiohttp
989
+ arxiv
990
+ asyncache
991
+ asyncer
992
+ distro
993
+ duckduckgo_search==5.3.1b1
994
+ filelock
995
+ func_timeout
996
+ griffe<1.0
997
+ json5
998
+ jsonschema
999
+ jupyter==1.0.0
1000
+ jupyter_client==8.6.2
1001
+ jupyter_core==5.7.2
1002
+ pydantic==2.6.4
1003
+ requests
1004
+ termcolor
1005
+ tiktoken
1006
+ timeout-decorator
1007
+ typing-extensions
1008
+ griffe==0.48.0
1009
+ ```
1010
+ ![ ] ( https://raw.githubusercontent.com/fresh-little-lemon/image/main/InternML-Tutorial/Pasted%20image%2020241223091226.png )
1011
+
1012
+
1013
+ 由于 Huggingface Spaces 要求 file 中必须有一个名称为 ` app.py ` 的文件,否则会出现 ` No application file ` 错误。
1014
+ ![ ] ( https://raw.githubusercontent.com/fresh-little-lemon/image/main/InternML-Tutorial/Pasted%20image%2020241223085618.png )
1015
+
1016
+ 我们当然可以把 ` agent_api_web_demo.py ` 和 ` multi_agents_api_web_demo.py ` 更名为 ` app.py ` ,然而考虑到这两个页面文件会调用到其他代码,我们又不希望把时间浪费在找依赖上,于是我们直接在 ` agent_camp4/lagent ` 文件夹下做一个 ` app.py ` 的入口文件当作 HomePage,编写一个多页面的 streamlit 首页实现对天气查询小助手和博客写作小助手两个 agent 的导航,代码如下(我们这里采用代码写入环境变量的方式,这样子别人来访问的时候可以不用消耗你自己的 api_token,而是让他们自己填写)
1017
+ ``` python
1018
+ import streamlit as st
1019
+ import os
1020
+ import runpy
1021
+ st.set_page_config(layout = " wide" , page_title = " My Multi-Page App" )
1022
+ def set_env_variable (key , value ):
1023
+ os.environ[key] = value
1024
+ def home_page ():
1025
+ st.header(" 欢迎来到首页" )
1026
+ # 设置输入框为隐私状态
1027
+ token = st.text_input(" 请输入浦语token:" , type = " password" , key = " token" )
1028
+ weather_token = st.text_input(" 请输入和风天气token:" , type = " password" , key = " weather_token" )
1029
+ if st.button(" 保存并体验agent" ):
1030
+ if token and weather_token:
1031
+ set_env_variable(" token" , token) # 设置环境变量为 'token'
1032
+ set_env_variable(" weather_token" , weather_token) # 设置环境变量为 'weather_token'
1033
+ st.session_state.token_entered = True
1034
+ st.rerun()
1035
+ else :
1036
+ st.error(" 请输入所有token" )
1037
+ if ' token_entered' not in st.session_state:
1038
+ st.session_state.token_entered = False
1039
+ if not st.session_state.token_entered:
1040
+ home_page()
1041
+ else :
1042
+ # 动态加载子页面
1043
+ page = st.sidebar.radio(" 选择页面" , [" 天气查询助手" , " 博客写作助手" ])
1044
+ if page == " 天气查询助手" :
1045
+ runpy.run_path(" examples/agent_api_web_demo.py" , run_name = " __main__" )
1046
+ elif page == " 博客写作助手" :
1047
+ runpy.run_path(" examples/multi_agents_api_web_demo.py" , run_name = " __main__" )
1048
+ ```
1049
+
1050
+ 此外由于 streamlit 要求一个页面内** 只能有一个** ` st.set_page_config() ` 函数,因此需要把 ` agent_api_web_demo.py ` 和 ` multi_agents_api_web_demo.py ` 中的相应代码注释掉,不然会报错
1051
+
1052
+ ` agent_api_web_demo.py ` 第 49\~ 53 行和第 136\~ 140 行
1053
+ ![ ] ( https://raw.githubusercontent.com/fresh-little-lemon/image/main/InternML-Tutorial/Pasted%20image%2020241223090619.png )
1054
+ ![ ] ( https://raw.githubusercontent.com/fresh-little-lemon/image/main/InternML-Tutorial/Pasted%20image%2020241223090707.png )
1055
+ ` multi_agents_api_web_demo.py ` 第 153 行
1056
+ ![ ] ( https://raw.githubusercontent.com/fresh-little-lemon/image/main/InternML-Tutorial/Pasted%20image%2020241223090819.png )
1057
+
1058
+ 然后我们就可以将 ` agent_camp4/lagent ` 文件夹下需要的文件用 ` rsync ` 全都拷贝到自己新建的 huggingface Spaces 仓库下了(注意!由于 git 文件和 ` README ` 中有仓库的配置信息,一定要警惕不能被覆盖掉,保持原来的就行,然后别忘了把 ` {your_huggingface_name} ` 替换成自己的 huggingface 用户名)
1059
+ ```
1060
+ git clone https://hf-mirror.com/spaces/{your_huggingface_name}/Lagent
1061
+ cd Lagent/
1062
+ rsync -av -o -t --exclude='.git*' --exclude='README.md' /root/agent_camp4/lagent/ /root/Lagent/
1063
+ git add .
1064
+ git commit -m "Add files"
1065
+ git push
1066
+ ```
1067
+
1068
+ 这样我们就在 huggingface 上部署成功了~~
1069
+ ![ ] ( https://raw.githubusercontent.com/fresh-little-lemon/image/main/InternML-Tutorial/Pasted%20image%2020241223092958.png )
1070
+ ![ ] ( https://raw.githubusercontent.com/fresh-little-lemon/image/main/InternML-Tutorial/Pasted%20image%2020241223092847.png )
1071
+ ![ ] ( https://raw.githubusercontent.com/fresh-little-lemon/image/main/InternML-Tutorial/Pasted%20image%2020241223092907.png )
1072
+ ![ ] ( https://raw.githubusercontent.com/fresh-little-lemon/image/main/InternML-Tutorial/Pasted%20image%2020241223092818.png )
1073
+
0 commit comments