Plone 5 and how to use machine learning with it.
CC Attribution - NonCommercial - ShareAlike 3.0 Unported:
You are free to use, adapt and copy, distribute and transmit the work or content in adapted or unchanged form for any legal and non-commercial purpose as long as the work is attributed to the author in the manner specified by the author or licensor and the work or content is shared also in adapted form only under the conditions of this
Bosch, Ramon Navarro
Ramon Navarro Bosch - Plone 5 and how to use machine learning with it. Plone is a Document Management System and Content Management System that has been in the Python scope for more than 10 years. Plone 5’s features allow us to manage content, define various kinds of content and provide a nice useful UI to work on semantic web technologies. In this talk we are going to explain our approach for using Plone with the Python machine learning toolkit sklearn to enable clusterization and classification of content using a scalable content management system. We will also add some sophisticated front-end gloss using the new functionalities on frontend development added on Plone 5 and some real use cases of CMS/DMS with machine learning using sklean and solr.
 So good morning to the people who are with Hangover. I'm sorry because it's late early in the morning. I think it's going to be more like a friendly talk because I nearly know most of the faces. That's really great. So what I'm going to talk about is Plone 5. Who does not know what's Plone? One person? That's great. There is one person. So then I finish the talk and I go to take some beers. So let's go to try to do that. Who am I? I'm Romon Navarro Bosque. I'm a Plone Foundation member. I'm in the framework team in Plone. That's the core Plone team that's doing its meeting every week. It's really boring. And then there is the CTO at the company in Catalonia. Yeah, I'm Catalan. So that's who am I. You can see the measure in Catalonia. So how I'm going to organize this talk. I'm going first to talk about Plone 5 because we are now in a good moment in Plone. We are going to release Plone 5. So I'm going to try to explain you what's going to change there and how you are going to program there. And then I'm going to talk about machine learning because otherwise you cannot include your talk in every Python. So let's talk about. Let's talk about Plone 5. So from the user point of view, from the developer point of view, from the city opener view, from the business point of view, it's mostly quality, user interface, testing. It's really all software. We have nearly 12 years that's been there. We grow really fast. We have a lot of sites around the world for some of the Brazilian government. And it's really being used a lot on big companies, ABB, some other big companies are using that. And why they are using it? Because it has a good quality. It's really stable. You can grow from a really small site that's only for your personal usage for your shop under your flat. Or you can just use the same software for building really a big site, a weak internet, or a big content management system. So everybody knows Plone. So that's going to be boring, because I'm going to talk about what's Plone from the user point of view. So Plone from the user point of view is content. Content is the king. That's the king in Japanese. So what does it mean? That everything is content oriented. You have pages. You have documents. You have folders. You have events. You have whatever you want. For example, there is an hospital in my city that they want to store the passion sheets about, OK, he's ill. He has these problems. We solve that. This is content. Everything that's a piece of a document that we can have in a word, or an Excel, or whatever, or we can have in a piece of text is a document. So content is the king. Content is the center of Plone. And we have full multilingual support in Catalan also. So that's great. It's translated in more than 50 languages. I added this, because most of the CMSs that we have in other languages, like Java, I think, or something like that, doesn't have full multilingual support. That means that all the content can be translated to all the languages, and you have connection between one translation to the other, blah, blah, blah. OK. One of the most important things about Plone is the security. Why is being used by FEI? Why is it being used by the Zilden government? Why is it being used by ABB? Because they know that it's really secure. So all the content that's there, all the fields, everything that's there, is not going to be seen by anybody that you don't want that to be seen. And why is it because we have this security granularity? It's because we have Jope and ZLDB. I'm going to talk a bit about that later. And we have workflows. So all the content goes through different steps, and each step has different permissions for different users, groups, et cetera. Theming. If you were using Plone before Plone 5, 4.4, you surely would quit using Plone, because it was really difficult to use. The curve of entrance. I've been asking some of the European people, have you used Plone in the past? Yeah, yeah, but I quit it because it was so difficult to understand. So we solved that. We solved most of the problems that we had with the Theming. For example, now we are using some kind of rules we call the ASO. It's using, they are being, they are designed so you can see your site without knowing anything, neither about Python, if you want. It's using rules to move things from place to the other. Later I'm going to show. Ah, yeah, we integrated required JS and less. So if you want to build a nice front end with Angular or with V app or whatever, Plone directly provides you the tools that you need to do that. We have inline edition through the web edition. So you can see in the back, you can create content, move content around. This is Mosaic project. It's one spin off of Plone that's still working progress. It's really cool because you can just create content. You can just upload an image through the web with a drag and drop and push it wherever you want in the page. OK, if you want, we can try. Let's see. So this is the new Plone 5 front end. It's really cool because it's using a theme called Barcelona. Barcelona from Barcelona. Catalonia again. Ah. Thank you. Just you can see, I think it's English. So there is some kind of cool things you can browse. All your content here, this resolution is not really good for doing these kinds of things. But you can go to the folders. You can go to the content and see whatever you have here. You can create a new page wherever you want. And just write down whatever you want. You have this tiny mc4 that's really cool. So you can push images. You can push files, whatever, and save it. OK, so then you can go to content. There is a lot of good features that if I would show that, we will still until tomorrow. So just sharing. You can decide who can edit, who can, the history button, where you can see who edited, which is the difference, et cetera, et cetera. Yeah. OK. So now as we are in a technical conference, I'm going to talk a bit more about how it's technically blown, because that was like the commercial screencast. So let's go. URKC. The blown is based on a URKC database, because as all the users are used to have their desktops with folders, content inside that. So we are using a specific database. It's called Zodib. It's really, I think right now, Zodib has more than 10 years, maybe? More than 10, 12 years. OK. So at that time, nobody was talking about non-SQL. And Zodib is a non-SQL database that you store objects in, inside objects. And he stores directly the pickles on a really great structure. If you are not going to use blown, but you need some kind of database that you need to store a tree of objects that are going to have some kind of relation between them, Zodib is a really great database outside of blown also. So this concept of storing everything in a URKC mode, it's really, there is no other CMS that does that. Everybody is storing things in SQL data, but content management is not relational data. If you go to the university and you say, oh, I'm going to store an object and I'm going to put all the HTML in a field of my table. Sorry. You need to structure that. You need semantical. You need to have the option to have sons of your content. You have a folder, then you have content inside that, images inside that. So that's one of the main points of technically talking. But the content is the king. We have this folder structure. So then what are we using to have the content? We are using a project. It's called Dexterity in Plum 5. We remove it, our type. If you never use our types, I'm really sorry for you. But Dexterity is really a cool piece of software because it allows you to create defined content. Oh, where is my? Yeah. With a simple interface, just you decide, OK, I want to create a content. It's called a sponsor. And then you have a choice field where you can have different vocabulary, a little vocabulary that's going to be shown from the UI. You have a rich text. That means it's a tiny mc. It's going to render a tiny mc so you can write down. You can define a urie, you can define different kind of fields, files, images. You can define also permissions for specific fields. I want that. Timo doesn't see that field. So I can write that. Timo will not see that field. That's really cool. So with this simple file, there is no copy of strange thing that we use on our types that only defines really the interface, really the fields that you want in your content. The semantical meaning of your content, you can define your own content type. Then this content type, it's going to be mapped to the URL. So one of the good things also we have in Zoop, Blown, blah, blah, blah, blah, is that we have traversal. That means that all these folders that we have, I explain it to you that you have a folder and then a content and then an image, for example. You can access that through the URL. You can write the URL of your site, the folder, the content, blah, blah, blah. And then the view, a specific browser view, function that renders that and creates a templating stuff or whatever you want to use to see that. Here we have an example of what's a view. So here we have, OK, one of the cool things we added is all this JavaScript CSS management system. So you register CSS and JavaScript, and then it automatically pops up on your page when it's needed. So you can register, for example, a bundle, jQuery data tables. And you want that this view that's going to render some kind of page has this JavaScript included and the CSS that's needed for this resource to be loaded. So then you just add resource on request and you write the name of the resource that you want to add, and it's automatically going to be deployed on your view when you are rendering that. Yeah, there is a lot of technical details. Just don't want to step too much, maybe. Here is how we register a view. I've been asking a lot of people here in Uri Python, what's the worst thing about blown? And they say, this is XML because it's XML. XML is not bad, sorry. It's OK, it could be better. This is XML. It's really great because it allows us to have really a good list of the views, the content, all the definitions that we have. So I really think it's great to have this way of defining all the views and all the content. Yeah, and we have the templating. Yeah, because you can create a class to show you the content, to have your content type there. But you need some kind of class to render that on the view page. I have some kind of templating. And one of the cool things that we added at the end of blown4 is that we can use chameleon. So now, no more tau, no more way of defining variables with a specific crappy language that's only being used by Zoop. So we can define these variables and use the variables with these dollar stuff there. That's really interesting. Interesting. So Python. OK, I think that most of you know that. Zoop is the most Python-based framework for work on content management. You can access the object of your site, and it's everything mapped to the database. Then you can just go to the attribute of your site that's called a folder. And then you can go to the attribute of the folder that's called a document. And then you can access an attribute of the document. So you would really have the granularity and the Python way of doing content management. Yeah, I wanted to talk about Zoop component architecture, because maybe there was been a lot of talks. The last one I saw that pushed on internet was 2005. But it's really interesting infrastructure, and it's being misused, I think, because we have Zoop.interface and Zoop.component. That it's really two good packages for managing three good patterns of programming that, OK. Normally, when you write some Python code, you write a small program. But if your program is going to grow up, you will need to have some kind of patterns for designing that software. And sometimes there is really good libraries about patterns, how to develop big softwares with that. And Zoop is a really good one. I really love it. So where are we storing our components, our adapters, our patterns? It's in local storage, local registry, and global registry. We have two in Zoop, one is global for all the sites of your environment, of your process, of your thread, and then one specific for each site that's the local registry. So I wanted to first explain you, OK, what's an adapter? Adapter, it's one of the patterns that, and software, it's really good for using. Because we are using in the past subclassing classes. So we ended up having our types that maybe you were looking how many classes it was subtyped. And it was maybe 30 different classes that if you go up to see the parents of the class, you will never know what's going to be there. It was a mess. So they decided in Zoop community to create this adapter pattern. And it's an interface, you define, in this case, a person. You define some kind of normal interface, like Java, like whatever. You define some definitions and the attributes of that interface. And you have implementations of that interface. For example, we have an interface called Iperson that you define a function which the share time is wearing. And then you have an adaptation. It's called Catalan Guy. And then it returns a stilada. And if there is another implementation, it's called Bass Guy. It shares a t-shirt. So you can use any of these adapters to adapt an object and get the methods that you need. The subscriber, another kind of good pattern, the observer pattern, the subscriber pattern on software engineering. Here we have the kind of object that we want to look. I want to check if you modify this kind of object, if you modify the Iperson object. Then you can subscribe for Iperson. And you want to subscribe for the modified event. And you decide which function is going to be executed in case that's being modified. And utility, OK, that's just you want to store some kind of list of good alcohol. Then you define an interface, good alcohol. And then you have an object that will return all the list of good alcohol because it's an utility. That's really useful. And then at the end, in this more technical, well-blown stuff, I'm going to talk about the JavaScript and the CSS integration we did. We created our own kit, our own framework, JavaScript framework. That's the worst error we did, I think, because it's going to be hard to maintain. But at the moment, there was no the solutions we have right now on the community of JavaScript. But it was really great. It's using patterns, lib patterns, as a way of defining, OK, you have these elements. And then with data tags on the HTML elements, you can configure them. And they automatically run JavaScript on top of that and renders the correct widget for you. For example, this is the date picker date widget that we have on blow normally. Then you can see. This is the configuration. You define the format, the date, blah, blah, blah. And everything is integrated with required.js and less. That means that if you want, you can start your clone in debug mode. And then you are going to see everything compiled on time on the browser. So you will see the source code of select to there. So you can go and debug whatever thing you need. Because when you're blown, I think that has nearly 1 million lines of JavaScript with all the libraries that's including tiny mc is so big. So if you want to debug that, and you don't have the option to really have them uncompressed, and that you don't need to take care about loading everything. So we created a Python model that's taking care of that, creating the JavaScript configuration for required.js and compiling less. So you get the source code there on your browser. Diaso, I'm not going to stand on that just a way of defining themes. So you go to your designer and say, OK, I need to do this web page. So just design that. The designer draws it. You send to the people who does the HTML. And he does the HTML. OK, the HTML is done. And then you give to the clone guys, OK, this is the HTML of my site. And with these Diaso rules, you just remove. I want that this deep is this deep of the clone. This piece of here is this piece of here. And you can create your theme without doing so hard integration right now. That's also a really cool thing. OK, new things that we are working, that we are going to do in the next month, I hope, is the Plum Rest API. It's really clear that all the web frameworks or the web applications are going to move to JavaScript. All the UI needs to be done in JavaScript. So what's really needed is that we have a really cool rest API that we can interact with clone. So we created Plum for the rest. I think it's not released, but it's going to be released really soon. You can try it on GitHub. It's really great. We defined a way to define this HTTP verbs like put, get, delete, on a specific content type. OK, I have I person, and I want to delete the person. So then I can define a specific HTTP verb for deleting on this object, and which is the function that's going to be executed. So here, you see, for example, the implementation of the put. OK, testing. We improved a lot on testing. We really did a lot of work there. Jenkins.plone.org has the Plum 5 job has 101 acceptance stands, and I think there are more than 5,000 more? 9,000 integration tests and unit testing. We really test everything. If you commit something and you break the bill, then this guy comes to you and starts to yell at you. And you never go to sleep before the Jenkins screen again. So we have a really good testing. I really want to thank Tim and the testing team because they really did a great job on that. Because we have really, really a good testing environment. So that makes also the companies rely on us because, OK, we create a new release of Plone, and you know that's going to work because we have really tested everything. I changed the name of the button of a control panel and 10 test fields. So that's really, really great. And for companies that rely on that and they want the best money to get their sites done and the one that in five years is still there. So that's really important. So, OK, we have Plone 5 beta 3 release. Now we created a specific repository. So if anybody wants to try it and hit things, OK, it's going to be difficult to try Plone because it's a complex software. OK, it's one, two, three, four lines of on-soul to try that. You go just clone the jithub.com.plone jamming2. You run with Python 2.7. ZODB is already running on Python 3. So we think that we are going to someday to have options to have Python 3 and all the stack. It's really big. So we will try. Then we run without, and then you run instance fg. And you have your clone site running. It's only four lines of code, four lines of console. You need to go to take a coffee between the build out and the instance because it might take 10 or 15 minutes, depending on the machine and the network. OK, just one, two, five. We have a really good documentation. There is training.plot.r. There is docs.plot.r. Hundreds of different documentation written for developers and for users. And lots of training. There is a training that helps you to understand. OK, the future. We are going to move, maybe, to Azure to REST API. And we need a JSON front end. We are going to have some kind of a sync I.O. back end. Maybe with SubstanceD, maybe with pyramid. Who knows? We will see. We are going to talk about that. This talk also has the vn machine learning. And they sent me 10 minutes. So I'm going to talk about machine learning also. So what we did in clone is we created a proof of concept because our main goal, the goals that we had of using machine learning is that, OK, the user has used a CMS. So when you get to the content, you want to see, for example, the related content that's on your site. But the people doesn't go to see, oh, this is related to this one. And this is related to this one. Because nobody does that in the content management system. So we wanted to create a smart way of that everything is related between them automatically. Classification of the current content. So if you have your upload site that the people has already targeted the stuff there, then you won't just maybe to run some classification algorithms on top of that to just classify what's added on your content, on your clone. Recommendation of widgets and tags. That means that if you're creating a new content and you are editing the content, having a way of user feeling that it's suggesting you, OK, this content talks about that. Just asking the user if he wants to tag this content with this kind of subject. And semantic search on the live search. We have a really nice live search. So you can search in Google and get the content that's there. But it's completely text. It's looking for text on all the files that we have and all the content that we have. So we're trying to make that it to have semantic search. So it's related to stuff. So it gets more useful. So I started to try to understand what's machine learning. It's a completely big subject. I found one really good picture that I really love and I wanted to show you. This is Seiki Learn, a map. So you go from a star and say, OK, what I need to do? I need to. I have more than 50 samples. Yeah, I'm blown. Normally you have more than 50 samples. OK, I want to predict a category. Yes, I want to predict what's talking about. OK. I have label at data. No, because people doesn't have label at data. So then we are going to go to yes, but now we go to no. So we know how many categories we have. We don't know how many blocks of content is going to be in the blown side. But that needs to be defined for the administrator because we are not going to try to predict that. So then we are going to use kimmins. And kimmins is one of the algorithms that we have implemented. And I'm going to show you if you have that. Then in case that we have label at information, we have another branch. This is a really good Seiki spreadsheet that helps you a lot to decide which algorithms you need to use for different kind of usage. Seiki Learn maybe is not the best option, but we wanted something that is integrated in blown and you don't need to run anything else external. There is also implementation with Jensim. That works fine. But you need a external REST API. You need to export the content. And our clients are really specific about security. So they don't want that we export the content to any other external application. So we need to have everything embedded on the security of Jop. So we implemented this, Collective.Machine Learning in our Github. Das Clustering is one of the initial one. So what we created is an adapter. It's called iLearningString. You get from that adapter from this content type is iPerson. And you create this adapter. So this person, I want to get which text I want to use in the machine learning stuff. So maybe you want to join the name, the first name, and his birthday or whatever. And then you create a text line, a text that is going to be used for analyzing. Then we normalize it. We vectorize with NLTK with feature hasher that we get the corpus of each document. And we store that corpus on a pickle on the database. So we can reuse later. So it's not expensive later to use that. We clusterize. That means that with all the corpus that we have, we created the big metrics of all the things that are on the site. We tried with more than 150,000 documents. OK, you need 64 gigabytes of RAM or 32 gigabytes of RAM to run that on memory. If you want, you can just use the batch stuff of Kimin's. But this is what running on a single process. We try to use just memory. There is an algorithm that allows you to have batches, Kimin batch. So we clusterize that. We define the numbers of clusters that we want on the front end. And then we just use the Kimin's algorithms to decide groups of content. And we store this model, the model that we get on a pickle on the database. And then we use that model to predict in which cluster is going to be the next content you create. You create a new content. And then automatically, we'll see, OK, this content belongs to this cluster. Yeah, the good thing is that all this implementation has security implicitly because the ZODBs has its object and the catalog is secure. So nobody's going to get any information that doesn't need to be seen by them. And OK, in the future, we are now working with Naive Bayes for classification, recommendation, semantic search, and external. We want to be able to extern to push the computation outside of clone. But it's a bit difficult with a security issue. And I wanted to show you because they say, oh, maybe I'm not going to believe what you're saying. OK, so this side has a source in Catalan because I was doing this morning and was a bit sleepy. So yeah, not like that. So here I created, for example, some content, a lot of copy based content here. And if I go to any content here, I will see that it belongs to cluster one. This side, let me see. Where is my pointer? Yeah. So there is a sign map, automatic sign map, that gets and classifies all my content in different clusters. I'm creating content and it automatically defines the groups of content that's semantically close to that. So how it's configured, it's really nice, this control panel, new stuff. Victor did that there. So let's see. Yeah, machine learning settings. So here you define one of the first systems you're going to store the vehicles. You want to use an SDK steam, which are the stop words that you want to use, the different grades that we have. If you want to remember the hashing of the strings, so they are being restored. And then we define how many clusters we want, the maximum number of clusters, and which is the name of the pickle that we're going to use to store the clustering. And then you can press this compute button. And this compute button, it's getting all the content, processing all the content, steaming all the content, and creating in the catalog of the specific indexes that will allow us to, in the browser, see which object to which cluster it belongs. And we created this nice view. Yeah, this nice view is called autosite map, and automatically shows you the content grouped by this kind of cluster. And then it's a matter of each cluster you define what's about. And if you have real content, it's really easy to see that, because you see the titles. And OK, this cluster is talking about this kind of stuff. So you can name that cluster, and people will see all the content automatically pushed. So this, I'm going to return back to the talk. Yeah, we have a feature on this. This is a proof of concept we are using in production from some sites, because it was needed. But we are working really a lot on that, and we are sprinting on that a lot of times. So if there is any data science people that wants to help us to understand what's going on behind all this stuff, we are really happy that they help us. OK, Plum Community. It's a cool community. If anybody wants to join the Plum Community, we should try now that it's much easier than in the past. You're welcome. We are really cool. And if there is any questions, we're done. Thank you. Thank you for the presentation. Just one question. How does this handle content in different languages? Yeah, right now the steaming that we have uses English. And we need to add in the control panel drop down that allows you to decide which language do you want to use. The steaming is implemented in most of the languages. So it's just a matter of that we add in the control panel this option. Could you give us a few numbers? How long the computation takes? If you have, like, say, 100,000 or a million objects in a city to be? We do that at night. It starts, I think, at 1. And it finish at 4. So three hours. In 150,000. OK, so you most likely have a specific instance for that. So it does not block the other ones. We have a specific. The only problem is that when it's finished, the computation needs to write down on all the objects the cluster. And that's what takes more. Writing down in all the objects, which is the cluster that belongs to. What's the size once it's done the computation of the pickle on 150,000 documents? And is that read into memory with the sitemap generator on every page request? Or do you cache it somehow? Sorry, I didn't understand. Sorry. So what is the size of the pickle that's generated at the end of the computation? And is that read into memory on the autositemap on every page request? No, no, no. We are storing the model. And we are storing the vectors, the matrix, the corpus. We are storing the corpus. And we are storing the model. So we are storing the model because when you create a new content, you want to ask to the model, which is the cluster which it belongs to storing the attribute. And we store the matrix. So if you want to compute some more times, you don't need to recalculate everything. So everything can be cached. It is normally five. When you are using the site, when you are doing any request, nothing is computed. Because everything is stored on the catalog and on the attributes on the objects. So it's not real time machine learning. So it's more like we run the algorithms and we integrate with blown. Do I have more questions? Is there something that can do real time machine learning? You should talk with some data science. OK, because I mean, I know like solar or a lesson search or things like that, and I don't think that this is possible because it takes some time to build all the indexes. And I guess for machine learning, that's the same as true. And then you need incremental indexes and algorithms so that that might be hard to do. I just discovered talking with some data science from the platform. In Python, there is some kind of line of investigation. It's called online. How is it called? Online? Online learning, yeah. So that are the kind of algorithms that you grow incrementally. And it's designed more for online applications. So we need to investigate that line of usage. Some more questions? If not, it's lunch time. Let's thank this speaker again. Thank you. Thank you for lunch.
 So good morning to the people who are with Hangover.  I'm sorry because it's late early in the morning.  I think it's going to be more like a friendly talk because I  nearly know most of the faces.  That's really great.  So what I'm going to talk about is Plone 5.  Who does not know what's Plone?  One person?  That's great.  There is one person.  So then I finish the talk and I go to take some beers.  So let's go to try to do that.  Who am I?  I'm Romon Navarro Bosque.  I'm a Plone Foundation member.  I'm in the framework team in Plone.  That's the core Plone team that's doing its meeting every  week.  It's really boring.  And then there is the CTO at the company in Catalonia.  Yeah, I'm Catalan.  So that's who am I.  You can see the measure in Catalonia.  So how I'm going to organize this talk.  I'm going first to talk about Plone 5 because we are now in  a good moment in Plone.  We are going to release Plone 5.  So I'm going to try to explain you what's going to  change there and how you are going to program there.  And then I'm going to talk about machine learning because  otherwise you cannot include your talk in every Python.  So let's talk about.  Let's talk about Plone 5.  So from the user point of view, from the developer point of  view, from the city opener view, from the business point of  view, it's mostly quality, user interface, testing.  It's really all software.  We have nearly 12 years that's been there.  We grow really fast.  We have a lot of sites around the world for some of the  Brazilian government.  And it's really being used a lot on big companies, ABB, some  other big companies are using that.  And why they are using it?  Because it has a good quality.  It's really stable.  You can grow from a really small site that's only for your  personal usage for your shop under your flat.  Or you can just use the same software for building really a  big site, a weak internet, or a big content management  system.  So everybody knows Plone.  So that's going to be boring, because I'm going to talk  about what's Plone from the user point of view.  So Plone from the user point of view is content.  Content is the king.  That's the king in Japanese.  So what does it mean?  That everything is content oriented.  You have pages.  You have documents.  You have folders.  You have events.  You have whatever you want.  For example, there is an hospital in my city that they  want to store the passion sheets about, OK, he's ill.  He has these problems.  We solve that.  This is content.  Everything that's a piece of a document that we can have in  a word, or an Excel, or whatever, or we can have in a  piece of text is a document.  So content is the king.  Content is the center of Plone.  And we have full multilingual support in  Catalan also.  So that's great.  It's translated in more than 50 languages.  I added this, because most of the CMSs that we have in other  languages, like Java, I think, or something like that,  doesn't have full multilingual support.  That means that all the content can be translated to all  the languages, and you have connection between one  translation to the other, blah, blah, blah.  OK.  One of the most important things about Plone is the security.  Why is being used by FEI?  Why is it being used by the Zilden government?  Why is it being used by ABB?  Because they know that it's really secure.  So all the content that's there, all the fields, everything  that's there, is not going to be seen by anybody that you  don't want that to be seen.  And why is it because we have this security granularity?  It's because we have Jope and ZLDB.  I'm going to talk a bit about that later.  And we have workflows.  So all the content goes through different steps, and each  step has different permissions for different users,  groups, et cetera.  Theming.  If you were using Plone before Plone 5, 4.4, you  surely would quit using Plone, because it was really  difficult to use.  The curve of entrance.  I've been asking some of the European people, have you used  Plone in the past?  Yeah, yeah, but I quit it because it was so  difficult to understand.  So we solved that.  We solved most of the problems that we had with the Theming.  For example, now we are using some kind of rules we call  the ASO.  It's using, they are being, they are designed so you can  see your site without knowing anything, neither about  Python, if you want.  It's using rules to move things from place to the other.  Later I'm going to show.  Ah, yeah, we integrated required JS and less.  So if you want to build a nice front end with Angular or  with V app or whatever, Plone directly provides you the  tools that you need to do that.  We have inline edition through the web edition.  So you can see in the back, you can create content, move  content around.  This is Mosaic project.  It's one spin off of Plone that's still  working progress.  It's really cool because you can just create content.  You can just upload an image through the web with a  drag and drop and push it wherever you want in the page.  OK, if you want, we can try.  Let's see.  So this is the new Plone 5 front end.  It's really cool because it's using a theme called  Barcelona.  Barcelona from Barcelona.  Catalonia again.  Ah.  Thank you.  Just you can see, I think it's English.  So there is some kind of cool things you can browse.  All your content here, this resolution is not really  good for doing these kinds of things.  But you can go to the folders.  You can go to the content and see whatever you have here.  You can create a new page wherever you want.  And just write down whatever you want.  You have this tiny mc4 that's really cool.  So you can push images.  You can push files, whatever, and save it.  OK, so then you can go to content.  There is a lot of good features that if I would show  that, we will still until tomorrow.  So just sharing.  You can decide who can edit, who can, the history button,  where you can see who edited, which is the difference, et  cetera, et cetera.  Yeah.  OK.  So now as we are in a technical conference,  I'm going to talk a bit more about how it's technically  blown, because that was like the commercial screencast.  So let's go.  URKC.  The blown is based on a URKC database,  because as all the users are used to have their desktops  with folders, content inside that.  So we are using a specific database.  It's called Zodib.  It's really, I think right now, Zodib has more than 10 years,  maybe?  More than 10, 12 years.  OK.  So at that time, nobody was talking about non-SQL.  And Zodib is a non-SQL database that you store objects  in, inside objects.  And he stores directly the pickles on a really great  structure.  If you are not going to use blown,  but you need some kind of database  that you need to store a tree of objects that are going to have  some kind of relation between them,  Zodib is a really great database outside of blown also.  So this concept of storing everything in a URKC mode,  it's really, there is no other CMS that does that.  Everybody is storing things in SQL data,  but content management is not relational data.  If you go to the university and you say, oh, I'm going to store  an object and I'm going to put all the HTML in a field  of my table.  Sorry.  You need to structure that.  You need semantical.  You need to have the option to have sons of your content.  You have a folder, then you have content inside that,  images inside that.  So that's one of the main points of technically talking.  But the content is the king.  We have this folder structure.  So then what are we using to have the content?  We are using a project.  It's called Dexterity in Plum 5.  We remove it, our type.  If you never use our types, I'm really sorry for you.  But Dexterity is really a cool piece of software  because it allows you to create defined content.  Oh, where is my?  Yeah.  With a simple interface, just you decide, OK,  I want to create a content.  It's called a sponsor.  And then you have a choice field where  you can have different vocabulary,  a little vocabulary that's going to be shown from the UI.  You have a rich text.  That means it's a tiny mc.  It's going to render a tiny mc so you can write down.  You can define a urie, you can define different kind of fields,  files, images.  You can define also permissions for specific fields.  I want that.  Timo doesn't see that field.  So I can write that.  Timo will not see that field.  That's really cool.  So with this simple file, there is no copy of strange thing  that we use on our types that only defines really  the interface, really the fields that you want in your content.  The semantical meaning of your content,  you can define your own content type.  Then this content type, it's going to be mapped to the URL.  So one of the good things also we have in Zoop, Blown,  blah, blah, blah, blah, is that we have traversal.  That means that all these folders that we have,  I explain it to you that you have a folder and then a content  and then an image, for example.  You can access that through the URL.  You can write the URL of your site, the folder, the content,  blah, blah, blah.  And then the view, a specific browser view,  function that renders that and creates a templating stuff  or whatever you want to use to see that.  Here we have an example of what's a view.  So here we have, OK, one of the cool things we added  is all this JavaScript CSS management system.  So you register CSS and JavaScript,  and then it automatically pops up on your page  when it's needed.  So you can register, for example, a bundle,  jQuery data tables.  And you want that this view that's  going to render some kind of page has this JavaScript included  and the CSS that's needed for this resource to be loaded.  So then you just add resource on request  and you write the name of the resource that you want to add,  and it's automatically going to be deployed on your view  when you are rendering that.  Yeah, there is a lot of technical details.  Just don't want to step too much, maybe.  Here is how we register a view.  I've been asking a lot of people here in Uri Python,  what's the worst thing about blown?  And they say, this is XML because it's XML.  XML is not bad, sorry.  It's OK, it could be better.  This is XML.  It's really great because it allows  us to have really a good list of the views, the content,  all the definitions that we have.  So I really think it's great to have this way of defining  all the views and all the content.  Yeah, and we have the templating.  Yeah, because you can create a class  to show you the content, to have your content type there.  But you need some kind of class to render that on the view page.  I have some kind of templating.  And one of the cool things that we added at the end of blown4  is that we can use chameleon.  So now, no more tau, no more way of defining variables  with a specific crappy language that's only being used by Zoop.  So we can define these variables and use the variables  with these dollar stuff there.  That's really interesting.  Interesting.  So Python.  OK, I think that most of you know that.  Zoop is the most Python-based framework  for work on content management.  You can access the object of your site,  and it's everything mapped to the database.  Then you can just go to the attribute of your site  that's called a folder.  And then you can go to the attribute of the folder  that's called a document.  And then you can access an attribute of the document.  So you would really have the granularity and the Python  way of doing content management.  Yeah, I wanted to talk about Zoop component architecture,  because maybe there was been a lot of talks.  The last one I saw that pushed on internet was 2005.  But it's really interesting infrastructure,  and it's being misused, I think, because we have  Zoop.interface and Zoop.component.  That it's really two good packages  for managing three good patterns of programming that, OK.  Normally, when you write some Python code,  you write a small program.  But if your program is going to grow up,  you will need to have some kind of patterns  for designing that software.  And sometimes there is really good libraries about patterns,  how to develop big softwares with that.  And Zoop is a really good one.  I really love it.  So where are we storing our components, our adapters,  our patterns?  It's in local storage, local registry, and global registry.  We have two in Zoop, one is global for all the sites  of your environment, of your process, of your thread,  and then one specific for each site that's the local registry.  So I wanted to first explain you, OK, what's an adapter?  Adapter, it's one of the patterns that, and software,  it's really good for using.  Because we are using in the past subclassing classes.  So we ended up having our types that maybe you  were looking how many classes it was subtyped.  And it was maybe 30 different classes  that if you go up to see the parents of the class,  you will never know what's going to be there.  It was a mess.  So they decided in Zoop community  to create this adapter pattern.  And it's an interface, you define, in this case, a person.  You define some kind of normal interface, like Java,  like whatever.  You define some definitions and the attributes  of that interface.  And you have implementations of that interface.  For example, we have an interface called Iperson  that you define a function which the share time is wearing.  And then you have an adaptation.  It's called Catalan Guy.  And then it returns a stilada.  And if there is another implementation,  it's called Bass Guy.  It shares a t-shirt.  So you can use any of these adapters to adapt an object  and get the methods that you need.  The subscriber, another kind of good pattern,  the observer pattern, the subscriber pattern  on software engineering.  Here we have the kind of object that we want to look.  I want to check if you modify this kind of object,  if you modify the Iperson object.  Then you can subscribe for Iperson.  And you want to subscribe for the modified event.  And you decide which function is going to be executed  in case that's being modified.  And utility, OK, that's just you want  to store some kind of list of good alcohol.  Then you define an interface, good alcohol.  And then you have an object that will return  all the list of good alcohol because it's an utility.  That's really useful.  And then at the end, in this more technical,  well-blown stuff, I'm going to talk  about the JavaScript and the CSS integration we did.  We created our own kit, our own framework, JavaScript framework.  That's the worst error we did, I think,  because it's going to be hard to maintain.  But at the moment, there was no the solutions we have right  now on the community of JavaScript.  But it was really great.  It's using patterns, lib patterns,  as a way of defining, OK, you have these elements.  And then with data tags on the HTML elements,  you can configure them.  And they automatically run JavaScript on top of that  and renders the correct widget for you.  For example, this is the date picker date widget  that we have on blow normally.  Then you can see.  This is the configuration.  You define the format, the date, blah, blah, blah.  And everything is integrated with required.js  and less.  That means that if you want, you can start your clone  in debug mode.  And then you are going to see everything  compiled on time on the browser.  So you will see the source code of select to there.  So you can go and debug whatever thing you need.  Because when you're blown, I think  that has nearly 1 million lines of JavaScript  with all the libraries that's including tiny mc is so big.  So if you want to debug that, and you don't have the option  to really have them uncompressed,  and that you don't need to take care about loading everything.  So we created a Python model that's  taking care of that, creating the JavaScript configuration  for required.js and compiling less.  So you get the source code there on your browser.  Diaso, I'm not going to stand on that just a way of defining  themes.  So you go to your designer and say, OK,  I need to do this web page.  So just design that.  The designer draws it.  You send to the people who does the HTML.  And he does the HTML.  OK, the HTML is done.  And then you give to the clone guys,  OK, this is the HTML of my site.  And with these Diaso rules, you just remove.  I want that this deep is this deep of the clone.  This piece of here is this piece of here.  And you can create your theme without doing  so hard integration right now.  That's also a really cool thing.  OK, new things that we are working,  that we are going to do in the next month, I hope,  is the Plum Rest API.  It's really clear that all the web frameworks  or the web applications are going to move to JavaScript.  All the UI needs to be done in JavaScript.  So what's really needed is that we  have a really cool rest API that we can interact with clone.  So we created Plum for the rest.  I think it's not released, but it's  going to be released really soon.  You can try it on GitHub.  It's really great.  We defined a way to define this HTTP  verbs like put, get, delete, on a specific content type.  OK, I have I person, and I want to delete the person.  So then I can define a specific HTTP verb  for deleting on this object, and which  is the function that's going to be executed.  So here, you see, for example, the implementation of the put.  OK, testing.  We improved a lot on testing.  We really did a lot of work there.  Jenkins.plone.org has the Plum 5 job has 101 acceptance  stands, and I think there are more than 5,000 more?  9,000 integration tests and unit testing.  We really test everything.  If you commit something and you break the bill,  then this guy comes to you and starts to yell at you.  And you never go to sleep before the Jenkins screen again.  So we have a really good testing.  I really want to thank Tim and the testing team  because they really did a great job on that.  Because we have really, really a good testing environment.  So that makes also the companies rely on us because, OK,  we create a new release of Plone,  and you know that's going to work because we have really  tested everything.  I changed the name of the button of a control panel  and 10 test fields.  So that's really, really great.  And for companies that rely on that  and they want the best money to get their sites done  and the one that in five years is still there.  So that's really important.  So, OK, we have Plone 5 beta 3 release.  Now we created a specific repository.  So if anybody wants to try it and hit things,  OK, it's going to be difficult to try Plone  because it's a complex software.  OK, it's one, two, three, four lines of on-soul to try that.  You go just clone the jithub.com.plone jamming2.  You run with Python 2.7.  ZODB is already running on Python 3.  So we think that we are going to someday to have options  to have Python 3 and all the stack.  It's really big.  So we will try.  Then we run without, and then you run instance fg.  And you have your clone site running.  It's only four lines of code, four lines of console.  You need to go to take a coffee between the build out  and the instance because it might take 10 or 15 minutes,  depending on the machine and the network.  OK, just one, two, five.  We have a really good documentation.  There is training.plot.r.  There is docs.plot.r.  Hundreds of different documentation  written for developers and for users.  And lots of training.  There is a training that helps you to understand.  OK, the future.  We are going to move, maybe, to Azure to REST API.  And we need a JSON front end.  We are going to have some kind of a sync I.O. back end.  Maybe with SubstanceD, maybe with pyramid.  Who knows?  We will see.  We are going to talk about that.  This talk also has the vn machine learning.  And they sent me 10 minutes.  So I'm going to talk about machine learning also.  So what we did in clone is we created a proof of concept  because our main goal, the goals that we had of using  machine learning is that, OK, the user has used a CMS.  So when you get to the content, you  want to see, for example, the related content that's  on your site.  But the people doesn't go to see, oh,  this is related to this one.  And this is related to this one.  Because nobody does that in the content management system.  So we wanted to create a smart way of that everything is  related between them automatically.  Classification of the current content.  So if you have your upload site that the people has already  targeted the stuff there, then you won't just maybe  to run some classification algorithms on top of that  to just classify what's added on your content, on your clone.  Recommendation of widgets and tags.  That means that if you're creating a new content  and you are editing the content, having a way of user  feeling that it's suggesting you, OK, this content talks  about that.  Just asking the user if he wants to tag this content  with this kind of subject.  And semantic search on the live search.  We have a really nice live search.  So you can search in Google and get the content that's there.  But it's completely text.  It's looking for text on all the files that we have and all  the content that we have.  So we're trying to make that it to have semantic search.  So it's related to stuff.  So it gets more useful.  So I started to try to understand what's machine  learning.  It's a completely big subject.  I found one really good picture that I really love  and I wanted to show you.  This is Seiki Learn, a map.  So you go from a star and say, OK, what I need to do?  I need to.  I have more than 50 samples.  Yeah, I'm blown.  Normally you have more than 50 samples.  OK, I want to predict a category.  Yes, I want to predict what's talking about.  OK.  I have label at data.  No, because people doesn't have label at data.  So then we are going to go to yes, but now we go to no.  So we know how many categories we have.  We don't know how many blocks of content  is going to be in the blown side.  But that needs to be defined for the administrator  because we are not going to try to predict that.  So then we are going to use kimmins.  And kimmins is one of the algorithms  that we have implemented.  And I'm going to show you if you have that.  Then in case that we have label at information,  we have another branch.  This is a really good Seiki spreadsheet  that helps you a lot to decide which algorithms you need  to use for different kind of usage.  Seiki Learn maybe is not the best option,  but we wanted something that is integrated in blown  and you don't need to run anything else external.  There is also implementation with Jensim.  That works fine.  But you need a external REST API.  You need to export the content.  And our clients are really specific about security.  So they don't want that we export the content  to any other external application.  So we need to have everything embedded on the security of Jop.  So we implemented this, Collective.Machine Learning  in our Github.  Das Clustering is one of the initial one.  So what we created is an adapter.  It's called iLearningString.  You get from that adapter from this content type  is iPerson.  And you create this adapter.  So this person, I want to get which text I want to use  in the machine learning stuff.  So maybe you want to join the name, the first name,  and his birthday or whatever.  And then you create a text line, a text  that is going to be used for analyzing.  Then we normalize it.  We vectorize with NLTK with feature hasher  that we get the corpus of each document.  And we store that corpus on a pickle on the database.  So we can reuse later.  So it's not expensive later to use that.  We clusterize.  That means that with all the corpus that we have,  we created the big metrics of all the things  that are on the site.  We tried with more than 150,000 documents.  OK, you need 64 gigabytes of RAM or 32 gigabytes of RAM  to run that on memory.  If you want, you can just use the batch stuff of Kimin's.  But this is what running on a single process.  We try to use just memory.  There is an algorithm that allows you to have batches,  Kimin batch.  So we clusterize that.  We define the numbers of clusters  that we want on the front end.  And then we just use the Kimin's algorithms  to decide groups of content.  And we store this model, the model  that we get on a pickle on the database.  And then we use that model to predict  in which cluster is going to be the next content you create.  You create a new content.  And then automatically, we'll see, OK,  this content belongs to this cluster.  Yeah, the good thing is that all this implementation  has security implicitly because the ZODBs  has its object and the catalog is secure.  So nobody's going to get any information that  doesn't need to be seen by them.  And OK, in the future, we are now  working with Naive Bayes for classification, recommendation,  semantic search, and external.  We want to be able to extern to push the computation  outside of clone.  But it's a bit difficult with a security issue.  And I wanted to show you because they say, oh, maybe  I'm not going to believe what you're saying.  OK, so this side has a source in Catalan  because I was doing this morning and was a bit sleepy.  So yeah, not like that.  So here I created, for example, some content, a lot of copy  based content here.  And if I go to any content here, I  will see that it belongs to cluster one.  This side, let me see.  Where is my pointer?  Yeah.  So there is a sign map, automatic sign map,  that gets and classifies all my content in different clusters.  I'm creating content and it automatically  defines the groups of content that's  semantically close to that.  So how it's configured, it's really nice,  this control panel, new stuff.  Victor did that there.  So let's see.  Yeah, machine learning settings.  So here you define one of the first systems  you're going to store the vehicles.  You want to use an SDK steam, which  are the stop words that you want to use,  the different grades that we have.  If you want to remember the hashing of the strings,  so they are being restored.  And then we define how many clusters we want,  the maximum number of clusters, and which  is the name of the pickle that we're  going to use to store the clustering.  And then you can press this compute button.  And this compute button, it's getting all the content,  processing all the content, steaming all the content,  and creating in the catalog of the specific indexes  that will allow us to, in the browser,  see which object to which cluster it belongs.  And we created this nice view.  Yeah, this nice view is called autosite map,  and automatically shows you the content  grouped by this kind of cluster.  And then it's a matter of each cluster you define what's about.  And if you have real content, it's really easy to see that,  because you see the titles.  And OK, this cluster is talking about this kind of stuff.  So you can name that cluster, and people  will see all the content automatically pushed.  So this, I'm going to return back to the talk.  Yeah, we have a feature on this.  This is a proof of concept we are using in production  from some sites, because it was needed.  But we are working really a lot on that,  and we are sprinting on that a lot of times.  So if there is any data science people that  wants to help us to understand what's going on behind all  this stuff, we are really happy that they help us.  OK, Plum Community.  It's a cool community.  If anybody wants to join the Plum Community,  we should try now that it's much easier than in the past.  You're welcome.  We are really cool.  And if there is any questions, we're done.  Thank you.  Thank you for the presentation.  Just one question.  How does this handle content in different languages?  Yeah, right now the steaming that we have uses English.  And we need to add in the control panel  drop down that allows you to decide which language  do you want to use.  The steaming is implemented in most of the languages.  So it's just a matter of that we add in the control panel  this option.  Could you give us a few numbers?  How long the computation takes?  If you have, like, say, 100,000 or a million objects  in a city to be?  We do that at night.  It starts, I think, at 1.  And it finish at 4.  So three hours.  In 150,000.  OK, so you most likely have a specific instance for that.  So it does not block the other ones.  We have a specific.  The only problem is that when it's finished,  the computation needs to write down on all the objects  the cluster.  And that's what takes more.  Writing down in all the objects, which  is the cluster that belongs to.  What's the size once it's done the computation of the pickle  on 150,000 documents?  And is that read into memory with the sitemap generator  on every page request?  Or do you cache it somehow?  Sorry, I didn't understand.  Sorry.  So what is the size of the pickle that's generated  at the end of the computation?  And is that read into memory on the autositemap  on every page request?  No, no, no.  We are storing the model.  And we are storing the vectors, the matrix, the corpus.  We are storing the corpus.  And we are storing the model.  So we are storing the model because when  you create a new content, you want  to ask to the model, which is the cluster  which it belongs to storing the attribute.  And we store the matrix.  So if you want to compute some more times,  you don't need to recalculate everything.  So everything can be cached.  It is normally five.  When you are using the site, when you are doing any request,  nothing is computed.  Because everything is stored on the catalog  and on the attributes on the objects.  So it's not real time machine learning.  So it's more like we run the algorithms  and we integrate with blown.  Do I have more questions?  Is there something that can do real time machine learning?  You should talk with some data science.  OK, because I mean, I know like solar or a lesson  search or things like that, and I don't think that this  is possible because it takes some time to build all the indexes.  And I guess for machine learning,  that's the same as true.  And then you need incremental indexes and algorithms  so that that might be hard to do.  I just discovered talking with some data science  from the platform.  In Python, there is some kind of line of investigation.  It's called online.  How is it called?  Online?  Online learning, yeah.  So that are the kind of algorithms  that you grow incrementally.  And it's designed more for online applications.  So we need to investigate that line of usage.  Some more questions?  If not, it's lunch time.  Let's thank this speaker again.  Thank you.  Thank you for lunch.
