GithubHelp home page GithubHelp logo

3alan / docsmind Goto Github PK

View Code? Open in Web Editor NEW
171.0 7.0 72.0 37.26 MB

🤖 DocsMind allows you to chat with your docs and summarize your docs, support pdf, md.

Home Page: https://docs-mind.alanwang.site

License: GNU Affero General Public License v3.0

TypeScript 59.65% Python 33.23% JavaScript 0.77% Procfile 0.05% HTML 2.08% SCSS 4.21%
langchain llama-index markdown chatgpt chatpaper chatpdf pdf pdfgpt summarizer gpt

docsmind's Introduction

DocsMind

DocsMind is an open-source project that allows you to chat with your docs.

Stack

It is currently under development and there may be major changes at any time.

🎬 Demo

Demo Site

Warning

Due to the free plan of Railway only providing 500 hours per month, the Demo on the 21st day of each month will not be available. Please clone it locally for use at that time.

🌟 Features

  • 🤖 Ask a question with your docs
  • 📝 Summarize docs
  • 🖍️ Highlight source
  • 📤 Upload docs .pdf,.md(best support)
  • 💾 Data saved locally
  • 💰 Token usage tracker
  • 🐳 Dockerize

🚀 Road Map

  • Chat mode
  • Dark mode
  • / command (/fetch /summarize)
  • Reduce the size of the server image.
  • Support for more docs formats: txt...
  • Download docs from the internet
  • Markdown-formatted message
  • i18n
  • Desktop application

If you find this project helpful, please consider giving it a star 🌟

💻 Environment Variables

Name Description Optional
OPENAI_PROXY will replace https://api.openai.com/v1
VITE_SERVICES_URL backend url for frontend code
VITE_DISABLED_UPLOAD DISABLED_UPLOAD

❓ FAQ

This project includes both frontend (/client) and backend (/server) code. The frontend code is used to display the UI, while the backend code provides services to the UI.

How to deploy?

More details

How to run?

Warning

Please check if you can access OpenAI in your region, you can refer to the issue for more information.

  1. Create .env

Create a .env file and copy the contents of .env.example to modify it.

  1. Run App
docker-compose up -d

Please add --build to rebuild the image after each code update.

docker-compose up -d --build

now you can access the app at http://localhost:8081

All data will be saved in the ./data directory.

Local Development

Detail

Create .env

Create a .env file and copy the contents of .env.example to modify it.

Run Frontend UI

  1. Install dependencies
yarn
  1. Run app
yarn dev

Run Backend Services

you need a python environment

  1. Create virtual environment
cd server
python -m venv .venv
  1. Active virtual environment

windows

.venv\Scripts\activate

mac

. .venv/bin/activate
  1. Install dependencies
pip install -r requirements.txt
  1. Run Services
flask run --reload --port=8080

📝 License

AGPL-3.0 License

☕ Buy me a coffee

ko-fi

Alipay and Wechat

docsmind's People

Contributors

3alan avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

docsmind's Issues

The upload interface is missing the "openaiKey" parameter.

Describe the bug
A clear and concise description of what the bug is.

Provide logs
Please provide the log located at api-src/app.log and the client error (browser console) so that I can better understand the issue.

To Reproduce
Steps to reproduce the behavior.

Expected behavior
A clear and concise description of what you expected to happen.

Screenshots
If applicable, add screenshots to help explain your problem.

Additional context
Add any other context about the problem here.

Hosting Online

Hey @3Alan , Great work. You definitely deserve that coffee on me, I would love to contribute so you can keep your hard work.

Can you please update the readme for step-by-step process on hosting this app online. Its quite confusing. If you could provide clearer instructions that would be awesome. Im trying to host this app for my high school to use and would like to give them a simple url for students to access and use.

PS: Im working on hooking this up with Google Drive folder so users can search their existing documents on Drive.

File upload fail. undefined.

Describe the bug
Cannot upload PDF documents.

Provide logs
Please provide the log located at logs/app.log and the client error (browser console) so that I can better understand the issue.
image

To Reproduce
Follow instructions in README.md, hosting on github codespace, and gitpod.

Expected behavior
PDF would upload and be indexed.

Screenshots
image

This error occurs when the front-end uploads the file

Describe the bug
A clear and concise description of what the bug is.
image

Provide logs
Please provide the log located at logs/app.log and the client error (browser console) so that I can better understand the issue.

To Reproduce
Steps to reproduce the behavior.

