本文首發:從零到一:如何用阿里云百煉和火山引擎搭建專屬 AI 助手(DeepSeek)?
阿里云百煉和火山引擎都推出了免費的 DeepSeek 模型體驗額度,今天我和大家一起搭建一個本地的專屬 AI 助手。
- 阿里云百煉為 DeepSeek-R1 與 DeepSeek-V3 模型分別提供 100 萬 tokens 免費額度
🐳 https://www.aliyun.com/solution/tech-solution/deepseek-r1-for-platforms
- 火山引擎為 DeepSeek 在內的多種模型提供 50 萬 tokens 免費額度
🐳 https://www.volcengine.com/product/ark
一、阿里云百煉部署 DeepSeek 模型
1、登錄阿里云百煉
注冊并登錄阿里云百煉平臺,進入模型廣場即可查看 DeepSeek 模型。
2、創建 API Key
在阿里云百煉主頁右上角的個人圖標中,進入 API-KEY 頁面并創建專屬的 API Key。
3、調用 API 驗證
參考《配置 API Key 到環境變量》文檔,將 API Key 配置到環境變量中,并通過代碼調用 API 進行驗證。
🐳配置 API Key 到環境變量
https://help.aliyun.com/zh/model-studio/developer-reference/configure-api-key-through-environment-variables
以下是官方提供的代碼示例,幫助您快速上手:
?
import?os
from openai?import?OpenAIclient = OpenAI(# 若沒有配置環境變量,請用百煉API Key將下行替換為:api_key="sk-xxx",api_key=os.getenv("DASHSCOPE_API_KEY"), ?# 如何獲取API Key:https://help.aliyun.com/zh/model-studio/developer-reference/get-api-keybase_url="https://dashscope.aliyuncs.com/compatible-mode/v1"
)completion = client.chat.completions.create(model="deepseek-r1", ?# 此處以 deepseek-r1 為例,可按需更換模型名稱。messages=[{'role':?'user',?'content':?'9.9和9.11誰大'}]
)# 通過reasoning_content字段打印思考過程print("思考過程:")
print(completion.choices[0].message.reasoning_content)# 通過content字段打印最終答案print("最終答案:")
print(completion.choices[0].message.content)
二、火山引擎部署 DeepSeek 模型
1、登錄火山方舟
🐵
注冊并登錄火山方舟平臺,可使用我的邀請碼?9Z52V71T?可免費獲得每個模型 50 萬 tokens 的推理額度。
?
# 登錄后免費贈送每個模型50萬tokens推理額度。
https://www.volcengine.com/experience/ark?utm_term=202502dsinvite&ac=DSASUQY5&rc=9Z52V71T
登錄后就能體驗 DeepSeek-R1 等各種模型
2、創建 API Key
在“在線推理”頁面找到“API 接入”,按照提示創建 API Key。
3、創建自定義推理接入點
根據官方教程,在“在線推理”頁面選擇“創建推理接入點”。
創建過程比較簡單,填寫名稱并選擇模型(如 DeepSeek-R1),比如我選擇 DeepSeek-R1 模型,為了方便我自己識別,所以接入點名稱我填寫成“DeepSeek-R1”
在模型選擇頁,可以根據自己需求去選擇模型
創建完成就可以得到接入點名稱。注意:后續用到的 model_name 是火山平臺自動生成(以“ep-”開頭)。
4、調用 API 驗證
設置 API Key 作為環境變量,其中"YOUR_API_KEY"需要替換為火山方舟上創建的 API Key
?
export ARK_API_KEY="YOUR_API_KEY"
官方示例參考
import?os
from openai?import?OpenAIclient = OpenAI(api_key = os.environ.get("ARK_API_KEY"),base_url =?"https://ark.cn-beijing.volces.com/api/v3",
)# Non-streaming:
print("----- standard request -----")
completion = client.chat.completions.create(model =?"ep-", ?# your model endpoint IDmessages = [{"role":?"system",?"content":?"你是人工智能助手"},{"role":?"user",?"content":?"常見的十字花科植物有哪些?"},],
)
print(completion.choices[0].message.content)# Streaming:
print("----- streaming request -----")
stream = client.chat.completions.create(model =?"ep-", ?# your model endpoint IDmessages = [{"role":?"system",?"content":?"你是人工智能助手"},{"role":?"user",?"content":?"常見的十字花科植物有哪些?"},],stream=True
)for?chunk in stream:if?not chunk.choices:continueprint(chunk.choices[0].delta.content, end="")
print()
三、搭建專屬 AI 助手
無論是開發者還是普通用戶,都可以通過以下方式快速搭建專屬的 AI 助手:
1、用 streamlit 編寫個應用
對于程序員,可以使用 Streamlit 編寫一個簡單的網頁應用,實現本地化交互。
我已經編寫了一個基礎版,日常用用就足夠了,代碼參考
import?streamlit?as?st
import?uuid
import?os
import?hashlib
from?openai?import?OpenAI, AuthenticationError, APIError# 生成或獲取用戶特定的會話ID
if'user_session_id'notin?st.session_state:st.session_state.user_session_id =?str(uuid.uuid4())# 使用用戶會話ID來獲取或初始化用戶特定的數據
defget_user_data():if'user_data'notin?st.session_state:st.session_state.user_data = {}if?st.session_state.user_session_id?notin?st.session_state.user_data:st.session_state.user_data[st.session_state.user_session_id] = {'messages': [{"role":?"system",?"content":?"你是一個AI助手,請回答用戶提出的問題。"}],'uploaded_files': [],'api_key':?'sk-','base_url':?'https://dashscope.aliyuncs.com/compatible-mode/v1','model_name':?'deepseek-r1','past_sessions': []}return?st.session_state.user_data[st.session_state.user_session_id]# 更新用戶數據的輔助函數
defupdate_user_data(key, value):user_data = get_user_data()user_data[key] = value# 保存當前會話
defsave_current_session():user_data = get_user_data()iflen(user_data['messages']) >?1: ?# 只有當有實際對話時才保存current_session = {'id': st.session_state.user_session_id,'messages': user_data['messages']}# 檢查是否已存在相同ID的會話,如果存在則更新,不存在則插入existing_session =?next((session?for?session?in?user_data['past_sessions']?if?session['id'] == current_session['id']),?None)if?existing_session:existing_session.update(current_session)else:user_data['past_sessions'].insert(0, current_session)# 限制保存的會話數量,例如只保留最近的5個會話user_data['past_sessions'] = user_data['past_sessions'][:5]# 加載選定的會話
defload_session(session_id):user_data = get_user_data()for?session?in?user_data['past_sessions']:if?session['id'] == session_id:st.session_state.user_session_id = session_idst.session_state.user_data[session_id] = {'messages': session['messages'],'uploaded_files': [],'api_key': user_data['api_key'],'base_url': user_data['base_url'],'model_name': user_data['model_name'],'past_sessions': user_data['past_sessions']}breakdefsave_uploaded_files(upload_dir, uploaded_files):"""保存上傳的 txt 和 markdown 文件到臨時目錄并返回文件信息"""user_data = get_user_data()saved_files = []current_files = [f["name"]?for?f?in?user_data['uploaded_files']]for?file?in?uploaded_files:if?file.name?in?current_files:continueifnot?file.name.lower().endswith(('.txt',?'.md',?'.markdown')):st.warning(f"不支持的文件類型:?{file.name}。請上傳 .txt 或 .md 文件。")continueif?file.size >?1?*?1024?*?1024: ?# 1MB限制st.error(f"文件?{file.name}?超過大小限制(1MB)")continuetry:# 保存文件到指定目錄file_path = os.path.join(upload_dir, file.name)withopen(file_path,?"wb")?as?f:f.write(file.getbuffer())# 讀取文件內容withopen(file_path,?"r", encoding='utf-8')?as?f:content = f.read()# 生成內容哈希值content_hash = hashlib.md5(content.encode()).hexdigest()# 檢查重復內容ifany(f["hash"] == content_hash?for?f?in?user_data['uploaded_files']):st.info(f"文件?{file.name}?的內容與已上傳的文件重復,已跳過。")continuesaved_files.append({"name": file.name,"content": content,"size": file.size,"hash": content_hash})st.success(f"成功上傳文件:?{file.name}")except?Exception?as?e:st.error(f"處理文件?{file.name}?時出錯:?{str(e)}")continuereturn?saved_filesdefformat_file_contents(files):return"\n".join([f"===?{f['name']}?===\n{f['content']}\n"for?f?in?files])defget_active_api_config():user_data = get_user_data()return?user_data['base_url'], user_data['api_key'], user_data['model_name']defprocess_stream(stream):"""合并處理思考階段和響應階段"""thinking_content =?""response_content =?""# 在狀態塊外部預先創建響應占位符response_placeholder = st.empty()with?st.status("思考中...", expanded=True)?as?status:thinking_placeholder = st.empty()thinking_phase =?True# 思考階段標記for?chunk?in?stream:# 解析數據塊delta = chunk.choices[0].deltareasoning = delta.reasoning_content?ifhasattr(delta,?'reasoning_content')?else""content = delta.content?ifhasattr(delta,?'content')?else""role = delta.role?ifhasattr(delta,?'role')?else""# 處理思考階段if?thinking_phase:if?reasoning:thinking_content += reasoningthinking_placeholder.markdown(f"思考過程:\n{thinking_content}")# 檢測思考階段結束if?content:status.update(label="思考完成", state="complete", expanded=False)thinking_phase =?Falseresponse_placeholder.markdown("回答:\n▌") ?# 初始化響應光標# 處理響應階段(無論是否在思考階段都收集內容)if?content:response_content += contentifnot?thinking_phase:response_placeholder.markdown(f"回答:\n{response_content}▌")# 流結束后移除光標response_placeholder.markdown(f"回答:\n{response_content}")returnf"{thinking_content}{response_content}"defdisplay_chat_history():user_data = get_user_data()for?message?in?user_data['messages']:with?st.chat_message(message["role"]):st.markdown(message["content"])defhandle_user_input():user_data = get_user_data()base_url, api_key, model_name = get_active_api_config()ifnot?api_key?or?api_key ==?'sk-':st.error("請在側邊欄輸入有效的 API Key。")returntry:client = OpenAI(api_key=api_key, base_url=base_url)uploaded_files = st.file_uploader("上傳文本文件(支持 .txt 和 .md)",type=["txt",?"md",?"markdown"],accept_multiple_files=True,key="file_uploader")if?uploaded_files:new_files = save_uploaded_files(dirs, uploaded_files)user_data['uploaded_files'].extend(new_files)user_content = []if?user_input := st.chat_input("請問我任何事!"):user_content.append(user_input)if?user_data['uploaded_files']:file_content = format_file_contents(user_data['uploaded_files'])user_content.append("\n[上傳文件內容]\n"?+ file_content)user_data['uploaded_files'] = [] ?# 清空已處理的文件列表full_content =?"\n".join(user_content)user_data['messages'].append({"role":?"user",?"content": full_content})with?st.chat_message("user"):st.markdown(user_input)with?st.chat_message("assistant"):try:stream = client.chat.completions.create(model=model_name,messages=user_data['messages'],stream=True)response = process_stream(stream)user_data['messages'].append({"role":?"assistant",?"content": response})except?AuthenticationError:st.error("API 認證失敗。請檢查您的 API Key 是否正確。")except?APIError?as?e:st.error(f"API 錯誤:?{str(e)}")except?Exception?as?e:st.error(f"發生未知錯誤:?{str(e)}")except?Exception?as?e:st.error(f"設置 OpenAI 客戶端時發生錯誤:?{str(e)}")defmain_interface():st.title("AI 助手")user_data = get_user_data()with?st.sidebar:api_key = st.text_input("API Key", user_data['api_key'],?type="password")if?api_key:update_user_data('api_key', api_key)else:st.warning("請輸入有效的 API Key")# Base URL 選項base_url_options = {"DashScope":?"https://dashscope.aliyuncs.com/compatible-mode/v1","ARK":?"https://ark.cn-beijing.volces.com/api/v3","自定義":?"custom"}selected_base_url = st.selectbox("選擇 Base URL",options=list(base_url_options.keys()),index=list(base_url_options.keys()).index("DashScope")?if?user_data['base_url'] == base_url_options["DashScope"]?else0)if?selected_base_url ==?"自定義":custom_base_url = st.text_input("自定義 Base URL", user_data['base_url'])update_user_data('base_url', custom_base_url)else:update_user_data('base_url', base_url_options[selected_base_url])# Model Name 選項model_options = {"deepseek-r1":?"deepseek-r1","deepseek-v3":?"deepseek-v3","自定義":?"custom"}selected_model = st.selectbox("選擇 Model",options=list(model_options.keys()),index=list(model_options.keys()).index("deepseek-r1")?if?user_data['model_name'] ==?"deepseek-r1"else0)if?selected_model ==?"自定義":custom_model = st.text_input("自定義 Model Name", user_data['model_name'])update_user_data('model_name', custom_model)else:update_user_data('model_name', model_options[selected_model])if?st.button("🆕 新會話"):save_current_session() ?# 保存當前會話new_session_id =?str(uuid.uuid4())st.session_state.user_data[new_session_id] = {'messages': [{"role":?"system",?"content":?"你是一個AI助手,請回答用戶提出的問題。"}],'uploaded_files': [],'api_key': user_data['api_key'], ?# 保留當前的 API Key'base_url': user_data['base_url'], ?# 保留當前的 Base URL'model_name': user_data['model_name'], ?# 保留當前的 Model Name'past_sessions': user_data['past_sessions'] ?# 保留過去的會話記錄}st.session_state.user_session_id = new_session_idst.rerun()# 顯示過去的會話st.write("過去的會話:")for?past_session?in?user_data['past_sessions']:if?st.button(f"加載會話?{past_session['id'][:8]}...", key=past_session['id']):load_session(past_session['id'])st.rerun()display_chat_history()handle_user_input()defmain():if'user_session_id'notin?st.session_state:st.session_state.user_session_id =?str(uuid.uuid4())main_interface()if?__name__ ==?"__main__":dirs =?'uploads/'ifnot?os.path.exists(dirs):os.makedirs(dirs)main()
以下是啟動服務的命令:
?
streamlit run chat_ui.py
通過網頁界面,可以輕松填寫 API Key 并選擇平臺與模型,如阿里云百煉或火山方舟。
比如我用 阿里百煉 驗證交互過程
2、使用 Cherry Studio
如果您希望更便捷地使用 AI 助手,可以直接下載并安裝開源的 Cherry Studio。
🐳https://cherry-ai.com/
安裝好 Cherry Studio 之后,可配置需要接入的大模型應用后就可以本地化使用了,教程可參考 Cherry 官方文檔。
往期閱讀
手把手教你用 DeepSeek 和 Kimi,輕松搞定 PPT!
用 PyMuPDF 和 Pillow 打造 PDF 超級工具
基于 DeepSeek+AutoGen 的智能體協作系統
清華大學:普通人如何抓住 DeepSeek 紅利?(65 頁 PDF)
AI 時代,如何用 Python 腳本輕松搞定 PDF 需求?
DeepSeek 與 Ollama:本地運行 AI 模型的完美組合