mirror of
https://github.com/TeamWiseFlow/wiseflow.git
synced 2025-01-23 02:20:20 +08:00
v0.3.6 release
This commit is contained in:
parent
1f9b6d5d6c
commit
35fbff0f27
31
CHANGELOG.md
31
CHANGELOG.md
@ -1,7 +1,34 @@
|
||||
# V0.3.6
|
||||
- 引入视觉大模型,大幅提升页面获取能力;
|
||||
- 改用 Crawl4ai 作为底层爬虫框架,其实Crawl4ai 和 Crawlee 的获取效果差别不大,二者也都是基于 Playwright ,但 Crawl4ai 的 html2markdown 功能很实用,而这对llm 信息提取作用很大,另外 Crawl4ai 的架构也更加符合我的思路;
|
||||
- 在 Crawl4ai 的 html2markdown 基础上,增加了 deep scraper,进一步把页面的独立链接与正文进行区分,便于后一步 llm 的精准提取。由于html2markdown和deep scraper已经将原始网页数据做了很好的清理,极大降低了llm所受的干扰和误导,保证了最终结果的质量,同时也减少了不必要的 token 消耗;
|
||||
|
||||
*列表页面和文章页面的区分是所有爬虫类项目都头痛的地方,尤其是现代网页往往习惯在文章页面的侧边栏和底部增加大量推荐阅读,使得二者几乎不存在文本统计上的特征差异。*
|
||||
*这一块我本来想用视觉大模型进行 layout 分析,但最终实现起来发现获取不受干扰的网页截图是一件会极大增加程序复杂度并降低处理效率的事情……*
|
||||
|
||||
- 改进 pocketbase 的前期下载以及用户名密码配置方案,感谢 @ourines 贡献了 install_pocketbase.sh 脚本;
|
||||
- 重构了提取策略、llm 的 prompt 等;
|
||||
|
||||
*有关 prompt 我想说的是,我理解好的 prompt 是清晰的工作流指导,每一步都足够明确,明确到很难犯错。但我不太相信过于复杂的 prompt 的价值,这个很难评估,如果你有更好的方案,欢迎提供 PR*
|
||||
|
||||
- 引入视觉大模型,自动在提取前对高权重(目前由 Crawl4ai 评估权重)图片进行识别,并补充相关信息到页面文本中;
|
||||
- 继续减少 requirement.txt 的依赖项,目前不需要 json_repair了(实践中也发现让 llm 按 json 格式生成,还是会明显增加处理时间和失败率,因此我现在采用更简单的方式,同时增加对处理结果的后处理)
|
||||
- pb info 表单的结构做了小调整,增加了 web_title 和 reference 两项。
|
||||
- @ourines 贡献了 install_pocketbase.sh 脚本 (docker运行方案被暂时移除了,感觉大家用起来也不是很方便……)
|
||||
|
||||
|
||||
- Switched to Crawl4ai as the underlying web crawling framework. Although Crawl4ai and Crawlee both rely on Playwright with similar fetching results, Crawl4ai's html2markdown feature is quite practical for LLM information extraction. Additionally, Crawl4ai's architecture better aligns with my design philosophy.
|
||||
- Built upon Crawl4ai's html2markdown, we added a deep scraper to further differentiate standalone links from the main content, facilitating more precise LLM extraction. The preprocessing done by html2markdown and deep scraper significantly cleans up raw web data, minimizing interference and misleading information for LLMs, ensuring higher quality outcomes while reducing unnecessary token consumption.
|
||||
|
||||
*Distinguishing between list pages and article pages is a common challenge in web scraping projects, especially when modern webpages often include extensive recommended readings in sidebars and footers of articles, making it difficult to differentiate them through text statistics.*
|
||||
*Initially, I considered using large visual models for layout analysis, but found that obtaining undistorted webpage screenshots greatly increases program complexity and reduces processing efficiency...*
|
||||
|
||||
- Restructured extraction strategies and LLM prompts;
|
||||
|
||||
*Regarding prompts, I believe that a good prompt serves as clear workflow guidance, with each step being explicit enough to minimize errors. However, I am skeptical about the value of overly complex prompts, which are hard to evaluate. If you have better solutions, feel free to submit a PR.*
|
||||
|
||||
- Introduced large visual models to automatically recognize high-weight images (currently evaluated by Crawl4ai) before extraction and append relevant information to the page text;
|
||||
- Continued to reduce dependencies in requirement.txt; json_repair is no longer needed (in practice, having LLMs generate JSON format still noticeably increases processing time and failure rates, so I now adopt a simpler approach with additional post-processing of results)
|
||||
- Made minor adjustments to the pb info form structure, adding web_title and reference fields.
|
||||
- @ourines contributed the install_pocketbase.sh script (the Docker running solution has been temporarily removed as it wasn't very convenient for users...)
|
||||
|
||||
# V0.3.5
|
||||
- 引入 Crawlee(playwrigt模块),大幅提升通用爬取能力,适配实际项目场景;
|
||||
|
55
README.md
55
README.md
@ -10,10 +10,33 @@
|
||||
|
||||
https://github.com/user-attachments/assets/fc328977-2366-4271-9909-a89d9e34a07b
|
||||
|
||||
## 🔥 测试脚本与测试报告发布
|
||||
## 🔥 虽迟但到, V0.3.6来了
|
||||
|
||||
我们在四个现实案例任务以及共计十个真实网页 sample 中横向测试并比较了由 siliconflow 提供的deepseekV2.5、Qwen2.5-32B-Instruct、Qwen2.5-14B-Instruct、Qwen2.5-coder-7B-Instruct 模型的表现情况,
|
||||
测试结果请参考 [report](./test/reports/wiseflow_report_20241223_bigbrother666/README.md)
|
||||
V0.3.6 是 V0.3.5的效果改进版本,针对诸多社区反馈进行了改进,建议所有用户升级。
|
||||
|
||||
- 改用 Crawl4ai 作为底层爬虫框架,其实Crawl4ai 和 Crawlee 的获取效果差别不大,二者也都是基于 Playwright ,但 Crawl4ai 的 html2markdown 功能很实用,而这对llm 信息提取作用很大,另外 Crawl4ai 的架构也更加符合我的思路;
|
||||
- 在 Crawl4ai 的 html2markdown 基础上,增加了 deep scraper,进一步把页面的独立链接与正文进行区分,便于后一步 llm 的精准提取。由于html2markdown和deep scraper已经将原始网页数据做了很好的清理,极大降低了llm所受的干扰和误导,保证了最终结果的质量,同时也减少了不必要的 token 消耗;
|
||||
|
||||
*列表页面和文章页面的区分是所有爬虫类项目都头痛的地方,尤其是现代网页往往习惯在文章页面的侧边栏和底部增加大量推荐阅读,使得二者几乎不存在文本统计上的特征差异。*
|
||||
*这一块我本来想用视觉大模型进行 layout 分析,但最终实现起来发现获取不受干扰的网页截图是一件会极大增加程序复杂度并降低处理效率的事情……*
|
||||
|
||||
- 重构了提取策略、llm 的 prompt 等;
|
||||
|
||||
*有关 prompt 我想说的是,我理解好的 prompt 是清晰的工作流指导,每一步都足够明确,明确到很难犯错。但我不太相信过于复杂的 prompt 的价值,这个很难评估,如果你有更好的方案,欢迎提供 PR*
|
||||
|
||||
- 引入视觉大模型,自动在提取前对高权重(目前由 Crawl4ai 评估权重)图片进行识别,并补充相关信息到页面文本中;
|
||||
- 继续减少 requirement.txt 的依赖项,目前不需要 json_repair了(实践中也发现让 llm 按 json 格式生成,还是会明显增加处理时间和失败率,因此我现在采用更简单的方式,同时增加对处理结果的后处理)
|
||||
- pb info 表单的结构做了小调整,增加了 web_title 和 reference 两项。
|
||||
- @ourines 贡献了 install_pocketbase.sh 脚本 (docker运行方案被暂时移除了,感觉大家用起来也不是很方便……)
|
||||
|
||||
**升级V0.3.6 版本依然需要重构 pocketbase 数据库,请删除pb/pb_data 文件夹后重新执行**
|
||||
|
||||
**V0.3.6版本 .env 中需要把SECONDARY_MODEL替换为VL_MODEL,请参考最新的 [env_sample](./env_sample)**
|
||||
|
||||
### V0.3.6 测试报告
|
||||
|
||||
我们在四个现实案例任务以及共计六个真实网页 sample 中横向测试并比较了由 siliconflow 提供的deepseekV2.5、Qwen2.5-32B-Instruct、Qwen2.5-14B-Instruct、Qwen2.5-72B-Instruct 模型的表现情况,
|
||||
测试结果请参考 [report](./test/reports/wiseflow_report_v036_bigbrother666/README.md)
|
||||
|
||||
同时我们也将测试脚本进行开源,欢迎大家踊跃提交更多测试结果,wiseflow 是一个开源项目,希望通过大家共同的贡献,打造“人人可用的信息爬取工具”!
|
||||
|
||||
@ -21,21 +44,15 @@ https://github.com/user-attachments/assets/fc328977-2366-4271-9909-a89d9e34a07b
|
||||
|
||||
现阶段,**提交测试结果等同于提交项目代码**,同样会被接纳为contributor,甚至受邀参加商业化项目!
|
||||
|
||||
另外我们改进了 pocketbase 的下载以及用户名密码配置方案,感谢 @ourines 贡献了 install_pocketbase.sh 脚本。
|
||||
|
||||
(docker运行方案被暂时移除了,感觉大家用起来也不是很方便……)
|
||||
|
||||
🌟 **V0.3.6 版本预告**
|
||||
|
||||
V0.3.6 版本计划于2024年12月30日前发布,该版本是 v0.3.5 的性能优化版本,信息抽取质量将有质的提升,同时还会引入视觉大模型,在网页信息不足时提取页面图片信息作为补充。
|
||||
|
||||
**V0.3.x 计划**
|
||||
🌟**V0.3.x 计划**
|
||||
|
||||
- 尝试支持微信公众号免wxbot订阅(V0.3.7);
|
||||
- 引入对 RSS 信息源的支持(V0.3.8);
|
||||
- 尝试引入 LLM 驱动的轻量级知识图谱,帮助用户从 infos 中建立洞察(V0.3.9)。
|
||||
- 引入对 RSS 信息源和搜索引擎的支持(V0.3.8);
|
||||
- 尝试部分支持社交平台(V0.3.9)。
|
||||
|
||||
伴随着上述三个版本,我会持续改进 deep scraper 以及 llm 提取策略,也欢迎大家持续反馈应用场景和抽取效果不理想的信源地址,欢迎在 [issue #136](https://github.com/TeamWiseFlow/wiseflow/issues/136) 中进行反馈。
|
||||
|
||||
自V0.3.5版本开始 wiseflow 使用全新的架构,并引入 [Crawlee](https://github.com/apify/crawlee-python) 作为基础爬虫和任务管理框架,大幅提升页面获取能力。后续我们会持续提升wiseflow 的页面获取能力,大家碰到不能很好获取的页面,欢迎在 [issue #136](https://github.com/TeamWiseFlow/wiseflow/issues/136) 中进行反馈。
|
||||
|
||||
## ✋ wiseflow 与传统的爬虫工具、AI搜索、知识库(RAG)项目有何不同?
|
||||
|
||||
@ -45,10 +62,12 @@ wiseflow自2024年6月底发布 V0.3.0版本来受到了开源社区的广泛关
|
||||
|
||||
| | 与 **首席情报官(Wiseflow)** 的比较说明|
|
||||
|-------------|-----------------|
|
||||
| **爬虫类工具** | 首先 wiseflow 是基于爬虫工具的项目(目前我们基于的是 Crawl4ai),但传统的爬虫工具在信息提取方面需要人工的提供明确的 Xpath 等信息……这不仅阻挡了普通用户,同时也毫无通用性可言,对于不同网站(包括已有网站升级后)都需要人工重做分析,更新程序。wiseflow致力于使用 LLM 自动化网页的分析和提取工作,用户只要告诉程序他的关注点即可。 如果以 Crawl4ai 为例对比说明,Crawl4ai 是会使用 llm 进行信息提取的爬虫,而wiseflow 则是会使用爬虫工具的llm信息提取器。|
|
||||
| **爬虫类工具** | 首先 wiseflow 是基于爬虫工具的项目,但传统的爬虫工具在信息提取方面需要人工的提供明确的 Xpath 等信息……这不仅阻挡了普通用户,同时也毫无通用性可言,对于不同网站(包括已有网站升级后)都需要人工重做分析,更新程序。wiseflow致力于使用 LLM 自动化网页的分析和提取工作,用户只要告诉程序他的关注点即可。 如果以 Crawl4ai 为例对比说明,Crawl4ai 是会使用 llm 进行信息提取的爬虫,而wiseflow 则是会使用爬虫工具的llm信息提取器。|
|
||||
| **AI搜索** | AI搜索主要的应用场景是**具体问题的即时问答**,举例:”XX公司的创始人是谁“、“xx品牌下的xx产品哪里有售” ,用户要的是**一个答案**;wiseflow主要的应用场景是**某一方面信息的持续采集**,比如XX公司的关联信息追踪,XX品牌市场行为的持续追踪……在这些场景下,用户能提供关注点(某公司、某品牌)、甚至能提供信源(站点 url 等),但无法提出具体搜索问题,用户要的是**一系列相关信息**|
|
||||
| **知识库(RAG)类项目** | 知识库(RAG)类项目一般是基于已有信息的下游任务,并且一般面向的是私有知识(比如企业内的操作手册、产品手册、政府部门的文件等);wiseflow 目前并未整合下游任务,同时面向的是互联网上的公开信息,如果从“智能体”的角度来看,二者属于为不同目的而构建的智能体,RAG 类项目是“(内部)知识助理智能体”,而 wiseflow 则是“(外部)信息采集智能体”|
|
||||
|
||||
**wiseflow 0.4.x 版本将关注下游任务的集成, 引入 LLM 驱动的轻量级知识图谱,帮助用户从 infos 中建立洞察。**
|
||||
|
||||
## 📥 安装与使用
|
||||
|
||||
### 1. 克隆代码仓库
|
||||
@ -94,7 +113,6 @@ siliconflow(硅基流动)提供大部分主流开源模型的在线 MaaS 服
|
||||
export LLM_API_KEY=Your_API_KEY
|
||||
export LLM_API_BASE="https://api.siliconflow.cn/v1"
|
||||
export PRIMARY_MODEL="Qwen/Qwen2.5-32B-Instruct"
|
||||
export SECONDARY_MODEL="Qwen/Qwen2.5-7B-Instruct"
|
||||
export VL_MODEL="OpenGVLab/InternVL2-26B"
|
||||
```
|
||||
|
||||
@ -109,7 +127,6 @@ export VL_MODEL="OpenGVLab/InternVL2-26B"
|
||||
export LLM_API_KEY=Your_API_KEY
|
||||
export LLM_API_BASE="https://aihubmix.com/v1" # 具体参考 https://doc.aihubmix.com/
|
||||
export PRIMARY_MODEL="gpt-4o"
|
||||
export SECONDARY_MODEL="gpt-4o-mini"
|
||||
export VL_MODEL="gpt-4o"
|
||||
```
|
||||
|
||||
@ -123,7 +140,6 @@ export VL_MODEL="gpt-4o"
|
||||
# LLM_API_KEY='' 本地服务无需这一项,请注释掉或删除
|
||||
export LLM_API_BASE='http://127.0.0.1:9997'
|
||||
export PRIMARY_MODEL=启动的模型 ID
|
||||
export SECONDARY_MODEL=启动的模型 ID
|
||||
export VL_MODEL=启动的模型 ID
|
||||
```
|
||||
|
||||
@ -233,8 +249,7 @@ PocketBase作为流行的轻量级数据库,目前已有 Go/Javascript/Python
|
||||
|
||||
## 🤝 本项目基于如下优秀的开源项目:
|
||||
|
||||
- crawlee-python (A web scraping and browser automation library for Python to build reliable crawlers. Works with BeautifulSoup, Playwright, and raw HTTP. Both headful and headless mode. With proxy rotation.) https://github.com/apify/crawlee-python
|
||||
- json_repair(Repair invalid JSON documents ) https://github.com/josdejong/jsonrepair/tree/main
|
||||
- crawl4ai(Open-source LLM Friendly Web Crawler & Scraper) https://github.com/unclecode/crawl4ai
|
||||
- python-pocketbase (pocketBase client SDK for python) https://github.com/vaphes/pocketbase
|
||||
|
||||
本项目开发受 [GNE](https://github.com/GeneralNewsExtractor/GeneralNewsExtractor)、[AutoCrawler](https://github.com/kingname/AutoCrawler) 、[SeeAct](https://github.com/OSU-NLP-Group/SeeAct) 启发。
|
||||
|
59
README_EN.md
59
README_EN.md
@ -10,32 +10,48 @@
|
||||
|
||||
https://github.com/user-attachments/assets/fc328977-2366-4271-9909-a89d9e34a07b
|
||||
|
||||
## 🔥 Test Scripts and Test Reports Release
|
||||
## 🔥 V0.3.6 is Here
|
||||
|
||||
We have horizontally tested and compared the performance of deepseekV2.5, Qwen2.5-32B-Instruct, Qwen2.5-14B-Instruct, and Qwen2.5-coder-7B-Instruct models provided by siliconflow across four real-case tasks and a total of ten real webpage samples.
|
||||
Please refer to the [report](./test/reports/wiseflow_report_20241223_bigbrother666/README.md) for test results.
|
||||
V0.3.6 is an enhanced version of V0.3.5, incorporating numerous improvements based on community feedback. We recommend all users to upgrade.
|
||||
|
||||
We have also open-sourced the test scripts and welcome everyone to actively submit more test results. Wiseflow is an open-source project, and we hope to create an "information crawling tool that everyone can use" through our collective contributions!
|
||||
- Switched to Crawl4ai as the underlying web crawling framework. Although Crawl4ai and Crawlee both rely on Playwright with similar fetching results, Crawl4ai's html2markdown feature is quite practical for LLM information extraction. Additionally, Crawl4ai's architecture better aligns with my design philosophy.
|
||||
- Built upon Crawl4ai's html2markdown, we added a deep scraper to further differentiate standalone links from the main content, facilitating more precise LLM extraction. The preprocessing done by html2markdown and deep scraper significantly cleans up raw web data, minimizing interference and misleading information for LLMs, ensuring higher quality outcomes while reducing unnecessary token consumption.
|
||||
|
||||
For details, please refer to [test/README_EN.md](./test/README_EN.md)
|
||||
*Distinguishing between list pages and article pages is a common challenge in web scraping projects, especially when modern webpages often include extensive recommended readings in sidebars and footers of articles, making it difficult to differentiate them through text statistics.*
|
||||
*Initially, I considered using large visual models for layout analysis, but found that obtaining undistorted webpage screenshots greatly increases program complexity and reduces processing efficiency...*
|
||||
|
||||
At this stage, **submitting test results is equivalent to submitting project code**, and you will similarly be accepted as a contributor and may even be invited to participate in commercialization projects!
|
||||
- Restructured extraction strategies and LLM prompts;
|
||||
|
||||
Additionally, we have improved the download and username/password configuration solution for pocketbase. Thanks to @ourines for contributing the install_pocketbase.sh script.
|
||||
*Regarding prompts, I believe that a good prompt serves as clear workflow guidance, with each step being explicit enough to minimize errors. However, I am skeptical about the value of overly complex prompts, which are hard to evaluate. If you have better solutions, feel free to submit a PR.*
|
||||
|
||||
(The docker deployment solution has been temporarily removed as we felt it wasn't very convenient for users...)
|
||||
- Introduced large visual models to automatically recognize high-weight images (currently evaluated by Crawl4ai) before extraction and append relevant information to the page text;
|
||||
- Continued to reduce dependencies in requirement.txt; json_repair is no longer needed (in practice, having LLMs generate JSON format still noticeably increases processing time and failure rates, so I now adopt a simpler approach with additional post-processing of results)
|
||||
- Made minor adjustments to the pb info form structure, adding web_title and reference fields.
|
||||
- @ourines contributed the install_pocketbase.sh script (the Docker running solution has been temporarily removed as it wasn't very convenient for users...)
|
||||
|
||||
🌟 **V0.3.6 Version Preview**
|
||||
**Upgrading to V0.3.6 requires restructuring the PocketBase database. Please delete the pb/pb_data folder and re-run the setup**
|
||||
|
||||
Version V0.3.6 is planned for release before December 30, 2024. This version is a performance optimization of v0.3.5, with significant improvements in information extraction quality. It will also introduce visual large models to extract page image information as supplementary when webpage information is insufficient.
|
||||
**In V0.3.6, replace SECONDARY_MODEL with VL_MODEL in the .env file. Refer to the latest [env_sample](./env_sample)**
|
||||
|
||||
**V0.3.x Plan**
|
||||
### V0.3.6 Test Report
|
||||
|
||||
- Attempt to support WeChat official account subscription without wxbot (V0.3.7)
|
||||
- Introduce support for RSS information sources (V0.3.8)
|
||||
- Attempt to introduce LLM-driven lightweight knowledge graphs to help users build insights from infos (V0.3.9)
|
||||
We conducted horizontal tests across four real-world tasks and six real web samples using deepseekV2.5, Qwen2.5-32B-Instruct, Qwen2.5-14B-Instruct, and Qwen2.5-72B-Instruct models provided by siliconflow. For detailed test results, please refer to [report](./test/reports/wiseflow_report_v036_bigbrother666/README.md).
|
||||
|
||||
We have also open-sourced our testing scripts. We welcome everyone to submit more test results. Wiseflow is an open-source project aiming to create an "information retrieval tool accessible to everyone"!
|
||||
|
||||
Refer to [test/README.md](./test/README.md)
|
||||
|
||||
At this stage, **submitting test results is equivalent to contributing code**, and contributors may even be invited to participate in commercial projects!
|
||||
|
||||
|
||||
🌟**V0.3.x Roadmap**
|
||||
|
||||
- Attempt to support WeChat Official Account subscription without wxbot (V0.3.7);
|
||||
- Introduce support for RSS feeds and search engines (V0.3.8);
|
||||
- Attempt partial support for social platforms (V0.3.9).
|
||||
|
||||
Throughout these versions, I will continuously improve the deep scraper and LLM extraction strategies. We welcome continuous feedback on application scenarios and sources where extraction performance is unsatisfactory. Please provide feedback in [issue #136](https://github.com/TeamWiseFlow/wiseflow/issues/136).
|
||||
|
||||
Starting from version V0.3.5, wiseflow uses a completely new architecture and introduces [Crawlee](https://github.com/apify/crawlee-python) as the basic crawler and task management framework, significantly improving page acquisition capabilities. We will continue to enhance wiseflow's page acquisition capabilities. If you encounter pages that cannot be properly acquired, please provide feedback in [issue #136](https://github.com/TeamWiseFlow/wiseflow/issues/136).
|
||||
|
||||
## ✋ How is wiseflow Different from Traditional Crawler Tools, AI Search, and Knowledge Base (RAG) Projects?
|
||||
|
||||
@ -45,10 +61,12 @@ However, we have also noticed some misunderstandings about the functional positi
|
||||
|
||||
| | Comparison with **Chief Intelligence Officer (Wiseflow)** |
|
||||
|-------------|-----------------|
|
||||
| **Crawler Tools** | First, wiseflow is a project based on crawler tools (in the current version, we use the crawler framework Crawlee). However, traditional crawler tools require manual intervention in information extraction, providing explicit Xpath, etc. This not only blocks ordinary users but also lacks generality. For different websites (including upgraded websites), manual reanalysis and updating of extraction code are required. Wiseflow is committed to automating web analysis and extraction using LLM. Users only need to tell the program their focus points. From this perspective, wiseflow can be simply understood as an "AI agent that can automatically use crawler tools." |
|
||||
| **Crawler Tools** | First of all, wiseflow is a project based on a web crawler tool, but traditional crawler tools require manual provision of explicit Xpath information for data extraction... This not only blocks ordinary users but also lacks universality. For different websites (including existing websites after upgrades), manual re-analysis and program updates are required. wiseflow is committed to using LLM to automate the analysis and extraction of web pages. Users only need to tell the program their focus points. Taking Crawl4ai as an example for comparison, Crawl4ai is a crawler that uses LLM for information extraction, while wiseflow is an LLM information extractor that uses crawler tools. |
|
||||
| **AI Search** | AI search is mainly used for **instant question-and-answer** scenarios, such as "Who is the founder of XX company?" or "Where can I buy the xx product under the xx brand?" Users want **a single answer**; wiseflow is mainly used for **continuous information collection** in certain areas, such as tracking related information of XX company, continuously tracking market behavior of XX brand, etc. In these scenarios, users can provide focus points (a company, a brand) or even information sources (site URLs, etc.), but cannot pose specific search questions. Users want **a series of related information**.|
|
||||
| **Knowledge Base (RAG) Projects** | Knowledge base (RAG) projects are generally based on downstream tasks of existing information and usually face private knowledge (such as operation manuals, product manuals, government documents within enterprises, etc.); wiseflow currently does not integrate downstream tasks and faces public information on the internet. From the perspective of "agents," the two belong to agents built for different purposes. RAG projects are "internal knowledge assistant agents," while wiseflow is an "external information collection agent."|
|
||||
|
||||
**The wiseflow 0.4.x version will focus on the integration of downstream tasks, introducing an LLM-driven lightweight knowledge graph to help users gain insights from infos.**
|
||||
|
||||
## 📥 Installation and Usage
|
||||
|
||||
### 1. Clone the Code Repository
|
||||
@ -92,7 +110,6 @@ Siliconflow provides online MaaS services for most mainstream open-source models
|
||||
export LLM_API_KEY=Your_API_KEY
|
||||
export LLM_API_BASE="https://api.siliconflow.cn/v1"
|
||||
export PRIMARY_MODEL="Qwen/Qwen2.5-32B-Instruct"
|
||||
export SECONDARY_MODEL="Qwen/Qwen2.5-7B-Instruct"
|
||||
export VL_MODEL="OpenGVLab/InternVL2-26B"
|
||||
```
|
||||
|
||||
@ -108,7 +125,6 @@ When using AiHubMix models, the .env configuration can refer to the following:
|
||||
export LLM_API_KEY=Your_API_KEY
|
||||
export LLM_API_BASE="https://aihubmix.com/v1" # refer to https://doc.aihubmix.com/
|
||||
export PRIMARY_MODEL="gpt-4o"
|
||||
export SECONDARY_MODEL="gpt-4o-mini"
|
||||
export VL_MODEL="gpt-4o"
|
||||
```
|
||||
|
||||
@ -122,7 +138,6 @@ Taking Xinference as an example, the .env configuration can refer to the followi
|
||||
# LLM_API_KEY='' no need for local service, please comment out or delete
|
||||
export LLM_API_BASE='http://127.0.0.1:9997'
|
||||
export PRIMARY_MODEL=launched_model_id
|
||||
export SECONDARY_MODEL=launched_model_id
|
||||
export VL_MODEL=launched_model_id
|
||||
```
|
||||
|
||||
@ -232,12 +247,10 @@ If you have any questions or suggestions, please feel free to leave a message vi
|
||||
|
||||
## 🤝 This Project is Based on the Following Excellent Open-Source Projects:
|
||||
|
||||
- crawlee-python (A web scraping and browser automation library for Python to build reliable crawlers. Works with BeautifulSoup, Playwright, and raw HTTP. Both headful and headless mode. With proxy rotation.) https://github.com/apify/crawlee-python
|
||||
- json_repair (Repair invalid JSON documents) https://github.com/josdejong/jsonrepair/tree/main
|
||||
- crawl4ai(Open-source LLM Friendly Web Crawler & Scraper) https://github.com/unclecode/crawl4ai
|
||||
- python-pocketbase (pocketBase client SDK for python) https://github.com/vaphes/pocketbase
|
||||
- SeeAct (a system for generalist web agents that autonomously carry out tasks on any given website, with a focus on large multimodal models (LMMs) such as GPT-4Vision.) https://github.com/OSU-NLP-Group/SeeAct
|
||||
|
||||
Also inspired by [GNE](https://github.com/GeneralNewsExtractor/GeneralNewsExtractor) and [AutoCrawler](https://github.com/kingname/AutoCrawler).
|
||||
Also inspired by [GNE](https://github.com/GeneralNewsExtractor/GeneralNewsExtractor) [AutoCrawler](https://github.com/kingname/AutoCrawler) [SeeAct](https://github.com/OSU-NLP-Group/SeeAct) .
|
||||
|
||||
## Citation
|
||||
|
||||
|
60
README_JP.md
60
README_JP.md
@ -10,32 +10,49 @@
|
||||
|
||||
https://github.com/user-attachments/assets/fc328977-2366-4271-9909-a89d9e34a07b
|
||||
|
||||
## 🔥 テストスクリプトとテストレポートの公開
|
||||
## 🔥 遅れましたが、V0.3.6が到着しました
|
||||
|
||||
siliconflowが提供するdeepseekV2.5、Qwen2.5-32B-Instruct、Qwen2.5-14B-Instruct、Qwen2.5-coder-7B-Instructモデルの性能を、4つの実際のケースタスクと合計10の実際のウェブページサンプルで横断的にテストし比較しました。
|
||||
テスト結果は[report](./test/reports/wiseflow_report_20241223_bigbrother666/README.md)をご参照ください。
|
||||
V0.3.6はV0.3.5の効果改善版で、多くのコミュニティからのフィードバックに基づいて改良が行われました。すべてのユーザーにアップグレードすることをお勧めします。
|
||||
|
||||
また、テストスクリプトもオープンソース化しましたので、より多くのテスト結果の提出をお待ちしています。wiseflowはオープンソースプロジェクトであり、皆様の共同貢献を通じて「誰もが使える情報収集ツール」を作り上げたいと考えています!
|
||||
- Crawl4aiを基盤クローリングフレームワークとして採用しました。実際、Crawl4aiとCrawleeの取得結果には大きな違いはありませんが、両者ともPlaywrightに基づいています。しかし、Crawl4aiのhtml2markdown機能が非常に便利で、これはLLM情報抽出に大いに役立ちます。さらに、Crawl4aiのアーキテクチャは私の考え方により適合しています。
|
||||
- Crawl4aiのhtml2markdown機能を基に、deep scraperを追加し、ページ内の独立リンクと本文を区別するようにしました。これにより、次のステップでのLLMによる正確な抽出が容易になります。html2markdownとdeep scraperは元のウェブページデータを十分にクリーニングし、LLMに対する干渉や誤導を大幅に低減し、最終結果の品質を保証するとともに、不要なトークン消費を削減します。
|
||||
|
||||
詳細は[test/README_EN.md](./test/README_EN.md)をご参照ください。
|
||||
*リストページと記事ページの区別は、すべてのクローリングプロジェクトにとって頭痛の種です。特に現代のウェブページでは、記事ページのサイドバーとフッターに大量の関連コンテンツが含まれているため、テキスト統計上の特徴的な違いを見つけるのは困難です。*
|
||||
*この部分については、視覚的大規模モデルを使用してレイアウト分析を行うことを検討しましたが、干渉のないウェブページスクリーンショットを取得することは、プログラムの複雑さを大幅に増加させ、処理効率を低下させることがわかりました……*
|
||||
|
||||
現段階では、**テスト結果の提出はプロジェクトコードの提出と同等**とみなされ、contributorとして認められ、さらには商業化プロジェクトへの参加招待を受ける可能性もあります!
|
||||
- 抽出戦略やLLMのプロンプトを再構築しました。
|
||||
|
||||
また、pocketbaseのダウンロードとユーザー名/パスワード設定方法を改善しました。@ourinesのinstall_pocketbase.shスクリプトの貢献に感謝いたします。
|
||||
*プロンプトについて補足説明すると、私は良いプロンプトは明確な作業フロー指示であるべきだと考えています。各ステップが十分に明確で、間違いを犯すのが難しいものです。しかし、過度に複雑なプロンプトの価値については懐疑的です。評価が難しく、もしより良いソリューションがある場合はPRをお願いします*
|
||||
|
||||
(dockerでの実行方案は一時的に削除されました。皆様にとってあまり便利ではないと感じたため...)
|
||||
- 視覚的大規模モデルを導入し、抽出前に高ウェイト(現在はCrawl4aiによって評価)の画像を自動的に認識し、関連情報をページテキストに追加します。
|
||||
- requirement.txtの依存関係をさらに削減し、json_repairは必要なくなった(実際の運用中、LLMがJSON形式で生成すると、処理時間と失敗率が明らかに増加することがわかったため、よりシンプルな方法を採用し、処理結果の後処理を強化)
|
||||
- pb infoフォームの構造を微調整し、web_titleとreferenceの2項目を追加しました。
|
||||
- @ourinesがinstall_pocketbase.shスクリプトを貢献しました (Docker実行方案は一時的に削除されました、使い勝手が良くなかったため……)
|
||||
|
||||
🌟 **V0.3.6バージョン予告**
|
||||
**V0.3.6バージョンへのアップグレードにはpocketbaseデータベースの再構築が必要です。pb/pb_dataフォルダを削除した後、再度実行してください**
|
||||
|
||||
V0.3.6バージョンは2024年12月30日までにリリース予定で、このバージョンはv0.3.5のパフォーマンス最適化版となります。情報抽出の品質が大幅に向上し、さらに視覚大規模モデルを導入して、ウェブページの情報が不足している場合にページ画像情報を補完として抽出します。
|
||||
**V0.3.6バージョンでは.envファイルのSECONDARY_MODELをVL_MODELに置き換えてください。最新の[env_sample](./env_sample)を参照してください**
|
||||
|
||||
### V0.3.6テスト報告書
|
||||
|
||||
**V0.3.xプラン**
|
||||
siliconflowが提供するdeepseekV2.5、Qwen2.5-32B-Instruct、Qwen2.5-14B-Instruct、Qwen2.5-72B-Instructの4つのモデルの性能を4つの現実的なタスクと合計6つの実際のウェブページサンプルで横断的にテストおよび比較しました。
|
||||
テスト結果については[report](./test/reports/wiseflow_report_v036_bigbrother666/README.md)を参照してください。
|
||||
|
||||
- WeChat公式アカウントのwxbotなしでの購読サポートを試行(V0.3.7)
|
||||
- RSS情報ソースのサポートを導入(V0.3.8)
|
||||
- LLM駆動の軽量知識グラフを導入し、ユーザーがinfosから洞察を得られるよう支援(V0.3.9)
|
||||
また、テストスクリプトもオープンソース化しており、より多くのテスト結果を提出していただけます。wiseflowはオープンソースプロジェクトであり、皆さんの共同の貢献により「誰でも使える情報収集ツール」を目指しています!
|
||||
|
||||
詳細は[test/README.md](./test/README.md)を参照してください。
|
||||
|
||||
現時点では、**テスト結果の提出はプロジェクトコードの提出と同じ**であり、貢献者として受け入れられ、商業プロジェクトへの招待も期待できます!
|
||||
|
||||
|
||||
🌟**V0.3.x プラン**
|
||||
|
||||
- WeChat公式アカウントのwxbotなしでの購読をサポートする(V0.3.7);
|
||||
- RSS情報源と検索エンジンのサポートを導入する(V0.3.8);
|
||||
- 部分的なソーシャルプラットフォームのサポートを試みる(V0.3.9)。
|
||||
|
||||
これらのバージョンに伴い、deep scraperおよびLLM抽出戦略を継続的に改善します。アプリケーションシナリオや抽出効果が不十分な情報源のURLについて引き続きフィードバックをお寄せください。[issue #136](https://github.com/TeamWiseFlow/wiseflow/issues/136)でフィードバックをお願いします。
|
||||
|
||||
V0.3.5バージョンからwiseflowは全く新しいアーキテクチャを採用し、[Crawlee](https://github.com/apify/crawlee-python)を基本クローラーとタスク管理フレームワークとして導入し、ページ取得能力を大幅に向上させました。今後もwiseflowのページ取得能力を継続的に向上させていきます。うまく取得できないページがありましたら、[issue #136](https://github.com/TeamWiseFlow/wiseflow/issues/136)でフィードバックをお願いします。
|
||||
|
||||
## ✋ wiseflow と従来のクローラーツール、AI検索、知識ベース(RAG)プロジェクトの違いは何ですか?
|
||||
|
||||
@ -45,10 +62,12 @@ wiseflowは2024年6月末にV0.3.0バージョンをリリースして以来、
|
||||
|
||||
| | **首席情報官(Wiseflow)** との比較説明|
|
||||
|-------------|-----------------|
|
||||
| **クローラーツール** | まず、wiseflowはクローラーツールに基づくプロジェクトです(現在のバージョンでは、クローラーフレームワークCrawleeを基にしています)。しかし、従来のクローラーツールは情報抽出において人間の介入が必要で、明確なXpathなどを提供する必要があります……これは一般ユーザーを妨げるだけでなく、汎用性も全くありません。異なるウェブサイト(既存のウェブサイトのアップグレード後を含む)ごとに人間が再分析し、抽出コードを更新する必要があります。wiseflowはLLMを使用してウェブページの分析と抽出を自動化することを目指しており、ユーザーはプログラムに関心事を伝えるだけで済みます。この観点から、wiseflowは「自動的にクローラーツールを使用できるAIエージェント」と簡単に理解できます |
|
||||
| **クローラーツール** | まず、wiseflowはクローラーツールを基にしたプロジェクトですが、従来のクローラーツールは情報抽出において明確なXpathなどの情報を手動で提供する必要があります...これは一般ユーザーを阻むだけでなく、汎用性もありません。異なるウェブサイト(既存のウェブサイトのアップグレード後を含む)に対して、手動で再分析し、プログラムを更新する必要があります。wiseflowはLLMを使用してウェブページの分析と抽出を自動化することに努めており、ユーザーはプログラムに自分の関心点を伝えるだけで済みます。Crawl4aiを例として比較すると、Crawl4aiはLLMを使用して情報抽出を行うクローラーであり、wiseflowはクローラーツールを使用するLLM情報抽出ツールです。 |
|
||||
| **AI検索** | AI検索の主なアプリケーションシナリオは**具体的な問題の即時回答**です。例:「XX社の創設者は誰ですか」、「xxブランドのxx製品はどこで販売されていますか」。ユーザーが求めているのは**一つの答え**です;wiseflowの主なアプリケーションシナリオは**ある方面の情報の継続的な収集**です。例えば、XX社の関連情報の追跡、XXブランドの市場行動の継続的な追跡……これらのシナリオでは、ユーザーは関心事(ある会社、あるブランド)、さらには情報源(サイトURLなど)を提供できますが、具体的な検索問題を提起することはできません。ユーザーが求めているのは**一連の関連情報**です|
|
||||
| **知識ベース(RAG)類プロジェクト** | 知識ベース(RAG)類プロジェクトは通常、既存の情報に基づく下流タスクであり、一般的にプライベート知識(例えば、企業内の操作マニュアル、製品マニュアル、政府部門の文書など)を対象としています;wiseflowは現在、下流タスクを統合しておらず、インターネット上の公開情報を対象としています。「エージェント」の観点から見ると、両者は異なる目的のために構築されたエージェントであり、RAG類プロジェクトは「(内部)知識アシスタントエージェント」であり、wiseflowは「(外部)情報収集エージェント」です|
|
||||
|
||||
**wiseflow 0.4.x バージョンは、ダウンストリームタスクの統合に焦点を当て、LLM 駆動の軽量なナレッジグラフを導入し、ユーザーが infos から洞察を得るのを支援します。**
|
||||
|
||||
## 📥 インストールと使用
|
||||
|
||||
### 1. コードリポジトリのクローン
|
||||
@ -92,7 +111,6 @@ Siliconflowは、主流のオープンソースモデルのほとんどにオン
|
||||
export LLM_API_KEY=Your_API_KEY
|
||||
export LLM_API_BASE="https://api.siliconflow.cn/v1"
|
||||
export PRIMARY_MODEL="Qwen/Qwen2.5-32B-Instruct"
|
||||
export SECONDARY_MODEL="Qwen/Qwen2.5-7B-Instruct"
|
||||
export VL_MODEL="OpenGVLab/InternVL2-26B"
|
||||
```
|
||||
|
||||
@ -108,7 +126,6 @@ AiHubMixモデルを使用する場合、.envの設定は以下を参考にし
|
||||
export LLM_API_KEY=Your_API_KEY
|
||||
export LLM_API_BASE="https://aihubmix.com/v1" # referhttps://doc.aihubmix.com/
|
||||
export PRIMARY_MODEL="gpt-4o"
|
||||
export SECONDARY_MODEL="gpt-4o-mini"
|
||||
export VL_MODEL="gpt-4o"
|
||||
```
|
||||
😄 [AiHubMixの紹介リンク](https://aihubmix.com?aff=Gp54)からご登録いただけますと幸いです 🌹
|
||||
@ -121,7 +138,6 @@ Xinferenceを例にすると、.envの設定は以下を参考にできます:
|
||||
# LLM_API_KEY='' no need for local service, please comment out or delete
|
||||
export LLM_API_BASE='http://127.0.0.1:9997'
|
||||
export PRIMARY_MODEL=launched_model_id
|
||||
export SECONDARY_MODEL=launched_model_id
|
||||
export VL_MODEL=launched_model_id
|
||||
```
|
||||
|
||||
@ -232,12 +248,10 @@ PocketBaseは人気のある軽量データベースで、現在Go/Javascript/Py
|
||||
|
||||
## 🤝 本プロジェクトは以下の優れたオープンソースプロジェクトに基づいています:
|
||||
|
||||
- crawlee-python (A web scraping and browser automation library for Python to build reliable crawlers. Works with BeautifulSoup, Playwright, and raw HTTP. Both headful and headless mode. With proxy rotation.) https://github.com/apify/crawlee-python
|
||||
- json_repair(Repair invalid JSON documents ) https://github.com/josdejong/jsonrepair/tree/main
|
||||
- crawl4ai(Open-source LLM Friendly Web Crawler & Scraper) https://github.com/unclecode/crawl4ai
|
||||
- python-pocketbase (pocketBase client SDK for python) https://github.com/vaphes/pocketbase
|
||||
- SeeAct(a system for generalist web agents that autonomously carry out tasks on any given website, with a focus on large multimodal models (LMMs) such as GPT-4Vision.) https://github.com/OSU-NLP-Group/SeeAct
|
||||
|
||||
また、[GNE](https://github.com/GeneralNewsExtractor/GeneralNewsExtractor)、[AutoCrawler](https://github.com/kingname/AutoCrawler) からもインスピレーションを受けています。
|
||||
また、[GNE](https://github.com/GeneralNewsExtractor/GeneralNewsExtractor)、[AutoCrawler](https://github.com/kingname/AutoCrawler)、[SeeAct](https://github.com/OSU-NLP-Group/SeeAct) からもインスピレーションを受けています。
|
||||
|
||||
## Citation
|
||||
|
||||
|
68
README_KR.md
68
README_KR.md
@ -10,32 +10,49 @@
|
||||
|
||||
https://github.com/user-attachments/assets/fc328977-2366-4271-9909-a89d9e34a07b
|
||||
|
||||
## 🔥 테스트 스크립트 및 테스트 보고서 발표
|
||||
## 🔥 늦었지만 도착했습니다, V0.3.6가 출시되었습니다
|
||||
|
||||
siliconflow에서 제공하는 deepseekV2.5, Qwen2.5-32B-Instruct, Qwen2.5-14B-Instruct, Qwen2.5-coder-7B-Instruct 모델의 성능을 4개의 실제 사례 작업과 총 10개의 실제 웹페이지 샘플에서 수평적으로 테스트하고 비교했습니다.
|
||||
테스트 결과는 [report](./test/reports/wiseflow_report_20241223_bigbrother666/README.md)를 참조하세요.
|
||||
V0.3.6은 V0.3.5의 개선 버전으로, 많은 커뮤니티 피드백을 반영하여 업그레이드를 권장드립니다.
|
||||
|
||||
또한 테스트 스크립트도 오픈소스로 공개했으니, 더 많은 테스트 결과를 적극적으로 제출해 주시기 바랍니다. wiseflow는 오픈소스 프로젝트이며, 모두의 공동 기여를 통해 "누구나 사용할 수 있는 정보 수집 도구"를 만들고자 합니다!
|
||||
- Crawl4ai를 기본 크롤링 프레임워크로 변경하였습니다. 사실 Crawl4ai와 Crawlee는 Playwright 기반이며 얻는 결과가 비슷하지만, Crawl4ai의 html2markdown 기능이 매우 유용하며 이는 llm 정보 추출에 큰 도움이 됩니다. 또한 Crawl4ai의 아키텍처가 저의 생각과 더 잘 맞습니다.
|
||||
- Crawl4ai의 html2markdown 기능을 바탕으로 deep scraper를 추가하여 페이지의 독립 링크와 본문을 구분함으로써 llm의 정확한 추출을 용이하게 하였습니다. html2markdown과 deep scraper가 원본 웹 페이지 데이터를 잘 정리하여 llm이 받는 간섭과 오도를 크게 줄이고 최종 결과의 품질을 보장하며 불필요한 token 소비도 줄였습니다.
|
||||
|
||||
자세한 내용은 [test/README_EN.md](./test/README_EN.md)를 참조하세요.
|
||||
*리스트 페이지와 문서 페이지의 구분은 모든 크롤링 프로젝트에서 어려운 문제입니다. 특히 현대 웹 페이지는 종종 문서 페이지의 사이드바와 하단에 많은 추천 읽기 항목을 추가하여 두 가지가 텍스트 통계적 특징 차이 없이 혼동됩니다.*
|
||||
*이 부분에서는 시각 대형 모델을 사용하여 레이아웃 분석을 고려했으나, 간섭받지 않는 웹 페이지 스크린샷을 얻는 것이 프로그램 복잡성을 크게 증가시키고 처리 효율성을 낮추는 것으로 나타났습니다.*
|
||||
|
||||
현 단계에서는 **테스트 결과 제출이 프로젝트 코드 제출과 동일하게 취급**되며, contributor로 인정받을 수 있고, 심지어 상업화 프로젝트에 초대될 수도 있습니다!
|
||||
- 추출 전략과 llm의 prompt를 재구성하였습니다.
|
||||
|
||||
또한 pocketbase의 다운로드 및 사용자 이름/비밀번호 구성 방안을 개선했으며, @ourines가 기여한 install_pocketbase.sh 스크립트에 감사드립니다.
|
||||
*좋은 prompt는 명확한 작업 지침이며 각 단계가 충분히 명확해야 실수를 하기 어렵습니다. 하지만 너무 복잡한 prompt의 가치는 평가하기 어렵습니다. 더 나은 방법이 있으시다면 PR을 환영합니다.*
|
||||
|
||||
(docker 실행 방안은 일시적으로 제거되었습니다. 사용하기에 그다지 편리하지 않다고 느껴져서...)
|
||||
- 시각 대형 모델을 도입하여 Crawl4ai가 높은 가중치(현재 Crawl4ai가 평가)를 부여한 이미지를 자동으로 인식하고 관련 정보를 페이지 텍스트에 추가합니다.
|
||||
- requirement.txt 의 의존성 항목을 계속 줄였으며, 이제 json_repair가 필요하지 않습니다. (실제로 llm이 JSON 형식으로 생성하는 것은 처리 시간을 증가시키고 실패율을 높이므로 더 간단한 방식을 채택하고 처리 결과 후처리를 강화하였습니다.)
|
||||
- pb info 양식 구조를 약간 조정하여 web_title과 reference 항목을 추가했습니다.
|
||||
- @ourines님이 install_pocketbase.sh 스크립트를 기여하셨습니다. (Docker 실행 방안은 일시적으로 제거되었으며 사용이 편리하지 않아서……)
|
||||
|
||||
🌟 **V0.3.6 버전 예고**
|
||||
**V0.3.6 버전으로 업그레이드하려면 pocketbase 데이터베이스를 다시 구성해야 합니다. pb/pb_data 폴더를 삭제한 후 다시 실행해 주세요.**
|
||||
|
||||
V0.3.6 버전은 2024년 12월 30일 이전에 출시될 예정이며, 이 버전은 v0.3.5의 성능 최적화 버전입니다. 정보 추출 품질이 크게 향상될 것이며, 시각적 대형 모델도 도입하여 웹페이지 정보가 부족할 때 페이지 이미지 정보를 보완 자료로 추출할 예정입니다.
|
||||
**V0.3.6 버전에서는 .env에서 SECONDARY_MODEL을 VL_MODEL로 변경해야 합니다. 최신 [env_sample](./env_sample)을 참고해 주세요.**
|
||||
|
||||
### V0.3.6 테스트 보고서
|
||||
|
||||
**V0.3.x 계획**
|
||||
siliconflow의 deepseekV2.5, Qwen2.5-32B-Instruct, Qwen2.5-14B-Instruct, Qwen2.5-72B-Instruct 모델의 성능을 네 가지 실제 사례 및 여섯 개의 실제 웹 페이지 샘플에서 횡断적으로 테스트하고 비교하였습니다.
|
||||
테스트 결과는 [report](./test/reports/wiseflow_report_v036_bigbrother666/README.md)를 참조해 주세요.
|
||||
|
||||
- 위챗 공중 계정 wxbot 없이 구독 지원 시도 (V0.3.7)
|
||||
- RSS 정보 소스 지원 도입 (V0.3.8)
|
||||
- LLM 기반의 경량 지식 그래프 도입 시도, 사용자가 infos에서 통찰력을 구축하도록 지원 (V0.3.9)
|
||||
또한 테스트 스크립트도 오픈소스로 제공되며 더 많은 테스트 결과를 제출해 주시길 바랍니다. wiseflow는 오픈소스 프로젝트로서 모두의 공헌으로 "누구나 사용할 수 있는 정보 수집 도구"를 만들고자 합니다!
|
||||
|
||||
참고: [test/README.md](./test/README.md)
|
||||
|
||||
현재, **테스트 결과 제출은 프로젝트 코드 제출과 동일하며** 기여자로 인정되며 상업 프로젝트 참여 초청까지 받을 수도 있습니다!
|
||||
|
||||
|
||||
🌟**V0.3.x 계획**
|
||||
|
||||
- WeChat 공개 계정 wxbot 없이 구독 지원 (V0.3.7);
|
||||
- RSS 정보 소스 및 검색 엔진 지원 도입 (V0.3.8);
|
||||
- 일부 사회적 플랫폼 지원 시도 (V0.3.9).
|
||||
|
||||
이 세 가지 버전 동안 deep scraper 및 llm 추출 전략을 지속적으로 개선할 예정입니다. 또한 적용 장면과 추출 효과가 이상적인 정보 원본 주소를 지속적으로 피드백해 주시길 바랍니다. [issue #136](https://github.com/TeamWiseFlow/wiseflow/issues/136)에서 피드백을 남겨주세요.
|
||||
|
||||
V0.3.5 버전부터 wiseflow는 완전히 새로운 아키텍처를 사용하며, [Crawlee](https://github.com/apify/crawlee-python)를 기본 크롤러 및 작업 관리 프레임워크로 도입하여 페이지 획득 능력을 크게 향상시켰습니다. 앞으로도 wiseflow의 페이지 획득 능력을 지속적으로 향상시킬 예정이며, 잘 획득되지 않는 페이지가 있다면 [issue #136](https://github.com/TeamWiseFlow/wiseflow/issues/136)에서 피드백을 주시기 바랍니다.
|
||||
|
||||
## ✋ wiseflow는 전통적인 크롤러 도구, AI 검색, 지식 베이스(RAG) 프로젝트와 어떻게 다를까요?
|
||||
|
||||
@ -43,11 +60,13 @@ wiseflow는 2024년 6월 말 V0.3.0 버전 출시 이후 오픈소스 커뮤니
|
||||
|
||||
그러나 우리는 일부 관심 있는 분들이 wiseflow의 기능 위치에 대해 일부 이해 오류가 있음을 알게 되었습니다. 아래 표는 전통적인 크롤러 도구, AI 검색, 지식 베이스(RAG) 프로젝트와의 비교를 통해 wiseflow 제품의 최신 위치에 대한 우리의 생각을 나타냅니다.
|
||||
|
||||
| | **수석 정보 책임자 (Wiseflow)**와의 비교 설명 |
|
||||
|-------------|-----------------|
|
||||
| **크롤러 도구** | 먼저 wiseflow는 크롤러 도구 기반 프로젝트입니다 (현재 버전 기준으로, 우리는 크롤러 프레임워크 Crawlee를 기반으로 합니다). 그러나 전통적인 크롤러 도구는 정보 추출 측면에서 인간의 개입이 필요하며, 명확한 Xpath 등을 제공해야 합니다. 이는 일반 사용자를 막을 뿐만 아니라 일반성이 전혀 없으며, 다른 웹사이트 (기존 웹사이트 업그레이드 포함)에 대해서는 인간이 다시 분석을 수행하고 추출 코드를 업데이트해야 합니다. wiseflow는 LLM을 사용하여 웹페이지의 자동 분석 및 추출 작업을 추구하며, 사용자는 프로그램에 그의 관심사만 알려주면 됩니다. 이 관점에서 wiseflow를 "자동으로 크롤러 도구를 사용할 수 있는 AI 에이전트"로 간단히 이해할 수 있습니다. |
|
||||
| **AI 검색** | AI 검색의 주요 응용 시나리오는 **구체적인 문제의 즉각적인 질문 및 답변**입니다. 예: "XX 회사의 창립자는 누구인가", "xx 브랜드의 xx 제품은 어디서 구매할 수 있는가". 사용자는 **하나의 답변**을 원합니다. wiseflow의 주요 응용 시나리오는 **특정 측면의 정보 지속적 수집**입니다. 예: XX 회사의 관련 정보 추적, XX 브랜드의 시장 행동 지속 추적 등. 이러한 시나리오에서 사용자는 관심사 (특정 회사, 특정 브랜드) 및 신뢰할 수 있는 소스 (사이트 URL 등)를 제공할 수 있지만, 구체적인 검색 질문을 제시할 수 없습니다. 사용자는 **일련의 관련 정보**를 원합니다. |
|
||||
| **지식 베이스 (RAG) 프로젝트** | 지식 베이스 (RAG) 프로젝트는 일반적으로 기존 정보를 기반으로 한 하류 작업을 기반으로 하며, 일반적으로 개인 지식 (예: 기업 내 운영 매뉴얼, 제품 매뉴얼, 정부 부서의 문서 등)을 대상으로 합니다. wiseflow는 현재 하류 작업을 통합하지 않으며, 인터넷상의 공개 정보를 대상으로 합니다. "에이전트"의 관점에서 볼 때, 둘은 서로 다른 목적으로 구축된 에이전트입니다. RAG 프로젝트는 "내부 지식 보조 에이전트"이며, wiseflow는 "외부 정보 수집 에이전트"입니다. |
|
||||
| | **수석 정보 책임자 (Wiseflow)**와의 비교 설명 |
|
||||
|-------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| **크롤러 도구** | 먼저, wiseflow는 크롤러 도구를 기반으로 한 프로젝트이지만, 전통적인 크롤러 도구는 정보 추출을 위해 명시적인 Xpath 등의 정보를 수동으로 제공해야 합니다... 이는 일반 사용자를 막을 뿐만 아니라 범용성도 없습니다. 다양한 웹사이트(기존 웹사이트 업그레이드 후 포함)에 대해 수동으로 재분석하고 프로그램을 업데이트해야 합니다. wiseflow는 LLM을 사용하여 웹 페이지의 분석과 추출을 자동화하는 데 주력하고 있으며, 사용자는 프로그램에 자신의 관심사를 알리기만 하면 됩니다. Crawl4ai를 예로 들어 비교하자면, Crawl4ai는 LLM을 사용하여 정보를 추출하는 크롤러이고, wiseflow는 크롤러 도구를 사용하는 LLM 정보 추출기입니다. |
|
||||
| **AI 검색** | AI 검색의 주요 응용 시나리오는 **구체적인 문제의 즉각적인 질문 및 답변**입니다. 예: "XX 회사의 창립자는 누구인가", "xx 브랜드의 xx 제품은 어디서 구매할 수 있는가". 사용자는 **하나의 답변**을 원합니다. wiseflow의 주요 응용 시나리오는 **특정 측면의 정보 지속적 수집**입니다. 예: XX 회사의 관련 정보 추적, XX 브랜드의 시장 행동 지속 추적 등. 이러한 시나리오에서 사용자는 관심사 (특정 회사, 특정 브랜드) 및 신뢰할 수 있는 소스 (사이트 URL 등)를 제공할 수 있지만, 구체적인 검색 질문을 제시할 수 없습니다. 사용자는 **일련의 관련 정보**를 원합니다. |
|
||||
| **지식 베이스 (RAG) 프로젝트** | 지식 베이스 (RAG) 프로젝트는 일반적으로 기존 정보를 기반으로 한 하류 작업을 기반으로 하며, 일반적으로 개인 지식 (예: 기업 내 운영 매뉴얼, 제품 매뉴얼, 정부 부서의 문서 등)을 대상으로 합니다. wiseflow는 현재 하류 작업을 통합하지 않으며, 인터넷상의 공개 정보를 대상으로 합니다. "에이전트"의 관점에서 볼 때, 둘은 서로 다른 목적으로 구축된 에이전트입니다. RAG 프로젝트는 "내부 지식 보조 에이전트"이며, wiseflow는 "외부 정보 수집 에이전트"입니다. |
|
||||
|
||||
**wiseflow 0.4.x 버전은 다운스트림 작업의 통합에 초점을 맞추고, LLM 기반의 경량 지식 그래프를 도입하여 사용자가 infos에서 통찰력을 얻을 수 있도록 돕습니다.**
|
||||
|
||||
## 📥 설치 및 사용
|
||||
|
||||
@ -92,7 +111,6 @@ Siliconflow는 대부분의 주류 오픈소스 모델에 대한 온라인 MaaS
|
||||
export LLM_API_KEY=Your_API_KEY
|
||||
export LLM_API_BASE="https://api.siliconflow.cn/v1"
|
||||
export PRIMARY_MODEL="Qwen/Qwen2.5-32B-Instruct"
|
||||
export SECONDARY_MODEL="Qwen/Qwen2.5-7B-Instruct"
|
||||
export VL_MODEL="OpenGVLab/InternVL2-26B"
|
||||
```
|
||||
|
||||
@ -108,7 +126,6 @@ AiHubMix 모델을 사용할 때 .env 구성은 다음을 참조할 수 있습
|
||||
export LLM_API_KEY=Your_API_KEY
|
||||
export LLM_API_BASE="https://aihubmix.com/v1" # refer https://doc.aihubmix.com/
|
||||
export PRIMARY_MODEL="gpt-4o"
|
||||
export SECONDARY_MODEL="gpt-4o-mini"
|
||||
export VL_MODEL="gpt-4o"
|
||||
```
|
||||
|
||||
@ -122,7 +139,6 @@ Xinference를 예로 들면, .env 구성은 다음을 참조할 수 있습니다
|
||||
# LLM_API_KEY='' no need for local service, please comment out or delete
|
||||
export LLM_API_BASE='http://127.0.0.1:9997'
|
||||
export PRIMARY_MODEL=launched_model_id
|
||||
export SECONDARY_MODEL=launched_model_id
|
||||
export VL_MODEL=launched_model_id
|
||||
```
|
||||
|
||||
@ -229,12 +245,10 @@ PocketBase는 인기 있는 경량 데이터베이스로, 현재 Go/Javascript/P
|
||||
|
||||
## 🤝 이 프로젝트는 다음과 같은 우수한 오픈소스 프로젝트를 기반으로 합니다:
|
||||
|
||||
- crawlee-python (Python용 웹 스크래핑 및 브라우저 자동화 라이브러리로, 신뢰할 수 있는 크롤러를 구축합니다. BeautifulSoup, Playwright 및 원시 HTTP와 함께 작동합니다. headful 및 headless 모드 모두 지원. 프록시 회전 기능 포함.) https://github.com/apify/crawlee-python
|
||||
- json_repair (유효하지 않은 JSON 문서 복구) https://github.com/josdejong/jsonrepair/tree/main
|
||||
- crawl4ai(Open-source LLM Friendly Web Crawler & Scraper) https://github.com/unclecode/crawl4ai
|
||||
- python-pocketbase (pocketBase 클라이언트 SDK for python) https://github.com/vaphes/pocketbase
|
||||
- SeeAct (모든 주어진 웹사이트에서 자율적으로 작업을 수행하는 일반 웹 에이전트 시스템, 특히 GPT-4Vision과 같은 대형 멀티모달 모델 (LMMs)에 중점을 둡니다.) https://github.com/OSU-NLP-Group/SeeAct
|
||||
|
||||
또한 [GNE](https://github.com/GeneralNewsExtractor/GeneralNewsExtractor), [AutoCrawler](https://github.com/kingname/AutoCrawler)에서 영감을 받았습니다.
|
||||
또한 [GNE](https://github.com/GeneralNewsExtractor/GeneralNewsExtractor), [AutoCrawler](https://github.com/kingname/AutoCrawler), [SeeAct](https://github.com/OSU-NLP-Group/SeeAct) 에서 영감을 받았습니다.
|
||||
|
||||
## Citation
|
||||
|
||||
|
@ -1,23 +1,21 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from loguru import logger
|
||||
import os, re, sys
|
||||
|
||||
current_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
project_root = os.path.dirname(current_dir) # get parent dir
|
||||
sys.path.append(project_root)
|
||||
|
||||
from core.utils.pb_api import PbTalker
|
||||
from core.llms.openai_wrapper import openai_llm as llm
|
||||
import os, re
|
||||
from utils.pb_api import PbTalker
|
||||
from llms.openai_wrapper import openai_llm as llm
|
||||
# from core.llms.siliconflow_wrapper import sfa_llm # or other llm wrapper
|
||||
from core.utils.general_utils import is_chinese, extract_and_convert_dates
|
||||
from utils.general_utils import is_chinese, extract_and_convert_dates
|
||||
|
||||
|
||||
async def get_author_and_publish_date(text: str, model: str) -> tuple[str, str]:
|
||||
if not text:
|
||||
return "", ""
|
||||
|
||||
if len(text) > 1024:
|
||||
text = f'{text[:999]}......'
|
||||
if len(text) > 100:
|
||||
text = text[20:]
|
||||
|
||||
if len(text) > 2048:
|
||||
text = f'{text[:2048]}......'
|
||||
|
||||
system_prompt = "As an information extraction assistant, your task is to accurately extract the source (or author) and publication date from the given webpage text. It is important to adhere to extracting the information directly from the original text. If the original text does not contain a particular piece of information, please replace it with NA"
|
||||
suffix = '''Please output the extracted information in the following format(output only the result, no other content):
|
||||
@ -248,7 +246,7 @@ When performing the association analysis, please follow these principles:
|
||||
url_tags = re.findall(r'\[(Ref_\d+)]', content)
|
||||
refences = {url_tag: text_links[url_tag] for url_tag in url_tags if url_tag in text_links}
|
||||
|
||||
final.append({'tag': self.focus_dict[item['focus']], 'content': f"{info_pre_fix}{content}", 'references': refences})
|
||||
final.append({'tag': self.focus_dict[focus], 'content': f"{info_pre_fix}{content}", 'references': refences})
|
||||
|
||||
return final
|
||||
|
||||
|
@ -1,93 +1,3 @@
|
||||
# wiseflow 自定义解析器说明
|
||||
|
||||
## 概述
|
||||
|
||||
scraper 在 wiseflow 产品语境中指从已渲染的html提取出便于大模型“阅读和理解”的部分的过程。虽然wiseflow的产品逻辑是“爬查一体”,即致力于用大模型的理解和分析能力直接从html编码中提取出用户需要的信息,但实际操作中,我们发现:
|
||||
|
||||
- 直接把 html 编码送给大模型,哪怕是已经去除了不必要的标签,依然会带有大量的干扰信息,比如:列表页面中的summary容易被 llm 提取为 info,这样后续再进入详情页面,就可能造成重复提取;再比如文章页面中的链接 list,也很容易被 llm 提取为 info。而判定一个页面是列表页面还是文章页面,这非常困难,且很多新闻类网站喜欢一半是文章正文一半是“阅读更多”的列表页面这样的布局,这种情况下无论是舍弃正文还是舍弃列表,都是比较粗糙的方案;
|
||||
|
||||
- 对于使用视觉大模型进行布局分析,虽然理论上可以解决上述问题,但实际操作中,获取无干扰的网页截图并不容易,需要考虑各种情况,比如 cookie 警告等(很多 cookie 警告并不是简单的弹窗)、窗口大小设定以及因此带来的可能的多轮处理等;
|
||||
|
||||
另外,在送入大模型之前,先进行一道“提纯”处理还能够带来处理速度以及 token 消耗费用上的好处。因此 scraper 是十分有必要的。
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
它的输入是 已渲染的 html 编码(配合网站的 base_url),输出是三个值:
|
||||
|
||||
- `action_dict`:页面中可执行的元素项目,类型为 `dict`,格式如下:
|
||||
|
||||
```python
|
||||
{
|
||||
'item_name': {"type": 交互类型, "values": ["value1", "value2"]}
|
||||
}
|
||||
```
|
||||
|
||||
这个内容供 llm 判断是否需要采取行动以及采取什么行动,从而可以进一步获得需要的信息。
|
||||
|
||||
- `link_dict`:页面中所有链接的字典,类型为 `dict`,格式如下:
|
||||
|
||||
```python
|
||||
{
|
||||
'link_key': "link_url"
|
||||
}
|
||||
```
|
||||
|
||||
其中 key 是页面链接的唯一编号,general_scraper 中使用顺序编号生成,比如 url1, url2, url3 等。
|
||||
|
||||
这个内容供 llm 从中提取可能包含用户关注点信息的链接,被提取的链接会被加入爬虫获取队列。
|
||||
|
||||
- `text`:页面中所有文字的拼接,类型为 `str`
|
||||
|
||||
llm 从中提取用户关注点信息。
|
||||
|
||||
|
||||
*有关这个机制其实我做过很多实验,包括让 llm 直接分析 html 编码(去除不必要标签或者分段),以及使用视觉大模型结合网页截图进行分析,最终发现综合考虑实现复杂度、抗干扰和异常能力、时间成本以及效果,目前方案是最优的。其中视觉大模型方案虽然我一直很期待,但实践中发现获取无干扰的网页截图并不容易,需要考虑各种情况,比如 cookie 警告等(很多 cookie 警告并不是简单的弹窗)、窗口大小设定以及因此带来的可能的多轮处理等……最关键的是,最终我发现如果网页文本处理得当,纯文本分析的效果是优于视觉大模型的……当然这里面的关键就是对 html 的处理,你不能指望把整个 html直接喂给 llm,那自然得不到好的结果,甚至粗糙的提取全部的文本和链接送给 llm 也很难得到好的结果,并且这样还会很烦 token,且拉长单次处理时间……*
|
||||
|
||||
wiseflow 目前搭配的 general_scraper 包括了对诸多常见 html 元素的处理,包括表格、列表、图片、视频、音频、表单、按钮、链接、文本等, 它能将这些元素统一转为适合 llm “阅读和理解”的文本,尤其是对于链接的处理,general_scraper 将链接替换为带编号的tag,而不是直接在文字中混入 url,一方面避免了对 llm 的干扰,同时也降低了token 的消耗,并且保证了 url 的准确。
|
||||
|
||||
general_scraper 目前被测试适合绝大部分常见的页面,并且通过分析得到的 link_dict 和 text 比例特征,很容易判断出页面是列表页面还是文章页面。
|
||||
|
||||
不过如果对于特定站点需要使用特殊的提取逻辑,您可以参考 general_scraper 配置自定义解析器。
|
||||
|
||||
## 自定义解析器的开发:
|
||||
|
||||
自定义解析器需要满足如下规格,否则无法被主流程整合:
|
||||
|
||||
- Scraper 应该是一个函数(而不是类)。
|
||||
|
||||
- 入参:
|
||||
- `html`:渲染后的页面 html 编码,类型为 `str`,scraper 可以直接使用 `bs` `parsel`等库进行解析;
|
||||
- ` base_url`:当前页面的 base url 地址,类型为 `str`(仅是为了特殊操作,用不到的话可以直接忽略)。
|
||||
|
||||
*目前 wiseflow 仅支持使用内置的爬虫(Crawlee['playwright_crawler'])进行页面获取,因此入参都是由主流程传递给 scraper 的。*
|
||||
|
||||
- 出参:
|
||||
|
||||
- `action_dict`:页面中可执行的元素项目,类型为 `dict`,格式如下:
|
||||
|
||||
```python
|
||||
{
|
||||
'item_name': {"type": 交互类型, "values": ["value1", "value2"]}
|
||||
}
|
||||
```
|
||||
|
||||
这个内容供 llm 判断是否需要采取行动以及采取什么行动,从而可以进一步获得需要的信息。
|
||||
|
||||
- `link_dict`:页面中所有链接的字典,类型为 `dict`,格式如下:
|
||||
|
||||
```python
|
||||
{
|
||||
'link_key': "link_url"
|
||||
}
|
||||
```
|
||||
|
||||
- `text`:页面中所有文字的拼接,类型为 `str`
|
||||
|
||||
llm 从中提取用户关注点信息。
|
||||
|
||||
## 自定义解析器的注册
|
||||
|
||||
在 `core/scrapers/__init__.py` 中注册,参考:
|
||||
|
@ -1,81 +1,3 @@
|
||||
# Wiseflow Custom Scraper Documentation
|
||||
|
||||
## Overview
|
||||
|
||||
wiseflow aims to automate web crawling and information extraction processes using large language models' understanding and analysis capabilities, known as the "integrated crawling and analysis" architecture. Therefore, the scraper in wiseflow's product context differs slightly from traditional positioning - here it only refers to the data preprocessing that converts rendered HTML from web crawlers into a format suitable for large models to "read and understand".
|
||||
|
||||
Its input is rendered HTML code (along with the website's base_url), and it outputs three values:
|
||||
|
||||
- `action_dict`: Executable elements on the page, type `dict`, formatted as follows:
|
||||
|
||||
```python
|
||||
{
|
||||
'item_name': {"type": interaction type, "values": ["value1", "value2"]}
|
||||
}
|
||||
```
|
||||
|
||||
This content allows the LLM to determine whether actions need to be taken and what actions to take, in order to obtain further required information.
|
||||
|
||||
- `link_dict`: Dictionary of all links on the page, type `dict`, formatted as follows:
|
||||
|
||||
```python
|
||||
{
|
||||
'link_key': "link_url"
|
||||
}
|
||||
```
|
||||
|
||||
where the key is a unique identifier for the page link. In general_scraper, sequential numbering is used to generate these, such as url1, url2, url3, etc.
|
||||
|
||||
This content allows the LLM to extract links that may contain information relevant to user interests. The extracted links are added to the crawler's queue.
|
||||
|
||||
- `text`: Concatenation of all text on the page, type `str`
|
||||
|
||||
The LLM extracts user-relevant information from this.
|
||||
|
||||
*I've actually done many experiments with this mechanism, including having the LLM directly analyze HTML code (removing unnecessary tags or segmenting), and using visual large models combined with webpage screenshots for analysis. After considering implementation complexity, interference and exception handling capabilities, time cost, and effectiveness, the current approach proved optimal. While I've always been excited about the visual large model approach, in practice I found that obtaining interference-free webpage screenshots isn't easy - you need to consider various scenarios like cookie warnings (many of which aren't simple popups), window size settings, and the resulting potential multi-round processing... Most crucially, I discovered that with proper webpage text processing, pure text analysis performs better than visual large models... Of course, the key here is HTML processing - you can't expect good results from feeding entire HTML directly to the LLM, and even rough extraction of all text and links sent to the LLM rarely yields good results, while also consuming more tokens and extending processing time...*
|
||||
|
||||
The general_scraper currently used by wiseflow includes processing for many common HTML elements, including tables, lists, images, videos, audio, forms, buttons, links, text, etc. It can convert these elements uniformly into text suitable for LLM "reading and understanding". Particularly for link processing, general_scraper replaces links with numbered tags rather than mixing URLs directly into the text, which both avoids interference with the LLM and reduces token consumption while ensuring URL accuracy.
|
||||
|
||||
general_scraper has been tested and found suitable for most common pages, and through analysis of the link_dict and text proportion characteristics, it's easy to determine whether a page is a list page or an article page.
|
||||
|
||||
However, if special extraction logic is needed for specific sites, you can refer to general_scraper to configure custom scraper.
|
||||
|
||||
## Custom Scraper Development:
|
||||
|
||||
Custom scraper must meet the following specifications to be integrated into the main process:
|
||||
|
||||
- The Scraper should be a function (not a class).
|
||||
|
||||
- Input parameters:
|
||||
- `html`: Rendered page HTML code, type `str`. The scraper can directly use libraries like `bs` or `parsel` for parsing;
|
||||
- `base_url`: The current page's base URL address, type `str` (only for special operations, can be ignored if not needed).
|
||||
|
||||
*Currently wiseflow only supports using the built-in crawler (Crawlee['playwright_crawler']) for page retrieval, so input parameters are all passed to the scraper by the main process.*
|
||||
|
||||
- Output parameters:
|
||||
|
||||
- `action_dict`: Executable elements on the page, type `dict`, formatted as follows:
|
||||
|
||||
```python
|
||||
{
|
||||
'item_name': {"type": interaction type, "values": ["value1", "value2"]}
|
||||
}
|
||||
```
|
||||
|
||||
This content allows the LLM to determine whether actions need to be taken and what actions to take, in order to obtain further required information.
|
||||
|
||||
- `link_dict`: Dictionary of all links on the page, type `dict`, formatted as follows:
|
||||
|
||||
```python
|
||||
{
|
||||
'link_key': "link_url"
|
||||
}
|
||||
```
|
||||
|
||||
- `text`: Concatenation of all text on the page, type `str`
|
||||
|
||||
The LLM extracts user-relevant information from this.
|
||||
|
||||
## Custom Scraper Registration
|
||||
|
||||
Register in `core/scrapers/__init__.py`, for example:
|
||||
|
@ -3,12 +3,11 @@ from utils.pb_api import PbTalker
|
||||
from utils.general_utils import get_logger, extract_and_convert_dates
|
||||
from utils.deep_scraper import *
|
||||
from agents.get_info import *
|
||||
import os
|
||||
import json
|
||||
import asyncio
|
||||
from custom_fetchings import *
|
||||
from urllib.parse import urlparse
|
||||
from crawl4ai import AsyncWebCrawler, CacheMode, CrawlerRunConfig
|
||||
from crawl4ai import AsyncWebCrawler, CacheMode
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
|
||||
@ -43,18 +42,11 @@ async def save_to_pb(url: str, url_title: str, infos: list):
|
||||
with open(os.path.join(project_dir, f'{timestamp}_cache_infos.json'), 'w', encoding='utf-8') as f:
|
||||
json.dump(info, f, ensure_ascii=False, indent=4)
|
||||
|
||||
default_crawler_config = CrawlerRunConfig(
|
||||
delay_before_return_html=2.0,
|
||||
exclude_social_media_links=True,
|
||||
magic=True,
|
||||
scan_full_page=True,
|
||||
remove_overlay_elements=True
|
||||
)
|
||||
|
||||
async def main_process(sites: set):
|
||||
async def main_process(_sites: set | list):
|
||||
working_list = set()
|
||||
working_list.update(sites)
|
||||
async with AsyncWebCrawler(headless=True, verbose=True) as crawler:
|
||||
working_list.update(_sites)
|
||||
async with AsyncWebCrawler(headless=True, verbose=False) as crawler:
|
||||
while working_list:
|
||||
url = working_list.pop()
|
||||
existing_urls.add(url)
|
||||
@ -64,47 +56,46 @@ async def main_process(sites: set):
|
||||
continue
|
||||
|
||||
parsed_url = urlparse(url)
|
||||
existing_urls.add(f"{parsed_url.scheme}://{parsed_url.netloc}")
|
||||
existing_urls.add(f"{parsed_url.scheme}://{parsed_url.netloc}/")
|
||||
domain = parsed_url.netloc
|
||||
if domain in custom_scrapers:
|
||||
wiseflow_logger.debug(f'{url} is a custom scraper, use custom scraper')
|
||||
raw_markdown, metadata_dict, media_dict = custom_scrapers[domain](url)
|
||||
else:
|
||||
run_config = crawl4ai_custom_configs[domain] if domain in crawl4ai_custom_configs else default_crawler_config
|
||||
crawl4ai_cache_mode = CacheMode.WRITE_ONLY if url in sites else CacheMode.ENABLED
|
||||
result = await crawler.arun(url=url, crawler_config=run_config, cache_mode=crawl4ai_cache_mode)
|
||||
raw_markdown = result.markdown_v2.raw_markdown
|
||||
metadata_dict = result.metadata
|
||||
media_dict = result.media
|
||||
crawl4ai_cache_mode = CacheMode.WRITE_ONLY if url in _sites else CacheMode.ENABLED
|
||||
result = await crawler.arun(url=url, delay_before_return_html=2.0, exclude_social_media_links=True,
|
||||
magic=True, scan_full_page=True, remove_overlay_elements=True,
|
||||
cache_mode=crawl4ai_cache_mode)
|
||||
if not result.success:
|
||||
wiseflow_logger.warning(f'{url} failed to crawl, destination web cannot reach, skip')
|
||||
continue
|
||||
|
||||
raw_markdown = result.markdown
|
||||
if not raw_markdown:
|
||||
wiseflow_logger.warning(f'{url} no content, something during fetching failed, skip')
|
||||
continue
|
||||
metadata_dict = result.metadata if result.metadata else {}
|
||||
media_dict = result.media if result.media else {}
|
||||
|
||||
web_title = metadata_dict.get('title', '')
|
||||
base_url = metadata_dict.get('base_url', '')
|
||||
base_url = metadata_dict.get('base', '')
|
||||
if not base_url:
|
||||
base_url = f"{parsed_url.scheme}://{parsed_url.netloc}{parsed_url.path}"
|
||||
if not base_url.endswith('/'):
|
||||
base_url = base_url.rsplit('/', 1)[0] + '/'
|
||||
|
||||
existing_urls.add(base_url)
|
||||
base_url = url
|
||||
|
||||
author = metadata_dict.get('author', '')
|
||||
publish_date = extract_and_convert_dates(metadata_dict.get('publish_date', ''))
|
||||
if not author or author.lower() == 'na' or not publish_date or publish_date.lower() == 'na':
|
||||
author, publish_date = await get_author_and_publish_date(raw_markdown, llm_model)
|
||||
wiseflow_logger.debug(f'get author and publish date by llm: {author}, {publish_date}')
|
||||
|
||||
if not author or author.lower() == 'na':
|
||||
author = parsed_url.netloc
|
||||
|
||||
if not publish_date:
|
||||
publish_date = datetime.now().strftime('%Y-%m-%d')
|
||||
|
||||
img_dict = media_dict.get('images', [])
|
||||
if not img_dict or not isinstance(img_dict, list):
|
||||
used_img = {}
|
||||
used_img = []
|
||||
else:
|
||||
used_img = {d['src']: d['alt'] for d in img_dict}
|
||||
used_img = [d['src'] for d in img_dict]
|
||||
|
||||
link_dict, (text, reference_map) = deep_scraper(raw_markdown, base_url, used_img)
|
||||
wiseflow_logger.debug(f'deep scraper get {len(link_dict)} links, {len(reference_map)} references for text')
|
||||
_duplicate_url = set(link_dict.keys()) & existing_urls
|
||||
for _d in _duplicate_url:
|
||||
del link_dict[_d]
|
||||
|
||||
to_be_replaces = {}
|
||||
for u, des in link_dict.items():
|
||||
@ -133,14 +124,22 @@ async def main_process(sites: set):
|
||||
to_be_replaces[img_url] = ["content"]
|
||||
wiseflow_logger.debug(f'total {len(to_be_replaces)} images to be recognized')
|
||||
recognized_result = await extract_info_from_img(list(to_be_replaces.keys()), vl_model)
|
||||
recognized_img_cache.update(recognized_result)
|
||||
recognized_img_cache.update({key: value for key, value in recognized_result.items() if value.strip()})
|
||||
for img_url, content in recognized_result.items():
|
||||
for u in to_be_replaces[img_url]:
|
||||
if u == "content":
|
||||
text = text.replace(img_url, content)
|
||||
else:
|
||||
link_dict[u] = link_dict[u].replace(img_url, content)
|
||||
|
||||
|
||||
if not author or author.lower() == 'na' or not publish_date or publish_date.lower() == 'na':
|
||||
author, publish_date = await get_author_and_publish_date(text, llm_model)
|
||||
wiseflow_logger.debug(f'get author and publish date by llm: {author}, {publish_date}')
|
||||
if not author or author.lower() == 'na':
|
||||
author = parsed_url.netloc
|
||||
if not publish_date:
|
||||
publish_date = datetime.now().strftime('%Y-%m-%d')
|
||||
|
||||
more_urls, infos = await gie(link_dict, text, reference_map, author, publish_date)
|
||||
wiseflow_logger.debug(f'get {len(more_urls)} more urls and {len(infos)} infos')
|
||||
if more_urls:
|
||||
@ -152,4 +151,4 @@ async def main_process(sites: set):
|
||||
if __name__ == '__main__':
|
||||
sites = pb.read('sites', filter='activated=True')
|
||||
wiseflow_logger.info('execute all sites one time')
|
||||
asyncio.run(main_process(set([site['url'] for site in sites])))
|
||||
asyncio.run(main_process([site['url'] for site in sites]))
|
||||
|
@ -45,11 +45,6 @@ def normalize_url(url: str, base_url: str) -> str:
|
||||
_url = f"https:{url}"
|
||||
elif url.startswith(('http:/', 'https:/')):
|
||||
_url = url
|
||||
elif url.startswith('/'):
|
||||
if base_url.endswith('/'):
|
||||
_url = base_url[:-1] + url
|
||||
else:
|
||||
_url = base_url + url
|
||||
else:
|
||||
_url = urljoin(base_url, url)
|
||||
# 处理url中path部分的多余斜杠
|
||||
@ -65,7 +60,7 @@ def normalize_url(url: str, base_url: str) -> str:
|
||||
_url = f"{_url}#{parsed.fragment}"
|
||||
return _url
|
||||
|
||||
def deep_scraper(raw_markdown: str, base_url: str, used_img: dict[str, str]) -> tuple[dict, tuple[str, dict]]:
|
||||
def deep_scraper(raw_markdown: str, base_url: str, used_img: list[str]) -> tuple[dict, tuple[str, dict]]:
|
||||
link_dict = {}
|
||||
def check_url_text(text):
|
||||
text = text.strip()
|
||||
@ -147,8 +142,8 @@ def deep_scraper(raw_markdown: str, base_url: str, used_img: dict[str, str]) ->
|
||||
link_text = f"{link_text} {text}"
|
||||
|
||||
# 去除首尾的common_chars和数字
|
||||
link_text = link_text.strip(''.join(common_chars + '0123456789'))
|
||||
if len(link_text) >= 3:
|
||||
link_text = link_text.strip()
|
||||
if link_text:
|
||||
if url not in link_dict:
|
||||
link_dict[url] = link_text
|
||||
else:
|
||||
@ -190,19 +185,17 @@ def deep_scraper(raw_markdown: str, base_url: str, used_img: dict[str, str]) ->
|
||||
html_text = '\n\n'.join(texts)
|
||||
|
||||
# 处理图片标记 ![alt](src)
|
||||
img_pattern = r'(!\[.*?\]\(.*?\))'
|
||||
img_pattern = r'!\[(.*?)\]\((.*?)\)'
|
||||
matches = re.findall(img_pattern, html_text)
|
||||
text_link_map = {}
|
||||
for match in matches:
|
||||
src = re.search(r'!\[.*?]\((.*?)\)', match).group(1)
|
||||
for alt, src in matches:
|
||||
if src not in used_img:
|
||||
html_text = html_text.replace(match, '')
|
||||
html_text = html_text.replace(f'![{alt}]({src})', '')
|
||||
continue
|
||||
|
||||
alt = used_img[src]
|
||||
src = src.strip().lower()
|
||||
if not src or src.startswith('#'):
|
||||
html_text = html_text.replace(match, alt)
|
||||
html_text = html_text.replace(f'![{alt}]({src})', alt)
|
||||
continue
|
||||
|
||||
key = f"Ref_{len(text_link_map)+1}"
|
||||
@ -210,16 +203,16 @@ def deep_scraper(raw_markdown: str, base_url: str, used_img: dict[str, str]) ->
|
||||
src = normalize_url(src, base_url)
|
||||
|
||||
if not src:
|
||||
html_text = html_text.replace(match, f"{alt}[{key}]")
|
||||
html_text = html_text.replace(f'![{alt}]({src})', f"{alt}[{key}]")
|
||||
continue
|
||||
|
||||
if any(src.endswith(tld) or src.endswith(tld + '/') for tld in common_tlds):
|
||||
html_text = html_text.replace(match, f"{alt}[{key}]")
|
||||
html_text = html_text.replace(f'![{alt}]({src})', f"{alt}[{key}]")
|
||||
continue
|
||||
if any(src.endswith(ext) for ext in common_file_exts if ext not in ['jpg', 'jpeg', 'png']):
|
||||
html_text = html_text.replace(match, f"{alt}[{key}]")
|
||||
html_text = html_text.replace(f'![{alt}]({src})', f"{alt}[{key}]")
|
||||
continue
|
||||
html_text = html_text.replace(match, f" {alt}[{key}]§to_be_recognized_by_visual_llm_{src[1:]}§") # to avoid conflict with the url pattern
|
||||
html_text = html_text.replace(f'![{alt}]({src})', f" {alt}[{key}]§to_be_recognized_by_visual_llm_{src[1:]}§") # to avoid conflict with the url pattern
|
||||
|
||||
# 接下来要处理所有的[]()文本了
|
||||
link_pattern = r'\[(.*?)\]\((.*?)\)'
|
||||
|
25
pb/pb_migrations/1735986415_updated_infos.js
Normal file
25
pb/pb_migrations/1735986415_updated_infos.js
Normal file
@ -0,0 +1,25 @@
|
||||
/// <reference path="../pb_data/types.d.ts" />
|
||||
migrate((app) => {
|
||||
const collection = app.findCollectionByNameOrId("pbc_629947526")
|
||||
|
||||
// add field
|
||||
collection.fields.addAt(7, new Field({
|
||||
"hidden": false,
|
||||
"id": "json2669555100",
|
||||
"maxSize": 0,
|
||||
"name": "references",
|
||||
"presentable": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "json"
|
||||
}))
|
||||
|
||||
return app.save(collection)
|
||||
}, (app) => {
|
||||
const collection = app.findCollectionByNameOrId("pbc_629947526")
|
||||
|
||||
// remove field
|
||||
collection.fields.removeById("json2669555100")
|
||||
|
||||
return app.save(collection)
|
||||
})
|
@ -4,14 +4,26 @@
|
||||
|
||||
[craw4ai_fetching.py](./craw4ai_fetching.py)
|
||||
|
||||
```
|
||||
python craw4ai_fetching.py -S 'url1,url2...'
|
||||
```
|
||||
|
||||
## html 内容解析
|
||||
|
||||
[deep_scraper_test.py](./deep_scraper_test.py)
|
||||
|
||||
```
|
||||
python deep_scraper_test.py -F 'json_file_path'
|
||||
```
|
||||
|
||||
## 视觉大模型信息提取
|
||||
|
||||
[get_visual_info_for_samples.py](./get_visual_info_for_samples.py)
|
||||
|
||||
```
|
||||
python get_visual_info_for_samples.py -F 'json_file_path'
|
||||
```
|
||||
|
||||
## 大模型信息提取测试
|
||||
|
||||
[get_info_test.py](./get_info_test.py)
|
||||
@ -20,6 +32,10 @@
|
||||
|
||||
- 要更改 get_info 的 prompt,请编辑 [prompts.py](./prompts.py)
|
||||
|
||||
```
|
||||
python get_info_test.py -D 'sample dir'
|
||||
```
|
||||
|
||||
# 结果提交与共享
|
||||
|
||||
wiseflow 是一个开源项目,希望通过大家共同的贡献,打造“人人可用的信息爬取工具”!
|
||||
|
@ -4,14 +4,26 @@
|
||||
|
||||
[craw4ai_fetching.py](./craw4ai_fetching.py)
|
||||
|
||||
```
|
||||
python craw4ai_fetching.py -S 'url1,url2...'
|
||||
```
|
||||
|
||||
## HTML Content Parsing
|
||||
|
||||
[deep_scraper_test.py](./deep_scraper_test.py)
|
||||
|
||||
```
|
||||
python deep_scraper_test.py -F 'json_file_path'
|
||||
```
|
||||
|
||||
## Visual Large Model Information Extraction
|
||||
|
||||
[get_visual_info_for_samples.py](./get_visual_info_for_samples.py)
|
||||
|
||||
```
|
||||
python get_visual_info_for_samples.py -F 'json_file_path'
|
||||
```
|
||||
|
||||
## Large Model Information Extraction Testing
|
||||
|
||||
[get_info_test.py](./get_info_test.py)
|
||||
@ -20,6 +32,10 @@
|
||||
|
||||
- To modify the prompt for get_info, edit [prompts.py](./prompts.py)
|
||||
|
||||
```
|
||||
python get_info_test.py -D 'sample dir'
|
||||
```
|
||||
|
||||
# Result Submission and Sharing
|
||||
|
||||
Wiseflow is an open source project aiming to create an "information crawling tool for everyone" through collective contributions!
|
||||
|
@ -1,31 +1,20 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import asyncio
|
||||
from crawl4ai import AsyncWebCrawler, CacheMode, CrawlerRunConfig
|
||||
from crawl4ai import AsyncWebCrawler, CacheMode
|
||||
import os
|
||||
import hashlib
|
||||
import json
|
||||
|
||||
|
||||
sites = [
|
||||
"https://www.lejucaijing.com/news-7280844510992200941.html"
|
||||
]
|
||||
|
||||
save_dir = 'webpage_samples'
|
||||
|
||||
async def main(sites: list):
|
||||
config = CrawlerRunConfig(
|
||||
delay_before_return_html=2.0,
|
||||
exclude_social_media_links=True,
|
||||
magic=True,
|
||||
scan_full_page=True,
|
||||
remove_overlay_elements=True
|
||||
)
|
||||
async with AsyncWebCrawler(headless=True, verbose=True) as crawler:
|
||||
for site in sites:
|
||||
# 排除社交媒体 todo 后续要用特定爬虫
|
||||
# 排除自动爬虫
|
||||
# 排除已经爬过的
|
||||
result = await crawler.arun(url=site, crawler_config=config, cache_mode=CacheMode.BYPASS)
|
||||
result = await crawler.arun(url=site, delay_before_return_html=2.0, exclude_social_media_links=True,
|
||||
magic=True,
|
||||
scan_full_page=True,
|
||||
remove_overlay_elements=True, cache_mode=CacheMode.BYPASS)
|
||||
|
||||
record_file = os.path.join(save_dir, f"{hashlib.sha256(site.encode()).hexdigest()[-6:]}.json")
|
||||
with open(record_file, 'w', encoding='utf-8') as f:
|
||||
@ -33,4 +22,13 @@ async def main(sites: list):
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import argparse
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('--sites', '-S', type=str)
|
||||
parser.add_argument('--save_dir', '-D', type=str, default=save_dir)
|
||||
args = parser.parse_args()
|
||||
|
||||
sites = [site.strip() for site in args.sites.split(',')]
|
||||
save_dir = args.save_dir
|
||||
os.makedirs(save_dir, exist_ok=True)
|
||||
asyncio.run(main(sites))
|
||||
|
@ -5,16 +5,22 @@ current_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
project_root = os.path.dirname(current_dir) # get parent dir
|
||||
sys.path.append(project_root)
|
||||
|
||||
from core.agents.get_info import extract_info_from_img
|
||||
|
||||
vl_model = os.environ.get("VL_MODEL", "")
|
||||
if not vl_model:
|
||||
print("错误: VL_MODEL not set, will skip extracting info from img, some info may be lost!")
|
||||
sys.exit(1)
|
||||
|
||||
from core.llms.openai_wrapper import openai_llm as llm
|
||||
|
||||
async def main(task: list):
|
||||
return await extract_info_from_img(task, vl_model)
|
||||
vl_model = os.environ.get("VL_MODEL", "")
|
||||
if not vl_model:
|
||||
print("错误: VL_MODEL not set, will skip extracting info from img, some info may be lost!")
|
||||
sys.exit(1)
|
||||
cache = {}
|
||||
for url in task:
|
||||
llm_output = await llm([{"role": "user",
|
||||
"content": [{"type": "image_url", "image_url": {"url": url, "detail": "high"}},
|
||||
{"type": "text",
|
||||
"text": "提取图片中的所有文字,如果图片不包含文字或者文字很少或者你判断图片仅是网站logo、商标、图标等,则输出NA。注意请仅输出提取出的文字,不要输出别的任何内容。"}]}],
|
||||
model=vl_model)
|
||||
cache[url] = llm_output
|
||||
return cache
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
Loading…
Reference in New Issue
Block a user