Expected behavior
A clear and concise description of what you expected to happen.

Screenshots
If applicable, add screenshots to help explain your problem.

Additional context
Add any other context about the problem here.

[Bug]:

Describe the bug

~/DocsMind$ sudo docker-compose up -d
[+] Building 837.4s (10/15)
[+] Building 1771.6s (10/15)
=> [internal] load build definition from Dockerfile.client 0.1s
=> => transferring dockerfile: 359B 0.0s0 => [internal] load .dockerignore 0.1s
=> => transferring context: 2B 0.0s
=> [internal] load metadata for docker.io/library/nginx:1.23.4-alpine 0.4s
=> [internal] load metadata for docker.io/library/node:16-alpine 0.4s
=> [client 1/7] FROM docker.io/library/node:16-alpine@sha256:296f32946d2fb5227e43f 0.0s
=> [internal] load build context 0.1s
=> => transferring context: 218.73kB 0.0s
=> CACHED [stage-1 1/3] FROM docker.io/library/nginx:1.23.4-alpine@sha256:02ffd439 0.0s
=> CACHED [client 2/7] WORKDIR /client 0.0s
=> CACHED [client 3/7] COPY ./client . 0.0s
=> CACHED [client 4/7] RUN yarn install 0.0s
=> [client 5/7] RUN yarn build 1789.3s
=> => # $ tsc && vite build
=> => # vite v4.3.5 building for production...
=> => # transforming...
=> => # Use of eval in "node_modules/pdfjs-dist/build/pdf.js" is strongly disc
=> => # ouraged as it poses security risks and may cause issues with minificat
=> => # ion.


你好,请在Build的过程中遇到 关于提醒 pdf.js 的库调用的一个风险, 似乎这里有个确认要完成,,不能往下走了

请问如何解决

Relevant log output

=> => # $ tsc && vite build
 => => # vite v4.3.5 building for production...
 => => # transforming...
 => => # Use of eval in "node_modules/pdfjs-dist/build/pdf.js" is strongly disc
 => => # ouraged as it poses security risks and may cause issues with minificat
 => => # ion.

Validations

  • Already read the README
  • Check that there isn't already an issue that reports the same bug to avoid creating a duplicate.

[Bug]: 上传pdf文件超过一次分页就死循环

Describe the bug

本来的问题是md上传很快,pdf上传永远卡死,也没有报错日志出现,
代码在 pdf_loader.py的 text_chunks = sentence_splitter.split_text(text) 这一行
经过debug后,调整了 llama_index/langchain_helpers/text_splitter.py 的 new_splits.pop(0) 这一行,pdf可以上传成功,但是只是上传成功而已,功能好像是欠缺的,截图如下,请参考
如果不调整,会一直死循环在 while len(new_splits) > 0: 的循环里

7cda41c4187fc813b179b6e985f4f5e

Relevant log output

