deepseek+python实现对话中上传文件

部署本地api:https://blog.csdn.net/qq_35809258/article/details/145481113
实现持续对话:https://blog.csdn.net/qq_35809258/article/details/145490986

通过以上两个链接基本对话环境齐备,直接进行下一步
上传的文件类型可能有多种,需要安装所用到的python库

pip install python-docx  # Word文档处理
pip install pdfplumber   # PDF解析
pip install opencv-python # 图像处理

代码:

import os
from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig
import torch

# 支持的文件类型白名单
ALLOWED_EXTENSIONS = {'.txt', '.py', '.md', '.csv'}


def handle_file_upload(file_path: str) -> str:
    """处理文件上传并返回内容"""
    try:
        # 验证文件类型
        _, ext = os.path.splitext(file_path)
        if ext.lower() not in ALLOWED_EXTENSIONS:
            return f"错误:不支持的文件类型 {ext}"

        # 读取文件内容
        with open(file_path, 'r', encoding='utf-8') as f:
            content = f.read()

        # 限制文件大小(例如最大 1MB)
        if len(content) > 1_000_000:
            return "错误:文件大小超过 1MB 限制"

        return content

    except FileNotFoundError:
        return "错误:文件不存在"
    except UnicodeDecodeError:
        return "错误:文件编码格式不支持"


def chat_session(tokenizer,model):
    """管理对话会话"""
    conversation_history = []
    attached_files = {}  # 存储附件内容 {文件名: 内容}

    while True:
        user_input = input("\nYou: ").strip()

        # 处理特殊命令
        if user_input.lower() == "stop":
            break
        elif user_input.lower().startswith("upload "):
            file_path = user_input.split(" ", 1)[1]
            file_content = handle_file_upload(file_path)

            if file_content.startswith("错误"):
                print(file_content)
            else:
                filename = os.path.basename(file_path)
                attached_files[filename] = file_content
                print(f"成功上传文件: {filename} ({len(file_content)} 字符)")
            continue

        # 将附件内容合并到提示词
        full_prompt = "\n".join(conversation_history)
        if attached_files:
            file_context = "\n".join(
                [f"【文件 {name} 内容】\n{content[:1000]}..." for name, content in attached_files.items()]
            )
            full_prompt += f"\n{file_context}\n用户提问: {user_input}\n助理回答:"
        else:
            full_prompt += f"\n用户提问: {user_input}\n助理回答:"

        # 编码并生成回复
        inputs = tokenizer(full_prompt, return_tensors="pt").to(model.device)
        outputs = model.generate(
            inputs.input_ids,
            attention_mask=inputs.attention_mask,
            max_new_tokens=300,
            temperature=0.7,
            pad_token_id=tokenizer.pad_token_id
        )

        response = tokenizer.decode(outputs[0][inputs.input_ids.shape[-1]:], skip_special_tokens=True)
        response = response.split("。")[0] + "。"  # 截断第一个完整句子

        # 更新对话历史
        conversation_history.append(f"用户: {user_input}\n助理: {response}")
        print(f"\nAssistant: {response}")


def main():
    # 初始化模型和分词器
    quantization_config = BitsAndBytesConfig(
        load_in_4bit=True,
        bnb_4bit_use_double_quant=True,
        bnb_4bit_quant_type="nf4",
        bnb_4bit_compute_dtype=torch.float16
    )

    model = AutoModelForCausalLM.from_pretrained(
        "./deepseek-coder-7b-instruct",
        quantization_config=quantization_config,
        device_map="auto"
    )

    tokenizer = AutoTokenizer.from_pretrained("./deepseek-coder-7b-instruct")
    tokenizer.pad_token_id = tokenizer.eos_token_id

    # 主循环
    while True:
        cmd = input("\n输入 'start' 开始对话,'exit' 退出: ").lower()

        if cmd == "exit":
            break
        elif cmd == "start":
            print("\n==== 新对话开始 ====")
            print("可用命令:")
            print("  - upload <文件路径> : 上传文本文件")
            print("  - stop              : 结束当前对话")
            chat_session(tokenizer,model)


if __name__ == "__main__":
    main()

随便建个txt,输入一段内容,比如:
在这里插入图片描述

运行结果如下:

输入 'start' 开始对话,'exit' 退出: start

==== 新对话开始 ====
可用命令:
  - upload <文件路径> : 上传文本文件
  - stop              : 结束当前对话

You: upload example.txt
成功上传文件: example.txt (20 字符)

You: 请解释这个代码文件的功能

Assistant:  这个代码文件是一个Python脚本,它打印出"hello world"。

You: stop

输入 'start' 开始对话,'exit' 退出: exit
### 实现文件上传与提问 为了实现Python 中使用 DeepSeek 进行文件上传并随后基于该文件的内容进行提问,需先确保环境中已安装必要的依赖库。对于不同类型的文件处理,如Word文档、PDF以及图像等,相应的Python库是必不可少的[^1]。 针对此目标,可以构建一个简单的API客户端来交互。下面是一个简化版的例子,假设已经有一个运行中的DeepSeek服务端实例: ```python import requests from pathlib import Path def upload_file(file_path, api_url='http://localhost:8000/upload'): """ 向指定URL上传单个文件。 参数: file_path (str): 文件路径字符串表示形式。 api_url (str): 接收文件的服务地址,默认为本地服务器上的特定端口。 返回: response.json() : 来自服务器响应的数据结构化信息。 """ path = Path(file_path) files = {'file': open(path, 'rb')} try: response = requests.post(api_url, files=files) result = response.json() return result finally: files['file'].close() def ask_question(question_text, context_id=None, api_url='http://localhost:8000/ask'): """ 发送问题给定context下的文本内容至指定url获取答案 参数: question_text (str): 用户输入的问题文本。 context_id (str or None): 上下文ID用于关联之前上传过的文件;如果未提供,则默认为空。 api_url (str): 提问接口所在位置,默认指向本地部署的服务。 返回: dict: 包含来自服务器的回答和其他元数据的信息字典。 """ payload = { "question": question_text, "contextId": context_id } response = requests.post(api_url, json=payload) answer_info = response.json() return answer_info ``` 上述代码片段展示了如何创建两个函数`upload_file()`和`ask_question()`分别用来执行文件上传操作及向DeepSeek发送带有上下文标识符的问题请求。这里假定了存在一个RESTful API作为中介层连接前端应用与后台逻辑处理单元[^3]。 当调用这些方法时,应当注意递正确的参数值,并且确认目标API的实际地址是否匹配当前配置环境的要求。此外,在实际项目里还需要考虑错误处理机制以增强程序健壮性。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值