{"repo": "bangaluoer/agent-", "files": {"README.md": {"9d455d6324dce34e73ed4de0c6cec56ad3852d2c": {"t": 1785746653.0101514, "n": 9527, "h": "3a754d308c9c2874", "c": "# agent-学习路线记录\n-----------------------\n## 2026.5.9\n今天观看了黑马程序员的课程\n\"image\"\n看到了提示词工程\n然后这是大致的代码块:\n```bash\nfrom openai import OpenAI\n\nclient=OpenAI(\n base_url=\"https://api.deepseek.com\"\n)\n\n#调用模型\nresponse=client.chat.completions.create(\n model=\"deepseek-v4-pro\",\n messages=[\n {\"role\": \"system\", \"content\": \"你是一个Python编程专家,并且说话很多\"},\n {\"role\":\"assistant\",\"content\":\"好的,我是Python编程专家,你想问什么?\"},\n {\"role\":\"user\",\"content\":\"输出1-10的数字,使用Python代码。\"}\n ],\n #打开流式输出开关\n stream=True\n)\n\n#处理结果\nfor chunk in response:\n\n # 取出content\n content = chunk.choices[0].delta.content\n\n # 过滤None\n if content is not None:\n print(content, end=\"\", flush=True)\n```\n觉得今天看的课程比较重要的就是这段代码,流式输出,然后过滤none\n-------------------------------------------------------------\n## 2026.5.10\n```bash\nmessages = [\n {\"role\": \"system\",\n \"content\": \"你是金融专家,将文本分类为['新闻报道', '财务报道', '公司公告', '分析师报告'],不清楚的分类为'不清楚类别' 下面有示例:\"},\n]\nfor key,value in examples_data.items():\n messages.append({\"role\": \"user\",\"content\": value})\n messages.append({\"role\": \"assistant\",\"content\": key})#动态添加message\n\nfor q in questions:\n response=client.chat.completions.create(\n model=\"deepseek-v4-pro\",\n messages=messages+[{\n \"role\":\"user\",\n \"content\": q#把要问的问题添加进来\n }]\n )\n```\n这是今天学的动态创建提示词\n然后今天还学了list转json和json转list\n```bash\njson.dumps(list,ensure_ascii=flase)#将字典或者列表转换成json\njson.loads(json)#将json转换成list或者字典\n```\n之前Python的数据结构学的迷迷糊糊,再总结一下字典和列表取值的时候用的方法:\n```bash\n字典:键(key) -> 值(value)\nperson = {\n \"name\": \"张三\",\n \"age\": 18\n}\nperson[\"name\"]=“张三”\n列表:类似于数组,通过下标来取对应的数据\n```\n\"image\"\n--------------------------------------------------------------------------------------------------------------------------------------\n\n## 2026.5.11\n今天学习langchain,我自己的理解就是langchain集成了很多功能,可以直接调用\n还学了文字转向量,使用的是huggingface的embedding模型\n```bash\nfrom langchain_community.embeddings import HuggingFaceEmbeddings\n\nembed = HuggingFaceEmbeddings(\n model_name=\"BAAI/bge-small-zh-v1.5\"\n)\n\nresult = embed.embed_query(\"我喜欢你\")#embed_query单次转换,一次转换一句话\nresult1=embed.embed_documents([\"我喜欢你\",\"我稀饭你\",\"晚上吃什么\"])#embed_documents一次转换多句话,传入的变量是一个列表[]\nprint(result1[:5])\n```\n\"image\"\n\n今天还学了关于langchain里面的fewshot\n```bash\nfrom langchain_core.prompts import PromptTemplate, FewShotPromptTemplate\nfrom langchain_openai import ChatOpenAI\n\nexample_prompt = PromptTemplate.from_template(\n \"输入:{input}, 输出:{output}\"\n)\n\nexamples = [\n {\"input\": \"示例1\", \"output\": \"答案1\"},\n {\"input\": \"示例2\", \"output\": \"答案2\"},\n]\n\nprompt = FewShotPromptTemplate(\n examples=examples,\n example_prompt=example_prompt,\n prefix=\"下面是一些示例:\",\n suffix=\"请回答:{question}\",\n input_variables=[\"question\"]\n)\n\nprompt_text = prompt.invoke({\"question\": \"真正的问题\"}).to_string()\n\nllm = ChatOpenAI(\n model=\"deepseek-chat\",\n base_url=\"https://api.deepseek.com\",\n temperature=0\n)\n\nres = llm.invoke(prompt_text).content\nprint(res)\n# 1. 导入 LangChain 的提示词模板和 DeepSeek 模型\n\n# 2. 定义单个示例的格式\n\n# 3. 准备 few-shot 示例数据\n\n# 4. 定义 few-shot 总模板\n\n# 5. 把变量填进去,生成最终 prompt\n\n# 6. 调用 DeepSeek\n\n# 7. 输出结果\n```\n还有今天学了format和invoke的区别:\n\"image\"\n## 2026.5.13\n今天学习了把模型的回复作为下一个模型的输入得到最后的结果\n```bash\nfrom langchain_core.prompts import PromptTemplate\nfrom langchain_core.output_parsers import JsonOutputParser,StrOutputParser\nfrom langchain_openai import ChatOpenAI\nfrom langchain_core.runnables import RunnableLambda\nfirst_prompt=PromptTemplate.from_template(\n \"我的邻居姓{last_name},生了一个{gender},你给取个名字,只要名字,不要其他信息\"\n)\nsecond_prompt=PromptTemplate.from_template(\n \"给你一个{name},解析一下含义\"\n)\nstr_parser=StrOutputParser()\njson_parser=JsonOutputParser()\n\nmodel=ChatOpenAI(\n model=\"deepseek-chat\",\n base_url=\"https://api.deepseek.com\",\n temperature=0\n)\nfunc=RunnableLambda(lambda ai_msg :{\"name\":ai_msg.content} )\nchain=first_prompt|model|func|second_prompt|model|str_parser\nfor chunk in chain.stream({\"last_name\":\"张\",\"gender\":\"女儿\"}):\n print(chunk,end=\"\",flush=True)\n```\n或者也可以调用jsonparser 但是这样的话提示词就需要强制ai输出json格式 并且指名键和对应的数据\n-----------------------------------------------------------------------------------------\n## 2026.5.15 \n今天学习了向量检索生成提示词 然后学习了将向量检索入chain\n```bash\n# 1. 用户问题\ninput_text = \"用户的问题\"\n\n# 2. 检索资料\ndocs = vector_store.similarity_search(input_text, k=2)\n\n# 3. 整理资料\ncontext = \"\\n\".join([doc.page_content for doc in docs])\n\n# 4. 问模型\nchain = prompt | model | StrOutputParser()\n\nres = chain.invoke({\n \"input\": input_text,\n \"context\": context\n})\n\nprint(res)\n```\n---------------------------\n## 2026.5.18\n这几天学的是一个Rag的项目 主要功能是用户上传文件作为系统的知识库 然后用户提问 模型根据知识库的内容来回答问题\n## 上传流程\n\napp_file_uploader.py\n-> KnowledgeBaseService.upload_by_str()\n-> md5 去重\n-> 文本切分\n-> Chroma.add_texts()\n-> chroma_db\n\n## 问答流程\n\napp_qa.py\n-> RagService().chain\n-> RunnableWithMessageHistory 加载历史\n-> retriever 检索知识库\n-> format_document 整理 context\n-> format_for_prompt_template 整理 input/context/history\n-> prompt_template\n-> DeepSeek\n-> StrOutputParser\n\n## 我理解的核心\n\n用户输入进入后,一路通过 RunnablePassthrough 保留原始 input 和 history,另一路取出 input 交给 retriever 检索知识库,检索结果整理成 context。最后把 input、context、history 统一整理成 prompt,让 DeepSeek 回答。\n--------------------------------------------\n## 2026.5.20\n针对 knowledge_base.py的总结\n```bash\n用户传入一个字符串,会创建一个KnowledgeBaseService类,然后判断目前的文件夹是否已经存在,如果不存在就创建,存在就跳过。\n然后计算传入字符串的md5值,如果已经存在这个字符串了,就提示知识在数据库中已经存在。\n然后判断传入的字符串是否超过了设定的最大文本长度,如果超过,就对文本进行切分。\n然后使用嵌入式模型将切分后的字符串转为向量,切分出来的每段文本都会添加一个metdata,用来记录文本的信息:名称,创建时间,操作人员名称,然后将数据传入数据库中存储。\n```\nvector_stores.py\n## 1. 负责什么?\n\n负责打开本地 Chroma 向量库,并返回 retriever 检索器。\n\n## 2. 输入是什么?\n\n输入是 embedding 模型。检索时 retriever 接收用户问题字符串。\n\n## 3. 输出是什么?\n\n输出是 retriever。调用 retriever.invoke(\"问题\") 后,会返回 Document 列表。\n\n## 4. 核心代码\n\n```python\nself.vector_store = Chroma(\n collection_name=config.collection_name,\n embedding_function=self.embedding,\n persist_directory=config.persist_directory,\n)\n```\n## 2026.5.21\n# rag.py\n\n## 1. 负责什么?\n\n负责构建 RAG 问答链,把用户问题、知识库检索结果和历史对话一起交给大模型回答。\n\n## 2. 输入是什么?\n\n输入是:\n{\"input\": \"用户问题\"}\n\n同时需要 session_config:\n{\"configurable\": {\"session_id\": \"user_001\"}}\n\n## 3. 输出是什么?\n\n输出是大模型回答的字符串。\n\n## 4. 核心流程\n\n1. VectorStoreService 创建 retriever\n2. format_for_retriever 从输入字典中提取用户问题\n3. retriever 检索 Chroma,返回 Document 列表\n4. format_document 把 Document 列表整理成 context 字符串\n5. format_for_prompt_template 整理成 input/context/history\n6. prompt_template 生成最终 prompt\n7. DeepSeek 生成回答\n8. StrOutputParser 转成字符串\n9. RunnableWithMessageHistory 保存历史\n\n## 5. 关键变量\n\ninput:用户当前问题 \ncontext:检索出来的知识库资料 \nhistory:历史对话消息 \n\n## 6. 容易错的地方\n\nRunnablePassthrough() 保留的是整个输入字典。 \n所以 value[\"input\"] 不是字符串,而是 {\"input\": ..., \"history\": ...}。 \n真正的问题要用 value[\"input\"][\"input\"] 取出。 \nMessagesPlaceholder(\"history\") 必须和 history_messages_key=\"history\" 对应。 \ninput_messages_key=\"input\" 必须和 invoke 里的 {\"input\": \"...\"} 对应。 \nretriever 返回的是 Document 列表,不是字符串。\n\n# file_history_store.py\n\n## 1. 负责什么?\n\n负责把多轮对话历史保存到本地文件中,并在下一次对话时读取出来。\n\n## 2. 输入是什么?\n\nget_history(session_id) 接收 session_id,例如 user_001。\n\nadd_messages(messages) 接收新的消息列表,例如用户消息和 AI 回复。\n\n## 3. 输出是什么?\n\nget_history 返回 FileChatMessageHistory 对象。\n\nmessages 属性返回历史消息列表 list[BaseMessage]。\n\n## 4. 核心流程\n\n1. RunnableWithMessageHistory 根据 session_config 拿到 session_id\n2. 调用 get_history(session_id)\n3. 创建 FileChatMessageHistory 对象\n4. 根据 session_id 确定历史文件路径\n5. messages 属性从本地 JSON 文件读取历史\n6. chain 执行完成后,add_messages 把新消息追加保存到文件\n\n## 5. 关键函数\n\nget_history:根据 session_id 返回历史管理对象 \nmessages:读取历史消息 \nadd_messages:追加并保存新消息 \nclear:清空历史 \n\n## 6. 容易错的地方\n\nsession_id 决定历史保存在哪个文件。 \nmessages 是属性,不是普通方法,所以用 self.messages,不用 self.messages()。 \n保存时要用 message_to_dict,把消息对象转成字典。 \n读取时要用 messages_from_dict,把字典恢复成消息对象。 \nadd_messages 不是只保存新消息,而是读取旧消息后合并再整体写回文件。\n\n------------------\n## 2026.5.23\n```bash\n用户在 Streamlit 输入问题\n↓\napp_agent_qa.py 接收 prompt\n↓\n调用 AgentService.chat_stream(prompt)\n↓\nAgentService 把用户问题加入 self.messages\n↓\nagent.stream / agent.invoke 开始运行\n↓\nAgent 判断是否调用 search_knowledge_base 工具\n↓\n工具内部执行 retriever.invoke(query)\n↓\nChroma 返回 docs\n↓\nformat_doc 把 docs 整理成字符串\n↓\nAgent 根据资料生成回答\n↓\n页面流式显示回答\n↓\n把回答和 trace 保存到页面历史\n```\n## 每个文件负责的功能\n```bash\napp_file_uploader.py\n= 上传 txt,更新知识库\n\nknowledge_base.py\n= 文本去重、切分、入库\n\nvector_stores.py\n= 连接 Chroma,返回 retriever\n\nagent_service.py\n= Agent 大脑,负责工具、检索、多轮记忆、流式输出\n\napp_agent_qa.py\n= Streamlit 网页,负责输入、显示、聊天历史、检索过程展示\n```\n## Agentservice的结构\n```bash\n__init__()\n= 初始化 embedding、retriever、model、tools、agent、messages、last_trace\n\nformat_doc()\n= 把检索结果 docs 整理成 Agent 能读的文本\n\ncreate_search_knowledgebase_tool()\n= 把 retriever.invoke(query) 包装成 Agent 工具\n\nchat()\n= 非流式版本,方便测试\n\nchat_stream()\n= 流式版本,给网页用\n\nget_last_trace()\n= 返回本轮工具调用和检索来源\n```\n## 项目总结\n我做的是一个 Agentic RAG 智能客服。普通 RAG 是用户问题固定进入检索流程,而我这里把知识库检索封装成 LangChain Tool,交给 Agent 自主决策。Agent 会根据用户问题判断是否调用 search_knowledge_base 工具,工具内部通过 Chroma retriever 检索本地知识库,并把检索结果返回给模型生成答案。同时我维护 messages 实现多轮上下文记忆,并在 Streamlit 页面中展示工具调用过程和检索来源。\n\n----\n## 2026.5.24\n```bash\nAgentService 初始化时创建 embedding、retriever、model、tool、agent。\n\n用户问题进入 chat_stream。\n\nchat_stream 把问题加入 messages,然后调用 agent.stream。\n\nAgent 需要知识库时会调用 search_knowledge_base 工具。\n\n工具内部用 retriever.invoke(query) 查 Chroma。\n\n查到的 docs 用 format_doc 整理后返回给 Agent。\n\nAgent 生成回答,chat_stream 一边 yield 给页面,一边保存完整回答。\n\nlast_trace 用来给页面展示本轮工具调用和来源。\n```\n"}, "9b849e537d6239c985c63fce132a51cc7a598f0b": {"t": 1785766598.640878, "n": 9172, "h": "59d8d557ad2297d1", "c": "# agent-学习路线记录\n-----------------------\n## 2026.5.9\n今天观看了黑马程序员的课程\n\"image\"\n看到了提示词工程\n然后这是大致的代码块:\n```bash\nfrom openai import OpenAI\n\nclient=OpenAI(\n base_url=\"https://api.deepseek.com\"\n)\n\n#调用模型\nresponse=client.chat.completions.create(\n model=\"deepseek-v4-pro\",\n messages=[\n {\"role\": \"system\", \"content\": \"你是一个Python编程专家,并且说话很多\"},\n {\"role\":\"assistant\",\"content\":\"好的,我是Python编程专家,你想问什么?\"},\n {\"role\":\"user\",\"content\":\"输出1-10的数字,使用Python代码。\"}\n ],\n #打开流式输出开关\n stream=True\n)\n\n#处理结果\nfor chunk in response:\n\n # 取出content\n content = chunk.choices[0].delta.content\n\n # 过滤None\n if content is not None:\n print(content, end=\"\", flush=True)\n```\n觉得今天看的课程比较重要的就是这段代码,流式输出,然后过滤none\n-------------------------------------------------------------\n## 2026.5.10\n```bash\nmessages = [\n {\"role\": \"system\",\n \"content\": \"你是金融专家,将文本分类为['新闻报道', '财务报道', '公司公告', '分析师报告'],不清楚的分类为'不清楚类别' 下面有示例:\"},\n]\nfor key,value in examples_data.items():\n messages.append({\"role\": \"user\",\"content\": value})\n messages.append({\"role\": \"assistant\",\"content\": key})#动态添加message\n\nfor q in questions:\n response=client.chat.completions.create(\n model=\"deepseek-v4-pro\",\n messages=messages+[{\n \"role\":\"user\",\n \"content\": q#把要问的问题添加进来\n }]\n )\n```\n这是今天学的动态创建提示词\n然后今天还学了list转json和json转list\n```bash\njson.dumps(list,ensure_ascii=flase)#将字典或者列表转换成json\njson.loads(json)#将json转换成list或者字典\n```\n之前Python的数据结构学的迷迷糊糊,再总结一下字典和列表取值的时候用的方法:\n```bash\n字典:键(key) -> 值(value)\nperson = {\n \"name\": \"张三\",\n \"age\": 18\n}\nperson[\"name\"]=“张三”\n列表:类似于数组,通过下标来取对应的数据\n```\n\"image\"\n--------------------------------------------------------------------------------------------------------------------------------------\n\n## 2026.5.11\n今天学习langchain,我自己的理解就是langchain集成了很多功能,可以直接调用\n还学了文字转向量,使用的是huggingface的embedding模型\n```bash\nfrom langchain_community.embeddings import HuggingFaceEmbeddings\n\nembed = HuggingFaceEmbeddings(\n model_name=\"BAAI/bge-small-zh-v1.5\"\n)\n\nresult = embed.embed_query(\"我喜欢你\")#embed_query单次转换,一次转换一句话\nresult1=embed.embed_documents([\"我喜欢你\",\"我稀饭你\",\"晚上吃什么\"])#embed_documents一次转换多句话,传入的变量是一个列表[]\nprint(result1[:5])\n```\n\"image\"\n\n今天还学了关于langchain里面的fewshot\n```bash\nfrom langchain_core.prompts import PromptTemplate, FewShotPromptTemplate\nfrom langchain_openai import ChatOpenAI\n\nexample_prompt = PromptTemplate.from_template(\n \"输入:{input}, 输出:{output}\"\n)\n\nexamples = [\n {\"input\": \"示例1\", \"output\": \"答案1\"},\n {\"input\": \"示例2\", \"output\": \"答案2\"},\n]\n\nprompt = FewShotPromptTemplate(\n examples=examples,\n example_prompt=example_prompt,\n prefix=\"下面是一些示例:\",\n suffix=\"请回答:{question}\",\n input_variables=[\"question\"]\n)\n\nprompt_text = prompt.invoke({\"question\": \"真正的问题\"}).to_string()\n\nllm = ChatOpenAI(\n model=\"deepseek-chat\",\n base_url=\"https://api.deepseek.com\",\n temperature=0\n)\n\nres = llm.invoke(prompt_text).content\nprint(res)\n# 1. 导入 LangChain 的提示词模板和 DeepSeek 模型\n\n# 2. 定义单个示例的格式\n\n# 3. 准备 few-shot 示例数据\n\n# 4. 定义 few-shot 总模板\n\n# 5. 把变量填进去,生成最终 prompt\n\n# 6. 调用 DeepSeek\n\n# 7. 输出结果\n```\n还有今天学了format和invoke的区别:\n\"image\"\n## 2026.5.13\n今天学习了把模型的回复作为下一个模型的输入得到最后的结果\n```bash\nfrom langchain_core.prompts import PromptTemplate\nfrom langchain_core.output_parsers import JsonOutputParser,StrOutputParser\nfrom langchain_openai import ChatOpenAI\nfrom langchain_core.runnables import RunnableLambda\nfirst_prompt=PromptTemplate.from_template(\n \"我的邻居姓{last_name},生了一个{gender},你给取个名字,只要名字,不要其他信息\"\n)\nsecond_prompt=PromptTemplate.from_template(\n \"给你一个{name},解析一下含义\"\n)\nstr_parser=StrOutputParser()\njson_parser=JsonOutputParser()\n\nmodel=ChatOpenAI(\n model=\"deepseek-chat\",\n base_url=\"https://api.deepseek.com\",\n temperature=0\n)\nfunc=RunnableLambda(lambda ai_msg :{\"name\":ai_msg.content} )\nchain=first_prompt|model|func|second_prompt|model|str_parser\nfor chunk in chain.stream({\"last_name\":\"张\",\"gender\":\"女儿\"}):\n print(chunk,end=\"\",flush=True)\n```\n或者也可以调用jsonparser 但是这样的话提示词就需要强制ai输出json格式 并且指名键和对应的数据\n-----------------------------------------------------------------------------------------\n## 2026.5.15 \n今天学习了向量检索生成提示词 然后学习了将向量检索入chain\n```bash\n# 1. 用户问题\ninput_text = \"用户的问题\"\n\n# 2. 检索资料\ndocs = vector_store.similarity_search(input_text, k=2)\n\n# 3. 整理资料\ncontext = \"\\n\".join([doc.page_content for doc in docs])\n\n# 4. 问模型\nchain = prompt | model | StrOutputParser()\n\nres = chain.invoke({\n \"input\": input_text,\n \"context\": context\n})\n\nprint(res)\n```\n---------------------------\n## 2026.5.18\n这几天学的是一个Rag的项目 主要功能是用户上传文件作为系统的知识库 然后用户提问 模型根据知识库的内容来回答问题\n## 上传流程\n\napp_file_uploader.py\n-> KnowledgeBaseService.upload_by_str()\n-> md5 去重\n-> 文本切分\n-> Chroma.add_texts()\n-> chroma_db\n\n## 问答流程\n\napp_qa.py\n-> RagService().chain\n-> RunnableWithMessageHistory 加载历史\n-> retriever 检索知识库\n-> format_document 整理 context\n-> format_for_prompt_template 整理 input/context/history\n-> prompt_template\n-> DeepSeek\n-> StrOutputParser\n\n## 我理解的核心\n\n用户输入进入后,一路通过 RunnablePassthrough 保留原始 input 和 history,另一路取出 input 交给 retriever 检索知识库,检索结果整理成 context。最后把 input、context、history 统一整理成 prompt,让 DeepSeek 回答。\n--------------------------------------------\n## 2026.5.20\n针对 knowledge_base.py的总结\n```bash\n用户传入一个字符串,会创建一个KnowledgeBaseService类,然后判断目前的文件夹是否已经存在,如果不存在就创建,存在就跳过。\n然后计算传入字符串的md5值,如果已经存在这个字符串了,就提示知识在数据库中已经存在。\n然后判断传入的字符串是否超过了设定的最大文本长度,如果超过,就对文本进行切分。\n然后使用嵌入式模型将切分后的字符串转为向量,切分出来的每段文本都会添加一个metdata,用来记录文本的信息:名称,创建时间,操作人员名称,然后将数据传入数据库中存储。\n```\nvector_stores.py\n## 1. 负责什么?\n\n负责打开本地 Chroma 向量库,并返回 retriever 检索器。\n\n## 2. 输入是什么?\n\n输入是 embedding 模型。检索时 retriever 接收用户问题字符串。\n\n## 3. 输出是什么?\n\n输出是 retriever。调用 retriever.invoke(\"问题\") 后,会返回 Document 列表。\n\n## 4. 核心代码\n\n```python\nself.vector_store = Chroma(\n collection_name=config.collection_name,\n embedding_function=self.embedding,\n persist_directory=config.persist_directory,\n)\n```\n## 2026.5.21\n# rag.py\n\n## 1. 负责什么?\n\n负责构建 RAG 问答链,把用户问题、知识库检索结果和历史对话一起交给大模型回答。\n\n## 2. 输入是什么?\n\n输入是:\n{\"input\": \"用户问题\"}\n\n同时需要 session_config:\n{\"configurable\": {\"session_id\": \"user_001\"}}\n\n## 3. 输出是什么?\n\n输出是大模型回答的字符串。\n\n## 4. 核心流程\n\n1. VectorStoreService 创建 retriever\n2. format_for_retriever 从输入字典中提取用户问题\n3. retriever 检索 Chroma,返回 Document 列表\n4. format_document 把 Document 列表整理成 context 字符串\n5. format_for_prompt_template 整理成 input/context/history\n6. prompt_template 生成最终 prompt\n7. DeepSeek 生成回答\n8. StrOutputParser 转成字符串\n9. RunnableWithMessageHistory 保存历史\n\n## 5. 关键变量\n\ninput:用户当前问题 \ncontext:检索出来的知识库资料 \nhistory:历史对话消息 \n\n## 6. 容易错的地方\n\nRunnablePassthrough() 保留的是整个输入字典。 \n所以 value[\"input\"] 不是字符串,而是 {\"input\": ..., \"history\": ...}。 \n真正的问题要用 value[\"input\"][\"input\"] 取出。 \nMessagesPlaceholder(\"history\") 必须和 history_messages_key=\"history\" 对应。 \ninput_messages_key=\"input\" 必须和 invoke 里的 {\"input\": \"...\"} 对应。 \nretriever 返回的是 Document 列表,不是字符串。\n\n# file_history_store.py\n\n## 1. 负责什么?\n\n负责把多轮对话历史保存到本地文件中,并在下一次对话时读取出来。\n\n## 2. 输入是什么?\n\nget_history(session_id) 接收 session_id,例如 user_001。\n\nadd_messages(messages) 接收新的消息列表,例如用户消息和 AI 回复。\n\n## 3. 输出是什么?\n\nget_history 返回 FileChatMessageHistory 对象。\n\nmessages 属性返回历史消息列表 list[BaseMessage]。\n\n## 4. 核心流程\n\n1. RunnableWithMessageHistory 根据 session_config 拿到 session_id\n2. 调用 get_history(session_id)\n3. 创建 FileChatMessageHistory 对象\n4. 根据 session_id 确定历史文件路径\n5. messages 属性从本地 JSON 文件读取历史\n6. chain 执行完成后,add_messages 把新消息追加保存到文件\n\n## 5. 关键函数\n\nget_history:根据 session_id 返回历史管理对象 \nmessages:读取历史消息 \nadd_messages:追加并保存新消息 \nclear:清空历史 \n\n## 6. 容易错的地方\n\nsession_id 决定历史保存在哪个文件。 \nmessages 是属性,不是普通方法,所以用 self.messages,不用 self.messages()。 \n保存时要用 message_to_dict,把消息对象转成字典。 \n读取时要用 messages_from_dict,把字典恢复成消息对象。 \nadd_messages 不是只保存新消息,而是读取旧消息后合并再整体写回文件。\n\n------------------\n## 2026.5.23\n```bash\n用户在 Streamlit 输入问题\n↓\napp_agent_qa.py 接收 prompt\n↓\n调用 AgentService.chat_stream(prompt)\n↓\nAgentService 把用户问题加入 self.messages\n↓\nagent.stream / agent.invoke 开始运行\n↓\nAgent 判断是否调用 search_knowledge_base 工具\n↓\n工具内部执行 retriever.invoke(query)\n↓\nChroma 返回 docs\n↓\nformat_doc 把 docs 整理成字符串\n↓\nAgent 根据资料生成回答\n↓\n页面流式显示回答\n↓\n把回答和 trace 保存到页面历史\n```\n## 每个文件负责的功能\n```bash\napp_file_uploader.py\n= 上传 txt,更新知识库\n\nknowledge_base.py\n= 文本去重、切分、入库\n\nvector_stores.py\n= 连接 Chroma,返回 retriever\n\nagent_service.py\n= Agent 大脑,负责工具、检索、多轮记忆、流式输出\n\napp_agent_qa.py\n= Streamlit 网页,负责输入、显示、聊天历史、检索过程展示\n```\n## Agentservice的结构\n```bash\n__init__()\n= 初始化 embedding、retriever、model、tools、agent、messages、last_trace\n\nformat_doc()\n= 把检索结果 docs 整理成 Agent 能读的文本\n\ncreate_search_knowledgebase_tool()\n= 把 retriever.invoke(query) 包装成 Agent 工具\n\nchat()\n= 非流式版本,方便测试\n\nchat_stream()\n= 流式版本,给网页用\n\nget_last_trace()\n= 返回本轮工具调用和检索来源\n```\n## 项目总结\n我做的是一个 Agentic RAG 智能客服。普通 RAG 是用户问题固定进入检索流程,而我这里把知识库检索封装成 LangChain Tool,交给 Agent 自主决策。Agent 会根据用户问题判断是否调用 search_knowledge_base 工具,工具内部通过 Chroma retriever 检索本地知识库,并把检索结果返回给模型生成答案。同时我维护 messages 实现多轮上下文记忆,并在 Streamlit 页面中展示工具调用过程和检索来源。\n"}, "03d75f2f87250e3c781f6616b0f43d2199a39b2e": {"t": 1785766600.4155505, "n": 8927, "h": "c183e7336c31de8b", "c": "# agent-学习路线记录\n-----------------------\n## 2026.5.9\n今天观看了黑马程序员的课程\n\"image\"\n看到了提示词工程\n然后这是大致的代码块:\n```bash\nfrom openai import OpenAI\n\nclient=OpenAI(\n base_url=\"https://api.deepseek.com\"\n)\n\n#调用模型\nresponse=client.chat.completions.create(\n model=\"deepseek-v4-pro\",\n messages=[\n {\"role\": \"system\", \"content\": \"你是一个Python编程专家,并且说话很多\"},\n {\"role\":\"assistant\",\"content\":\"好的,我是Python编程专家,你想问什么?\"},\n {\"role\":\"user\",\"content\":\"输出1-10的数字,使用Python代码。\"}\n ],\n #打开流式输出开关\n stream=True\n)\n\n#处理结果\nfor chunk in response:\n\n # 取出content\n content = chunk.choices[0].delta.content\n\n # 过滤None\n if content is not None:\n print(content, end=\"\", flush=True)\n```\n觉得今天看的课程比较重要的就是这段代码,流式输出,然后过滤none\n-------------------------------------------------------------\n## 2026.5.10\n```bash\nmessages = [\n {\"role\": \"system\",\n \"content\": \"你是金融专家,将文本分类为['新闻报道', '财务报道', '公司公告', '分析师报告'],不清楚的分类为'不清楚类别' 下面有示例:\"},\n]\nfor key,value in examples_data.items():\n messages.append({\"role\": \"user\",\"content\": value})\n messages.append({\"role\": \"assistant\",\"content\": key})#动态添加message\n\nfor q in questions:\n response=client.chat.completions.create(\n model=\"deepseek-v4-pro\",\n messages=messages+[{\n \"role\":\"user\",\n \"content\": q#把要问的问题添加进来\n }]\n )\n```\n这是今天学的动态创建提示词\n然后今天还学了list转json和json转list\n```bash\njson.dumps(list,ensure_ascii=flase)#将字典或者列表转换成json\njson.loads(json)#将json转换成list或者字典\n```\n之前Python的数据结构学的迷迷糊糊,再总结一下字典和列表取值的时候用的方法:\n```bash\n字典:键(key) -> 值(value)\nperson = {\n \"name\": \"张三\",\n \"age\": 18\n}\nperson[\"name\"]=“张三”\n列表:类似于数组,通过下标来取对应的数据\n```\n\"image\"\n--------------------------------------------------------------------------------------------------------------------------------------\n\n## 2026.5.11\n今天学习langchain,我自己的理解就是langchain集成了很多功能,可以直接调用\n还学了文字转向量,使用的是huggingface的embedding模型\n```bash\nfrom langchain_community.embeddings import HuggingFaceEmbeddings\n\nembed = HuggingFaceEmbeddings(\n model_name=\"BAAI/bge-small-zh-v1.5\"\n)\n\nresult = embed.embed_query(\"我喜欢你\")#embed_query单次转换,一次转换一句话\nresult1=embed.embed_documents([\"我喜欢你\",\"我稀饭你\",\"晚上吃什么\"])#embed_documents一次转换多句话,传入的变量是一个列表[]\nprint(result1[:5])\n```\n\"image\"\n\n今天还学了关于langchain里面的fewshot\n```bash\nfrom langchain_core.prompts import PromptTemplate, FewShotPromptTemplate\nfrom langchain_openai import ChatOpenAI\n\nexample_prompt = PromptTemplate.from_template(\n \"输入:{input}, 输出:{output}\"\n)\n\nexamples = [\n {\"input\": \"示例1\", \"output\": \"答案1\"},\n {\"input\": \"示例2\", \"output\": \"答案2\"},\n]\n\nprompt = FewShotPromptTemplate(\n examples=examples,\n example_prompt=example_prompt,\n prefix=\"下面是一些示例:\",\n suffix=\"请回答:{question}\",\n input_variables=[\"question\"]\n)\n\nprompt_text = prompt.invoke({\"question\": \"真正的问题\"}).to_string()\n\nllm = ChatOpenAI(\n model=\"deepseek-chat\",\n base_url=\"https://api.deepseek.com\",\n temperature=0\n)\n\nres = llm.invoke(prompt_text).content\nprint(res)\n# 1. 导入 LangChain 的提示词模板和 DeepSeek 模型\n\n# 2. 定义单个示例的格式\n\n# 3. 准备 few-shot 示例数据\n\n# 4. 定义 few-shot 总模板\n\n# 5. 把变量填进去,生成最终 prompt\n\n# 6. 调用 DeepSeek\n\n# 7. 输出结果\n```\n还有今天学了format和invoke的区别:\n\"image\"\n## 2026.5.13\n今天学习了把模型的回复作为下一个模型的输入得到最后的结果\n```bash\nfrom langchain_core.prompts import PromptTemplate\nfrom langchain_core.output_parsers import JsonOutputParser,StrOutputParser\nfrom langchain_openai import ChatOpenAI\nfrom langchain_core.runnables import RunnableLambda\nfirst_prompt=PromptTemplate.from_template(\n \"我的邻居姓{last_name},生了一个{gender},你给取个名字,只要名字,不要其他信息\"\n)\nsecond_prompt=PromptTemplate.from_template(\n \"给你一个{name},解析一下含义\"\n)\nstr_parser=StrOutputParser()\njson_parser=JsonOutputParser()\n\nmodel=ChatOpenAI(\n model=\"deepseek-chat\",\n base_url=\"https://api.deepseek.com\",\n temperature=0\n)\nfunc=RunnableLambda(lambda ai_msg :{\"name\":ai_msg.content} )\nchain=first_prompt|model|func|second_prompt|model|str_parser\nfor chunk in chain.stream({\"last_name\":\"张\",\"gender\":\"女儿\"}):\n print(chunk,end=\"\",flush=True)\n```\n或者也可以调用jsonparser 但是这样的话提示词就需要强制ai输出json格式 并且指名键和对应的数据\n-----------------------------------------------------------------------------------------\n## 2026.5.15 \n今天学习了向量检索生成提示词 然后学习了将向量检索入chain\n```bash\n# 1. 用户问题\ninput_text = \"用户的问题\"\n\n# 2. 检索资料\ndocs = vector_store.similarity_search(input_text, k=2)\n\n# 3. 整理资料\ncontext = \"\\n\".join([doc.page_content for doc in docs])\n\n# 4. 问模型\nchain = prompt | model | StrOutputParser()\n\nres = chain.invoke({\n \"input\": input_text,\n \"context\": context\n})\n\nprint(res)\n```\n---------------------------\n## 2026.5.18\n这几天学的是一个Rag的项目 主要功能是用户上传文件作为系统的知识库 然后用户提问 模型根据知识库的内容来回答问题\n## 上传流程\n\napp_file_uploader.py\n-> KnowledgeBaseService.upload_by_str()\n-> md5 去重\n-> 文本切分\n-> Chroma.add_texts()\n-> chroma_db\n\n## 问答流程\n\napp_qa.py\n-> RagService().chain\n-> RunnableWithMessageHistory 加载历史\n-> retriever 检索知识库\n-> format_document 整理 context\n-> format_for_prompt_template 整理 input/context/history\n-> prompt_template\n-> DeepSeek\n-> StrOutputParser\n\n## 我理解的核心\n\n用户输入进入后,一路通过 RunnablePassthrough 保留原始 input 和 history,另一路取出 input 交给 retriever 检索知识库,检索结果整理成 context。最后把 input、context、history 统一整理成 prompt,让 DeepSeek 回答。\n--------------------------------------------\n## 2026.5.20\n针对 knowledge_base.py的总结\n```bash\n用户传入一个字符串,会创建一个KnowledgeBaseService类,然后判断目前的文件夹是否已经存在,如果不存在就创建,存在就跳过。\n然后计算传入字符串的md5值,如果已经存在这个字符串了,就提示知识在数据库中已经存在。\n然后判断传入的字符串是否超过了设定的最大文本长度,如果超过,就对文本进行切分。\n然后使用嵌入式模型将切分后的字符串转为向量,切分出来的每段文本都会添加一个metdata,用来记录文本的信息:名称,创建时间,操作人员名称,然后将数据传入数据库中存储。\n```\nvector_stores.py\n## 1. 负责什么?\n\n负责打开本地 Chroma 向量库,并返回 retriever 检索器。\n\n## 2. 输入是什么?\n\n输入是 embedding 模型。检索时 retriever 接收用户问题字符串。\n\n## 3. 输出是什么?\n\n输出是 retriever。调用 retriever.invoke(\"问题\") 后,会返回 Document 列表。\n\n## 4. 核心代码\n\n```python\nself.vector_store = Chroma(\n collection_name=config.collection_name,\n embedding_function=self.embedding,\n persist_directory=config.persist_directory,\n)\n```\n## 2026.5.21\n# rag.py\n\n## 1. 负责什么?\n\n负责构建 RAG 问答链,把用户问题、知识库检索结果和历史对话一起交给大模型回答。\n\n## 2. 输入是什么?\n\n输入是:\n{\"input\": \"用户问题\"}\n\n同时需要 session_config:\n{\"configurable\": {\"session_id\": \"user_001\"}}\n\n## 3. 输出是什么?\n\n输出是大模型回答的字符串。\n\n## 4. 核心流程\n\n1. VectorStoreService 创建 retriever\n2. format_for_retriever 从输入字典中提取用户问题\n3. retriever 检索 Chroma,返回 Document 列表\n4. format_document 把 Document 列表整理成 context 字符串\n5. format_for_prompt_template 整理成 input/context/history\n6. prompt_template 生成最终 prompt\n7. DeepSeek 生成回答\n8. StrOutputParser 转成字符串\n9. RunnableWithMessageHistory 保存历史\n\n## 5. 关键变量\n\ninput:用户当前问题 \ncontext:检索出来的知识库资料 \nhistory:历史对话消息 \n\n## 6. 容易错的地方\n\nRunnablePassthrough() 保留的是整个输入字典。 \n所以 value[\"input\"] 不是字符串,而是 {\"input\": ..., \"history\": ...}。 \n真正的问题要用 value[\"input\"][\"input\"] 取出。 \nMessagesPlaceholder(\"history\") 必须和 history_messages_key=\"history\" 对应。 \ninput_messages_key=\"input\" 必须和 invoke 里的 {\"input\": \"...\"} 对应。 \nretriever 返回的是 Document 列表,不是字符串。\n\n# file_history_store.py\n\n## 1. 负责什么?\n\n负责把多轮对话历史保存到本地文件中,并在下一次对话时读取出来。\n\n## 2. 输入是什么?\n\nget_history(session_id) 接收 session_id,例如 user_001。\n\nadd_messages(messages) 接收新的消息列表,例如用户消息和 AI 回复。\n\n## 3. 输出是什么?\n\nget_history 返回 FileChatMessageHistory 对象。\n\nmessages 属性返回历史消息列表 list[BaseMessage]。\n\n## 4. 核心流程\n\n1. RunnableWithMessageHistory 根据 session_config 拿到 session_id\n2. 调用 get_history(session_id)\n3. 创建 FileChatMessageHistory 对象\n4. 根据 session_id 确定历史文件路径\n5. messages 属性从本地 JSON 文件读取历史\n6. chain 执行完成后,add_messages 把新消息追加保存到文件\n\n## 5. 关键函数\n\nget_history:根据 session_id 返回历史管理对象 \nmessages:读取历史消息 \nadd_messages:追加并保存新消息 \nclear:清空历史 \n\n## 6. 容易错的地方\n\nsession_id 决定历史保存在哪个文件。 \nmessages 是属性,不是普通方法,所以用 self.messages,不用 self.messages()。 \n保存时要用 message_to_dict,把消息对象转成字典。 \n读取时要用 messages_from_dict,把字典恢复成消息对象。 \nadd_messages 不是只保存新消息,而是读取旧消息后合并再整体写回文件。\n\n------------------\n## 2026.5.23\n```bash\n用户在 Streamlit 输入问题\n↓\napp_agent_qa.py 接收 prompt\n↓\n调用 AgentService.chat_stream(prompt)\n↓\nAgentService 把用户问题加入 self.messages\n↓\nagent.stream / agent.invoke 开始运行\n↓\nAgent 判断是否调用 search_knowledge_base 工具\n↓\n工具内部执行 retriever.invoke(query)\n↓\nChroma 返回 docs\n↓\nformat_doc 把 docs 整理成字符串\n↓\nAgent 根据资料生成回答\n↓\n页面流式显示回答\n↓\n把回答和 trace 保存到页面历史\n```\n## 每个文件负责的功能\n```bash\napp_file_uploader.py\n= 上传 txt,更新知识库\n\nknowledge_base.py\n= 文本去重、切分、入库\n\nvector_stores.py\n= 连接 Chroma,返回 retriever\n\nagent_service.py\n= Agent 大脑,负责工具、检索、多轮记忆、流式输出\n\napp_agent_qa.py\n= Streamlit 网页,负责输入、显示、聊天历史、检索过程展示\n```\n## Agentservice的结构\n```bash\n__init__()\n= 初始化 embedding、retriever、model、tools、agent、messages、last_trace\n\nformat_doc()\n= 把检索结果 docs 整理成 Agent 能读的文本\n\ncreate_search_knowledgebase_tool()\n= 把 retriever.invoke(query) 包装成 Agent 工具\n\nchat()\n= 非流式版本,方便测试\n\nchat_stream()\n= 流式版本,给网页用\n\nget_last_trace()\n= 返回本轮工具调用和检索来源\n```\n"}, "0e913d41a2ee9ef6965267f8add5a9344910e3f8": {"t": 1785766601.99187, "n": 8619, "h": "8910756dbf6a8173", "c": "# agent-学习路线记录\n-----------------------\n## 2026.5.9\n今天观看了黑马程序员的课程\n\"image\"\n看到了提示词工程\n然后这是大致的代码块:\n```bash\nfrom openai import OpenAI\n\nclient=OpenAI(\n base_url=\"https://api.deepseek.com\"\n)\n\n#调用模型\nresponse=client.chat.completions.create(\n model=\"deepseek-v4-pro\",\n messages=[\n {\"role\": \"system\", \"content\": \"你是一个Python编程专家,并且说话很多\"},\n {\"role\":\"assistant\",\"content\":\"好的,我是Python编程专家,你想问什么?\"},\n {\"role\":\"user\",\"content\":\"输出1-10的数字,使用Python代码。\"}\n ],\n #打开流式输出开关\n stream=True\n)\n\n#处理结果\nfor chunk in response:\n\n # 取出content\n content = chunk.choices[0].delta.content\n\n # 过滤None\n if content is not None:\n print(content, end=\"\", flush=True)\n```\n觉得今天看的课程比较重要的就是这段代码,流式输出,然后过滤none\n-------------------------------------------------------------\n## 2026.5.10\n```bash\nmessages = [\n {\"role\": \"system\",\n \"content\": \"你是金融专家,将文本分类为['新闻报道', '财务报道', '公司公告', '分析师报告'],不清楚的分类为'不清楚类别' 下面有示例:\"},\n]\nfor key,value in examples_data.items():\n messages.append({\"role\": \"user\",\"content\": value})\n messages.append({\"role\": \"assistant\",\"content\": key})#动态添加message\n\nfor q in questions:\n response=client.chat.completions.create(\n model=\"deepseek-v4-pro\",\n messages=messages+[{\n \"role\":\"user\",\n \"content\": q#把要问的问题添加进来\n }]\n )\n```\n这是今天学的动态创建提示词\n然后今天还学了list转json和json转list\n```bash\njson.dumps(list,ensure_ascii=flase)#将字典或者列表转换成json\njson.loads(json)#将json转换成list或者字典\n```\n之前Python的数据结构学的迷迷糊糊,再总结一下字典和列表取值的时候用的方法:\n```bash\n字典:键(key) -> 值(value)\nperson = {\n \"name\": \"张三\",\n \"age\": 18\n}\nperson[\"name\"]=“张三”\n列表:类似于数组,通过下标来取对应的数据\n```\n\"image\"\n--------------------------------------------------------------------------------------------------------------------------------------\n\n## 2026.5.11\n今天学习langchain,我自己的理解就是langchain集成了很多功能,可以直接调用\n还学了文字转向量,使用的是huggingface的embedding模型\n```bash\nfrom langchain_community.embeddings import HuggingFaceEmbeddings\n\nembed = HuggingFaceEmbeddings(\n model_name=\"BAAI/bge-small-zh-v1.5\"\n)\n\nresult = embed.embed_query(\"我喜欢你\")#embed_query单次转换,一次转换一句话\nresult1=embed.embed_documents([\"我喜欢你\",\"我稀饭你\",\"晚上吃什么\"])#embed_documents一次转换多句话,传入的变量是一个列表[]\nprint(result1[:5])\n```\n\"image\"\n\n今天还学了关于langchain里面的fewshot\n```bash\nfrom langchain_core.prompts import PromptTemplate, FewShotPromptTemplate\nfrom langchain_openai import ChatOpenAI\n\nexample_prompt = PromptTemplate.from_template(\n \"输入:{input}, 输出:{output}\"\n)\n\nexamples = [\n {\"input\": \"示例1\", \"output\": \"答案1\"},\n {\"input\": \"示例2\", \"output\": \"答案2\"},\n]\n\nprompt = FewShotPromptTemplate(\n examples=examples,\n example_prompt=example_prompt,\n prefix=\"下面是一些示例:\",\n suffix=\"请回答:{question}\",\n input_variables=[\"question\"]\n)\n\nprompt_text = prompt.invoke({\"question\": \"真正的问题\"}).to_string()\n\nllm = ChatOpenAI(\n model=\"deepseek-chat\",\n base_url=\"https://api.deepseek.com\",\n temperature=0\n)\n\nres = llm.invoke(prompt_text).content\nprint(res)\n# 1. 导入 LangChain 的提示词模板和 DeepSeek 模型\n\n# 2. 定义单个示例的格式\n\n# 3. 准备 few-shot 示例数据\n\n# 4. 定义 few-shot 总模板\n\n# 5. 把变量填进去,生成最终 prompt\n\n# 6. 调用 DeepSeek\n\n# 7. 输出结果\n```\n还有今天学了format和invoke的区别:\n\"image\"\n## 2026.5.13\n今天学习了把模型的回复作为下一个模型的输入得到最后的结果\n```bash\nfrom langchain_core.prompts import PromptTemplate\nfrom langchain_core.output_parsers import JsonOutputParser,StrOutputParser\nfrom langchain_openai import ChatOpenAI\nfrom langchain_core.runnables import RunnableLambda\nfirst_prompt=PromptTemplate.from_template(\n \"我的邻居姓{last_name},生了一个{gender},你给取个名字,只要名字,不要其他信息\"\n)\nsecond_prompt=PromptTemplate.from_template(\n \"给你一个{name},解析一下含义\"\n)\nstr_parser=StrOutputParser()\njson_parser=JsonOutputParser()\n\nmodel=ChatOpenAI(\n model=\"deepseek-chat\",\n base_url=\"https://api.deepseek.com\",\n temperature=0\n)\nfunc=RunnableLambda(lambda ai_msg :{\"name\":ai_msg.content} )\nchain=first_prompt|model|func|second_prompt|model|str_parser\nfor chunk in chain.stream({\"last_name\":\"张\",\"gender\":\"女儿\"}):\n print(chunk,end=\"\",flush=True)\n```\n或者也可以调用jsonparser 但是这样的话提示词就需要强制ai输出json格式 并且指名键和对应的数据\n-----------------------------------------------------------------------------------------\n## 2026.5.15 \n今天学习了向量检索生成提示词 然后学习了将向量检索入chain\n```bash\n# 1. 用户问题\ninput_text = \"用户的问题\"\n\n# 2. 检索资料\ndocs = vector_store.similarity_search(input_text, k=2)\n\n# 3. 整理资料\ncontext = \"\\n\".join([doc.page_content for doc in docs])\n\n# 4. 问模型\nchain = prompt | model | StrOutputParser()\n\nres = chain.invoke({\n \"input\": input_text,\n \"context\": context\n})\n\nprint(res)\n```\n---------------------------\n## 2026.5.18\n这几天学的是一个Rag的项目 主要功能是用户上传文件作为系统的知识库 然后用户提问 模型根据知识库的内容来回答问题\n## 上传流程\n\napp_file_uploader.py\n-> KnowledgeBaseService.upload_by_str()\n-> md5 去重\n-> 文本切分\n-> Chroma.add_texts()\n-> chroma_db\n\n## 问答流程\n\napp_qa.py\n-> RagService().chain\n-> RunnableWithMessageHistory 加载历史\n-> retriever 检索知识库\n-> format_document 整理 context\n-> format_for_prompt_template 整理 input/context/history\n-> prompt_template\n-> DeepSeek\n-> StrOutputParser\n\n## 我理解的核心\n\n用户输入进入后,一路通过 RunnablePassthrough 保留原始 input 和 history,另一路取出 input 交给 retriever 检索知识库,检索结果整理成 context。最后把 input、context、history 统一整理成 prompt,让 DeepSeek 回答。\n--------------------------------------------\n## 2026.5.20\n针对 knowledge_base.py的总结\n```bash\n用户传入一个字符串,会创建一个KnowledgeBaseService类,然后判断目前的文件夹是否已经存在,如果不存在就创建,存在就跳过。\n然后计算传入字符串的md5值,如果已经存在这个字符串了,就提示知识在数据库中已经存在。\n然后判断传入的字符串是否超过了设定的最大文本长度,如果超过,就对文本进行切分。\n然后使用嵌入式模型将切分后的字符串转为向量,切分出来的每段文本都会添加一个metdata,用来记录文本的信息:名称,创建时间,操作人员名称,然后将数据传入数据库中存储。\n```\nvector_stores.py\n## 1. 负责什么?\n\n负责打开本地 Chroma 向量库,并返回 retriever 检索器。\n\n## 2. 输入是什么?\n\n输入是 embedding 模型。检索时 retriever 接收用户问题字符串。\n\n## 3. 输出是什么?\n\n输出是 retriever。调用 retriever.invoke(\"问题\") 后,会返回 Document 列表。\n\n## 4. 核心代码\n\n```python\nself.vector_store = Chroma(\n collection_name=config.collection_name,\n embedding_function=self.embedding,\n persist_directory=config.persist_directory,\n)\n```\n## 2026.5.21\n# rag.py\n\n## 1. 负责什么?\n\n负责构建 RAG 问答链,把用户问题、知识库检索结果和历史对话一起交给大模型回答。\n\n## 2. 输入是什么?\n\n输入是:\n{\"input\": \"用户问题\"}\n\n同时需要 session_config:\n{\"configurable\": {\"session_id\": \"user_001\"}}\n\n## 3. 输出是什么?\n\n输出是大模型回答的字符串。\n\n## 4. 核心流程\n\n1. VectorStoreService 创建 retriever\n2. format_for_retriever 从输入字典中提取用户问题\n3. retriever 检索 Chroma,返回 Document 列表\n4. format_document 把 Document 列表整理成 context 字符串\n5. format_for_prompt_template 整理成 input/context/history\n6. prompt_template 生成最终 prompt\n7. DeepSeek 生成回答\n8. StrOutputParser 转成字符串\n9. RunnableWithMessageHistory 保存历史\n\n## 5. 关键变量\n\ninput:用户当前问题 \ncontext:检索出来的知识库资料 \nhistory:历史对话消息 \n\n## 6. 容易错的地方\n\nRunnablePassthrough() 保留的是整个输入字典。 \n所以 value[\"input\"] 不是字符串,而是 {\"input\": ..., \"history\": ...}。 \n真正的问题要用 value[\"input\"][\"input\"] 取出。 \nMessagesPlaceholder(\"history\") 必须和 history_messages_key=\"history\" 对应。 \ninput_messages_key=\"input\" 必须和 invoke 里的 {\"input\": \"...\"} 对应。 \nretriever 返回的是 Document 列表,不是字符串。\n\n# file_history_store.py\n\n## 1. 负责什么?\n\n负责把多轮对话历史保存到本地文件中,并在下一次对话时读取出来。\n\n## 2. 输入是什么?\n\nget_history(session_id) 接收 session_id,例如 user_001。\n\nadd_messages(messages) 接收新的消息列表,例如用户消息和 AI 回复。\n\n## 3. 输出是什么?\n\nget_history 返回 FileChatMessageHistory 对象。\n\nmessages 属性返回历史消息列表 list[BaseMessage]。\n\n## 4. 核心流程\n\n1. RunnableWithMessageHistory 根据 session_config 拿到 session_id\n2. 调用 get_history(session_id)\n3. 创建 FileChatMessageHistory 对象\n4. 根据 session_id 确定历史文件路径\n5. messages 属性从本地 JSON 文件读取历史\n6. chain 执行完成后,add_messages 把新消息追加保存到文件\n\n## 5. 关键函数\n\nget_history:根据 session_id 返回历史管理对象 \nmessages:读取历史消息 \nadd_messages:追加并保存新消息 \nclear:清空历史 \n\n## 6. 容易错的地方\n\nsession_id 决定历史保存在哪个文件。 \nmessages 是属性,不是普通方法,所以用 self.messages,不用 self.messages()。 \n保存时要用 message_to_dict,把消息对象转成字典。 \n读取时要用 messages_from_dict,把字典恢复成消息对象。 \nadd_messages 不是只保存新消息,而是读取旧消息后合并再整体写回文件。\n\n------------------\n## 2026.5.23\n```bash\n用户在 Streamlit 输入问题\n↓\napp_agent_qa.py 接收 prompt\n↓\n调用 AgentService.chat_stream(prompt)\n↓\nAgentService 把用户问题加入 self.messages\n↓\nagent.stream / agent.invoke 开始运行\n↓\nAgent 判断是否调用 search_knowledge_base 工具\n↓\n工具内部执行 retriever.invoke(query)\n↓\nChroma 返回 docs\n↓\nformat_doc 把 docs 整理成字符串\n↓\nAgent 根据资料生成回答\n↓\n页面流式显示回答\n↓\n把回答和 trace 保存到页面历史\n```\n## 每个文件负责的功能\n```bash\napp_file_uploader.py\n= 上传 txt,更新知识库\n\nknowledge_base.py\n= 文本去重、切分、入库\n\nvector_stores.py\n= 连接 Chroma,返回 retriever\n\nagent_service.py\n= Agent 大脑,负责工具、检索、多轮记忆、流式输出\n\napp_agent_qa.py\n= Streamlit 网页,负责输入、显示、聊天历史、检索过程展示\n```\n"}, "a37246a4e8f858384765a7d67c9959afa126d8d9": {"t": 1785766603.6343844, "n": 8384, "h": "6f4b20e754b46567", "c": "# agent-学习路线记录\n-----------------------\n## 2026.5.9\n今天观看了黑马程序员的课程\n\"image\"\n看到了提示词工程\n然后这是大致的代码块:\n```bash\nfrom openai import OpenAI\n\nclient=OpenAI(\n base_url=\"https://api.deepseek.com\"\n)\n\n#调用模型\nresponse=client.chat.completions.create(\n model=\"deepseek-v4-pro\",\n messages=[\n {\"role\": \"system\", \"content\": \"你是一个Python编程专家,并且说话很多\"},\n {\"role\":\"assistant\",\"content\":\"好的,我是Python编程专家,你想问什么?\"},\n {\"role\":\"user\",\"content\":\"输出1-10的数字,使用Python代码。\"}\n ],\n #打开流式输出开关\n stream=True\n)\n\n#处理结果\nfor chunk in response:\n\n # 取出content\n content = chunk.choices[0].delta.content\n\n # 过滤None\n if content is not None:\n print(content, end=\"\", flush=True)\n```\n觉得今天看的课程比较重要的就是这段代码,流式输出,然后过滤none\n-------------------------------------------------------------\n## 2026.5.10\n```bash\nmessages = [\n {\"role\": \"system\",\n \"content\": \"你是金融专家,将文本分类为['新闻报道', '财务报道', '公司公告', '分析师报告'],不清楚的分类为'不清楚类别' 下面有示例:\"},\n]\nfor key,value in examples_data.items():\n messages.append({\"role\": \"user\",\"content\": value})\n messages.append({\"role\": \"assistant\",\"content\": key})#动态添加message\n\nfor q in questions:\n response=client.chat.completions.create(\n model=\"deepseek-v4-pro\",\n messages=messages+[{\n \"role\":\"user\",\n \"content\": q#把要问的问题添加进来\n }]\n )\n```\n这是今天学的动态创建提示词\n然后今天还学了list转json和json转list\n```bash\njson.dumps(list,ensure_ascii=flase)#将字典或者列表转换成json\njson.loads(json)#将json转换成list或者字典\n```\n之前Python的数据结构学的迷迷糊糊,再总结一下字典和列表取值的时候用的方法:\n```bash\n字典:键(key) -> 值(value)\nperson = {\n \"name\": \"张三\",\n \"age\": 18\n}\nperson[\"name\"]=“张三”\n列表:类似于数组,通过下标来取对应的数据\n```\n\"image\"\n--------------------------------------------------------------------------------------------------------------------------------------\n\n## 2026.5.11\n今天学习langchain,我自己的理解就是langchain集成了很多功能,可以直接调用\n还学了文字转向量,使用的是huggingface的embedding模型\n```bash\nfrom langchain_community.embeddings import HuggingFaceEmbeddings\n\nembed = HuggingFaceEmbeddings(\n model_name=\"BAAI/bge-small-zh-v1.5\"\n)\n\nresult = embed.embed_query(\"我喜欢你\")#embed_query单次转换,一次转换一句话\nresult1=embed.embed_documents([\"我喜欢你\",\"我稀饭你\",\"晚上吃什么\"])#embed_documents一次转换多句话,传入的变量是一个列表[]\nprint(result1[:5])\n```\n\"image\"\n\n今天还学了关于langchain里面的fewshot\n```bash\nfrom langchain_core.prompts import PromptTemplate, FewShotPromptTemplate\nfrom langchain_openai import ChatOpenAI\n\nexample_prompt = PromptTemplate.from_template(\n \"输入:{input}, 输出:{output}\"\n)\n\nexamples = [\n {\"input\": \"示例1\", \"output\": \"答案1\"},\n {\"input\": \"示例2\", \"output\": \"答案2\"},\n]\n\nprompt = FewShotPromptTemplate(\n examples=examples,\n example_prompt=example_prompt,\n prefix=\"下面是一些示例:\",\n suffix=\"请回答:{question}\",\n input_variables=[\"question\"]\n)\n\nprompt_text = prompt.invoke({\"question\": \"真正的问题\"}).to_string()\n\nllm = ChatOpenAI(\n model=\"deepseek-chat\",\n base_url=\"https://api.deepseek.com\",\n temperature=0\n)\n\nres = llm.invoke(prompt_text).content\nprint(res)\n# 1. 导入 LangChain 的提示词模板和 DeepSeek 模型\n\n# 2. 定义单个示例的格式\n\n# 3. 准备 few-shot 示例数据\n\n# 4. 定义 few-shot 总模板\n\n# 5. 把变量填进去,生成最终 prompt\n\n# 6. 调用 DeepSeek\n\n# 7. 输出结果\n```\n还有今天学了format和invoke的区别:\n\"image\"\n## 2026.5.13\n今天学习了把模型的回复作为下一个模型的输入得到最后的结果\n```bash\nfrom langchain_core.prompts import PromptTemplate\nfrom langchain_core.output_parsers import JsonOutputParser,StrOutputParser\nfrom langchain_openai import ChatOpenAI\nfrom langchain_core.runnables import RunnableLambda\nfirst_prompt=PromptTemplate.from_template(\n \"我的邻居姓{last_name},生了一个{gender},你给取个名字,只要名字,不要其他信息\"\n)\nsecond_prompt=PromptTemplate.from_template(\n \"给你一个{name},解析一下含义\"\n)\nstr_parser=StrOutputParser()\njson_parser=JsonOutputParser()\n\nmodel=ChatOpenAI(\n model=\"deepseek-chat\",\n base_url=\"https://api.deepseek.com\",\n temperature=0\n)\nfunc=RunnableLambda(lambda ai_msg :{\"name\":ai_msg.content} )\nchain=first_prompt|model|func|second_prompt|model|str_parser\nfor chunk in chain.stream({\"last_name\":\"张\",\"gender\":\"女儿\"}):\n print(chunk,end=\"\",flush=True)\n```\n或者也可以调用jsonparser 但是这样的话提示词就需要强制ai输出json格式 并且指名键和对应的数据\n-----------------------------------------------------------------------------------------\n## 2026.5.15 \n今天学习了向量检索生成提示词 然后学习了将向量检索入chain\n```bash\n# 1. 用户问题\ninput_text = \"用户的问题\"\n\n# 2. 检索资料\ndocs = vector_store.similarity_search(input_text, k=2)\n\n# 3. 整理资料\ncontext = \"\\n\".join([doc.page_content for doc in docs])\n\n# 4. 问模型\nchain = prompt | model | StrOutputParser()\n\nres = chain.invoke({\n \"input\": input_text,\n \"context\": context\n})\n\nprint(res)\n```\n---------------------------\n## 2026.5.18\n这几天学的是一个Rag的项目 主要功能是用户上传文件作为系统的知识库 然后用户提问 模型根据知识库的内容来回答问题\n## 上传流程\n\napp_file_uploader.py\n-> KnowledgeBaseService.upload_by_str()\n-> md5 去重\n-> 文本切分\n-> Chroma.add_texts()\n-> chroma_db\n\n## 问答流程\n\napp_qa.py\n-> RagService().chain\n-> RunnableWithMessageHistory 加载历史\n-> retriever 检索知识库\n-> format_document 整理 context\n-> format_for_prompt_template 整理 input/context/history\n-> prompt_template\n-> DeepSeek\n-> StrOutputParser\n\n## 我理解的核心\n\n用户输入进入后,一路通过 RunnablePassthrough 保留原始 input 和 history,另一路取出 input 交给 retriever 检索知识库,检索结果整理成 context。最后把 input、context、history 统一整理成 prompt,让 DeepSeek 回答。\n--------------------------------------------\n## 2026.5.20\n针对 knowledge_base.py的总结\n```bash\n用户传入一个字符串,会创建一个KnowledgeBaseService类,然后判断目前的文件夹是否已经存在,如果不存在就创建,存在就跳过。\n然后计算传入字符串的md5值,如果已经存在这个字符串了,就提示知识在数据库中已经存在。\n然后判断传入的字符串是否超过了设定的最大文本长度,如果超过,就对文本进行切分。\n然后使用嵌入式模型将切分后的字符串转为向量,切分出来的每段文本都会添加一个metdata,用来记录文本的信息:名称,创建时间,操作人员名称,然后将数据传入数据库中存储。\n```\nvector_stores.py\n## 1. 负责什么?\n\n负责打开本地 Chroma 向量库,并返回 retriever 检索器。\n\n## 2. 输入是什么?\n\n输入是 embedding 模型。检索时 retriever 接收用户问题字符串。\n\n## 3. 输出是什么?\n\n输出是 retriever。调用 retriever.invoke(\"问题\") 后,会返回 Document 列表。\n\n## 4. 核心代码\n\n```python\nself.vector_store = Chroma(\n collection_name=config.collection_name,\n embedding_function=self.embedding,\n persist_directory=config.persist_directory,\n)\n```\n## 2026.5.21\n# rag.py\n\n## 1. 负责什么?\n\n负责构建 RAG 问答链,把用户问题、知识库检索结果和历史对话一起交给大模型回答。\n\n## 2. 输入是什么?\n\n输入是:\n{\"input\": \"用户问题\"}\n\n同时需要 session_config:\n{\"configurable\": {\"session_id\": \"user_001\"}}\n\n## 3. 输出是什么?\n\n输出是大模型回答的字符串。\n\n## 4. 核心流程\n\n1. VectorStoreService 创建 retriever\n2. format_for_retriever 从输入字典中提取用户问题\n3. retriever 检索 Chroma,返回 Document 列表\n4. format_document 把 Document 列表整理成 context 字符串\n5. format_for_prompt_template 整理成 input/context/history\n6. prompt_template 生成最终 prompt\n7. DeepSeek 生成回答\n8. StrOutputParser 转成字符串\n9. RunnableWithMessageHistory 保存历史\n\n## 5. 关键变量\n\ninput:用户当前问题 \ncontext:检索出来的知识库资料 \nhistory:历史对话消息 \n\n## 6. 容易错的地方\n\nRunnablePassthrough() 保留的是整个输入字典。 \n所以 value[\"input\"] 不是字符串,而是 {\"input\": ..., \"history\": ...}。 \n真正的问题要用 value[\"input\"][\"input\"] 取出。 \nMessagesPlaceholder(\"history\") 必须和 history_messages_key=\"history\" 对应。 \ninput_messages_key=\"input\" 必须和 invoke 里的 {\"input\": \"...\"} 对应。 \nretriever 返回的是 Document 列表,不是字符串。\n\n# file_history_store.py\n\n## 1. 负责什么?\n\n负责把多轮对话历史保存到本地文件中,并在下一次对话时读取出来。\n\n## 2. 输入是什么?\n\nget_history(session_id) 接收 session_id,例如 user_001。\n\nadd_messages(messages) 接收新的消息列表,例如用户消息和 AI 回复。\n\n## 3. 输出是什么?\n\nget_history 返回 FileChatMessageHistory 对象。\n\nmessages 属性返回历史消息列表 list[BaseMessage]。\n\n## 4. 核心流程\n\n1. RunnableWithMessageHistory 根据 session_config 拿到 session_id\n2. 调用 get_history(session_id)\n3. 创建 FileChatMessageHistory 对象\n4. 根据 session_id 确定历史文件路径\n5. messages 属性从本地 JSON 文件读取历史\n6. chain 执行完成后,add_messages 把新消息追加保存到文件\n\n## 5. 关键函数\n\nget_history:根据 session_id 返回历史管理对象 \nmessages:读取历史消息 \nadd_messages:追加并保存新消息 \nclear:清空历史 \n\n## 6. 容易错的地方\n\nsession_id 决定历史保存在哪个文件。 \nmessages 是属性,不是普通方法,所以用 self.messages,不用 self.messages()。 \n保存时要用 message_to_dict,把消息对象转成字典。 \n读取时要用 messages_from_dict,把字典恢复成消息对象。 \nadd_messages 不是只保存新消息,而是读取旧消息后合并再整体写回文件。\n\n------------------\n## 2026.5.23\n```bash\n用户在 Streamlit 输入问题\n↓\napp_agent_qa.py 接收 prompt\n↓\n调用 AgentService.chat_stream(prompt)\n↓\nAgentService 把用户问题加入 self.messages\n↓\nagent.stream / agent.invoke 开始运行\n↓\nAgent 判断是否调用 search_knowledge_base 工具\n↓\n工具内部执行 retriever.invoke(query)\n↓\nChroma 返回 docs\n↓\nformat_doc 把 docs 整理成字符串\n↓\nAgent 根据资料生成回答\n↓\n页面流式显示回答\n↓\n把回答和 trace 保存到页面历史\n```\n"}, "1a70719d95b270d5c53e3ead7b47d861a71967f3": {"t": 1785766605.021212, "n": 8372, "h": "6c39e71347d5b208", "c": "# agent-学习路线记录\n-----------------------\n## 2026.5.9\n今天观看了黑马程序员的课程\n\"image\"\n看到了提示词工程\n然后这是大致的代码块:\n```bash\nfrom openai import OpenAI\n\nclient=OpenAI(\n base_url=\"https://api.deepseek.com\"\n)\n\n#调用模型\nresponse=client.chat.completions.create(\n model=\"deepseek-v4-pro\",\n messages=[\n {\"role\": \"system\", \"content\": \"你是一个Python编程专家,并且说话很多\"},\n {\"role\":\"assistant\",\"content\":\"好的,我是Python编程专家,你想问什么?\"},\n {\"role\":\"user\",\"content\":\"输出1-10的数字,使用Python代码。\"}\n ],\n #打开流式输出开关\n stream=True\n)\n\n#处理结果\nfor chunk in response:\n\n # 取出content\n content = chunk.choices[0].delta.content\n\n # 过滤None\n if content is not None:\n print(content, end=\"\", flush=True)\n```\n觉得今天看的课程比较重要的就是这段代码,流式输出,然后过滤none\n-------------------------------------------------------------\n## 2026.5.10\n```bash\nmessages = [\n {\"role\": \"system\",\n \"content\": \"你是金融专家,将文本分类为['新闻报道', '财务报道', '公司公告', '分析师报告'],不清楚的分类为'不清楚类别' 下面有示例:\"},\n]\nfor key,value in examples_data.items():\n messages.append({\"role\": \"user\",\"content\": value})\n messages.append({\"role\": \"assistant\",\"content\": key})#动态添加message\n\nfor q in questions:\n response=client.chat.completions.create(\n model=\"deepseek-v4-pro\",\n messages=messages+[{\n \"role\":\"user\",\n \"content\": q#把要问的问题添加进来\n }]\n )\n```\n这是今天学的动态创建提示词\n然后今天还学了list转json和json转list\n```bash\njson.dumps(list,ensure_ascii=flase)#将字典或者列表转换成json\njson.loads(json)#将json转换成list或者字典\n```\n之前Python的数据结构学的迷迷糊糊,再总结一下字典和列表取值的时候用的方法:\n```bash\n字典:键(key) -> 值(value)\nperson = {\n \"name\": \"张三\",\n \"age\": 18\n}\nperson[\"name\"]=“张三”\n列表:类似于数组,通过下标来取对应的数据\n```\n\"image\"\n--------------------------------------------------------------------------------------------------------------------------------------\n\n## 2026.5.11\n今天学习langchain,我自己的理解就是langchain集成了很多功能,可以直接调用\n还学了文字转向量,使用的是huggingface的embedding模型\n```bash\nfrom langchain_community.embeddings import HuggingFaceEmbeddings\n\nembed = HuggingFaceEmbeddings(\n model_name=\"BAAI/bge-small-zh-v1.5\"\n)\n\nresult = embed.embed_query(\"我喜欢你\")#embed_query单次转换,一次转换一句话\nresult1=embed.embed_documents([\"我喜欢你\",\"我稀饭你\",\"晚上吃什么\"])#embed_documents一次转换多句话,传入的变量是一个列表[]\nprint(result1[:5])\n```\n\"image\"\n\n今天还学了关于langchain里面的fewshot\n```bash\nfrom langchain_core.prompts import PromptTemplate, FewShotPromptTemplate\nfrom langchain_openai import ChatOpenAI\n\nexample_prompt = PromptTemplate.from_template(\n \"输入:{input}, 输出:{output}\"\n)\n\nexamples = [\n {\"input\": \"示例1\", \"output\": \"答案1\"},\n {\"input\": \"示例2\", \"output\": \"答案2\"},\n]\n\nprompt = FewShotPromptTemplate(\n examples=examples,\n example_prompt=example_prompt,\n prefix=\"下面是一些示例:\",\n suffix=\"请回答:{question}\",\n input_variables=[\"question\"]\n)\n\nprompt_text = prompt.invoke({\"question\": \"真正的问题\"}).to_string()\n\nllm = ChatOpenAI(\n model=\"deepseek-chat\",\n base_url=\"https://api.deepseek.com\",\n temperature=0\n)\n\nres = llm.invoke(prompt_text).content\nprint(res)\n# 1. 导入 LangChain 的提示词模板和 DeepSeek 模型\n\n# 2. 定义单个示例的格式\n\n# 3. 准备 few-shot 示例数据\n\n# 4. 定义 few-shot 总模板\n\n# 5. 把变量填进去,生成最终 prompt\n\n# 6. 调用 DeepSeek\n\n# 7. 输出结果\n```\n还有今天学了format和invoke的区别:\n\"image\"\n## 2026.5.13\n今天学习了把模型的回复作为下一个模型的输入得到最后的结果\n```bash\nfrom langchain_core.prompts import PromptTemplate\nfrom langchain_core.output_parsers import JsonOutputParser,StrOutputParser\nfrom langchain_openai import ChatOpenAI\nfrom langchain_core.runnables import RunnableLambda\nfirst_prompt=PromptTemplate.from_template(\n \"我的邻居姓{last_name},生了一个{gender},你给取个名字,只要名字,不要其他信息\"\n)\nsecond_prompt=PromptTemplate.from_template(\n \"给你一个{name},解析一下含义\"\n)\nstr_parser=StrOutputParser()\njson_parser=JsonOutputParser()\n\nmodel=ChatOpenAI(\n model=\"deepseek-chat\",\n base_url=\"https://api.deepseek.com\",\n temperature=0\n)\nfunc=RunnableLambda(lambda ai_msg :{\"name\":ai_msg.content} )\nchain=first_prompt|model|func|second_prompt|model|str_parser\nfor chunk in chain.stream({\"last_name\":\"张\",\"gender\":\"女儿\"}):\n print(chunk,end=\"\",flush=True)\n```\n或者也可以调用jsonparser 但是这样的话提示词就需要强制ai输出json格式 并且指名键和对应的数据\n-----------------------------------------------------------------------------------------\n## 2026.5.15 \n今天学习了向量检索生成提示词 然后学习了将向量检索入chain\n```bash\n# 1. 用户问题\ninput_text = \"用户的问题\"\n\n# 2. 检索资料\ndocs = vector_store.similarity_search(input_text, k=2)\n\n# 3. 整理资料\ncontext = \"\\n\".join([doc.page_content for doc in docs])\n\n# 4. 问模型\nchain = prompt | model | StrOutputParser()\n\nres = chain.invoke({\n \"input\": input_text,\n \"context\": context\n})\n\nprint(res)\n```\n---------------------------\n## 2026.5.18\n这几天学的是一个Rag的项目 主要功能是用户上传文件作为系统的知识库 然后用户提问 模型根据知识库的内容来回答问题\n## 上传流程\n\napp_file_uploader.py\n-> KnowledgeBaseService.upload_by_str()\n-> md5 去重\n-> 文本切分\n-> Chroma.add_texts()\n-> chroma_db\n\n## 问答流程\n\napp_qa.py\n-> RagService().chain\n-> RunnableWithMessageHistory 加载历史\n-> retriever 检索知识库\n-> format_document 整理 context\n-> format_for_prompt_template 整理 input/context/history\n-> prompt_template\n-> DeepSeek\n-> StrOutputParser\n\n## 我理解的核心\n\n用户输入进入后,一路通过 RunnablePassthrough 保留原始 input 和 history,另一路取出 input 交给 retriever 检索知识库,检索结果整理成 context。最后把 input、context、history 统一整理成 prompt,让 DeepSeek 回答。\n--------------------------------------------\n## 2026.5.20\n针对 knowledge_base.py的总结\n```bash\n用户传入一个字符串,会创建一个KnowledgeBaseService类,然后判断目前的文件夹是否已经存在,如果不存在就创建,存在就跳过。\n然后计算传入字符串的md5值,如果已经存在这个字符串了,就提示知识在数据库中已经存在。\n然后判断传入的字符串是否超过了设定的最大文本长度,如果超过,就对文本进行切分。\n然后使用嵌入式模型将切分后的字符串转为向量,切分出来的每段文本都会添加一个metdata,用来记录文本的信息:名称,创建时间,操作人员名称,然后将数据传入数据库中存储。\n```\nvector_stores.py\n## 1. 负责什么?\n\n负责打开本地 Chroma 向量库,并返回 retriever 检索器。\n\n## 2. 输入是什么?\n\n输入是 embedding 模型。检索时 retriever 接收用户问题字符串。\n\n## 3. 输出是什么?\n\n输出是 retriever。调用 retriever.invoke(\"问题\") 后,会返回 Document 列表。\n\n## 4. 核心代码\n\n```python\nself.vector_store = Chroma(\n collection_name=config.collection_name,\n embedding_function=self.embedding,\n persist_directory=config.persist_directory,\n)\n```\n## 2026.5.21\n# rag.py\n\n## 1. 负责什么?\n\n负责构建 RAG 问答链,把用户问题、知识库检索结果和历史对话一起交给大模型回答。\n\n## 2. 输入是什么?\n\n输入是:\n{\"input\": \"用户问题\"}\n\n同时需要 session_config:\n{\"configurable\": {\"session_id\": \"user_001\"}}\n\n## 3. 输出是什么?\n\n输出是大模型回答的字符串。\n\n## 4. 核心流程\n\n1. VectorStoreService 创建 retriever\n2. format_for_retriever 从输入字典中提取用户问题\n3. retriever 检索 Chroma,返回 Document 列表\n4. format_document 把 Document 列表整理成 context 字符串\n5. format_for_prompt_template 整理成 input/context/history\n6. prompt_template 生成最终 prompt\n7. DeepSeek 生成回答\n8. StrOutputParser 转成字符串\n9. RunnableWithMessageHistory 保存历史\n\n## 5. 关键变量\n\ninput:用户当前问题 \ncontext:检索出来的知识库资料 \nhistory:历史对话消息 \n\n## 6. 容易错的地方\n\nRunnablePassthrough() 保留的是整个输入字典。 \n所以 value[\"input\"] 不是字符串,而是 {\"input\": ..., \"history\": ...}。 \n真正的问题要用 value[\"input\"][\"input\"] 取出。 \nMessagesPlaceholder(\"history\") 必须和 history_messages_key=\"history\" 对应。 \ninput_messages_key=\"input\" 必须和 invoke 里的 {\"input\": \"...\"} 对应。 \nretriever 返回的是 Document 列表,不是字符串。\n\n# file_history_store.py\n\n## 1. 负责什么?\n\n负责把多轮对话历史保存到本地文件中,并在下一次对话时读取出来。\n\n## 2. 输入是什么?\n\nget_history(session_id) 接收 session_id,例如 user_001。\n\nadd_messages(messages) 接收新的消息列表,例如用户消息和 AI 回复。\n\n## 3. 输出是什么?\n\nget_history 返回 FileChatMessageHistory 对象。\n\nmessages 属性返回历史消息列表 list[BaseMessage]。\n\n## 4. 核心流程\n\n1. RunnableWithMessageHistory 根据 session_config 拿到 session_id\n2. 调用 get_history(session_id)\n3. 创建 FileChatMessageHistory 对象\n4. 根据 session_id 确定历史文件路径\n5. messages 属性从本地 JSON 文件读取历史\n6. chain 执行完成后,add_messages 把新消息追加保存到文件\n\n## 5. 关键函数\n\nget_history:根据 session_id 返回历史管理对象 \nmessages:读取历史消息 \nadd_messages:追加并保存新消息 \nclear:清空历史 \n\n## 6. 容易错的地方\n\nsession_id 决定历史保存在哪个文件。 \nmessages 是属性,不是普通方法,所以用 self.messages,不用 self.messages()。 \n保存时要用 message_to_dict,把消息对象转成字典。 \n读取时要用 messages_from_dict,把字典恢复成消息对象。 \nadd_messages 不是只保存新消息,而是读取旧消息后合并再整体写回文件。\n\n------------------\n## 2026.5.23\n用户在 Streamlit 输入问题\n↓\napp_agent_qa.py 接收 prompt\n↓\n调用 AgentService.chat_stream(prompt)\n↓\nAgentService 把用户问题加入 self.messages\n↓\nagent.stream / agent.invoke 开始运行\n↓\nAgent 判断是否调用 search_knowledge_base 工具\n↓\n工具内部执行 retriever.invoke(query)\n↓\nChroma 返回 docs\n↓\nformat_doc 把 docs 整理成字符串\n↓\nAgent 根据资料生成回答\n↓\n页面流式显示回答\n↓\n把回答和 trace 保存到页面历史\n"}, "10e98c5c9062a95e9cc36529a166445e9cdb7770": {"t": 1785766606.5446339, "n": 8016, "h": "83ed6e08b6cd9783", "c": "# agent-学习路线记录\n-----------------------\n## 2026.5.9\n今天观看了黑马程序员的课程\n\"image\"\n看到了提示词工程\n然后这是大致的代码块:\n```bash\nfrom openai import OpenAI\n\nclient=OpenAI(\n base_url=\"https://api.deepseek.com\"\n)\n\n#调用模型\nresponse=client.chat.completions.create(\n model=\"deepseek-v4-pro\",\n messages=[\n {\"role\": \"system\", \"content\": \"你是一个Python编程专家,并且说话很多\"},\n {\"role\":\"assistant\",\"content\":\"好的,我是Python编程专家,你想问什么?\"},\n {\"role\":\"user\",\"content\":\"输出1-10的数字,使用Python代码。\"}\n ],\n #打开流式输出开关\n stream=True\n)\n\n#处理结果\nfor chunk in response:\n\n # 取出content\n content = chunk.choices[0].delta.content\n\n # 过滤None\n if content is not None:\n print(content, end=\"\", flush=True)\n```\n觉得今天看的课程比较重要的就是这段代码,流式输出,然后过滤none\n-------------------------------------------------------------\n## 2026.5.10\n```bash\nmessages = [\n {\"role\": \"system\",\n \"content\": \"你是金融专家,将文本分类为['新闻报道', '财务报道', '公司公告', '分析师报告'],不清楚的分类为'不清楚类别' 下面有示例:\"},\n]\nfor key,value in examples_data.items():\n messages.append({\"role\": \"user\",\"content\": value})\n messages.append({\"role\": \"assistant\",\"content\": key})#动态添加message\n\nfor q in questions:\n response=client.chat.completions.create(\n model=\"deepseek-v4-pro\",\n messages=messages+[{\n \"role\":\"user\",\n \"content\": q#把要问的问题添加进来\n }]\n )\n```\n这是今天学的动态创建提示词\n然后今天还学了list转json和json转list\n```bash\njson.dumps(list,ensure_ascii=flase)#将字典或者列表转换成json\njson.loads(json)#将json转换成list或者字典\n```\n之前Python的数据结构学的迷迷糊糊,再总结一下字典和列表取值的时候用的方法:\n```bash\n字典:键(key) -> 值(value)\nperson = {\n \"name\": \"张三\",\n \"age\": 18\n}\nperson[\"name\"]=“张三”\n列表:类似于数组,通过下标来取对应的数据\n```\n\"image\"\n--------------------------------------------------------------------------------------------------------------------------------------\n\n## 2026.5.11\n今天学习langchain,我自己的理解就是langchain集成了很多功能,可以直接调用\n还学了文字转向量,使用的是huggingface的embedding模型\n```bash\nfrom langchain_community.embeddings import HuggingFaceEmbeddings\n\nembed = HuggingFaceEmbeddings(\n model_name=\"BAAI/bge-small-zh-v1.5\"\n)\n\nresult = embed.embed_query(\"我喜欢你\")#embed_query单次转换,一次转换一句话\nresult1=embed.embed_documents([\"我喜欢你\",\"我稀饭你\",\"晚上吃什么\"])#embed_documents一次转换多句话,传入的变量是一个列表[]\nprint(result1[:5])\n```\n\"image\"\n\n今天还学了关于langchain里面的fewshot\n```bash\nfrom langchain_core.prompts import PromptTemplate, FewShotPromptTemplate\nfrom langchain_openai import ChatOpenAI\n\nexample_prompt = PromptTemplate.from_template(\n \"输入:{input}, 输出:{output}\"\n)\n\nexamples = [\n {\"input\": \"示例1\", \"output\": \"答案1\"},\n {\"input\": \"示例2\", \"output\": \"答案2\"},\n]\n\nprompt = FewShotPromptTemplate(\n examples=examples,\n example_prompt=example_prompt,\n prefix=\"下面是一些示例:\",\n suffix=\"请回答:{question}\",\n input_variables=[\"question\"]\n)\n\nprompt_text = prompt.invoke({\"question\": \"真正的问题\"}).to_string()\n\nllm = ChatOpenAI(\n model=\"deepseek-chat\",\n base_url=\"https://api.deepseek.com\",\n temperature=0\n)\n\nres = llm.invoke(prompt_text).content\nprint(res)\n# 1. 导入 LangChain 的提示词模板和 DeepSeek 模型\n\n# 2. 定义单个示例的格式\n\n# 3. 准备 few-shot 示例数据\n\n# 4. 定义 few-shot 总模板\n\n# 5. 把变量填进去,生成最终 prompt\n\n# 6. 调用 DeepSeek\n\n# 7. 输出结果\n```\n还有今天学了format和invoke的区别:\n\"image\"\n## 2026.5.13\n今天学习了把模型的回复作为下一个模型的输入得到最后的结果\n```bash\nfrom langchain_core.prompts import PromptTemplate\nfrom langchain_core.output_parsers import JsonOutputParser,StrOutputParser\nfrom langchain_openai import ChatOpenAI\nfrom langchain_core.runnables import RunnableLambda\nfirst_prompt=PromptTemplate.from_template(\n \"我的邻居姓{last_name},生了一个{gender},你给取个名字,只要名字,不要其他信息\"\n)\nsecond_prompt=PromptTemplate.from_template(\n \"给你一个{name},解析一下含义\"\n)\nstr_parser=StrOutputParser()\njson_parser=JsonOutputParser()\n\nmodel=ChatOpenAI(\n model=\"deepseek-chat\",\n base_url=\"https://api.deepseek.com\",\n temperature=0\n)\nfunc=RunnableLambda(lambda ai_msg :{\"name\":ai_msg.content} )\nchain=first_prompt|model|func|second_prompt|model|str_parser\nfor chunk in chain.stream({\"last_name\":\"张\",\"gender\":\"女儿\"}):\n print(chunk,end=\"\",flush=True)\n```\n或者也可以调用jsonparser 但是这样的话提示词就需要强制ai输出json格式 并且指名键和对应的数据\n-----------------------------------------------------------------------------------------\n## 2026.5.15 \n今天学习了向量检索生成提示词 然后学习了将向量检索入chain\n```bash\n# 1. 用户问题\ninput_text = \"用户的问题\"\n\n# 2. 检索资料\ndocs = vector_store.similarity_search(input_text, k=2)\n\n# 3. 整理资料\ncontext = \"\\n\".join([doc.page_content for doc in docs])\n\n# 4. 问模型\nchain = prompt | model | StrOutputParser()\n\nres = chain.invoke({\n \"input\": input_text,\n \"context\": context\n})\n\nprint(res)\n```\n---------------------------\n## 2026.5.18\n这几天学的是一个Rag的项目 主要功能是用户上传文件作为系统的知识库 然后用户提问 模型根据知识库的内容来回答问题\n## 上传流程\n\napp_file_uploader.py\n-> KnowledgeBaseService.upload_by_str()\n-> md5 去重\n-> 文本切分\n-> Chroma.add_texts()\n-> chroma_db\n\n## 问答流程\n\napp_qa.py\n-> RagService().chain\n-> RunnableWithMessageHistory 加载历史\n-> retriever 检索知识库\n-> format_document 整理 context\n-> format_for_prompt_template 整理 input/context/history\n-> prompt_template\n-> DeepSeek\n-> StrOutputParser\n\n## 我理解的核心\n\n用户输入进入后,一路通过 RunnablePassthrough 保留原始 input 和 history,另一路取出 input 交给 retriever 检索知识库,检索结果整理成 context。最后把 input、context、history 统一整理成 prompt,让 DeepSeek 回答。\n--------------------------------------------\n## 2026.5.20\n针对 knowledge_base.py的总结\n```bash\n用户传入一个字符串,会创建一个KnowledgeBaseService类,然后判断目前的文件夹是否已经存在,如果不存在就创建,存在就跳过。\n然后计算传入字符串的md5值,如果已经存在这个字符串了,就提示知识在数据库中已经存在。\n然后判断传入的字符串是否超过了设定的最大文本长度,如果超过,就对文本进行切分。\n然后使用嵌入式模型将切分后的字符串转为向量,切分出来的每段文本都会添加一个metdata,用来记录文本的信息:名称,创建时间,操作人员名称,然后将数据传入数据库中存储。\n```\nvector_stores.py\n## 1. 负责什么?\n\n负责打开本地 Chroma 向量库,并返回 retriever 检索器。\n\n## 2. 输入是什么?\n\n输入是 embedding 模型。检索时 retriever 接收用户问题字符串。\n\n## 3. 输出是什么?\n\n输出是 retriever。调用 retriever.invoke(\"问题\") 后,会返回 Document 列表。\n\n## 4. 核心代码\n\n```python\nself.vector_store = Chroma(\n collection_name=config.collection_name,\n embedding_function=self.embedding,\n persist_directory=config.persist_directory,\n)\n```\n## 2026.5.21\n# rag.py\n\n## 1. 负责什么?\n\n负责构建 RAG 问答链,把用户问题、知识库检索结果和历史对话一起交给大模型回答。\n\n## 2. 输入是什么?\n\n输入是:\n{\"input\": \"用户问题\"}\n\n同时需要 session_config:\n{\"configurable\": {\"session_id\": \"user_001\"}}\n\n## 3. 输出是什么?\n\n输出是大模型回答的字符串。\n\n## 4. 核心流程\n\n1. VectorStoreService 创建 retriever\n2. format_for_retriever 从输入字典中提取用户问题\n3. retriever 检索 Chroma,返回 Document 列表\n4. format_document 把 Document 列表整理成 context 字符串\n5. format_for_prompt_template 整理成 input/context/history\n6. prompt_template 生成最终 prompt\n7. DeepSeek 生成回答\n8. StrOutputParser 转成字符串\n9. RunnableWithMessageHistory 保存历史\n\n## 5. 关键变量\n\ninput:用户当前问题 \ncontext:检索出来的知识库资料 \nhistory:历史对话消息 \n\n## 6. 容易错的地方\n\nRunnablePassthrough() 保留的是整个输入字典。 \n所以 value[\"input\"] 不是字符串,而是 {\"input\": ..., \"history\": ...}。 \n真正的问题要用 value[\"input\"][\"input\"] 取出。 \nMessagesPlaceholder(\"history\") 必须和 history_messages_key=\"history\" 对应。 \ninput_messages_key=\"input\" 必须和 invoke 里的 {\"input\": \"...\"} 对应。 \nretriever 返回的是 Document 列表,不是字符串。\n\n# file_history_store.py\n\n## 1. 负责什么?\n\n负责把多轮对话历史保存到本地文件中,并在下一次对话时读取出来。\n\n## 2. 输入是什么?\n\nget_history(session_id) 接收 session_id,例如 user_001。\n\nadd_messages(messages) 接收新的消息列表,例如用户消息和 AI 回复。\n\n## 3. 输出是什么?\n\nget_history 返回 FileChatMessageHistory 对象。\n\nmessages 属性返回历史消息列表 list[BaseMessage]。\n\n## 4. 核心流程\n\n1. RunnableWithMessageHistory 根据 session_config 拿到 session_id\n2. 调用 get_history(session_id)\n3. 创建 FileChatMessageHistory 对象\n4. 根据 session_id 确定历史文件路径\n5. messages 属性从本地 JSON 文件读取历史\n6. chain 执行完成后,add_messages 把新消息追加保存到文件\n\n## 5. 关键函数\n\nget_history:根据 session_id 返回历史管理对象 \nmessages:读取历史消息 \nadd_messages:追加并保存新消息 \nclear:清空历史 \n\n## 6. 容易错的地方\n\nsession_id 决定历史保存在哪个文件。 \nmessages 是属性,不是普通方法,所以用 self.messages,不用 self.messages()。 \n保存时要用 message_to_dict,把消息对象转成字典。 \n读取时要用 messages_from_dict,把字典恢复成消息对象。 \nadd_messages 不是只保存新消息,而是读取旧消息后合并再整体写回文件。\n"}, "df7ea6625ec03e91612d360eb1a993bef4c2bff5": {"t": 1785766608.8456426, "n": 7180, "h": "968f136e331e07c0", "c": "# agent-学习路线记录\n-----------------------\n## 2026.5.9\n今天观看了黑马程序员的课程\n\"image\"\n看到了提示词工程\n然后这是大致的代码块:\n```bash\nfrom openai import OpenAI\n\nclient=OpenAI(\n base_url=\"https://api.deepseek.com\"\n)\n\n#调用模型\nresponse=client.chat.completions.create(\n model=\"deepseek-v4-pro\",\n messages=[\n {\"role\": \"system\", \"content\": \"你是一个Python编程专家,并且说话很多\"},\n {\"role\":\"assistant\",\"content\":\"好的,我是Python编程专家,你想问什么?\"},\n {\"role\":\"user\",\"content\":\"输出1-10的数字,使用Python代码。\"}\n ],\n #打开流式输出开关\n stream=True\n)\n\n#处理结果\nfor chunk in response:\n\n # 取出content\n content = chunk.choices[0].delta.content\n\n # 过滤None\n if content is not None:\n print(content, end=\"\", flush=True)\n```\n觉得今天看的课程比较重要的就是这段代码,流式输出,然后过滤none\n-------------------------------------------------------------\n## 2026.5.10\n```bash\nmessages = [\n {\"role\": \"system\",\n \"content\": \"你是金融专家,将文本分类为['新闻报道', '财务报道', '公司公告', '分析师报告'],不清楚的分类为'不清楚类别' 下面有示例:\"},\n]\nfor key,value in examples_data.items():\n messages.append({\"role\": \"user\",\"content\": value})\n messages.append({\"role\": \"assistant\",\"content\": key})#动态添加message\n\nfor q in questions:\n response=client.chat.completions.create(\n model=\"deepseek-v4-pro\",\n messages=messages+[{\n \"role\":\"user\",\n \"content\": q#把要问的问题添加进来\n }]\n )\n```\n这是今天学的动态创建提示词\n然后今天还学了list转json和json转list\n```bash\njson.dumps(list,ensure_ascii=flase)#将字典或者列表转换成json\njson.loads(json)#将json转换成list或者字典\n```\n之前Python的数据结构学的迷迷糊糊,再总结一下字典和列表取值的时候用的方法:\n```bash\n字典:键(key) -> 值(value)\nperson = {\n \"name\": \"张三\",\n \"age\": 18\n}\nperson[\"name\"]=“张三”\n列表:类似于数组,通过下标来取对应的数据\n```\n\"image\"\n--------------------------------------------------------------------------------------------------------------------------------------\n\n## 2026.5.11\n今天学习langchain,我自己的理解就是langchain集成了很多功能,可以直接调用\n还学了文字转向量,使用的是huggingface的embedding模型\n```bash\nfrom langchain_community.embeddings import HuggingFaceEmbeddings\n\nembed = HuggingFaceEmbeddings(\n model_name=\"BAAI/bge-small-zh-v1.5\"\n)\n\nresult = embed.embed_query(\"我喜欢你\")#embed_query单次转换,一次转换一句话\nresult1=embed.embed_documents([\"我喜欢你\",\"我稀饭你\",\"晚上吃什么\"])#embed_documents一次转换多句话,传入的变量是一个列表[]\nprint(result1[:5])\n```\n\"image\"\n\n今天还学了关于langchain里面的fewshot\n```bash\nfrom langchain_core.prompts import PromptTemplate, FewShotPromptTemplate\nfrom langchain_openai import ChatOpenAI\n\nexample_prompt = PromptTemplate.from_template(\n \"输入:{input}, 输出:{output}\"\n)\n\nexamples = [\n {\"input\": \"示例1\", \"output\": \"答案1\"},\n {\"input\": \"示例2\", \"output\": \"答案2\"},\n]\n\nprompt = FewShotPromptTemplate(\n examples=examples,\n example_prompt=example_prompt,\n prefix=\"下面是一些示例:\",\n suffix=\"请回答:{question}\",\n input_variables=[\"question\"]\n)\n\nprompt_text = prompt.invoke({\"question\": \"真正的问题\"}).to_string()\n\nllm = ChatOpenAI(\n model=\"deepseek-chat\",\n base_url=\"https://api.deepseek.com\",\n temperature=0\n)\n\nres = llm.invoke(prompt_text).content\nprint(res)\n# 1. 导入 LangChain 的提示词模板和 DeepSeek 模型\n\n# 2. 定义单个示例的格式\n\n# 3. 准备 few-shot 示例数据\n\n# 4. 定义 few-shot 总模板\n\n# 5. 把变量填进去,生成最终 prompt\n\n# 6. 调用 DeepSeek\n\n# 7. 输出结果\n```\n还有今天学了format和invoke的区别:\n\"image\"\n## 2026.5.13\n今天学习了把模型的回复作为下一个模型的输入得到最后的结果\n```bash\nfrom langchain_core.prompts import PromptTemplate\nfrom langchain_core.output_parsers import JsonOutputParser,StrOutputParser\nfrom langchain_openai import ChatOpenAI\nfrom langchain_core.runnables import RunnableLambda\nfirst_prompt=PromptTemplate.from_template(\n \"我的邻居姓{last_name},生了一个{gender},你给取个名字,只要名字,不要其他信息\"\n)\nsecond_prompt=PromptTemplate.from_template(\n \"给你一个{name},解析一下含义\"\n)\nstr_parser=StrOutputParser()\njson_parser=JsonOutputParser()\n\nmodel=ChatOpenAI(\n model=\"deepseek-chat\",\n base_url=\"https://api.deepseek.com\",\n temperature=0\n)\nfunc=RunnableLambda(lambda ai_msg :{\"name\":ai_msg.content} )\nchain=first_prompt|model|func|second_prompt|model|str_parser\nfor chunk in chain.stream({\"last_name\":\"张\",\"gender\":\"女儿\"}):\n print(chunk,end=\"\",flush=True)\n```\n或者也可以调用jsonparser 但是这样的话提示词就需要强制ai输出json格式 并且指名键和对应的数据\n-----------------------------------------------------------------------------------------\n## 2026.5.15 \n今天学习了向量检索生成提示词 然后学习了将向量检索入chain\n```bash\n# 1. 用户问题\ninput_text = \"用户的问题\"\n\n# 2. 检索资料\ndocs = vector_store.similarity_search(input_text, k=2)\n\n# 3. 整理资料\ncontext = \"\\n\".join([doc.page_content for doc in docs])\n\n# 4. 问模型\nchain = prompt | model | StrOutputParser()\n\nres = chain.invoke({\n \"input\": input_text,\n \"context\": context\n})\n\nprint(res)\n```\n---------------------------\n## 2026.5.18\n这几天学的是一个Rag的项目 主要功能是用户上传文件作为系统的知识库 然后用户提问 模型根据知识库的内容来回答问题\n## 上传流程\n\napp_file_uploader.py\n-> KnowledgeBaseService.upload_by_str()\n-> md5 去重\n-> 文本切分\n-> Chroma.add_texts()\n-> chroma_db\n\n## 问答流程\n\napp_qa.py\n-> RagService().chain\n-> RunnableWithMessageHistory 加载历史\n-> retriever 检索知识库\n-> format_document 整理 context\n-> format_for_prompt_template 整理 input/context/history\n-> prompt_template\n-> DeepSeek\n-> StrOutputParser\n\n## 我理解的核心\n\n用户输入进入后,一路通过 RunnablePassthrough 保留原始 input 和 history,另一路取出 input 交给 retriever 检索知识库,检索结果整理成 context。最后把 input、context、history 统一整理成 prompt,让 DeepSeek 回答。\n--------------------------------------------\n## 2026.5.20\n针对 knowledge_base.py的总结\n```bash\n用户传入一个字符串,会创建一个KnowledgeBaseService类,然后判断目前的文件夹是否已经存在,如果不存在就创建,存在就跳过。\n然后计算传入字符串的md5值,如果已经存在这个字符串了,就提示知识在数据库中已经存在。\n然后判断传入的字符串是否超过了设定的最大文本长度,如果超过,就对文本进行切分。\n然后使用嵌入式模型将切分后的字符串转为向量,切分出来的每段文本都会添加一个metdata,用来记录文本的信息:名称,创建时间,操作人员名称,然后将数据传入数据库中存储。\n```\nvector_stores.py\n## 1. 负责什么?\n\n负责打开本地 Chroma 向量库,并返回 retriever 检索器。\n\n## 2. 输入是什么?\n\n输入是 embedding 模型。检索时 retriever 接收用户问题字符串。\n\n## 3. 输出是什么?\n\n输出是 retriever。调用 retriever.invoke(\"问题\") 后,会返回 Document 列表。\n\n## 4. 核心代码\n\n```python\nself.vector_store = Chroma(\n collection_name=config.collection_name,\n embedding_function=self.embedding,\n persist_directory=config.persist_directory,\n)\n```\n## 2026.5.21\n# rag.py\n\n## 1. 负责什么?\n\n负责构建 RAG 问答链,把用户问题、知识库检索结果和历史对话一起交给大模型回答。\n\n## 2. 输入是什么?\n\n输入是:\n{\"input\": \"用户问题\"}\n\n同时需要 session_config:\n{\"configurable\": {\"session_id\": \"user_001\"}}\n\n## 3. 输出是什么?\n\n输出是大模型回答的字符串。\n\n## 4. 核心流程\n\n1. VectorStoreService 创建 retriever\n2. format_for_retriever 从输入字典中提取用户问题\n3. retriever 检索 Chroma,返回 Document 列表\n4. format_document 把 Document 列表整理成 context 字符串\n5. format_for_prompt_template 整理成 input/context/history\n6. prompt_template 生成最终 prompt\n7. DeepSeek 生成回答\n8. StrOutputParser 转成字符串\n9. RunnableWithMessageHistory 保存历史\n\n## 5. 关键变量\n\ninput:用户当前问题 \ncontext:检索出来的知识库资料 \nhistory:历史对话消息 \n\n## 6. 容易错的地方\n\nRunnablePassthrough() 保留的是整个输入字典。 \n所以 value[\"input\"] 不是字符串,而是 {\"input\": ..., \"history\": ...}。 \n真正的问题要用 value[\"input\"][\"input\"] 取出。 \nMessagesPlaceholder(\"history\") 必须和 history_messages_key=\"history\" 对应。 \ninput_messages_key=\"input\" 必须和 invoke 里的 {\"input\": \"...\"} 对应。 \nretriever 返回的是 Document 列表,不是字符串。\n"}, "2bacc15c9830b40932050d701298832a300d6ece": {"t": 1785766610.120482, "n": 7176, "h": "fb69614960eebd53", "c": "# agent-学习路线记录\n-----------------------\n## 2026.5.9\n今天观看了黑马程序员的课程\n\"image\"\n看到了提示词工程\n然后这是大致的代码块:\n```bash\nfrom openai import OpenAI\n\nclient=OpenAI(\n base_url=\"https://api.deepseek.com\"\n)\n\n#调用模型\nresponse=client.chat.completions.create(\n model=\"deepseek-v4-pro\",\n messages=[\n {\"role\": \"system\", \"content\": \"你是一个Python编程专家,并且说话很多\"},\n {\"role\":\"assistant\",\"content\":\"好的,我是Python编程专家,你想问什么?\"},\n {\"role\":\"user\",\"content\":\"输出1-10的数字,使用Python代码。\"}\n ],\n #打开流式输出开关\n stream=True\n)\n\n#处理结果\nfor chunk in response:\n\n # 取出content\n content = chunk.choices[0].delta.content\n\n # 过滤None\n if content is not None:\n print(content, end=\"\", flush=True)\n```\n觉得今天看的课程比较重要的就是这段代码,流式输出,然后过滤none\n-------------------------------------------------------------\n## 2026.5.10\n```bash\nmessages = [\n {\"role\": \"system\",\n \"content\": \"你是金融专家,将文本分类为['新闻报道', '财务报道', '公司公告', '分析师报告'],不清楚的分类为'不清楚类别' 下面有示例:\"},\n]\nfor key,value in examples_data.items():\n messages.append({\"role\": \"user\",\"content\": value})\n messages.append({\"role\": \"assistant\",\"content\": key})#动态添加message\n\nfor q in questions:\n response=client.chat.completions.create(\n model=\"deepseek-v4-pro\",\n messages=messages+[{\n \"role\":\"user\",\n \"content\": q#把要问的问题添加进来\n }]\n )\n```\n这是今天学的动态创建提示词\n然后今天还学了list转json和json转list\n```bash\njson.dumps(list,ensure_ascii=flase)#将字典或者列表转换成json\njson.loads(json)#将json转换成list或者字典\n```\n之前Python的数据结构学的迷迷糊糊,再总结一下字典和列表取值的时候用的方法:\n```bash\n字典:键(key) -> 值(value)\nperson = {\n \"name\": \"张三\",\n \"age\": 18\n}\nperson[\"name\"]=“张三”\n列表:类似于数组,通过下标来取对应的数据\n```\n\"image\"\n--------------------------------------------------------------------------------------------------------------------------------------\n\n## 2026.5.11\n今天学习langchain,我自己的理解就是langchain集成了很多功能,可以直接调用\n还学了文字转向量,使用的是huggingface的embedding模型\n```bash\nfrom langchain_community.embeddings import HuggingFaceEmbeddings\n\nembed = HuggingFaceEmbeddings(\n model_name=\"BAAI/bge-small-zh-v1.5\"\n)\n\nresult = embed.embed_query(\"我喜欢你\")#embed_query单次转换,一次转换一句话\nresult1=embed.embed_documents([\"我喜欢你\",\"我稀饭你\",\"晚上吃什么\"])#embed_documents一次转换多句话,传入的变量是一个列表[]\nprint(result1[:5])\n```\n\"image\"\n\n今天还学了关于langchain里面的fewshot\n```bash\nfrom langchain_core.prompts import PromptTemplate, FewShotPromptTemplate\nfrom langchain_openai import ChatOpenAI\n\nexample_prompt = PromptTemplate.from_template(\n \"输入:{input}, 输出:{output}\"\n)\n\nexamples = [\n {\"input\": \"示例1\", \"output\": \"答案1\"},\n {\"input\": \"示例2\", \"output\": \"答案2\"},\n]\n\nprompt = FewShotPromptTemplate(\n examples=examples,\n example_prompt=example_prompt,\n prefix=\"下面是一些示例:\",\n suffix=\"请回答:{question}\",\n input_variables=[\"question\"]\n)\n\nprompt_text = prompt.invoke({\"question\": \"真正的问题\"}).to_string()\n\nllm = ChatOpenAI(\n model=\"deepseek-chat\",\n base_url=\"https://api.deepseek.com\",\n temperature=0\n)\n\nres = llm.invoke(prompt_text).content\nprint(res)\n# 1. 导入 LangChain 的提示词模板和 DeepSeek 模型\n\n# 2. 定义单个示例的格式\n\n# 3. 准备 few-shot 示例数据\n\n# 4. 定义 few-shot 总模板\n\n# 5. 把变量填进去,生成最终 prompt\n\n# 6. 调用 DeepSeek\n\n# 7. 输出结果\n```\n还有今天学了format和invoke的区别:\n\"image\"\n## 2026.5.13\n今天学习了把模型的回复作为下一个模型的输入得到最后的结果\n```bash\nfrom langchain_core.prompts import PromptTemplate\nfrom langchain_core.output_parsers import JsonOutputParser,StrOutputParser\nfrom langchain_openai import ChatOpenAI\nfrom langchain_core.runnables import RunnableLambda\nfirst_prompt=PromptTemplate.from_template(\n \"我的邻居姓{last_name},生了一个{gender},你给取个名字,只要名字,不要其他信息\"\n)\nsecond_prompt=PromptTemplate.from_template(\n \"给你一个{name},解析一下含义\"\n)\nstr_parser=StrOutputParser()\njson_parser=JsonOutputParser()\n\nmodel=ChatOpenAI(\n model=\"deepseek-chat\",\n base_url=\"https://api.deepseek.com\",\n temperature=0\n)\nfunc=RunnableLambda(lambda ai_msg :{\"name\":ai_msg.content} )\nchain=first_prompt|model|func|second_prompt|model|str_parser\nfor chunk in chain.stream({\"last_name\":\"张\",\"gender\":\"女儿\"}):\n print(chunk,end=\"\",flush=True)\n```\n或者也可以调用jsonparser 但是这样的话提示词就需要强制ai输出json格式 并且指名键和对应的数据\n-----------------------------------------------------------------------------------------\n## 2026.5.15 \n今天学习了向量检索生成提示词 然后学习了将向量检索入chain\n```bash\n# 1. 用户问题\ninput_text = \"用户的问题\"\n\n# 2. 检索资料\ndocs = vector_store.similarity_search(input_text, k=2)\n\n# 3. 整理资料\ncontext = \"\\n\".join([doc.page_content for doc in docs])\n\n# 4. 问模型\nchain = prompt | model | StrOutputParser()\n\nres = chain.invoke({\n \"input\": input_text,\n \"context\": context\n})\n\nprint(res)\n```\n---------------------------\n## 2026.5.18\n这几天学的是一个Rag的项目 主要功能是用户上传文件作为系统的知识库 然后用户提问 模型根据知识库的内容来回答问题\n## 上传流程\n\napp_file_uploader.py\n-> KnowledgeBaseService.upload_by_str()\n-> md5 去重\n-> 文本切分\n-> Chroma.add_texts()\n-> chroma_db\n\n## 问答流程\n\napp_qa.py\n-> RagService().chain\n-> RunnableWithMessageHistory 加载历史\n-> retriever 检索知识库\n-> format_document 整理 context\n-> format_for_prompt_template 整理 input/context/history\n-> prompt_template\n-> DeepSeek\n-> StrOutputParser\n\n## 我理解的核心\n\n用户输入进入后,一路通过 RunnablePassthrough 保留原始 input 和 history,另一路取出 input 交给 retriever 检索知识库,检索结果整理成 context。最后把 input、context、history 统一整理成 prompt,让 DeepSeek 回答。\n--------------------------------------------\n## 2026.5.20\n针对 knowledge_base.py的总结\n```bash\n用户传入一个字符串,会创建一个KnowledgeBaseService类,然后判断目前的文件夹是否已经存在,如果不存在就创建,存在就跳过。\n然后计算传入字符串的md5值,如果已经存在这个字符串了,就提示知识在数据库中已经存在。\n然后判断传入的字符串是否超过了设定的最大文本长度,如果超过,就对文本进行切分。\n然后使用嵌入式模型将切分后的字符串转为向量,切分出来的每段文本都会添加一个metdata,用来记录文本的信息:名称,创建时间,操作人员名称,然后将数据传入数据库中存储。\n```\nvector_stores.py\n## 1. 负责什么?\n\n负责打开本地 Chroma 向量库,并返回 retriever 检索器。\n\n## 2. 输入是什么?\n\n输入是 embedding 模型。检索时 retriever 接收用户问题字符串。\n\n## 3. 输出是什么?\n\n输出是 retriever。调用 retriever.invoke(\"问题\") 后,会返回 Document 列表。\n\n## 4. 核心代码\n\n```python\nself.vector_store = Chroma(\n collection_name=config.collection_name,\n embedding_function=self.embedding,\n persist_directory=config.persist_directory,\n)\n## 2026.5.21\n# rag.py\n\n## 1. 负责什么?\n\n负责构建 RAG 问答链,把用户问题、知识库检索结果和历史对话一起交给大模型回答。\n\n## 2. 输入是什么?\n\n输入是:\n{\"input\": \"用户问题\"}\n\n同时需要 session_config:\n{\"configurable\": {\"session_id\": \"user_001\"}}\n\n## 3. 输出是什么?\n\n输出是大模型回答的字符串。\n\n## 4. 核心流程\n\n1. VectorStoreService 创建 retriever\n2. format_for_retriever 从输入字典中提取用户问题\n3. retriever 检索 Chroma,返回 Document 列表\n4. format_document 把 Document 列表整理成 context 字符串\n5. format_for_prompt_template 整理成 input/context/history\n6. prompt_template 生成最终 prompt\n7. DeepSeek 生成回答\n8. StrOutputParser 转成字符串\n9. RunnableWithMessageHistory 保存历史\n\n## 5. 关键变量\n\ninput:用户当前问题 \ncontext:检索出来的知识库资料 \nhistory:历史对话消息 \n\n## 6. 容易错的地方\n\nRunnablePassthrough() 保留的是整个输入字典。 \n所以 value[\"input\"] 不是字符串,而是 {\"input\": ..., \"history\": ...}。 \n真正的问题要用 value[\"input\"][\"input\"] 取出。 \nMessagesPlaceholder(\"history\") 必须和 history_messages_key=\"history\" 对应。 \ninput_messages_key=\"input\" 必须和 invoke 里的 {\"input\": \"...\"} 对应。 \nretriever 返回的是 Document 列表,不是字符串。\n"}, "d5ea677d6c0bc663de7d54c084579a8624d365ab": {"t": 1785766611.7856536, "n": 6243, "h": "7b5be609a1be153e", "c": "# agent-学习路线记录\n-----------------------\n## 2026.5.9\n今天观看了黑马程序员的课程\n\"image\"\n看到了提示词工程\n然后这是大致的代码块:\n```bash\nfrom openai import OpenAI\n\nclient=OpenAI(\n base_url=\"https://api.deepseek.com\"\n)\n\n#调用模型\nresponse=client.chat.completions.create(\n model=\"deepseek-v4-pro\",\n messages=[\n {\"role\": \"system\", \"content\": \"你是一个Python编程专家,并且说话很多\"},\n {\"role\":\"assistant\",\"content\":\"好的,我是Python编程专家,你想问什么?\"},\n {\"role\":\"user\",\"content\":\"输出1-10的数字,使用Python代码。\"}\n ],\n #打开流式输出开关\n stream=True\n)\n\n#处理结果\nfor chunk in response:\n\n # 取出content\n content = chunk.choices[0].delta.content\n\n # 过滤None\n if content is not None:\n print(content, end=\"\", flush=True)\n```\n觉得今天看的课程比较重要的就是这段代码,流式输出,然后过滤none\n-------------------------------------------------------------\n## 2026.5.10\n```bash\nmessages = [\n {\"role\": \"system\",\n \"content\": \"你是金融专家,将文本分类为['新闻报道', '财务报道', '公司公告', '分析师报告'],不清楚的分类为'不清楚类别' 下面有示例:\"},\n]\nfor key,value in examples_data.items():\n messages.append({\"role\": \"user\",\"content\": value})\n messages.append({\"role\": \"assistant\",\"content\": key})#动态添加message\n\nfor q in questions:\n response=client.chat.completions.create(\n model=\"deepseek-v4-pro\",\n messages=messages+[{\n \"role\":\"user\",\n \"content\": q#把要问的问题添加进来\n }]\n )\n```\n这是今天学的动态创建提示词\n然后今天还学了list转json和json转list\n```bash\njson.dumps(list,ensure_ascii=flase)#将字典或者列表转换成json\njson.loads(json)#将json转换成list或者字典\n```\n之前Python的数据结构学的迷迷糊糊,再总结一下字典和列表取值的时候用的方法:\n```bash\n字典:键(key) -> 值(value)\nperson = {\n \"name\": \"张三\",\n \"age\": 18\n}\nperson[\"name\"]=“张三”\n列表:类似于数组,通过下标来取对应的数据\n```\n\"image\"\n--------------------------------------------------------------------------------------------------------------------------------------\n\n## 2026.5.11\n今天学习langchain,我自己的理解就是langchain集成了很多功能,可以直接调用\n还学了文字转向量,使用的是huggingface的embedding模型\n```bash\nfrom langchain_community.embeddings import HuggingFaceEmbeddings\n\nembed = HuggingFaceEmbeddings(\n model_name=\"BAAI/bge-small-zh-v1.5\"\n)\n\nresult = embed.embed_query(\"我喜欢你\")#embed_query单次转换,一次转换一句话\nresult1=embed.embed_documents([\"我喜欢你\",\"我稀饭你\",\"晚上吃什么\"])#embed_documents一次转换多句话,传入的变量是一个列表[]\nprint(result1[:5])\n```\n\"image\"\n\n今天还学了关于langchain里面的fewshot\n```bash\nfrom langchain_core.prompts import PromptTemplate, FewShotPromptTemplate\nfrom langchain_openai import ChatOpenAI\n\nexample_prompt = PromptTemplate.from_template(\n \"输入:{input}, 输出:{output}\"\n)\n\nexamples = [\n {\"input\": \"示例1\", \"output\": \"答案1\"},\n {\"input\": \"示例2\", \"output\": \"答案2\"},\n]\n\nprompt = FewShotPromptTemplate(\n examples=examples,\n example_prompt=example_prompt,\n prefix=\"下面是一些示例:\",\n suffix=\"请回答:{question}\",\n input_variables=[\"question\"]\n)\n\nprompt_text = prompt.invoke({\"question\": \"真正的问题\"}).to_string()\n\nllm = ChatOpenAI(\n model=\"deepseek-chat\",\n base_url=\"https://api.deepseek.com\",\n temperature=0\n)\n\nres = llm.invoke(prompt_text).content\nprint(res)\n# 1. 导入 LangChain 的提示词模板和 DeepSeek 模型\n\n# 2. 定义单个示例的格式\n\n# 3. 准备 few-shot 示例数据\n\n# 4. 定义 few-shot 总模板\n\n# 5. 把变量填进去,生成最终 prompt\n\n# 6. 调用 DeepSeek\n\n# 7. 输出结果\n```\n还有今天学了format和invoke的区别:\n\"image\"\n## 2026.5.13\n今天学习了把模型的回复作为下一个模型的输入得到最后的结果\n```bash\nfrom langchain_core.prompts import PromptTemplate\nfrom langchain_core.output_parsers import JsonOutputParser,StrOutputParser\nfrom langchain_openai import ChatOpenAI\nfrom langchain_core.runnables import RunnableLambda\nfirst_prompt=PromptTemplate.from_template(\n \"我的邻居姓{last_name},生了一个{gender},你给取个名字,只要名字,不要其他信息\"\n)\nsecond_prompt=PromptTemplate.from_template(\n \"给你一个{name},解析一下含义\"\n)\nstr_parser=StrOutputParser()\njson_parser=JsonOutputParser()\n\nmodel=ChatOpenAI(\n model=\"deepseek-chat\",\n base_url=\"https://api.deepseek.com\",\n temperature=0\n)\nfunc=RunnableLambda(lambda ai_msg :{\"name\":ai_msg.content} )\nchain=first_prompt|model|func|second_prompt|model|str_parser\nfor chunk in chain.stream({\"last_name\":\"张\",\"gender\":\"女儿\"}):\n print(chunk,end=\"\",flush=True)\n```\n或者也可以调用jsonparser 但是这样的话提示词就需要强制ai输出json格式 并且指名键和对应的数据\n-----------------------------------------------------------------------------------------\n## 2026.5.15 \n今天学习了向量检索生成提示词 然后学习了将向量检索入chain\n```bash\n# 1. 用户问题\ninput_text = \"用户的问题\"\n\n# 2. 检索资料\ndocs = vector_store.similarity_search(input_text, k=2)\n\n# 3. 整理资料\ncontext = \"\\n\".join([doc.page_content for doc in docs])\n\n# 4. 问模型\nchain = prompt | model | StrOutputParser()\n\nres = chain.invoke({\n \"input\": input_text,\n \"context\": context\n})\n\nprint(res)\n```\n---------------------------\n## 2026.5.18\n这几天学的是一个Rag的项目 主要功能是用户上传文件作为系统的知识库 然后用户提问 模型根据知识库的内容来回答问题\n## 上传流程\n\napp_file_uploader.py\n-> KnowledgeBaseService.upload_by_str()\n-> md5 去重\n-> 文本切分\n-> Chroma.add_texts()\n-> chroma_db\n\n## 问答流程\n\napp_qa.py\n-> RagService().chain\n-> RunnableWithMessageHistory 加载历史\n-> retriever 检索知识库\n-> format_document 整理 context\n-> format_for_prompt_template 整理 input/context/history\n-> prompt_template\n-> DeepSeek\n-> StrOutputParser\n\n## 我理解的核心\n\n用户输入进入后,一路通过 RunnablePassthrough 保留原始 input 和 history,另一路取出 input 交给 retriever 检索知识库,检索结果整理成 context。最后把 input、context、history 统一整理成 prompt,让 DeepSeek 回答。\n--------------------------------------------\n## 2026.5.20\n针对 knowledge_base.py的总结\n```bash\n用户传入一个字符串,会创建一个KnowledgeBaseService类,然后判断目前的文件夹是否已经存在,如果不存在就创建,存在就跳过。\n然后计算传入字符串的md5值,如果已经存在这个字符串了,就提示知识在数据库中已经存在。\n然后判断传入的字符串是否超过了设定的最大文本长度,如果超过,就对文本进行切分。\n然后使用嵌入式模型将切分后的字符串转为向量,切分出来的每段文本都会添加一个metdata,用来记录文本的信息:名称,创建时间,操作人员名称,然后将数据传入数据库中存储。\n```\nvector_stores.py\n## 1. 负责什么?\n\n负责打开本地 Chroma 向量库,并返回 retriever 检索器。\n\n## 2. 输入是什么?\n\n输入是 embedding 模型。检索时 retriever 接收用户问题字符串。\n\n## 3. 输出是什么?\n\n输出是 retriever。调用 retriever.invoke(\"问题\") 后,会返回 Document 列表。\n\n## 4. 核心代码\n\n```python\nself.vector_store = Chroma(\n collection_name=config.collection_name,\n embedding_function=self.embedding,\n persist_directory=config.persist_directory,\n)\n"}, "c6e8f90712e60c93c06a43a998d492631770acc7": {"t": 1785766613.3016765, "n": 5861, "h": "7adc24a4f5467acd", "c": "# agent-学习路线记录\n-----------------------\n## 2026.5.9\n今天观看了黑马程序员的课程\n\"image\"\n看到了提示词工程\n然后这是大致的代码块:\n```bash\nfrom openai import OpenAI\n\nclient=OpenAI(\n base_url=\"https://api.deepseek.com\"\n)\n\n#调用模型\nresponse=client.chat.completions.create(\n model=\"deepseek-v4-pro\",\n messages=[\n {\"role\": \"system\", \"content\": \"你是一个Python编程专家,并且说话很多\"},\n {\"role\":\"assistant\",\"content\":\"好的,我是Python编程专家,你想问什么?\"},\n {\"role\":\"user\",\"content\":\"输出1-10的数字,使用Python代码。\"}\n ],\n #打开流式输出开关\n stream=True\n)\n\n#处理结果\nfor chunk in response:\n\n # 取出content\n content = chunk.choices[0].delta.content\n\n # 过滤None\n if content is not None:\n print(content, end=\"\", flush=True)\n```\n觉得今天看的课程比较重要的就是这段代码,流式输出,然后过滤none\n-------------------------------------------------------------\n## 2026.5.10\n```bash\nmessages = [\n {\"role\": \"system\",\n \"content\": \"你是金融专家,将文本分类为['新闻报道', '财务报道', '公司公告', '分析师报告'],不清楚的分类为'不清楚类别' 下面有示例:\"},\n]\nfor key,value in examples_data.items():\n messages.append({\"role\": \"user\",\"content\": value})\n messages.append({\"role\": \"assistant\",\"content\": key})#动态添加message\n\nfor q in questions:\n response=client.chat.completions.create(\n model=\"deepseek-v4-pro\",\n messages=messages+[{\n \"role\":\"user\",\n \"content\": q#把要问的问题添加进来\n }]\n )\n```\n这是今天学的动态创建提示词\n然后今天还学了list转json和json转list\n```bash\njson.dumps(list,ensure_ascii=flase)#将字典或者列表转换成json\njson.loads(json)#将json转换成list或者字典\n```\n之前Python的数据结构学的迷迷糊糊,再总结一下字典和列表取值的时候用的方法:\n```bash\n字典:键(key) -> 值(value)\nperson = {\n \"name\": \"张三\",\n \"age\": 18\n}\nperson[\"name\"]=“张三”\n列表:类似于数组,通过下标来取对应的数据\n```\n\"image\"\n--------------------------------------------------------------------------------------------------------------------------------------\n\n## 2026.5.11\n今天学习langchain,我自己的理解就是langchain集成了很多功能,可以直接调用\n还学了文字转向量,使用的是huggingface的embedding模型\n```bash\nfrom langchain_community.embeddings import HuggingFaceEmbeddings\n\nembed = HuggingFaceEmbeddings(\n model_name=\"BAAI/bge-small-zh-v1.5\"\n)\n\nresult = embed.embed_query(\"我喜欢你\")#embed_query单次转换,一次转换一句话\nresult1=embed.embed_documents([\"我喜欢你\",\"我稀饭你\",\"晚上吃什么\"])#embed_documents一次转换多句话,传入的变量是一个列表[]\nprint(result1[:5])\n```\n\"image\"\n\n今天还学了关于langchain里面的fewshot\n```bash\nfrom langchain_core.prompts import PromptTemplate, FewShotPromptTemplate\nfrom langchain_openai import ChatOpenAI\n\nexample_prompt = PromptTemplate.from_template(\n \"输入:{input}, 输出:{output}\"\n)\n\nexamples = [\n {\"input\": \"示例1\", \"output\": \"答案1\"},\n {\"input\": \"示例2\", \"output\": \"答案2\"},\n]\n\nprompt = FewShotPromptTemplate(\n examples=examples,\n example_prompt=example_prompt,\n prefix=\"下面是一些示例:\",\n suffix=\"请回答:{question}\",\n input_variables=[\"question\"]\n)\n\nprompt_text = prompt.invoke({\"question\": \"真正的问题\"}).to_string()\n\nllm = ChatOpenAI(\n model=\"deepseek-chat\",\n base_url=\"https://api.deepseek.com\",\n temperature=0\n)\n\nres = llm.invoke(prompt_text).content\nprint(res)\n# 1. 导入 LangChain 的提示词模板和 DeepSeek 模型\n\n# 2. 定义单个示例的格式\n\n# 3. 准备 few-shot 示例数据\n\n# 4. 定义 few-shot 总模板\n\n# 5. 把变量填进去,生成最终 prompt\n\n# 6. 调用 DeepSeek\n\n# 7. 输出结果\n```\n还有今天学了format和invoke的区别:\n\"image\"\n## 2026.5.13\n今天学习了把模型的回复作为下一个模型的输入得到最后的结果\n```bash\nfrom langchain_core.prompts import PromptTemplate\nfrom langchain_core.output_parsers import JsonOutputParser,StrOutputParser\nfrom langchain_openai import ChatOpenAI\nfrom langchain_core.runnables import RunnableLambda\nfirst_prompt=PromptTemplate.from_template(\n \"我的邻居姓{last_name},生了一个{gender},你给取个名字,只要名字,不要其他信息\"\n)\nsecond_prompt=PromptTemplate.from_template(\n \"给你一个{name},解析一下含义\"\n)\nstr_parser=StrOutputParser()\njson_parser=JsonOutputParser()\n\nmodel=ChatOpenAI(\n model=\"deepseek-chat\",\n base_url=\"https://api.deepseek.com\",\n temperature=0\n)\nfunc=RunnableLambda(lambda ai_msg :{\"name\":ai_msg.content} )\nchain=first_prompt|model|func|second_prompt|model|str_parser\nfor chunk in chain.stream({\"last_name\":\"张\",\"gender\":\"女儿\"}):\n print(chunk,end=\"\",flush=True)\n```\n或者也可以调用jsonparser 但是这样的话提示词就需要强制ai输出json格式 并且指名键和对应的数据\n-----------------------------------------------------------------------------------------\n## 2026.5.15 \n今天学习了向量检索生成提示词 然后学习了将向量检索入chain\n```bash\n# 1. 用户问题\ninput_text = \"用户的问题\"\n\n# 2. 检索资料\ndocs = vector_store.similarity_search(input_text, k=2)\n\n# 3. 整理资料\ncontext = \"\\n\".join([doc.page_content for doc in docs])\n\n# 4. 问模型\nchain = prompt | model | StrOutputParser()\n\nres = chain.invoke({\n \"input\": input_text,\n \"context\": context\n})\n\nprint(res)\n```\n---------------------------\n## 2026.5.18\n这几天学的是一个Rag的项目 主要功能是用户上传文件作为系统的知识库 然后用户提问 模型根据知识库的内容来回答问题\n## 上传流程\n\napp_file_uploader.py\n-> KnowledgeBaseService.upload_by_str()\n-> md5 去重\n-> 文本切分\n-> Chroma.add_texts()\n-> chroma_db\n\n## 问答流程\n\napp_qa.py\n-> RagService().chain\n-> RunnableWithMessageHistory 加载历史\n-> retriever 检索知识库\n-> format_document 整理 context\n-> format_for_prompt_template 整理 input/context/history\n-> prompt_template\n-> DeepSeek\n-> StrOutputParser\n\n## 我理解的核心\n\n用户输入进入后,一路通过 RunnablePassthrough 保留原始 input 和 history,另一路取出 input 交给 retriever 检索知识库,检索结果整理成 context。最后把 input、context、history 统一整理成 prompt,让 DeepSeek 回答。\n--------------------------------------------\n## 2026.5.20\n针对 knowledge_base.py的总结\n```bash\n用户传入一个字符串,会创建一个KnowledgeBaseService类,然后判断目前的文件夹是否已经存在,如果不存在就创建,存在就跳过。\n然后计算传入字符串的md5值,如果已经存在这个字符串了,就提示知识在数据库中已经存在。\n然后判断传入的字符串是否超过了设定的最大文本长度,如果超过,就对文本进行切分。\n然后使用嵌入式模型将切分后的字符串转为向量,切分出来的每段文本都会添加一个metdata,用来记录文本的信息:名称,创建时间,操作人员名称,然后将数据传入数据库中存储。\n```\n"}, "b4961e82c7a1c842a793a3fdd3cb8107f3f873a2": {"t": 1785766614.8992827, "n": 5528, "h": "cef398670cfb15cf", "c": "# agent-学习路线记录\n-----------------------\n## 2026.5.9\n今天观看了黑马程序员的课程\n\"image\"\n看到了提示词工程\n然后这是大致的代码块:\n```bash\nfrom openai import OpenAI\n\nclient=OpenAI(\n base_url=\"https://api.deepseek.com\"\n)\n\n#调用模型\nresponse=client.chat.completions.create(\n model=\"deepseek-v4-pro\",\n messages=[\n {\"role\": \"system\", \"content\": \"你是一个Python编程专家,并且说话很多\"},\n {\"role\":\"assistant\",\"content\":\"好的,我是Python编程专家,你想问什么?\"},\n {\"role\":\"user\",\"content\":\"输出1-10的数字,使用Python代码。\"}\n ],\n #打开流式输出开关\n stream=True\n)\n\n#处理结果\nfor chunk in response:\n\n # 取出content\n content = chunk.choices[0].delta.content\n\n # 过滤None\n if content is not None:\n print(content, end=\"\", flush=True)\n```\n觉得今天看的课程比较重要的就是这段代码,流式输出,然后过滤none\n-------------------------------------------------------------\n## 2026.5.10\n```bash\nmessages = [\n {\"role\": \"system\",\n \"content\": \"你是金融专家,将文本分类为['新闻报道', '财务报道', '公司公告', '分析师报告'],不清楚的分类为'不清楚类别' 下面有示例:\"},\n]\nfor key,value in examples_data.items():\n messages.append({\"role\": \"user\",\"content\": value})\n messages.append({\"role\": \"assistant\",\"content\": key})#动态添加message\n\nfor q in questions:\n response=client.chat.completions.create(\n model=\"deepseek-v4-pro\",\n messages=messages+[{\n \"role\":\"user\",\n \"content\": q#把要问的问题添加进来\n }]\n )\n```\n这是今天学的动态创建提示词\n然后今天还学了list转json和json转list\n```bash\njson.dumps(list,ensure_ascii=flase)#将字典或者列表转换成json\njson.loads(json)#将json转换成list或者字典\n```\n之前Python的数据结构学的迷迷糊糊,再总结一下字典和列表取值的时候用的方法:\n```bash\n字典:键(key) -> 值(value)\nperson = {\n \"name\": \"张三\",\n \"age\": 18\n}\nperson[\"name\"]=“张三”\n列表:类似于数组,通过下标来取对应的数据\n```\n\"image\"\n--------------------------------------------------------------------------------------------------------------------------------------\n\n## 2026.5.11\n今天学习langchain,我自己的理解就是langchain集成了很多功能,可以直接调用\n还学了文字转向量,使用的是huggingface的embedding模型\n```bash\nfrom langchain_community.embeddings import HuggingFaceEmbeddings\n\nembed = HuggingFaceEmbeddings(\n model_name=\"BAAI/bge-small-zh-v1.5\"\n)\n\nresult = embed.embed_query(\"我喜欢你\")#embed_query单次转换,一次转换一句话\nresult1=embed.embed_documents([\"我喜欢你\",\"我稀饭你\",\"晚上吃什么\"])#embed_documents一次转换多句话,传入的变量是一个列表[]\nprint(result1[:5])\n```\n\"image\"\n\n今天还学了关于langchain里面的fewshot\n```bash\nfrom langchain_core.prompts import PromptTemplate, FewShotPromptTemplate\nfrom langchain_openai import ChatOpenAI\n\nexample_prompt = PromptTemplate.from_template(\n \"输入:{input}, 输出:{output}\"\n)\n\nexamples = [\n {\"input\": \"示例1\", \"output\": \"答案1\"},\n {\"input\": \"示例2\", \"output\": \"答案2\"},\n]\n\nprompt = FewShotPromptTemplate(\n examples=examples,\n example_prompt=example_prompt,\n prefix=\"下面是一些示例:\",\n suffix=\"请回答:{question}\",\n input_variables=[\"question\"]\n)\n\nprompt_text = prompt.invoke({\"question\": \"真正的问题\"}).to_string()\n\nllm = ChatOpenAI(\n model=\"deepseek-chat\",\n base_url=\"https://api.deepseek.com\",\n temperature=0\n)\n\nres = llm.invoke(prompt_text).content\nprint(res)\n# 1. 导入 LangChain 的提示词模板和 DeepSeek 模型\n\n# 2. 定义单个示例的格式\n\n# 3. 准备 few-shot 示例数据\n\n# 4. 定义 few-shot 总模板\n\n# 5. 把变量填进去,生成最终 prompt\n\n# 6. 调用 DeepSeek\n\n# 7. 输出结果\n```\n还有今天学了format和invoke的区别:\n\"image\"\n## 2026.5.13\n今天学习了把模型的回复作为下一个模型的输入得到最后的结果\n```bash\nfrom langchain_core.prompts import PromptTemplate\nfrom langchain_core.output_parsers import JsonOutputParser,StrOutputParser\nfrom langchain_openai import ChatOpenAI\nfrom langchain_core.runnables import RunnableLambda\nfirst_prompt=PromptTemplate.from_template(\n \"我的邻居姓{last_name},生了一个{gender},你给取个名字,只要名字,不要其他信息\"\n)\nsecond_prompt=PromptTemplate.from_template(\n \"给你一个{name},解析一下含义\"\n)\nstr_parser=StrOutputParser()\njson_parser=JsonOutputParser()\n\nmodel=ChatOpenAI(\n model=\"deepseek-chat\",\n base_url=\"https://api.deepseek.com\",\n temperature=0\n)\nfunc=RunnableLambda(lambda ai_msg :{\"name\":ai_msg.content} )\nchain=first_prompt|model|func|second_prompt|model|str_parser\nfor chunk in chain.stream({\"last_name\":\"张\",\"gender\":\"女儿\"}):\n print(chunk,end=\"\",flush=True)\n```\n或者也可以调用jsonparser 但是这样的话提示词就需要强制ai输出json格式 并且指名键和对应的数据\n-----------------------------------------------------------------------------------------\n## 2026.5.15 \n今天学习了向量检索生成提示词 然后学习了将向量检索入chain\n```bash\n# 1. 用户问题\ninput_text = \"用户的问题\"\n\n# 2. 检索资料\ndocs = vector_store.similarity_search(input_text, k=2)\n\n# 3. 整理资料\ncontext = \"\\n\".join([doc.page_content for doc in docs])\n\n# 4. 问模型\nchain = prompt | model | StrOutputParser()\n\nres = chain.invoke({\n \"input\": input_text,\n \"context\": context\n})\n\nprint(res)\n```\n---------------------------\n## 2026.5.18\n这几天学的是一个Rag的项目 主要功能是用户上传文件作为系统的知识库 然后用户提问 模型根据知识库的内容来回答问题\n## 上传流程\n\napp_file_uploader.py\n-> KnowledgeBaseService.upload_by_str()\n-> md5 去重\n-> 文本切分\n-> Chroma.add_texts()\n-> chroma_db\n\n## 问答流程\n\napp_qa.py\n-> RagService().chain\n-> RunnableWithMessageHistory 加载历史\n-> retriever 检索知识库\n-> format_document 整理 context\n-> format_for_prompt_template 整理 input/context/history\n-> prompt_template\n-> DeepSeek\n-> StrOutputParser\n\n## 我理解的核心\n\n用户输入进入后,一路通过 RunnablePassthrough 保留原始 input 和 history,另一路取出 input 交给 retriever 检索知识库,检索结果整理成 context。最后把 input、context、history 统一整理成 prompt,让 DeepSeek 回答。\n"}, "2b5716814502180c0373ea25a22f4ef80155f8f3": {"t": 1785766616.57091, "n": 4908, "h": "d17d0167782e88ea", "c": "# agent-学习路线记录\n-----------------------\n## 2026.5.9\n今天观看了黑马程序员的课程\n\"image\"\n看到了提示词工程\n然后这是大致的代码块:\n```bash\nfrom openai import OpenAI\n\nclient=OpenAI(\n base_url=\"https://api.deepseek.com\"\n)\n\n#调用模型\nresponse=client.chat.completions.create(\n model=\"deepseek-v4-pro\",\n messages=[\n {\"role\": \"system\", \"content\": \"你是一个Python编程专家,并且说话很多\"},\n {\"role\":\"assistant\",\"content\":\"好的,我是Python编程专家,你想问什么?\"},\n {\"role\":\"user\",\"content\":\"输出1-10的数字,使用Python代码。\"}\n ],\n #打开流式输出开关\n stream=True\n)\n\n#处理结果\nfor chunk in response:\n\n # 取出content\n content = chunk.choices[0].delta.content\n\n # 过滤None\n if content is not None:\n print(content, end=\"\", flush=True)\n```\n觉得今天看的课程比较重要的就是这段代码,流式输出,然后过滤none\n-------------------------------------------------------------\n## 2026.5.10\n```bash\nmessages = [\n {\"role\": \"system\",\n \"content\": \"你是金融专家,将文本分类为['新闻报道', '财务报道', '公司公告', '分析师报告'],不清楚的分类为'不清楚类别' 下面有示例:\"},\n]\nfor key,value in examples_data.items():\n messages.append({\"role\": \"user\",\"content\": value})\n messages.append({\"role\": \"assistant\",\"content\": key})#动态添加message\n\nfor q in questions:\n response=client.chat.completions.create(\n model=\"deepseek-v4-pro\",\n messages=messages+[{\n \"role\":\"user\",\n \"content\": q#把要问的问题添加进来\n }]\n )\n```\n这是今天学的动态创建提示词\n然后今天还学了list转json和json转list\n```bash\njson.dumps(list,ensure_ascii=flase)#将字典或者列表转换成json\njson.loads(json)#将json转换成list或者字典\n```\n之前Python的数据结构学的迷迷糊糊,再总结一下字典和列表取值的时候用的方法:\n```bash\n字典:键(key) -> 值(value)\nperson = {\n \"name\": \"张三\",\n \"age\": 18\n}\nperson[\"name\"]=“张三”\n列表:类似于数组,通过下标来取对应的数据\n```\n\"image\"\n--------------------------------------------------------------------------------------------------------------------------------------\n\n## 2026.5.11\n今天学习langchain,我自己的理解就是langchain集成了很多功能,可以直接调用\n还学了文字转向量,使用的是huggingface的embedding模型\n```bash\nfrom langchain_community.embeddings import HuggingFaceEmbeddings\n\nembed = HuggingFaceEmbeddings(\n model_name=\"BAAI/bge-small-zh-v1.5\"\n)\n\nresult = embed.embed_query(\"我喜欢你\")#embed_query单次转换,一次转换一句话\nresult1=embed.embed_documents([\"我喜欢你\",\"我稀饭你\",\"晚上吃什么\"])#embed_documents一次转换多句话,传入的变量是一个列表[]\nprint(result1[:5])\n```\n\"image\"\n\n今天还学了关于langchain里面的fewshot\n```bash\nfrom langchain_core.prompts import PromptTemplate, FewShotPromptTemplate\nfrom langchain_openai import ChatOpenAI\n\nexample_prompt = PromptTemplate.from_template(\n \"输入:{input}, 输出:{output}\"\n)\n\nexamples = [\n {\"input\": \"示例1\", \"output\": \"答案1\"},\n {\"input\": \"示例2\", \"output\": \"答案2\"},\n]\n\nprompt = FewShotPromptTemplate(\n examples=examples,\n example_prompt=example_prompt,\n prefix=\"下面是一些示例:\",\n suffix=\"请回答:{question}\",\n input_variables=[\"question\"]\n)\n\nprompt_text = prompt.invoke({\"question\": \"真正的问题\"}).to_string()\n\nllm = ChatOpenAI(\n model=\"deepseek-chat\",\n base_url=\"https://api.deepseek.com\",\n temperature=0\n)\n\nres = llm.invoke(prompt_text).content\nprint(res)\n# 1. 导入 LangChain 的提示词模板和 DeepSeek 模型\n\n# 2. 定义单个示例的格式\n\n# 3. 准备 few-shot 示例数据\n\n# 4. 定义 few-shot 总模板\n\n# 5. 把变量填进去,生成最终 prompt\n\n# 6. 调用 DeepSeek\n\n# 7. 输出结果\n```\n还有今天学了format和invoke的区别:\n\"image\"\n## 2026.5.13\n今天学习了把模型的回复作为下一个模型的输入得到最后的结果\n```bash\nfrom langchain_core.prompts import PromptTemplate\nfrom langchain_core.output_parsers import JsonOutputParser,StrOutputParser\nfrom langchain_openai import ChatOpenAI\nfrom langchain_core.runnables import RunnableLambda\nfirst_prompt=PromptTemplate.from_template(\n \"我的邻居姓{last_name},生了一个{gender},你给取个名字,只要名字,不要其他信息\"\n)\nsecond_prompt=PromptTemplate.from_template(\n \"给你一个{name},解析一下含义\"\n)\nstr_parser=StrOutputParser()\njson_parser=JsonOutputParser()\n\nmodel=ChatOpenAI(\n model=\"deepseek-chat\",\n base_url=\"https://api.deepseek.com\",\n temperature=0\n)\nfunc=RunnableLambda(lambda ai_msg :{\"name\":ai_msg.content} )\nchain=first_prompt|model|func|second_prompt|model|str_parser\nfor chunk in chain.stream({\"last_name\":\"张\",\"gender\":\"女儿\"}):\n print(chunk,end=\"\",flush=True)\n```\n或者也可以调用jsonparser 但是这样的话提示词就需要强制ai输出json格式 并且指名键和对应的数据\n-----------------------------------------------------------------------------------------\n## 2026.5.15 \n今天学习了向量检索生成提示词 然后学习了将向量检索入chain\n```bash\n# 1. 用户问题\ninput_text = \"用户的问题\"\n\n# 2. 检索资料\ndocs = vector_store.similarity_search(input_text, k=2)\n\n# 3. 整理资料\ncontext = \"\\n\".join([doc.page_content for doc in docs])\n\n# 4. 问模型\nchain = prompt | model | StrOutputParser()\n\nres = chain.invoke({\n \"input\": input_text,\n \"context\": context\n})\n\nprint(res)\n```\n"}, "0c387cf5349bef28574659e1d4833e4e5fe99d6b": {"t": 1785766617.972937, "n": 4458, "h": "09b1426db708ea2e", "c": "# agent-学习路线记录\n-----------------------\n## 2026.5.9\n今天观看了黑马程序员的课程\n\"image\"\n看到了提示词工程\n然后这是大致的代码块:\n```bash\nfrom openai import OpenAI\n\nclient=OpenAI(\n base_url=\"https://api.deepseek.com\"\n)\n\n#调用模型\nresponse=client.chat.completions.create(\n model=\"deepseek-v4-pro\",\n messages=[\n {\"role\": \"system\", \"content\": \"你是一个Python编程专家,并且说话很多\"},\n {\"role\":\"assistant\",\"content\":\"好的,我是Python编程专家,你想问什么?\"},\n {\"role\":\"user\",\"content\":\"输出1-10的数字,使用Python代码。\"}\n ],\n #打开流式输出开关\n stream=True\n)\n\n#处理结果\nfor chunk in response:\n\n # 取出content\n content = chunk.choices[0].delta.content\n\n # 过滤None\n if content is not None:\n print(content, end=\"\", flush=True)\n```\n觉得今天看的课程比较重要的就是这段代码,流式输出,然后过滤none\n-------------------------------------------------------------\n## 2026.5.10\n```bash\nmessages = [\n {\"role\": \"system\",\n \"content\": \"你是金融专家,将文本分类为['新闻报道', '财务报道', '公司公告', '分析师报告'],不清楚的分类为'不清楚类别' 下面有示例:\"},\n]\nfor key,value in examples_data.items():\n messages.append({\"role\": \"user\",\"content\": value})\n messages.append({\"role\": \"assistant\",\"content\": key})#动态添加message\n\nfor q in questions:\n response=client.chat.completions.create(\n model=\"deepseek-v4-pro\",\n messages=messages+[{\n \"role\":\"user\",\n \"content\": q#把要问的问题添加进来\n }]\n )\n```\n这是今天学的动态创建提示词\n然后今天还学了list转json和json转list\n```bash\njson.dumps(list,ensure_ascii=flase)#将字典或者列表转换成json\njson.loads(json)#将json转换成list或者字典\n```\n之前Python的数据结构学的迷迷糊糊,再总结一下字典和列表取值的时候用的方法:\n```bash\n字典:键(key) -> 值(value)\nperson = {\n \"name\": \"张三\",\n \"age\": 18\n}\nperson[\"name\"]=“张三”\n列表:类似于数组,通过下标来取对应的数据\n```\n\"image\"\n--------------------------------------------------------------------------------------------------------------------------------------\n\n## 2026.5.11\n今天学习langchain,我自己的理解就是langchain集成了很多功能,可以直接调用\n还学了文字转向量,使用的是huggingface的embedding模型\n```bash\nfrom langchain_community.embeddings import HuggingFaceEmbeddings\n\nembed = HuggingFaceEmbeddings(\n model_name=\"BAAI/bge-small-zh-v1.5\"\n)\n\nresult = embed.embed_query(\"我喜欢你\")#embed_query单次转换,一次转换一句话\nresult1=embed.embed_documents([\"我喜欢你\",\"我稀饭你\",\"晚上吃什么\"])#embed_documents一次转换多句话,传入的变量是一个列表[]\nprint(result1[:5])\n```\n\"image\"\n\n今天还学了关于langchain里面的fewshot\n```bash\nfrom langchain_core.prompts import PromptTemplate, FewShotPromptTemplate\nfrom langchain_openai import ChatOpenAI\n\nexample_prompt = PromptTemplate.from_template(\n \"输入:{input}, 输出:{output}\"\n)\n\nexamples = [\n {\"input\": \"示例1\", \"output\": \"答案1\"},\n {\"input\": \"示例2\", \"output\": \"答案2\"},\n]\n\nprompt = FewShotPromptTemplate(\n examples=examples,\n example_prompt=example_prompt,\n prefix=\"下面是一些示例:\",\n suffix=\"请回答:{question}\",\n input_variables=[\"question\"]\n)\n\nprompt_text = prompt.invoke({\"question\": \"真正的问题\"}).to_string()\n\nllm = ChatOpenAI(\n model=\"deepseek-chat\",\n base_url=\"https://api.deepseek.com\",\n temperature=0\n)\n\nres = llm.invoke(prompt_text).content\nprint(res)\n# 1. 导入 LangChain 的提示词模板和 DeepSeek 模型\n\n# 2. 定义单个示例的格式\n\n# 3. 准备 few-shot 示例数据\n\n# 4. 定义 few-shot 总模板\n\n# 5. 把变量填进去,生成最终 prompt\n\n# 6. 调用 DeepSeek\n\n# 7. 输出结果\n```\n还有今天学了format和invoke的区别:\n\"image\"\n## 2026.5.13\n今天学习了把模型的回复作为下一个模型的输入得到最后的结果\n```bash\nfrom langchain_core.prompts import PromptTemplate\nfrom langchain_core.output_parsers import JsonOutputParser,StrOutputParser\nfrom langchain_openai import ChatOpenAI\nfrom langchain_core.runnables import RunnableLambda\nfirst_prompt=PromptTemplate.from_template(\n \"我的邻居姓{last_name},生了一个{gender},你给取个名字,只要名字,不要其他信息\"\n)\nsecond_prompt=PromptTemplate.from_template(\n \"给你一个{name},解析一下含义\"\n)\nstr_parser=StrOutputParser()\njson_parser=JsonOutputParser()\n\nmodel=ChatOpenAI(\n model=\"deepseek-chat\",\n base_url=\"https://api.deepseek.com\",\n temperature=0\n)\nfunc=RunnableLambda(lambda ai_msg :{\"name\":ai_msg.content} )\nchain=first_prompt|model|func|second_prompt|model|str_parser\nfor chunk in chain.stream({\"last_name\":\"张\",\"gender\":\"女儿\"}):\n print(chunk,end=\"\",flush=True)\n```\n或者也可以调用jsonparser 但是这样的话提示词就需要强制ai输出json格式 并且指名键和对应的数据\n"}, "b592545f3457396485a0cf2426f671db3e325cdd": {"t": 1785766619.3908205, "n": 3578, "h": "336c918eb9ca2c51", "c": "# agent-学习路线记录\n-----------------------\n## 2026.5.9\n今天观看了黑马程序员的课程\n\"image\"\n看到了提示词工程\n然后这是大致的代码块:\n```bash\nfrom openai import OpenAI\n\nclient=OpenAI(\n base_url=\"https://api.deepseek.com\"\n)\n\n#调用模型\nresponse=client.chat.completions.create(\n model=\"deepseek-v4-pro\",\n messages=[\n {\"role\": \"system\", \"content\": \"你是一个Python编程专家,并且说话很多\"},\n {\"role\":\"assistant\",\"content\":\"好的,我是Python编程专家,你想问什么?\"},\n {\"role\":\"user\",\"content\":\"输出1-10的数字,使用Python代码。\"}\n ],\n #打开流式输出开关\n stream=True\n)\n\n#处理结果\nfor chunk in response:\n\n # 取出content\n content = chunk.choices[0].delta.content\n\n # 过滤None\n if content is not None:\n print(content, end=\"\", flush=True)\n```\n觉得今天看的课程比较重要的就是这段代码,流式输出,然后过滤none\n-------------------------------------------------------------\n## 2026.5.10\n```bash\nmessages = [\n {\"role\": \"system\",\n \"content\": \"你是金融专家,将文本分类为['新闻报道', '财务报道', '公司公告', '分析师报告'],不清楚的分类为'不清楚类别' 下面有示例:\"},\n]\nfor key,value in examples_data.items():\n messages.append({\"role\": \"user\",\"content\": value})\n messages.append({\"role\": \"assistant\",\"content\": key})#动态添加message\n\nfor q in questions:\n response=client.chat.completions.create(\n model=\"deepseek-v4-pro\",\n messages=messages+[{\n \"role\":\"user\",\n \"content\": q#把要问的问题添加进来\n }]\n )\n```\n这是今天学的动态创建提示词\n然后今天还学了list转json和json转list\n```bash\njson.dumps(list,ensure_ascii=flase)#将字典或者列表转换成json\njson.loads(json)#将json转换成list或者字典\n```\n之前Python的数据结构学的迷迷糊糊,再总结一下字典和列表取值的时候用的方法:\n```bash\n字典:键(key) -> 值(value)\nperson = {\n \"name\": \"张三\",\n \"age\": 18\n}\nperson[\"name\"]=“张三”\n列表:类似于数组,通过下标来取对应的数据\n```\n\"image\"\n--------------------------------------------------------------------------------------------------------------------------------------\n\n## 2026.5.11\n今天学习langchain,我自己的理解就是langchain集成了很多功能,可以直接调用\n还学了文字转向量,使用的是huggingface的embedding模型\n```bash\nfrom langchain_community.embeddings import HuggingFaceEmbeddings\n\nembed = HuggingFaceEmbeddings(\n model_name=\"BAAI/bge-small-zh-v1.5\"\n)\n\nresult = embed.embed_query(\"我喜欢你\")#embed_query单次转换,一次转换一句话\nresult1=embed.embed_documents([\"我喜欢你\",\"我稀饭你\",\"晚上吃什么\"])#embed_documents一次转换多句话,传入的变量是一个列表[]\nprint(result1[:5])\n```\n\"image\"\n\n今天还学了关于langchain里面的fewshot\n```bash\nfrom langchain_core.prompts import PromptTemplate, FewShotPromptTemplate\nfrom langchain_openai import ChatOpenAI\n\nexample_prompt = PromptTemplate.from_template(\n \"输入:{input}, 输出:{output}\"\n)\n\nexamples = [\n {\"input\": \"示例1\", \"output\": \"答案1\"},\n {\"input\": \"示例2\", \"output\": \"答案2\"},\n]\n\nprompt = FewShotPromptTemplate(\n examples=examples,\n example_prompt=example_prompt,\n prefix=\"下面是一些示例:\",\n suffix=\"请回答:{question}\",\n input_variables=[\"question\"]\n)\n\nprompt_text = prompt.invoke({\"question\": \"真正的问题\"}).to_string()\n\nllm = ChatOpenAI(\n model=\"deepseek-chat\",\n base_url=\"https://api.deepseek.com\",\n temperature=0\n)\n\nres = llm.invoke(prompt_text).content\nprint(res)\n# 1. 导入 LangChain 的提示词模板和 DeepSeek 模型\n\n# 2. 定义单个示例的格式\n\n# 3. 准备 few-shot 示例数据\n\n# 4. 定义 few-shot 总模板\n\n# 5. 把变量填进去,生成最终 prompt\n\n# 6. 调用 DeepSeek\n\n# 7. 输出结果\n```\n还有今天学了format和invoke的区别:\n\"image\"\n"}, "bd48dae858daf4efc2e65010a39c95b5f5d4eab0": {"t": 1785766620.8706686, "n": 3425, "h": "e7cb1539b36e73d3", "c": "# agent-学习路线记录\n-----------------------\n## 2026.5.9\n今天观看了黑马程序员的课程\n\"image\"\n看到了提示词工程\n然后这是大致的代码块:\n```bash\nfrom openai import OpenAI\n\nclient=OpenAI(\n base_url=\"https://api.deepseek.com\"\n)\n\n#调用模型\nresponse=client.chat.completions.create(\n model=\"deepseek-v4-pro\",\n messages=[\n {\"role\": \"system\", \"content\": \"你是一个Python编程专家,并且说话很多\"},\n {\"role\":\"assistant\",\"content\":\"好的,我是Python编程专家,你想问什么?\"},\n {\"role\":\"user\",\"content\":\"输出1-10的数字,使用Python代码。\"}\n ],\n #打开流式输出开关\n stream=True\n)\n\n#处理结果\nfor chunk in response:\n\n # 取出content\n content = chunk.choices[0].delta.content\n\n # 过滤None\n if content is not None:\n print(content, end=\"\", flush=True)\n```\n觉得今天看的课程比较重要的就是这段代码,流式输出,然后过滤none\n-------------------------------------------------------------\n## 2026.5.10\n```bash\nmessages = [\n {\"role\": \"system\",\n \"content\": \"你是金融专家,将文本分类为['新闻报道', '财务报道', '公司公告', '分析师报告'],不清楚的分类为'不清楚类别' 下面有示例:\"},\n]\nfor key,value in examples_data.items():\n messages.append({\"role\": \"user\",\"content\": value})\n messages.append({\"role\": \"assistant\",\"content\": key})#动态添加message\n\nfor q in questions:\n response=client.chat.completions.create(\n model=\"deepseek-v4-pro\",\n messages=messages+[{\n \"role\":\"user\",\n \"content\": q#把要问的问题添加进来\n }]\n )\n```\n这是今天学的动态创建提示词\n然后今天还学了list转json和json转list\n```bash\njson.dumps(list,ensure_ascii=flase)#将字典或者列表转换成json\njson.loads(json)#将json转换成list或者字典\n```\n之前Python的数据结构学的迷迷糊糊,再总结一下字典和列表取值的时候用的方法:\n```bash\n字典:键(key) -> 值(value)\nperson = {\n \"name\": \"张三\",\n \"age\": 18\n}\nperson[\"name\"]=“张三”\n列表:类似于数组,通过下标来取对应的数据\n```\n\"image\"\n--------------------------------------------------------------------------------------------------------------------------------------\n\n## 2026.5.11\n今天学习langchain,我自己的理解就是langchain集成了很多功能,可以直接调用\n还学了文字转向量,使用的是huggingface的embedding模型\n```bash\nfrom langchain_community.embeddings import HuggingFaceEmbeddings\n\nembed = HuggingFaceEmbeddings(\n model_name=\"BAAI/bge-small-zh-v1.5\"\n)\n\nresult = embed.embed_query(\"我喜欢你\")#embed_query单次转换,一次转换一句话\nresult1=embed.embed_documents([\"我喜欢你\",\"我稀饭你\",\"晚上吃什么\"])#embed_documents一次转换多句话,传入的变量是一个列表[]\nprint(result1[:5])\n```\n\"image\"\n\n今天还学了关于langchain里面的fewshot\n```bash\nfrom langchain_core.prompts import PromptTemplate, FewShotPromptTemplate\nfrom langchain_openai import ChatOpenAI\n\nexample_prompt = PromptTemplate.from_template(\n \"输入:{input}, 输出:{output}\"\n)\n\nexamples = [\n {\"input\": \"示例1\", \"output\": \"答案1\"},\n {\"input\": \"示例2\", \"output\": \"答案2\"},\n]\n\nprompt = FewShotPromptTemplate(\n examples=examples,\n example_prompt=example_prompt,\n prefix=\"下面是一些示例:\",\n suffix=\"请回答:{question}\",\n input_variables=[\"question\"]\n)\n\nprompt_text = prompt.invoke({\"question\": \"真正的问题\"}).to_string()\n\nllm = ChatOpenAI(\n model=\"deepseek-chat\",\n base_url=\"https://api.deepseek.com\",\n temperature=0\n)\n\nres = llm.invoke(prompt_text).content\nprint(res)\n```\n还有今天学了format和invoke的区别:\n\"image\"\n"}, "1e79ae8d85061f1787ed6f5c8d036ee717605c47": {"t": 1785766622.0885038, "n": 3270, "h": "f771eb8598ee286a", "c": "# agent-学习路线记录\n-----------------------\n## 2026.5.9\n今天观看了黑马程序员的课程\n\"image\"\n看到了提示词工程\n然后这是大致的代码块:\n```bash\nfrom openai import OpenAI\n\nclient=OpenAI(\n base_url=\"https://api.deepseek.com\"\n)\n\n#调用模型\nresponse=client.chat.completions.create(\n model=\"deepseek-v4-pro\",\n messages=[\n {\"role\": \"system\", \"content\": \"你是一个Python编程专家,并且说话很多\"},\n {\"role\":\"assistant\",\"content\":\"好的,我是Python编程专家,你想问什么?\"},\n {\"role\":\"user\",\"content\":\"输出1-10的数字,使用Python代码。\"}\n ],\n #打开流式输出开关\n stream=True\n)\n\n#处理结果\nfor chunk in response:\n\n # 取出content\n content = chunk.choices[0].delta.content\n\n # 过滤None\n if content is not None:\n print(content, end=\"\", flush=True)\n```\n觉得今天看的课程比较重要的就是这段代码,流式输出,然后过滤none\n-------------------------------------------------------------\n## 2026.5.10\n```bash\nmessages = [\n {\"role\": \"system\",\n \"content\": \"你是金融专家,将文本分类为['新闻报道', '财务报道', '公司公告', '分析师报告'],不清楚的分类为'不清楚类别' 下面有示例:\"},\n]\nfor key,value in examples_data.items():\n messages.append({\"role\": \"user\",\"content\": value})\n messages.append({\"role\": \"assistant\",\"content\": key})#动态添加message\n\nfor q in questions:\n response=client.chat.completions.create(\n model=\"deepseek-v4-pro\",\n messages=messages+[{\n \"role\":\"user\",\n \"content\": q#把要问的问题添加进来\n }]\n )\n```\n这是今天学的动态创建提示词\n然后今天还学了list转json和json转list\n```bash\njson.dumps(list,ensure_ascii=flase)#将字典或者列表转换成json\njson.loads(json)#将json转换成list或者字典\n```\n之前Python的数据结构学的迷迷糊糊,再总结一下字典和列表取值的时候用的方法:\n```bash\n字典:键(key) -> 值(value)\nperson = {\n \"name\": \"张三\",\n \"age\": 18\n}\nperson[\"name\"]=“张三”\n列表:类似于数组,通过下标来取对应的数据\n```\n\"image\"\n--------------------------------------------------------------------------------------------------------------------------------------\n\n## 2026.5.11\n今天学习langchain,我自己的理解就是langchain集成了很多功能,可以直接调用\n还学了文字转向量,使用的是huggingface的embedding模型\n```bash\nfrom langchain_community.embeddings import HuggingFaceEmbeddings\n\nembed = HuggingFaceEmbeddings(\n model_name=\"BAAI/bge-small-zh-v1.5\"\n)\n\nresult = embed.embed_query(\"我喜欢你\")#embed_query单次转换,一次转换一句话\nresult1=embed.embed_documents([\"我喜欢你\",\"我稀饭你\",\"晚上吃什么\"])#embed_documents一次转换多句话,传入的变量是一个列表[]\nprint(result1[:5])\n```\n\"image\"\n\n今天还学了关于langchain里面的fewshot\n```bash\nfrom langchain_core.prompts import PromptTemplate, FewShotPromptTemplate\nfrom langchain_openai import ChatOpenAI\n\nexample_prompt = PromptTemplate.from_template(\n \"输入:{input}, 输出:{output}\"\n)\n\nexamples = [\n {\"input\": \"示例1\", \"output\": \"答案1\"},\n {\"input\": \"示例2\", \"output\": \"答案2\"},\n]\n\nprompt = FewShotPromptTemplate(\n examples=examples,\n example_prompt=example_prompt,\n prefix=\"下面是一些示例:\",\n suffix=\"请回答:{question}\",\n input_variables=[\"question\"]\n)\n\nprompt_text = prompt.invoke({\"question\": \"真正的问题\"}).to_string()\n\nllm = ChatOpenAI(\n model=\"deepseek-chat\",\n base_url=\"https://api.deepseek.com\",\n temperature=0\n)\n\nres = llm.invoke(prompt_text).content\nprint(res)\n```\n"}, "56e5604dd5403aa42e50e2c4e110b9d67dabe2cf": {"t": 1785766623.4323394, "n": 2545, "h": "fe6aaace0f88dd85", "c": "# agent-学习路线记录\n-----------------------\n## 2026.5.9\n今天观看了黑马程序员的课程\n\"image\"\n看到了提示词工程\n然后这是大致的代码块:\n```bash\nfrom openai import OpenAI\n\nclient=OpenAI(\n base_url=\"https://api.deepseek.com\"\n)\n\n#调用模型\nresponse=client.chat.completions.create(\n model=\"deepseek-v4-pro\",\n messages=[\n {\"role\": \"system\", \"content\": \"你是一个Python编程专家,并且说话很多\"},\n {\"role\":\"assistant\",\"content\":\"好的,我是Python编程专家,你想问什么?\"},\n {\"role\":\"user\",\"content\":\"输出1-10的数字,使用Python代码。\"}\n ],\n #打开流式输出开关\n stream=True\n)\n\n#处理结果\nfor chunk in response:\n\n # 取出content\n content = chunk.choices[0].delta.content\n\n # 过滤None\n if content is not None:\n print(content, end=\"\", flush=True)\n```\n觉得今天看的课程比较重要的就是这段代码,流式输出,然后过滤none\n-------------------------------------------------------------\n## 2026.5.10\n```bash\nmessages = [\n {\"role\": \"system\",\n \"content\": \"你是金融专家,将文本分类为['新闻报道', '财务报道', '公司公告', '分析师报告'],不清楚的分类为'不清楚类别' 下面有示例:\"},\n]\nfor key,value in examples_data.items():\n messages.append({\"role\": \"user\",\"content\": value})\n messages.append({\"role\": \"assistant\",\"content\": key})#动态添加message\n\nfor q in questions:\n response=client.chat.completions.create(\n model=\"deepseek-v4-pro\",\n messages=messages+[{\n \"role\":\"user\",\n \"content\": q#把要问的问题添加进来\n }]\n )\n```\n这是今天学的动态创建提示词\n然后今天还学了list转json和json转list\n```bash\njson.dumps(list,ensure_ascii=flase)#将字典或者列表转换成json\njson.loads(json)#将json转换成list或者字典\n```\n之前Python的数据结构学的迷迷糊糊,再总结一下字典和列表取值的时候用的方法:\n```bash\n字典:键(key) -> 值(value)\nperson = {\n \"name\": \"张三\",\n \"age\": 18\n}\nperson[\"name\"]=“张三”\n列表:类似于数组,通过下标来取对应的数据\n```\n\"image\"\n--------------------------------------------------------------------------------------------------------------------------------------\n\n## 2026.5.11\n今天学习langchain,我自己的理解就是langchain集成了很多功能,可以直接调用\n还学了文字转向量,使用的是huggingface的embedding模型\n```bash\nfrom langchain_community.embeddings import HuggingFaceEmbeddings\n\nembed = HuggingFaceEmbeddings(\n model_name=\"BAAI/bge-small-zh-v1.5\"\n)\n\nresult = embed.embed_query(\"我喜欢你\")#embed_query单次转换,一次转换一句话\nresult1=embed.embed_documents([\"我喜欢你\",\"我稀饭你\",\"晚上吃什么\"])#embed_documents一次转换多句话,传入的变量是一个列表[]\nprint(result1[:5])\n```\n\"image\"\n\n"}, "c3d800449f4da92fae7e64de4cd4c60861a37ad0": {"t": 1785766624.9020677, "n": 2413, "h": "232e32a89d1ed63b", "c": "# agent-学习路线记录\n-----------------------\n## 2026.5.9\n今天观看了黑马程序员的课程\n\"image\"\n看到了提示词工程\n然后这是大致的代码块:\n```bash\nfrom openai import OpenAI\n\nclient=OpenAI(\n base_url=\"https://api.deepseek.com\"\n)\n\n#调用模型\nresponse=client.chat.completions.create(\n model=\"deepseek-v4-pro\",\n messages=[\n {\"role\": \"system\", \"content\": \"你是一个Python编程专家,并且说话很多\"},\n {\"role\":\"assistant\",\"content\":\"好的,我是Python编程专家,你想问什么?\"},\n {\"role\":\"user\",\"content\":\"输出1-10的数字,使用Python代码。\"}\n ],\n #打开流式输出开关\n stream=True\n)\n\n#处理结果\nfor chunk in response:\n\n # 取出content\n content = chunk.choices[0].delta.content\n\n # 过滤None\n if content is not None:\n print(content, end=\"\", flush=True)\n```\n觉得今天看的课程比较重要的就是这段代码,流式输出,然后过滤none\n-------------------------------------------------------------\n## 2026.5.10\n```bash\nmessages = [\n {\"role\": \"system\",\n \"content\": \"你是金融专家,将文本分类为['新闻报道', '财务报道', '公司公告', '分析师报告'],不清楚的分类为'不清楚类别' 下面有示例:\"},\n]\nfor key,value in examples_data.items():\n messages.append({\"role\": \"user\",\"content\": value})\n messages.append({\"role\": \"assistant\",\"content\": key})#动态添加message\n\nfor q in questions:\n response=client.chat.completions.create(\n model=\"deepseek-v4-pro\",\n messages=messages+[{\n \"role\":\"user\",\n \"content\": q#把要问的问题添加进来\n }]\n )\n```\n这是今天学的动态创建提示词\n然后今天还学了list转json和json转list\n```bash\njson.dumps(list,ensure_ascii=flase)#将字典或者列表转换成json\njson.loads(json)#将json转换成list或者字典\n```\n之前Python的数据结构学的迷迷糊糊,再总结一下字典和列表取值的时候用的方法:\n```bash\n字典:键(key) -> 值(value)\nperson = {\n \"name\": \"张三\",\n \"age\": 18\n}\nperson[\"name\"]=“张三”\n列表:类似于数组,通过下标来取对应的数据\n```\n\"image\"\n--------------------------------------------------------------------------------------------------------------------------------------\n\n## 2026.5.11\n今天学习langchain,我自己的理解就是langchain集成了很多功能,可以直接调用\n还学了文字转向量,使用的是huggingface的embedding模型\n```bash\nfrom langchain_community.embeddings import HuggingFaceEmbeddings\n\nembed = HuggingFaceEmbeddings(\n model_name=\"BAAI/bge-small-zh-v1.5\"\n)\n\nresult = embed.embed_query(\"我喜欢你\")#embed_query单次转换,一次转换一句话\nresult1=embed.embed_documents([\"我喜欢你\",\"我稀饭你\",\"晚上吃什么\"])#embed_documents一次转换多句话,传入的变量是一个列表[]\nprint(result1[:5])\n```\n\n"}, "1bb5cb6ac0b587430f3a49e85b20e35de70ccf15": {"t": 1785766626.2126002, "n": 2412, "h": "e26770f2b46c351e", "c": "# agent-学习路线记录\n-----------------------\n## 2026.5.9\n今天观看了黑马程序员的课程\n\"image\"\n看到了提示词工程\n然后这是大致的代码块:\n```bash\nfrom openai import OpenAI\n\nclient=OpenAI(\n base_url=\"https://api.deepseek.com\"\n)\n\n#调用模型\nresponse=client.chat.completions.create(\n model=\"deepseek-v4-pro\",\n messages=[\n {\"role\": \"system\", \"content\": \"你是一个Python编程专家,并且说话很多\"},\n {\"role\":\"assistant\",\"content\":\"好的,我是Python编程专家,你想问什么?\"},\n {\"role\":\"user\",\"content\":\"输出1-10的数字,使用Python代码。\"}\n ],\n #打开流式输出开关\n stream=True\n)\n\n#处理结果\nfor chunk in response:\n\n # 取出content\n content = chunk.choices[0].delta.content\n\n # 过滤None\n if content is not None:\n print(content, end=\"\", flush=True)\n```\n觉得今天看的课程比较重要的就是这段代码,流式输出,然后过滤none\n-------------------------------------------------------------\n## 2026.5.10\n```bash\nmessages = [\n {\"role\": \"system\",\n \"content\": \"你是金融专家,将文本分类为['新闻报道', '财务报道', '公司公告', '分析师报告'],不清楚的分类为'不清楚类别' 下面有示例:\"},\n]\nfor key,value in examples_data.items():\n messages.append({\"role\": \"user\",\"content\": value})\n messages.append({\"role\": \"assistant\",\"content\": key})#动态添加message\n\nfor q in questions:\n response=client.chat.completions.create(\n model=\"deepseek-v4-pro\",\n messages=messages+[{\n \"role\":\"user\",\n \"content\": q#把要问的问题添加进来\n }]\n )\n```\n这是今天学的动态创建提示词\n然后今天还学了list转json和json转list\n```bash\njson.dumps(list,ensure_ascii=flase)#将字典或者列表转换成json\njson.loads(json)#将json转换成list或者字典\n```\n之前Python的数据结构学的迷迷糊糊,再总结一下字典和列表取值的时候用的方法:\n```bash\n字典:键(key) -> 值(value)\nperson = {\n \"name\": \"张三\",\n \"age\": 18\n}\nperson[\"name\"]=“张三”\n列表:类似于数组,通过下标来取对应的数据\n```\n\"image\"\n--------------------------------------------------------------------------------------------------------------------------------------\n## 2026.5.11\n今天学习langchain,我自己的理解就是langchain集成了很多功能,可以直接调用\n还学了文字转向量,使用的是huggingface的embedding模型\n```bash\nfrom langchain_community.embeddings import HuggingFaceEmbeddings\n\nembed = HuggingFaceEmbeddings(\n model_name=\"BAAI/bge-small-zh-v1.5\"\n)\n\nresult = embed.embed_query(\"我喜欢你\")#embed_query单次转换,一次转换一句话\nresult1=embed.embed_documents([\"我喜欢你\",\"我稀饭你\",\"晚上吃什么\"])#embed_documents一次转换多句话,传入的变量是一个列表[]\nprint(result1[:5])\n```\n\n"}, "d09acaebd4cad7bf35ea9ee7ead396d12c3fdc52": {"t": 1785766628.2210038, "n": 2324, "h": "b9c65d72f50b5eaa", "c": "# agent-学习路线记录\n-----------------------\n## 2026.5.9\n今天观看了黑马程序员的课程\n\"image\"\n看到了提示词工程\n然后这是大致的代码块:\n```bash\nfrom openai import OpenAI\n\nclient=OpenAI(\n base_url=\"https://api.deepseek.com\"\n)\n\n#调用模型\nresponse=client.chat.completions.create(\n model=\"deepseek-v4-pro\",\n messages=[\n {\"role\": \"system\", \"content\": \"你是一个Python编程专家,并且说话很多\"},\n {\"role\":\"assistant\",\"content\":\"好的,我是Python编程专家,你想问什么?\"},\n {\"role\":\"user\",\"content\":\"输出1-10的数字,使用Python代码。\"}\n ],\n #打开流式输出开关\n stream=True\n)\n\n#处理结果\nfor chunk in response:\n\n # 取出content\n content = chunk.choices[0].delta.content\n\n # 过滤None\n if content is not None:\n print(content, end=\"\", flush=True)\n```\n觉得今天看的课程比较重要的就是这段代码,流式输出,然后过滤none\n-------------------------------------------------------------\n## 2026.5.10\n```bash\nmessages = [\n {\"role\": \"system\",\n \"content\": \"你是金融专家,将文本分类为['新闻报道', '财务报道', '公司公告', '分析师报告'],不清楚的分类为'不清楚类别' 下面有示例:\"},\n]\nfor key,value in examples_data.items():\n messages.append({\"role\": \"user\",\"content\": value})\n messages.append({\"role\": \"assistant\",\"content\": key})#动态添加message\n\nfor q in questions:\n response=client.chat.completions.create(\n model=\"deepseek-v4-pro\",\n messages=messages+[{\n \"role\":\"user\",\n \"content\": q#把要问的问题添加进来\n }]\n )\n```\n这是今天学的动态创建提示词\n然后今天还学了list转json和json转list\n```bash\njson.dumps(list,ensure_ascii=flase)#将字典或者列表转换成json\njson.loads(json)#将json转换成list或者字典\n```\n之前Python的数据结构学的迷迷糊糊,再总结一下字典和列表取值的时候用的方法:\n```bash\n字典:键(key) -> 值(value)\nperson = {\n \"name\": \"张三\",\n \"age\": 18\n}\nperson[\"name\"]=“张三”\n列表:类似于数组,通过下标来取对应的数据\n```\n\"image\"\n-------------------------------------------------\n2026.5.11\n今天学习langchain,我自己的理解就是langchain集成了很多功能,可以直接调用\n还学了文字转向量,使用的是huggingface的embedding模型\n```bash\nfrom langchain_community.embeddings import HuggingFaceEmbeddings\n\nembed = HuggingFaceEmbeddings(\n model_name=\"BAAI/bge-small-zh-v1.5\"\n)\n\nresult = embed.embed_query(\"我喜欢你\")#embed_query单次转换,一次转换一句话\nresult1=embed.embed_documents([\"我喜欢你\",\"我稀饭你\",\"晚上吃什么\"])#embed_documents一次转换多句话,传入的变量是一个列表[]\nprint(result1[:5])\n```\n\n"}, "76e2e479a890838988225ec8b645dce74327762e": {"t": 1785766629.5442667, "n": 1860, "h": "e49c6d95a35a10d3", "c": "# agent-学习路线记录\n-----------------------\n## 2026.5.9\n今天观看了黑马程序员的课程\n\"image\"\n看到了提示词工程\n然后这是大致的代码块:\n```bash\nfrom openai import OpenAI\n\nclient=OpenAI(\n base_url=\"https://api.deepseek.com\"\n)\n\n#调用模型\nresponse=client.chat.completions.create(\n model=\"deepseek-v4-pro\",\n messages=[\n {\"role\": \"system\", \"content\": \"你是一个Python编程专家,并且说话很多\"},\n {\"role\":\"assistant\",\"content\":\"好的,我是Python编程专家,你想问什么?\"},\n {\"role\":\"user\",\"content\":\"输出1-10的数字,使用Python代码。\"}\n ],\n #打开流式输出开关\n stream=True\n)\n\n#处理结果\nfor chunk in response:\n\n # 取出content\n content = chunk.choices[0].delta.content\n\n # 过滤None\n if content is not None:\n print(content, end=\"\", flush=True)\n```\n觉得今天看的课程比较重要的就是这段代码,流式输出,然后过滤none\n-------------------------------------------------------------\n## 2026.5.10\n```bash\nmessages = [\n {\"role\": \"system\",\n \"content\": \"你是金融专家,将文本分类为['新闻报道', '财务报道', '公司公告', '分析师报告'],不清楚的分类为'不清楚类别' 下面有示例:\"},\n]\nfor key,value in examples_data.items():\n messages.append({\"role\": \"user\",\"content\": value})\n messages.append({\"role\": \"assistant\",\"content\": key})#动态添加message\n\nfor q in questions:\n response=client.chat.completions.create(\n model=\"deepseek-v4-pro\",\n messages=messages+[{\n \"role\":\"user\",\n \"content\": q#把要问的问题添加进来\n }]\n )\n```\n这是今天学的动态创建提示词\n然后今天还学了list转json和json转list\n```bash\njson.dumps(list,ensure_ascii=flase)#将字典或者列表转换成json\njson.loads(json)#将json转换成list或者字典\n```\n之前Python的数据结构学的迷迷糊糊,再总结一下字典和列表取值的时候用的方法:\n```bash\n字典:键(key) -> 值(value)\nperson = {\n \"name\": \"张三\",\n \"age\": 18\n}\nperson[\"name\"]=“张三”\n列表:类似于数组,通过下标来取对应的数据\n```\n\"image\"\n\n"}, "54b35a803a09b51205ef6e5ef91f3271f0df9fdf": {"t": 1785766630.8633025, "n": 1859, "h": "761f63f5aa2201d0", "c": "# agent-学习路线记录\n-----------------------\n## 2026.5.9\n今天观看了黑马程序员的课程\n\"image\"\n看到了提示词工程\n然后这是大致的代码块:\n```bash\nfrom openai import OpenAI\n\nclient=OpenAI(\n base_url=\"https://api.deepseek.com\"\n)\n\n#调用模型\nresponse=client.chat.completions.create(\n model=\"deepseek-v4-pro\",\n messages=[\n {\"role\": \"system\", \"content\": \"你是一个Python编程专家,并且说话很多\"},\n {\"role\":\"assistant\",\"content\":\"好的,我是Python编程专家,你想问什么?\"},\n {\"role\":\"user\",\"content\":\"输出1-10的数字,使用Python代码。\"}\n ],\n #打开流式输出开关\n stream=True\n)\n\n#处理结果\nfor chunk in response:\n\n # 取出content\n content = chunk.choices[0].delta.content\n\n # 过滤None\n if content is not None:\n print(content, end=\"\", flush=True)\n```\n觉得今天看的课程比较重要的就是这段代码,流式输出,然后过滤none\n-------------------------------------------------------------\n## 2026.5.10\n```bash\nmessages = [\n {\"role\": \"system\",\n \"content\": \"你是金融专家,将文本分类为['新闻报道', '财务报道', '公司公告', '分析师报告'],不清楚的分类为'不清楚类别' 下面有示例:\"},\n]\nfor key,value in examples_data.items():\n messages.append({\"role\": \"user\",\"content\": value})\n messages.append({\"role\": \"assistant\",\"content\": key})#动态添加message\n\nfor q in questions:\n response=client.chat.completions.create(\n model=\"deepseek-v4-pro\",\n messages=messages+[{\n \"role\":\"user\",\n \"content\": q#把要问的问题添加进来\n }]\n )\n```\n这是今天学的动态创建提示词\n然后今天还学了list转json和json转list\n```bash\njson.dumps(list,ensure_ascii=flase)#将字典或者列表转换成json\njson.loads(json)#将json转换成list或者字典\n```\n之前Python的数据结构学的迷迷糊糊,再总结一下字典和列表取值的时候用的方法:\n```bash\n字典:键(key) -> 值(value)\nperson = {\n \"name\": \"张三\",\n \"age\": 18\n}\nperson[\"name\"]=“张三”\n列表:类似于数组,通过下标来取对应的数据\n\"image\"\n"}, "924da7283ef3c5a8d3824c868c9237de468353b3": {"t": 1785766632.0524085, "n": 1855, "h": "2ce90b0939356294", "c": "# agent-学习路线记录\n-----------------------\n## 2026.5.9\n今天观看了黑马程序员的课程\n\"image\"\n看到了提示词工程\n然后这是大致的代码块:\n```bash\nfrom openai import OpenAI\n\nclient=OpenAI(\n base_url=\"https://api.deepseek.com\"\n)\n\n#调用模型\nresponse=client.chat.completions.create(\n model=\"deepseek-v4-pro\",\n messages=[\n {\"role\": \"system\", \"content\": \"你是一个Python编程专家,并且说话很多\"},\n {\"role\":\"assistant\",\"content\":\"好的,我是Python编程专家,你想问什么?\"},\n {\"role\":\"user\",\"content\":\"输出1-10的数字,使用Python代码。\"}\n ],\n #打开流式输出开关\n stream=True\n)\n\n#处理结果\nfor chunk in response:\n\n # 取出content\n content = chunk.choices[0].delta.content\n\n # 过滤None\n if content is not None:\n print(content, end=\"\", flush=True)\n```\n觉得今天看的课程比较重要的就是这段代码,流式输出,然后过滤none\n-------------------------------------------------------------\n## 2026.5.10\n```bash\nmessages = [\n {\"role\": \"system\",\n \"content\": \"你是金融专家,将文本分类为['新闻报道', '财务报道', '公司公告', '分析师报告'],不清楚的分类为'不清楚类别' 下面有示例:\"},\n]\nfor key,value in examples_data.items():\n messages.append({\"role\": \"user\",\"content\": value})\n messages.append({\"role\": \"assistant\",\"content\": key})#动态添加message\n\nfor q in questions:\n response=client.chat.completions.create(\n model=\"deepseek-v4-pro\",\n messages=messages+[{\n \"role\":\"user\",\n \"content\": q#把要问的问题添加进来\n }]\n )\n```\n这是今天学的动态创建提示词\n然后今天还学了list转json和json转list\n```bash\njson.dumps(list,ensure_ascii=flase)#将字典或者列表转换成json\njson.loads(json)#将json转换成list或者字典\n```\n之前Python的数据结构学的迷迷糊糊,再总结一下字典和列表取值的时候用的方法:\n```bash\n字典:键(key) -> 值(value)\nperson = {\n \"name\": \"张三\",\n \"age\": 18\n}\nperson[\"name\"]=“张三”\n列表:类似于数组,通过下标来取对应的数据\n\"image\"\n"}, "11be85124dea4c1f5599cae5c29069b4f937a3e1": {"t": 1785766633.9355836, "n": 1567, "h": "e7d70ffc13b826d0", "c": "# agent-学习路线记录\n-----------------------\n## 2026.5.9\n今天观看了黑马程序员的课程\n\"image\"\n看到了提示词工程\n然后这是大致的代码块:\n```bash\nfrom openai import OpenAI\n\nclient=OpenAI(\n base_url=\"https://api.deepseek.com\"\n)\n\n#调用模型\nresponse=client.chat.completions.create(\n model=\"deepseek-v4-pro\",\n messages=[\n {\"role\": \"system\", \"content\": \"你是一个Python编程专家,并且说话很多\"},\n {\"role\":\"assistant\",\"content\":\"好的,我是Python编程专家,你想问什么?\"},\n {\"role\":\"user\",\"content\":\"输出1-10的数字,使用Python代码。\"}\n ],\n #打开流式输出开关\n stream=True\n)\n\n#处理结果\nfor chunk in response:\n\n # 取出content\n content = chunk.choices[0].delta.content\n\n # 过滤None\n if content is not None:\n print(content, end=\"\", flush=True)\n```\n觉得今天看的课程比较重要的就是这段代码,流式输出,然后过滤none\n-------------------------------------------------------------\n## 2026.5.10\n```bash\nmessages = [\n {\"role\": \"system\",\n \"content\": \"你是金融专家,将文本分类为['新闻报道', '财务报道', '公司公告', '分析师报告'],不清楚的分类为'不清楚类别' 下面有示例:\"},\n]\nfor key,value in examples_data.items():\n messages.append({\"role\": \"user\",\"content\": value})\n messages.append({\"role\": \"assistant\",\"content\": key})#动态添加message\n\nfor q in questions:\n response=client.chat.completions.create(\n model=\"deepseek-v4-pro\",\n messages=messages+[{\n \"role\":\"user\",\n \"content\": q#把要问的问题添加进来\n }]\n )\n```\n这是今天学的动态创建提示词\n然后今天还学了list转json和json转list\n```bash\njson.dumps(list,ensure_ascii=flase)#将字典或者列表转换成json\njson.loads(json)#将json转换成list或者字典\n```\n"}, "c40c6fc74534554b6e9440fab779d6e72b33818a": {"t": 1785766635.3904865, "n": 1567, "h": "2bf1fbfeb9af0bef", "c": "# agent-学习路线记录\n-----------------------\n## 2026.5.9\n今天观看了黑马程序员的课程\n\"image\"\n看到了提示词工程\n然后这是大致的代码块:\n```bash\nfrom openai import OpenAI\n\nclient=OpenAI(\n base_url=\"https://api.deepseek.com\"\n)\n\n#调用模型\nresponse=client.chat.completions.create(\n model=\"deepseek-v4-pro\",\n messages=[\n {\"role\": \"system\", \"content\": \"你是一个Python编程专家,并且说话很多\"},\n {\"role\":\"assistant\",\"content\":\"好的,我是Python编程专家,你想问什么?\"},\n {\"role\":\"user\",\"content\":\"输出1-10的数字,使用Python代码。\"}\n ],\n #打开流式输出开关\n stream=True\n)\n\n#处理结果\nfor chunk in response:\n\n # 取出content\n content = chunk.choices[0].delta.content\n\n # 过滤None\n if content is not None:\n print(content, end=\"\", flush=True)\n```\n觉得今天看的课程比较重要的就是这段代码,流式输出,然后过滤none\n-------------------------------------------------------------\n## 2026.5.10\n```bash\nmessages = [\n {\"role\": \"system\",\n \"content\": \"你是金融专家,将文本分类为['新闻报道', '财务报道', '公司公告', '分析师报告'],不清楚的分类为'不清楚类别' 下面有示例:\"},\n]\nfor key,value in examples_data.items():\n messages.append({\"role\": \"user\",\"content\": value})\n messages.append({\"role\": \"assistant\",\"content\": key})#动态添加message\n\nfor q in questions:\n response=client.chat.completions.create(\n model=\"deepseek-v4-pro\",\n messages=messages+[{\n \"role\":\"user\",\n \"content\": q#把要问的问题添加进来\n }]\n )\n```\n这是今天学的动态创建提示词\n然后今天还学了list转json和json转list\n```bash\njson.dumbs(list,ensure_ascii=flase)#将字典或者列表转换成json\njson.loads(json)#将json转换成list或者字典\n```\n"}, "e54520fa3991220123a973099035b24f0da06792": {"t": 1785766636.9814708, "n": 842, "h": "f2463c7bcb20d36c", "c": "# agent-学习路线记录\n-----------------------\n## 2026.5.9\n今天观看了黑马程序员的课程\n\"image\"\n看到了提示词工程\n然后这是大致的代码块:\n```bash\nfrom openai import OpenAI\n\nclient=OpenAI(\n base_url=\"https://api.deepseek.com\"\n)\n\n#调用模型\nresponse=client.chat.completions.create(\n model=\"deepseek-v4-pro\",\n messages=[\n {\"role\": \"system\", \"content\": \"你是一个Python编程专家,并且说话很多\"},\n {\"role\":\"assistant\",\"content\":\"好的,我是Python编程专家,你想问什么?\"},\n {\"role\":\"user\",\"content\":\"输出1-10的数字,使用Python代码。\"}\n ],\n #打开流式输出开关\n stream=True\n)\n\n#处理结果\nfor chunk in response:\n\n # 取出content\n content = chunk.choices[0].delta.content\n\n # 过滤None\n if content is not None:\n print(content, end=\"\", flush=True)\n```\n觉得今天看的课程比较重要的就是这段代码,流式输出,然后过滤none\n"}, "99c2bf56385b7c9e4b0be864be4ea241cfba382d": {"t": 1785766638.6827612, "n": 841, "h": "cd0628026ef0dae9", "c": "\"image\"# agent-学习路线记录\n-----------------------\n## 2026.5.9\n今天观看了黑马程序员的课程\n看到了提示词工程\n然后这是大致的代码块:\n```bash\nfrom openai import OpenAI\n\nclient=OpenAI(\n base_url=\"https://api.deepseek.com\"\n)\n\n#调用模型\nresponse=client.chat.completions.create(\n model=\"deepseek-v4-pro\",\n messages=[\n {\"role\": \"system\", \"content\": \"你是一个Python编程专家,并且说话很多\"},\n {\"role\":\"assistant\",\"content\":\"好的,我是Python编程专家,你想问什么?\"},\n {\"role\":\"user\",\"content\":\"输出1-10的数字,使用Python代码。\"}\n ],\n #打开流式输出开关\n stream=True\n)\n\n#处理结果\nfor chunk in response:\n\n # 取出content\n content = chunk.choices[0].delta.content\n\n # 过滤None\n if content is not None:\n print(content, end=\"\", flush=True)\n```\n觉得今天看的课程比较重要的就是这段代码,流式输出,然后过滤none\n"}, "1533c04d597f92fdae461b96b6e308c0dde7237c": {"t": 1785766640.5302267, "n": 8, "h": "1ba9e8f101299b0d", "c": "# agent-"}}}}