Ramon_Navarro_Bosch_-_Plone_5_and_how_to_use_machine_learning_with_it__0_47.png Ramon_Navarro_Bosch_-_Plone_5_and_how_to_use_machine_learning_with_it__48_503.png Ramon_Navarro_Bosch_-_Plone_5_and_how_to_use_machine_learning_with_it__504_551.png Ramon_Navarro_Bosch_-_Plone_5_and_how_to_use_machine_learning_with_it__552_623.png Ramon_Navarro_Bosch_-_Plone_5_and_how_to_use_machine_learning_with_it__624_839.png Ramon_Navarro_Bosch_-_Plone_5_and_how_to_use_machine_learning_with_it__840_971.png Ramon_Navarro_Bosch_-_Plone_5_and_how_to_use_machine_learning_with_it__972_1475.png Ramon_Navarro_Bosch_-_Plone_5_and_how_to_use_machine_learning_with_it__1476_8315.png Ramon_Navarro_Bosch_-_Plone_5_and_how_to_use_machine_learning_with_it__8316_9443.png Ramon_Navarro_Bosch_-_Plone_5_and_how_to_use_machine_learning_with_it__9444_9635.png Ramon_Navarro_Bosch_-_Plone_5_and_how_to_use_machine_learning_with_it__9636_10931.png Ramon_Navarro_Bosch_-_Plone_5_and_how_to_use_machine_learning_with_it__10932_17879.png Ramon_Navarro_Bosch_-_Plone_5_and_how_to_use_machine_learning_with_it__17880_18707.png Ramon_Navarro_Bosch_-_Plone_5_and_how_to_use_machine_learning_with_it__18708_20507.png Ramon_Navarro_Bosch_-_Plone_5_and_how_to_use_machine_learning_with_it__20508_22271.png Ramon_Navarro_Bosch_-_Plone_5_and_how_to_use_machine_learning_with_it__22272_24335.png Ramon_Navarro_Bosch_-_Plone_5_and_how_to_use_machine_learning_with_it__24336_25199.png Ramon_Navarro_Bosch_-_Plone_5_and_how_to_use_machine_learning_with_it__25200_28607.png Ramon_Navarro_Bosch_-_Plone_5_and_how_to_use_machine_learning_with_it__28608_30059.png Ramon_Navarro_Bosch_-_Plone_5_and_how_to_use_machine_learning_with_it__30060_30647.png Ramon_Navarro_Bosch_-_Plone_5_and_how_to_use_machine_learning_with_it__30648_31235.png Ramon_Navarro_Bosch_-_Plone_5_and_how_to_use_machine_learning_with_it__31236_32567.png Ramon_Navarro_Bosch_-_Plone_5_and_how_to_use_machine_learning_with_it__32568_32723.png Ramon_Navarro_Bosch_-_Plone_5_and_how_to_use_machine_learning_with_it__32724_32867.png Ramon_Navarro_Bosch_-_Plone_5_and_how_to_use_machine_learning_with_it__32868_34727.png Ramon_Navarro_Bosch_-_Plone_5_and_how_to_use_machine_learning_with_it__34728_37031.png Ramon_Navarro_Bosch_-_Plone_5_and_how_to_use_machine_learning_with_it__37032_37187.png Ramon_Navarro_Bosch_-_Plone_5_and_how_to_use_machine_learning_with_it__37188_38135.png Ramon_Navarro_Bosch_-_Plone_5_and_how_to_use_machine_learning_with_it__38136_38363.png Ramon_Navarro_Bosch_-_Plone_5_and_how_to_use_machine_learning_with_it__38364_44147.png Ramon_Navarro_Bosch_-_Plone_5_and_how_to_use_machine_learning_with_it__44148_44459.png Ramon_Navarro_Bosch_-_Plone_5_and_how_to_use_machine_learning_with_it__44460_45047.png Ramon_Navarro_Bosch_-_Plone_5_and_how_to_use_machine_learning_with_it__45048_45335.png Ramon_Navarro_Bosch_-_Plone_5_and_how_to_use_machine_learning_with_it__45336_46247.png Ramon_Navarro_Bosch_-_Plone_5_and_how_to_use_machine_learning_with_it__46248_46319.png Ramon_Navarro_Bosch_-_Plone_5_and_how_to_use_machine_learning_with_it__46320_46367.png Ramon_Navarro_Bosch_-_Plone_5_and_how_to_use_machine_learning_with_it__46368_46535.png Ramon_Navarro_Bosch_-_Plone_5_and_how_to_use_machine_learning_with_it__46536_46835.png Ramon_Navarro_Bosch_-_Plone_5_and_how_to_use_machine_learning_with_it__46836_46895.png Ramon_Navarro_Bosch_-_Plone_5_and_how_to_use_machine_learning_with_it__46896_48983.png Ramon_Navarro_Bosch_-_Plone_5_and_how_to_use_machine_learning_with_it__48984_49631.png Ramon_Navarro_Bosch_-_Plone_5_and_how_to_use_machine_learning_with_it__49632_50171.png Ramon_Navarro_Bosch_-_Plone_5_and_how_to_use_machine_learning_with_it__50172_50219.png Ramon_Navarro_Bosch_-_Plone_5_and_how_to_use_machine_learning_with_it__50220_50303.png Ramon_Navarro_Bosch_-_Plone_5_and_how_to_use_machine_learning_with_it__50304_50351.png Ramon_Navarro_Bosch_-_Plone_5_and_how_to_use_machine_learning_with_it__50352_50555.png Ramon_Navarro_Bosch_-_Plone_5_and_how_to_use_machine_learning_with_it__50556_51023.png Ramon_Navarro_Bosch_-_Plone_5_and_how_to_use_machine_learning_with_it__51024_51263.png Ramon_Navarro_Bosch_-_Plone_5_and_how_to_use_machine_learning_with_it__51264_51755.png Ramon_Navarro_Bosch_-_Plone_5_and_how_to_use_machine_learning_with_it__51756_53111.png Ramon_Navarro_Bosch_-_Plone_5_and_how_to_use_machine_learning_with_it__53112_54047.png Ramon_Navarro_Bosch_-_Plone_5_and_how_to_use_machine_learning_with_it__54048_54647.png Ramon_Navarro_Bosch_-_Plone_5_and_how_to_use_machine_learning_with_it__54648_55691.png Ramon_Navarro_Bosch_-_Plone_5_and_how_to_use_machine_learning_with_it__55692_55739.png Ramon_Navarro_Bosch_-_Plone_5_and_how_to_use_machine_learning_with_it__55740_56111.png Ramon_Navarro_Bosch_-_Plone_5_and_how_to_use_machine_learning_with_it__56112_56243.png Ramon_Navarro_Bosch_-_Plone_5_and_how_to_use_machine_learning_with_it__56244_56434.png