2023-06-20 06:16:38 ERROR: RetryError[<Future at 0x7f6013630280 state=finished raised RateLimitError>]
Traceback (most recent call last):
  File "/root/local/DocsMind/server/.venv/lib/python3.9/site-packages/tenacity/__init__.py", line 382, in __call__
    result = fn(*args, **kwargs)
  File "/root/local/DocsMind/server/.venv/lib/python3.9/site-packages/llama_index/embeddings/openai.py", line 106, in get_embedding
    return openai.Embedding.create(input=[text], engine=engine)["data"][0]["embedding"]
  File "/root/local/DocsMind/server/.venv/lib/python3.9/site-packages/openai/api_resources/embedding.py", line 33, in create
    response = super().create(*args, **kwargs)
  File "/root/local/DocsMind/server/.venv/lib/python3.9/site-packages/openai/api_resources/abstract/engine_api_resource.py", line 153, in create
    response, _, api_key = requestor.request(
  File "/root/local/DocsMind/server/.venv/lib/python3.9/site-packages/openai/api_requestor.py", line 226, in request
    resp, got_stream = self._interpret_response(result, stream)
  File "/root/local/DocsMind/server/.venv/lib/python3.9/site-packages/openai/api_requestor.py", line 619, in _interpret_response
    self._interpret_response_line(
  File "/root/local/DocsMind/server/.venv/lib/python3.9/site-packages/openai/api_requestor.py", line 682, in _interpret_response_line
    raise self.handle_error_response(
openai.error.RateLimitError: Your access was terminated due to violation of our policies, please check your email for more information. If you believe this is in error and would like to appeal, please contact us through our help center at help.openai.com.

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/root/local/DocsMind/server/.venv/lib/python3.9/site-packages/flask/app.py", line 1484, in full_dispatch_request
    rv = self.dispatch_request()
  File "/root/local/DocsMind/server/.venv/lib/python3.9/site-packages/flask/app.py", line 1469, in dispatch_request
    return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args)
  File "/root/local/DocsMind/server/app.py", line 148, in query_index
    res = index.query(query_text, streaming=True)
  File "/root/local/DocsMind/server/.venv/lib/python3.9/site-packages/llama_index/indices/base.py", line 260, in query
    return query_runner.query(query_str)
  File "/root/local/DocsMind/server/.venv/lib/python3.9/site-packages/llama_index/indices/query/query_runner.py", line 349, in query
    return query_combiner.run(query_bundle, level)
  File "/root/local/DocsMind/server/.venv/lib/python3.9/site-packages/llama_index/indices/query/query_combiner/base.py", line 68, in run
    return self._query_runner.query_transformed(
  File "/root/local/DocsMind/server/.venv/lib/python3.9/site-packages/llama_index/indices/query/query_runner.py", line 209, in query_transformed
    return query_obj.query(query_bundle)
  File "/root/local/DocsMind/server/.venv/lib/python3.9/site-packages/llama_index/token_counter/token_counter.py", line 78, in wrapped_llm_predict
    f_return_val = f(_self, *args, **kwargs)
  File "/root/local/DocsMind/server/.venv/lib/python3.9/site-packages/llama_index/indices/query/base.py", line 206, in query
    nodes = self.retrieve(query_bundle)
  File "/root/local/DocsMind/server/.venv/lib/python3.9/site-packages/llama_index/indices/query/base.py", line 166, in retrieve
    nodes = self._retrieve(query_bundle, similarity_tracker=similarity_tracker)
  File "/root/local/DocsMind/server/.venv/lib/python3.9/site-packages/llama_index/indices/vector_store/base_query.py", line 62, in _retrieve
    self._service_context.embed_model.get_agg_embedding_from_queries(
  File "/root/local/DocsMind/server/.venv/lib/python3.9/site-packages/llama_index/embeddings/base.py", line 83, in get_agg_embedding_from_queries
    query_embeddings = [self.get_query_embedding(query) for query in queries]
  File "/root/local/DocsMind/server/.venv/lib/python3.9/site-packages/llama_index/embeddings/base.py", line 83, in <listcomp>
    query_embeddings = [self.get_query_embedding(query) for query in queries]
  File "/root/local/DocsMind/server/.venv/lib/python3.9/site-packages/llama_index/embeddings/base.py", line 72, in get_query_embedding
    query_embedding = self._get_query_embedding(query)
  File "/root/local/DocsMind/server/.venv/lib/python3.9/site-packages/llama_index/embeddings/openai.py", line 223, in _get_query_embedding
    return get_embedding(query, engine=engine)
  File "/root/local/DocsMind/server/.venv/lib/python3.9/site-packages/tenacity/__init__.py", line 289, in wrapped_f
    return self(f, *args, **kw)
  File "/root/local/DocsMind/server/.venv/lib/python3.9/site-packages/tenacity/__init__.py", line 379, in __call__
    do = self.iter(retry_state=retry_state)
  File "/root/local/DocsMind/server/.venv/lib/python3.9/site-packages/tenacity/__init__.py", line 326, in iter
    raise retry_exc from fut.exception()
tenacity.RetryError: RetryError[<Future at 0x7f6013630280 state=finished raised RateLimitError>]

Validations

  • Already read the README
  • Check that there isn't already an issue that reports the same bug to avoid creating a duplicate.

[Bug]: Unable to upload file.

Describe the bug

Unable to upload file.
Looks like front end isn't communicating with back. pls help.

tried other ways as per other issues but unable to fix it.

Relevant log output

129.154.45.16/:1 Unchecked runtime.lastError: The message port closed before a response was received.
contentScript.bundle.js:533 Content script works!
contentScript.bundle.js:533 Must reload extension for modifications to take effect.
script.js:1 Uncaught SyntaxError: Unexpected token '<' (at script.js:1:1)
index-33b23838.js:337     GET http://localhost:8080/api/file-list net::ERR_CONNECTION_REFUSED
(anonymous) @ index-33b23838.js:337
xhr @ index-33b23838.js:337
dispatchRequest @ index-33b23838.js:337
request @ index-33b23838.js:337
(anonymous) @ index-33b23838.js:335
et @ index-33b23838.js:352
(anonymous) @ index-33b23838.js:352
Rj @ index-33b23838.js:40
Ik @ index-33b23838.js:40
Fk @ index-33b23838.js:40
jg @ index-33b23838.js:38
Xk @ index-33b23838.js:40
Qk @ index-33b23838.js:40
Hk @ index-33b23838.js:40
xt @ index-33b23838.js:25
Pt @ index-33b23838.js:25
index-33b23838.js:337 Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'data')
    at index-33b23838.js:337:16089
    at async et (index-33b23838.js:352:9019)

Validations

  • Already read the README
  • Check that there isn't already an issue that reports the same bug to avoid creating a duplicate.

App is not running

Hello,

I followed the steps mentioned under the LOCAL DEVELOPMENT. all steps were executed without any issue. however, when i try to access the app at http://localhost:5173/ i get the 404 error.

image

image

and checking the logs, its empty.


Then it tried to access and test the flask service at http://localhost:8080/ and i get :
{"message":"404 Not Found: The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again."}

I find this in the log :


werkzeug.exceptions.NotFound: 404 Not Found: The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.
2023-05-07 23:25:02 ERROR: 404 Not Found: The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.
Traceback (most recent call last):
  File "C:\Users\x\DocsMind-1\server\.venv\Lib\site-packages\flask\app.py", line 1484, in full_dispatch_request
    rv = self.dispatch_request()
         ^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\x\DocsMind-1\server\.venv\Lib\site-packages\flask\app.py", line 1458, in dispatch_request
    self.raise_routing_exception(req)
  File "C:\Users\x\DocsMind-1\server\.venv\Lib\site-packages\flask\app.py", line 1440, in raise_routing_exception
    raise request.routing_exception  # type: ignore
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\x\DocsMind-1\server\.venv\Lib\site-packages\flask\ctx.py", line 353, in match_request
    result = self.url_adapter.match(return_rule=True)  # type: ignore
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\x\DocsMind-1\server\.venv\Lib\site-packages\werkzeug\routing\map.py", line 652, in match
    raise NotFound() from None

[Bug]: "Please retry" appears

Describe the bug

image
When I upload the file successfully and generate the vector, I go to chat with the file and "please retry"

Relevant log output

INFO:llama_index.token_counter.token_counter:> [query] Total LLM token usage: 4142 tokens
INFO:llama_index.token_counter.token_counter:> [query] Total embedding token usage: 7 tokens
INFO:llama_index.token_counter.token_counter:> [query] Total LLM token usage: 0 tokens
INFO:llama_index.token_counter.token_counter:> [query] Total embedding token usage: 7 tokens
<generator object _get_response_gen at 0x7f33b49f7920>
INFO:werkzeug:127.0.0.1 - - [12/May/2023 23:07:25] "GET /api/query?index=大学生心理问题的性别差异研究&mode=cors&openAiKey=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&query=讲什么 HTTP/1.0" 200 -

Validations

  • Already read the README
  • Check that there isn't already an issue that reports the same bug to avoid creating a duplicate.

[Bug]: I can't upload file

Describe the bug

image

Relevant log output

* Debug mode: off
INFO:werkzeug:WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
 * Running on http://127.0.0.1:8080
INFO:werkzeug:Press CTRL+C to quit
INFO:werkzeug: * Restarting with stat
INFO:werkzeug:127.0.0.1 - - [13/Jun/2023 04:04:05] "GET /api/file-list HTTP/1.1" 200 -
INFO:werkzeug:127.0.0.1 - - [13/Jun/2023 04:04:05] "GET /api/file-list HTTP/1.1" 200 -
INFO:werkzeug:127.0.0.1 - - [13/Jun/2023 04:04:05] "GET /static/file/2302.13971.pdf HTTP/1.1" 304 -
INFO:werkzeug:127.0.0.1 - - [13/Jun/2023 04:04:22] "GET /api/file-list HTTP/1.1" 200 -
INFO:werkzeug:127.0.0.1 - - [13/Jun/2023 04:04:22] "GET /api/file-list HTTP/1.1" 200 -
INFO:werkzeug:127.0.0.1 - - [13/Jun/2023 04:04:22] "GET /static/file/AA-README.html HTTP/1.1" 304 -
INFO:werkzeug:127.0.0.1 - - [13/Jun/2023 04:04:25] "OPTIONS /api/upload HTTP/1.1" 200 -
/home/ubuntu/storage/DocsMind-main/server /home/ubuntu/storage/DocsMind-main/server/app.py
saved
create index [2302.13971.pdf]
aa
static/temp/2302.13971.pdf 2302.13971.pdf

---------------------------------
it time upload file ,go to folder temp. i can't read file. you can help me plz

Validations

  • Already read the README
  • Check that there isn't already an issue that reports the same bug to avoid creating a duplicate.

LIST INDEX OUT OF RANGE

Describe the bug
When uploading a file, an error occurred: LIST INDEX OUT OF RANGE.

As the program currently chunks the file based on headings, to temporarily solve this problem, try adding a heading to the markdown file:

# Heading

[Bug]: file upload failed. "The page could not be found\n\nNOT_FOUND\n"

Describe the bug

After deploying the app I get the following error when uploading PDFs: [Bug]: file upload failed. "The page could not be found\n\nNOT_FOUND\n"

image

Relevant log output

MAY 19 12:17:29.00
404
docsmind2-lyhwrm0vb-beralc.vercel.app
[GET] /docsmind-production-127f.up.railway.app/api/file-list
MAY 19 12:17:28.00
404
docsmind2-lyhwrm0vb-beralc.vercel.app
[GET] /_vercel/insights/script.js
MAY 19 12:14:05.00
404
docsmind2.vercel.app
[GET] /docsmind-production-127f.up.railway.app/api/upload
MAY 19 12:13:58.00
404
docsmind2.vercel.app
[GET] /_vercel/insights/script.js
MAY 19 12:13:58.00
404
docsmind2.vercel.app
[GET] /_vercel/insights/script.js
MAY 19 12:13:58.00
404
docsmind2.vercel.app
[GET] /docsmind-production-127f.up.railway.app/api/file-list
MAY 19 12:13:50.00
404
docsmind2.vercel.app
[GET] /_vercel/insights/script.js
MAY 19 12:13:50.00
404
docsmind2.vercel.app
[GET] /_vercel/insights/script.js
MAY 19 12:13:50.00
404
docsmind2.vercel.app
[GET] /docsmind-production-127f.up.railway.app/api/file-list
MAY 19 12:13:47.00
404
docsmind2.vercel.app
[GET] /robots.txt
MAY 19 12:13:43.00
404
docsmind2-lyhwrm0vb-beralc.vercel.app
[GET] /_vercel/insights/script.js
MAY 19 12:13:43.00
404
docsmind2-lyhwrm0vb-beralc.vercel.app
[GET] /_vercel/insights/script.js
MAY 19 12:13:43.00
404
docsmind2-lyhwrm0vb-beralc.vercel.app
[GET] /docsmind-production-127f.up.railway.app/api/file-list
MAY 19 12:13:43.00
404
docsmind2-lyhwrm0vb-beralc.vercel.app
[GET] /docsmind-production-127f.up.railway.app/api/file-list

Validations

  • Already read the README
  • Check that there isn't already an issue that reports the same bug to avoid creating a duplicate.

PDF2HTMLEX issue

Describe the bug
Running the following command run into error :

alias pdf2htmlex='docker run -ti --rm -v "pwd":/pdf -w /pdf pdf2htmlex/pdf2htmlex:0.18.8.rc2-master-20200820-alpine-3.12.0-x86_64'

alias : This command cannot find a matching alias because an alias with the name 'pdf2htmlEX=docker run -ti --rm -v "`pwd`":/pdf -w /pdf 
pdf2htmlex/pdf2htmlex:0.18.8.rc2-master-20200820-alpine-3.12.0-x86_64' does not exist.
At line:1 char:1
+ alias pdf2htmlEX='docker run -ti --rm -v "`pwd`":/pdf -w /pdf pdf2htm ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (pdf2htmlEX=dock...e-3.12.0-x86_64:String) [Get-Alias], ItemNotFoundException
    + FullyQualifiedErrorId : ItemNotFoundException,Microsoft.PowerShell.Commands.GetAliasCommand

[Bug]: .env文件不知道如何修改

Describe the bug

.env.example文件比较含糊,请问能否详细介绍一下,并加上注释,谢谢你

Relevant log output

no

Validations

  • Already read the README
  • Check that there isn't already an issue that reports the same bug to avoid creating a duplicate.

404 error

I'm getting this error:
{"message":"404 Not Found: The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again."}

image

What could the issue be?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.